浏览代码

Merge branch 'release/0.0.5'

yazid138 3 年之前
父节点
当前提交
411f7ad27b
共有 43 个文件被更改,包括 1579 次插入2093 次删除
  1. 52 0
      actions/auth.js
  2. 2 2
      actions/log.js
  3. 1 1
      components/Extras/calendar.view.js
  4. 13 13
      components/Layout/Head.js
  5. 213 252
      components/Layout/Header.js
  6. 5 71
      components/Layout/Menu.js
  7. 52 0
      components/Layout/MenuPT.js
  8. 378 380
      components/Layout/Offsidebar.js
  9. 277 318
      components/Layout/Sidebar.js
  10. 48 42
      components/Layout/SidebarUserBlock.js
  11. 1 1
      components/Main/DetailSanksi.js
  12. 2 2
      components/Main/PermohonanPT.js
  13. 33 31
      components/Main/TableSanksi.js
  14. 67 0
      components/Main/Timeline.js
  15. 7 9
      components/PT/JawabanKeberatan/ModalPermohonan.js
  16. 13 12
      components/PT/Keberatan/ModalPermohonan.js
  17. 0 1
      components/PT/Riwayat.js
  18. 1 1
      components/PT/TableSanksi.js
  19. 68 0
      components/PT/Timeline.js
  20. 3 1
      components/Pemeriksaan/TableRiwayat.js
  21. 1 1
      components/Sanksi/TablePenetapanSanksi.js
  22. 27 0
      config/axios.js
  23. 56 0
      json/dataUser.js
  24. 5 0
      package-lock.json
  25. 1 0
      package.json
  26. 8 0
      pages/app/_middleware.js
  27. 2 3
      pages/app/banding/detail.js
  28. 4 4
      pages/app/keberatan/detail.js
  29. 1 1
      pages/app/pemantauan-perbaikan/index.js
  30. 17 314
      pages/app/pemantauan/timeline.js
  31. 3 3
      pages/app/pencabutan-sanksi/detail.js
  32. 1 5
      pages/app/pt/dokumen-perbaikan/index.js
  33. 13 7
      pages/app/pt/jawaban-keberatan/detail.js
  34. 14 4
      pages/app/pt/keberatan/detail.js
  35. 15 329
      pages/app/pt/pemantauan.js
  36. 0 5
      pages/app/sanksi/detail.js
  37. 15 15
      pages/index.js
  38. 128 201
      pages/login.js
  39. 0 58
      pages/singleview.js
  40. 12 0
      store/actions/user.js
  41. 2 0
      store/reducers/reducers.js
  42. 12 0
      store/reducers/user.reducer.js
  43. 6 6
      store/store.js

+ 52 - 0
actions/auth.js

@@ -0,0 +1,52 @@
+import axios from "axios";
+import axiosJWT from "../config/axios";
+import qs from "qs";
+
+export const login = async (username, password) => {
+	try {
+		const data = qs.stringify({
+			username,
+			password,
+		});
+
+		const response = await axios.post("http://localhost:5000/login", data, {
+			headers: {
+				"Content-Type": "application/x-www-form-urlencoded",
+			},
+			withCredentials: true,
+		});
+
+		return response.data;
+	} catch (error) {
+		if (error.response) return error.response.data;
+	}
+};
+
+export const refreshToken = async () => {
+	try {
+		const response = await axios.get("http://localhost:5000/token", { withCredentials: true });
+		return response.data;
+	} catch (error) {
+		if (error.response) return error.response.data;
+	}
+};
+
+export const getUser = async () => {
+	try {
+		const response = await axiosJWT.get("http://localhost:5000/user");
+		return response.data;
+	} catch (error) {
+		if (error.response) return error.response.data;
+	}
+};
+
+export const logout = async () => {
+	try {
+		const response = await axios.delete("http://localhost:5000/logout", {
+			withCredentials: true,
+		});
+		return response.data;
+	} catch (error) {
+		if (error.response) return error.response.data;
+	}
+};

+ 2 - 2
actions/log.js

@@ -1,6 +1,6 @@
-export const getLog = async () => {
+export const getLog = async ({ ptId }) => {
 	try {
-		const res = await fetch("http://localhost:5000/log");
+		const res = await fetch(`http://localhost:5000/log?ptId=${ptId}`);
 		return await res.json();
 	} catch (error) {
 		console.log("error", error);

+ 1 - 1
components/Extras/calendar.view.js

@@ -60,7 +60,7 @@ class Calendar extends Component {
 		if (data[0].penjadwalan) {
 			color = data[0].penjadwalan.background_color;
 		}
-		this.setState({ externalEvents: [{ id: this.props.query.number, color: color, name: "Jadwal Pemeriksaan - BI:" + this.props.query.number }] });
+		this.setState({ externalEvents: [{ id: this.props.query.number, color: color, name: `Jadwal Pemeriksaan - BI: ${this.props.query.number} - Universitas Satyagama` }] });
 	}
 
 	getDataEvent = () => {

+ 13 - 13
components/Layout/Head.js

@@ -1,21 +1,21 @@
-import React from 'react';
-import NextHead from 'next/head';
-import PropTypes from 'prop-types';
+import React from "react";
+import NextHead from "next/head";
+import PropTypes from "prop-types";
 
-const defaultDescription = '';
+const defaultDescription = "";
 
-const Head = props => (
-    <NextHead>
-        <meta charSet="UTF-8" />
-        <title>PTB-Ristekdikti</title>
-        <meta name="description" content={props.description || defaultDescription} />
-        <meta name="viewport" content="width=device-width, initial-scale=1" />
-        <link rel="icon" href="/static/favicon.ico" />
-    </NextHead>
+const Head = (props) => (
+	<NextHead>
+		<meta charSet="UTF-8" />
+		<title>PTB-Ristekdikti</title>
+		<meta name="description" content={props.description || defaultDescription} />
+		<meta name="viewport" content="width=device-width, initial-scale=1" />
+		<link rel="icon" href="/static/img/logo-single.png" />
+	</NextHead>
 );
 
 Head.propTypes = {
-    description: PropTypes.string
+	description: PropTypes.string,
 };
 
 export default Head;

+ 213 - 252
components/Layout/Header.js

@@ -1,263 +1,224 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import Link from 'next/link';
-import {
-    UncontrolledDropdown,
-    DropdownToggle,
-    DropdownMenu,
-    DropdownItem,
-    ListGroup,
-    ListGroupItem
-} from 'reactstrap';
+import React, { Component } from "react";
+import Router from "next/router";
+import PropTypes from "prop-types";
+import Link from "next/link";
+import { UncontrolledDropdown, DropdownToggle, DropdownMenu, DropdownItem, ListGroup, ListGroupItem } from "reactstrap";
+import { logout } from "@/actions/auth";
 
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
-import * as actions from '../../store/actions/actions';
+import { connect } from "react-redux";
+import { bindActionCreators } from "redux";
+import * as actions from "../../store/actions/actions";
 
-import ToggleFullscreen from '../Common/ToggleFullscreen';
-import HeaderSearch from './HeaderSearch';
+import ToggleFullscreen from "../Common/ToggleFullscreen";
+import HeaderSearch from "./HeaderSearch";
 
 class Header extends Component {
-    state = {
-        navSearchOpen: false
-    };
-
-    toggleNavSearch = e => {
-        e.preventDefault();
-        this.setState({
-            navSearchOpen: !this.state.navSearchOpen
-        });
-    };
-
-    closeNavSearch = e => {
-        e.preventDefault();
-        this.setState({
-            navSearchOpen: false
-        });
-    };
-
-    toggleUserblock = e => {
-        e.preventDefault();
-        this.props.actions.toggleSetting('showUserBlock');
-    };
-
-    toggleOffsidebar = e => {
-        e.preventDefault();
-        this.props.actions.toggleSetting('offsidebarOpen');
-    };
-
-    toggleCollapsed = e => {
-        e.preventDefault();
-        this.props.actions.toggleSetting('isCollapsed');
-        this.resize();
-    };
-
-    toggleAside = e => {
-        e.preventDefault();
-        this.props.actions.toggleSetting('asideToggled');
-    };
-
-    resize() {
-        // all IE friendly dispatchEvent
-        var evt = document.createEvent('UIEvents');
-        evt.initUIEvent('resize', true, false, window, 0);
-        window.dispatchEvent(evt);
-        // modern dispatchEvent way
-        // window.dispatchEvent(new Event('resize'));
-    }
-
-    render() {
-        return (
-            <header className="topnavbar-wrapper">
-                {/* START Top Navbar */}
-                <nav className="navbar topnavbar">
-                    {/* START navbar header */}
-                    <div className="navbar-header">
-                        <a className="navbar-brand" href="#/">
-                            <div className="brand-logo">
-                                {/* <img
-                                    className="img-fluid"
-                                    src="/static/img/logo-inner.png"
-                                    alt="App Logo"
-                                /> */}
-                            </div>
-                            <div className="brand-logo-collapsed">
-                                <img
-                                    className="img-fluid"
-                                    src="/static/img/logo-single.png"
-                                    alt="App Logo"
-                                />
-                            </div>
-                        </a>
-                    </div>
-                    {/* END navbar header */}
-
-                    {/* START Left navbar */}
-                    <ul className="navbar-nav mr-auto flex-row">
-                        <li className="nav-item">
-                            {/* Button used to collapse the left sidebar. Only visible on tablet and desktops */}
-                            <a
-                                href=""
-                                className="nav-link d-none d-md-block d-lg-block d-xl-block"
-                                onClick={this.toggleCollapsed}
-                            >
-                                <em className="fas fa-bars" />
-                            </a>
-                            {/* Button to show/hide the sidebar on mobile. Visible on mobile only. */}
-                            <a
-                                href=""
-                                className="nav-link sidebar-toggle d-md-none"
-                                onClick={this.toggleAside}
-                            >
-                                <em className="fas fa-bars" />
-                            </a>
-                        </li>
-                        {/* START User avatar toggle */}
-                        <li className="nav-item d-none d-md-block">
-                            <a className="nav-link" onClick={this.toggleUserblock}>
-                                <em className="icon-user" />
-                            </a>
-                        </li>
-                        {/* END User avatar toggle */}
-                        {/* START lock screen */}
-                        <li className="nav-item d-none d-md-block">
-                            <Link href="/pages/lock" as="/lock">
-                                <a title="Lock screen" className="nav-link">
-                                    <em className="icon-lock" />
-                                </a>
-                            </Link>
-                        </li>
-                        {/* END lock screen */}
-                    </ul>
-                    {/* END Left navbar */}
-                    {/* START Right Navbar */}
-                    <ul className="navbar-nav flex-row">
-                        {/* Search icon */}
-                        <li className="nav-item">
-                            <a className="nav-link" href="" onClick={this.toggleNavSearch}>
-                                <em className="icon-magnifier" />
-                            </a>
-                        </li>
-                        {/* Fullscreen (only desktops) */}
-                        <li className="nav-item d-none d-md-block">
-                            <ToggleFullscreen className="nav-link" />
-                        </li>
-                        {/* START Alert menu */}
-                        <UncontrolledDropdown nav inNavbar className="dropdown-list">
-                            <DropdownToggle nav className="dropdown-toggle-nocaret">
-                                <em className="icon-bell" />
-                                <span className="badge badge-danger">11</span>
-                            </DropdownToggle>
-                            {/* START Dropdown menu */}
-                            <DropdownMenu right className="dropdown-menu-right animated flipInX">
-                                <DropdownItem>
-                                    {/* START list group */}
-                                    <ListGroup>
-                                        <ListGroupItem
-                                            action
-                                            tag="a"
-                                            href=""
-                                            onClick={e => e.preventDefault()}
-                                        >
-                                            <div className="media">
-                                                <div className="align-self-start mr-2">
-                                                    <em className="fab fa-twitter fa-2x text-info" />
-                                                </div>
-                                                <div className="media-body">
-                                                    <p className="m-0">New followers</p>
-                                                    <p className="m-0 text-muted text-sm">
-                                                        1 new follower
-                                                    </p>
-                                                </div>
-                                            </div>
-                                        </ListGroupItem>
-                                        <ListGroupItem
-                                            action
-                                            tag="a"
-                                            href=""
-                                            onClick={e => e.preventDefault()}
-                                        >
-                                            <div className="media">
-                                                <div className="align-self-start mr-2">
-                                                    <em className="fa fa-envelope fa-2x text-warning" />
-                                                </div>
-                                                <div className="media-body">
-                                                    <p className="m-0">New e-mails</p>
-                                                    <p className="m-0 text-muted text-sm">
-                                                        You have 10 new emails
-                                                    </p>
-                                                </div>
-                                            </div>
-                                        </ListGroupItem>
-                                        <ListGroupItem
-                                            action
-                                            tag="a"
-                                            href=""
-                                            onClick={e => e.preventDefault()}
-                                        >
-                                            <div className="media">
-                                                <div className="align-self-start mr-2">
-                                                    <em className="fa fa-tasks fa-2x text-success" />
-                                                </div>
-                                                <div className="media-body">
-                                                    <p className="m-0">Pending Tasks</p>
-                                                    <p className="m-0 text-muted text-sm">
-                                                        11 pending task
-                                                    </p>
-                                                </div>
-                                            </div>
-                                        </ListGroupItem>
-                                        <ListGroupItem
-                                            action
-                                            tag="a"
-                                            href=""
-                                            onClick={e => e.preventDefault()}
-                                        >
-                                            <span className="d-flex align-items-center">
-                                                <span className="text-sm">More notifications</span>
-                                                <span className="badge badge-danger ml-auto">
-                                                    14
-                                                </span>
-                                            </span>
-                                        </ListGroupItem>
-                                    </ListGroup>
-                                    {/* END list group */}
-                                </DropdownItem>
-                            </DropdownMenu>
-                            {/* END Dropdown menu */}
-                        </UncontrolledDropdown>
-                        {/* END Alert menu */}
-                        {/* START Offsidebar button */}
-                        <li className="nav-item">
-                            <a className="nav-link" href="" onClick={this.toggleOffsidebar}>
-                                <em className="icon-notebook" />
-                            </a>
-                        </li>
-                        {/* END Offsidebar menu */}
-                    </ul>
-                    {/* END Right Navbar */}
-
-                    {/* START Search form */}
-                    <HeaderSearch isOpen={this.state.navSearchOpen} onClose={this.closeNavSearch} />
-                    {/* END Search form */}
-                </nav>
-                {/* END Top Navbar */}
-            </header>
-        );
-    }
+	state = {
+		navSearchOpen: false,
+	};
+
+	toggleNavSearch = (e) => {
+		e.preventDefault();
+		this.setState({
+			navSearchOpen: !this.state.navSearchOpen,
+		});
+	};
+
+	closeNavSearch = (e) => {
+		e.preventDefault();
+		this.setState({
+			navSearchOpen: false,
+		});
+	};
+
+	toggleUserblock = (e) => {
+		e.preventDefault();
+		this.props.actions.toggleSetting("showUserBlock");
+	};
+
+	toggleOffsidebar = (e) => {
+		e.preventDefault();
+		this.props.actions.toggleSetting("offsidebarOpen");
+	};
+
+	toggleCollapsed = (e) => {
+		e.preventDefault();
+		this.props.actions.toggleSetting("isCollapsed");
+		this.resize();
+	};
+
+	toggleAside = (e) => {
+		e.preventDefault();
+		this.props.actions.toggleSetting("asideToggled");
+	};
+
+	handleLogout = async (e) => {
+		e.preventDefault();
+		const cek = await logout();
+		if (cek.success) {
+			Router.push({ pathname: "/login" });
+		}
+	};
+
+	resize() {
+		// all IE friendly dispatchEvent
+		var evt = document.createEvent("UIEvents");
+		evt.initUIEvent("resize", true, false, window, 0);
+		window.dispatchEvent(evt);
+		// modern dispatchEvent way
+		// window.dispatchEvent(new Event('resize'));
+	}
+
+	render() {
+		return (
+			<header className="topnavbar-wrapper">
+				{/* START Top Navbar */}
+				<nav className="navbar topnavbar">
+					{/* START navbar header */}
+					<div className="navbar-header">
+						<a className="navbar-brand" href="#/">
+							<div className="brand-logo">
+								<img className="img-fluid" src="/static/img/logo-inner.png" alt="App Logo" />
+							</div>
+							<div className="brand-logo-collapsed">
+								<img className="img-fluid" src="/static/img/logo-single.png" alt="App Logo" />
+							</div>
+						</a>
+					</div>
+					{/* END navbar header */}
+
+					{/* START Left navbar */}
+					<ul className="navbar-nav mr-auto flex-row">
+						<li className="nav-item">
+							{/* Button used to collapse the left sidebar. Only visible on tablet and desktops */}
+							<a href="" className="nav-link d-none d-md-block d-lg-block d-xl-block" onClick={this.toggleCollapsed}>
+								<em className="fas fa-bars" />
+							</a>
+							{/* Button to show/hide the sidebar on mobile. Visible on mobile only. */}
+							<a href="" className="nav-link sidebar-toggle d-md-none" onClick={this.toggleAside}>
+								<em className="fas fa-bars" />
+							</a>
+						</li>
+						{/* START User avatar toggle */}
+						{/* <li className="nav-item d-none d-md-block">
+							<a className="nav-link" onClick={this.toggleUserblock}>
+								<em className="icon-user" />
+							</a>
+						</li> */}
+						{/* END User avatar toggle */}
+						{/* START lock screen */}
+						{/* <li className="nav-item d-none d-md-block">
+							<Link href="/pages/lock" as="/lock">
+								<a title="Lock screen" className="nav-link">
+									<em className="icon-lock" />
+								</a>
+							</Link>
+						</li> */}
+						{/* END lock screen */}
+					</ul>
+					{/* END Left navbar */}
+					{/* START Right Navbar */}
+					<ul className="navbar-nav flex-row">
+						{/* Search icon */}
+						{/* <li className="nav-item">
+							<a className="nav-link" href="" onClick={this.toggleNavSearch}>
+								<em className="icon-magnifier" />
+							</a>
+						</li> */}
+						{/* Fullscreen (only desktops) */}
+						<li className="nav-item d-none d-md-block">
+							<ToggleFullscreen className="nav-link" />
+						</li>
+						{/* START Alert menu */}
+						<UncontrolledDropdown nav inNavbar className="dropdown-list">
+							<DropdownToggle nav className="dropdown-toggle-nocaret">
+								<em className="icon-bell" />
+								<span className="badge badge-danger">11</span>
+							</DropdownToggle>
+							{/* START Dropdown menu */}
+							<DropdownMenu right className="dropdown-menu-right animated flipInX">
+								<DropdownItem>
+									{/* START list group */}
+									<ListGroup>
+										<ListGroupItem action tag="a" href="" onClick={(e) => e.preventDefault()}>
+											<div className="media">
+												<div className="align-self-start mr-2">
+													<em className="fab fa-twitter fa-2x text-info" />
+												</div>
+												<div className="media-body">
+													<p className="m-0">New followers</p>
+													<p className="m-0 text-muted text-sm">1 new follower</p>
+												</div>
+											</div>
+										</ListGroupItem>
+										<ListGroupItem action tag="a" href="" onClick={(e) => e.preventDefault()}>
+											<div className="media">
+												<div className="align-self-start mr-2">
+													<em className="fa fa-envelope fa-2x text-warning" />
+												</div>
+												<div className="media-body">
+													<p className="m-0">New e-mails</p>
+													<p className="m-0 text-muted text-sm">You have 10 new emails</p>
+												</div>
+											</div>
+										</ListGroupItem>
+										<ListGroupItem action tag="a" href="" onClick={(e) => e.preventDefault()}>
+											<div className="media">
+												<div className="align-self-start mr-2">
+													<em className="fa fa-tasks fa-2x text-success" />
+												</div>
+												<div className="media-body">
+													<p className="m-0">Pending Tasks</p>
+													<p className="m-0 text-muted text-sm">11 pending task</p>
+												</div>
+											</div>
+										</ListGroupItem>
+										<ListGroupItem action tag="a" href="" onClick={(e) => e.preventDefault()}>
+											<span className="d-flex align-items-center">
+												<span className="text-sm">More notifications</span>
+												<span className="badge badge-danger ml-auto">14</span>
+											</span>
+										</ListGroupItem>
+									</ListGroup>
+									{/* END list group */}
+								</DropdownItem>
+							</DropdownMenu>
+							{/* END Dropdown menu */}
+						</UncontrolledDropdown>
+						{/* END Alert menu */}
+						<li className="nav-item">
+							<a className="nav-link" href="" onClick={this.handleLogout}>
+								<em className="icon-logout" />
+							</a>
+						</li>
+						{/* START Offsidebar button */}
+						<li className="nav-item">
+							<a className="nav-link" href="" onClick={this.toggleOffsidebar}>
+								<em className="icon-notebook" />
+							</a>
+						</li>
+						{/* END Offsidebar menu */}
+					</ul>
+					{/* END Right Navbar */}
+
+					{/* START Search form */}
+					<HeaderSearch isOpen={this.state.navSearchOpen} onClose={this.closeNavSearch} />
+					{/* END Search form */}
+				</nav>
+				{/* END Top Navbar */}
+			</header>
+		);
+	}
 }
 
 Header.propTypes = {
-    actions: PropTypes.object,
-    settings: PropTypes.object
+	actions: PropTypes.object,
+	settings: PropTypes.object,
 };
 
-const mapStateToProps = state => ({ settings: state.settings });
-const mapDispatchToProps = dispatch => ({
-    actions: bindActionCreators(actions, dispatch)
+const mapStateToProps = (state) => ({ settings: state.settings });
+const mapDispatchToProps = (dispatch) => ({
+	actions: bindActionCreators(actions, dispatch),
 });
 
-export default connect(
-    mapStateToProps,
-    mapDispatchToProps
-)(Header);
+export default connect(mapStateToProps, mapDispatchToProps)(Header);

+ 5 - 71
components/Layout/Menu.js

@@ -4,10 +4,10 @@ const Menu = [
 		translate: "sidebar.heading.HEADER",
 	},
 	{
-		name: "Login",
-		path: "/login",
-		icon: "icon-login",
-		translate: "sidebar.nav.LOGIN",
+		name: "Pemantauan",
+		path: "/app/pemantauan",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PEMANTAUAN",
 	},
 	{
 		name: "Pelaporan",
@@ -34,15 +34,9 @@ const Menu = [
 		translate: "sidebar.nav.SANKSI",
 	},
 	{
-		heading: "Dikti Ristek",
+		heading: "Dikti Ristek/LLDIKTI",
 		translate: "sidebar.heading.DIKTI_RISTEK",
 	},
-	{
-		name: "Pemantauan",
-		path: "/app/pemantauan",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PEMANTAUAN",
-	},
 	{
 		name: "Keberatan",
 		path: "/app/keberatan",
@@ -67,66 +61,6 @@ const Menu = [
 		icon: "icon-notebook",
 		translate: "sidebar.nav.PENCABUTAN_SANKSI",
 	},
-	{
-		heading: "Perguruan Tinggi",
-		translate: "sidebar.heading.PERGURUAN_TINGGI",
-	},
-	{
-		name: "Pemantauan",
-		path: "/app/pt/pemantauan",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PT_PEMANTAUAN",
-	},
-	{
-		name: "Pengajuan Keberatan",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PENGAJUAN_KEBERATAN",
-		submenu: [
-			{
-				name: "a. Permohonan Keberatan",
-				path: "/app/pt/keberatan",
-			},
-			{
-				name: "b. Jawaban atas permohonan keberatan",
-				path: "/app/pt/jawaban-keberatan",
-			},
-			{
-				name: "c. Jawaban atas permohonan banding",
-				path: "/app/pt/jawaban-banding",
-			},
-		],
-	},
-	{
-		name: "Dokumen Perbaikan",
-		path: "/app/pt/dokumen-perbaikan",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PT_DOKUMEN_PERBAIKAN",
-	},
-	{
-		name: "Permohonan Pencabutan Sanksi",
-		path: "/app/pt/pencabutan-sanksi",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PT_PENCABUTAN_SANKSI",
-	},
-	{
-		name: "Jawaban Permohonan Pencabutan Sanksi",
-		path: "/app/pt/jawaban-pencabutan-sanksi",
-		icon: "icon-notebook",
-		translate: "sidebar.nav.PT_JAWABAN_PENCABUTAN_SANKSI",
-	},
-
-	// {
-	// 	name: "FAQ",
-	// 	path: "/app/faq",
-	// 	icon: "icon-notebook",
-	// 	translate: "sidebar.nav.FAQ",
-	// },
-	// {
-	// 	name: "User List",
-	// 	path: "/app/userlist",
-	// 	icon: "icon-notebook",
-	// 	translate: "sidebar.nav.USERLIST",
-	// },
 ];
 
 export default Menu;

+ 52 - 0
components/Layout/MenuPT.js

@@ -0,0 +1,52 @@
+const MenuPT = [
+	{
+		heading: "Main Navigation",
+		translate: "sidebar.heading.HEADER",
+	},
+	{
+		name: "Pemantauan",
+		path: "/app/pt/pemantauan",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PT_PEMANTAUAN",
+	},
+	{
+		name: "Pengajuan Keberatan",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PENGAJUAN_KEBERATAN",
+		submenu: [
+			{
+				name: "a. Permohonan Keberatan",
+				path: "/app/pt/keberatan",
+			},
+			{
+				name: "b. Jawaban atas permohonan keberatan",
+				path: "/app/pt/jawaban-keberatan",
+			},
+			{
+				name: "c. Jawaban atas permohonan banding",
+				path: "/app/pt/jawaban-banding",
+			},
+		],
+	},
+	{
+		name: "Dokumen Perbaikan",
+		path: "/app/pt/dokumen-perbaikan",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PT_DOKUMEN_PERBAIKAN",
+	},
+	{
+		name: "Permohonan Pencabutan Sanksi",
+		path: "/app/pt/pencabutan-sanksi",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PT_PENCABUTAN_SANKSI",
+	},
+	{
+		name: "Jawaban Permohonan Pencabutan Sanksi",
+		path: "/app/pt/jawaban-pencabutan-sanksi",
+		icon: "icon-notebook",
+		translate: "sidebar.nav.PT_JAWABAN_PENCABUTAN_SANKSI",
+	},
+];
+
+export default MenuPT;
+``;

+ 378 - 380
components/Layout/Offsidebar.js

@@ -1,400 +1,398 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
 
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
-import * as actions from '../../store/actions/actions';
+import { connect } from "react-redux";
+import { bindActionCreators } from "redux";
+import * as actions from "../../store/actions/actions";
 
-import { TabContent, TabPane, Nav, NavItem, NavLink } from 'reactstrap';
+import { TabContent, TabPane, Nav, NavItem, NavLink } from "reactstrap";
 
 class Offsidebar extends Component {
+	state = {
+		activeTab: "settings",
+		offsidebarReady: false,
+	};
 
-    state = {
-        activeTab: 'settings',
-        offsidebarReady: false
-    }
+	componentDidMount() {
+		// When mounted display the offsidebar
+		window.requestAnimationFrame(() => this.setState({ offsidebarReady: true }));
+	}
 
-    componentDidMount() {
-        // When mounted display the offsidebar
-        window.requestAnimationFrame(() => this.setState({ offsidebarReady: true }));
-    }
+	toggle = (tab) => {
+		if (this.state.activeTab !== tab) {
+			this.setState({
+				activeTab: tab,
+			});
+		}
+	};
 
-    toggle = tab => {
-        if (this.state.activeTab !== tab) {
-            this.setState({
-                activeTab: tab
-            });
-        }
-    }
+	handleSettingCheckbox = (event) => {
+		this.props.actions.changeSetting(event.target.name, event.target.checked);
+	};
 
-    handleSettingCheckbox = event => {
-        this.props.actions.changeSetting(event.target.name, event.target.checked);
-    }
+	handleThemeRadio = (event) => {
+		this.props.actions.changeTheme(event.target.value);
+	};
 
-    handleThemeRadio = event => {
-        this.props.actions.changeTheme(event.target.value);
-    }
-
-    render() {
-
-        return (
-            this.state.offsidebarReady &&
-            <aside className="offsidebar">
-                { /* START Off Sidebar (right) */ }
-                <nav>
-                    <div>
-                        { /* Nav tabs */ }
-                        <Nav tabs justified>
-                            <NavItem>
-                                <NavLink className={ this.state.activeTab === 'settings' ? 'active':'' }
-                                    onClick={() => { this.toggle('settings'); }}
-                                >
-                                    <em className="icon-equalizer fa-lg"></em>
-                                </NavLink>
-                            </NavItem>
-                            <NavItem>
+	render() {
+		return (
+			this.state.offsidebarReady && (
+				<aside className="offsidebar">
+					{/* START Off Sidebar (right) */}
+					<nav>
+						<div>
+							{/* Nav tabs */}
+							<Nav tabs justified>
+								<NavItem>
+									<NavLink
+										className={this.state.activeTab === "settings" ? "active" : ""}
+										onClick={() => {
+											this.toggle("settings");
+										}}
+									>
+										<em className="icon-equalizer fa-lg"></em>
+									</NavLink>
+								</NavItem>
+								{/* <NavItem>
                                 <NavLink className={ this.state.activeTab === 'chat' ? 'active':'' }
                                     onClick={() => { this.toggle('chat'); }}
                                 >
                                     <em className="icon-user fa-lg"></em>
                                 </NavLink>
-                            </NavItem>
-                        </Nav>
-                        { /* Tab panes */ }
-                        <TabContent activeTab={this.state.activeTab}>
-                            <TabPane tabId="settings">
-                                <h3 className="text-center text-thin mt-4">Settings</h3>
-                                <div className="p-2">
-                                    <h4 className="text-muted text-thin">Themes</h4>
-                                    <div className="row row-flush mb-2">
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-a'}  value='theme-a' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-info"></span>
-                                                        <span className="color bg-info-light"></span>
-                                                    </span>
-                                                    <span className="color bg-white"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-b'}  value='theme-b' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-green"></span>
-                                                        <span className="color bg-green-light"></span>
-                                                    </span>
-                                                    <span className="color bg-white"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-c'}  value='theme-c' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-purple"></span>
-                                                        <span className="color bg-purple-light"></span>
-                                                    </span>
-                                                    <span className="color bg-white"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-d'}  value='theme-d' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-danger"></span>
-                                                        <span className="color bg-danger-light"></span>
-                                                    </span>
-                                                    <span className="color bg-white"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-e'}  value='theme-e' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-info-dark"></span>
-                                                        <span className="color bg-info"></span>
-                                                    </span>
-                                                    <span className="color bg-gray-dark"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-f'}  value='theme-f' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-green-dark"></span>
-                                                        <span className="color bg-green"></span>
-                                                    </span>
-                                                    <span className="color bg-gray-dark"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-g'}  value='theme-g' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-purple-dark"></span>
-                                                        <span className="color bg-purple"></span>
-                                                    </span>
-                                                    <span className="color bg-gray-dark"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                        <div className="col-3 mb-3">
-                                            <div className="setting-color">
-                                                <label>
-                                                    <input type="radio" name="setting-theme" checked={this.props.theme.name === 'theme-h'}  value='theme-h' onChange={this.handleThemeRadio} />
-                                                    <span className="icon-check"></span>
-                                                    <span className="split">
-                                                        <span className="color bg-danger-dark"></span>
-                                                        <span className="color bg-danger"></span>
-                                                    </span>
-                                                    <span className="color bg-gray-dark"></span>
-                                                </label>
-                                            </div>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div className="p-2">
-                                    <h4 className="text-muted text-thin">Layout</h4>
-                                    <div className="clearfix">
-                                        <p className="float-left">Fixed</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-fixed" type="checkbox" name="isFixed" checked={this.props.settings.isFixed} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                    <div className="clearfix">
-                                        <p className="float-left">Boxed</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-boxed" type="checkbox" name="isBoxed" checked={this.props.settings.isBoxed} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div className="p-2">
-                                    <h4 className="text-muted text-thin">Aside</h4>
-                                    <div className="clearfix">
-                                        <p className="float-left">Collapsed</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-collapsed" type="checkbox" name="isCollapsed" checked={this.props.settings.isCollapsed} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                    <div className="clearfix">
-                                        <p className="float-left">Collapsed Text</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-collapsed-text" type="checkbox" name="isCollapsedText" checked={this.props.settings.isCollapsedText} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                    <div className="clearfix">
-                                        <p className="float-left">Float</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-float" type="checkbox" name="isFloat" checked={this.props.settings.isFloat} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                    <div className="clearfix">
-                                        <p className="float-left">Hover</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-hover" type="checkbox" name="asideHover" checked={this.props.settings.asideHover} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                    <div className="clearfix">
-                                        <p className="float-left">Show Scrollbar</p>
-                                        <div className="float-right">
-                                            <label className="switch">
-                                                <input id="chk-scrollbar" type="checkbox" name="asideScrollbar" checked={this.props.settings.asideScrollbar} onChange={this.handleSettingCheckbox}/>
-                                                <span></span>
-                                            </label>
-                                        </div>
-                                    </div>
-                                </div>
-                            </TabPane>
-                            <TabPane tabId="chat">
-                                <h3 className="text-center text-thin mt-4">Connections</h3>
-                                <div className="list-group">
-                                    { /* START list title */ }
-                                    <div className="list-group-item border-0">
-                                        <small className="text-muted">ONLINE</small>
-                                    </div>
-                                    { /* END list title */ }
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/05.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Juan Sims</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-success circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/06.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Maureen Jenkins</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-success circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/07.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Billie Dunn</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-danger circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/08.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Tomothy Roberts</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-warning circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    { /* START list title */ }
-                                    <div className="list-group-item border-0">
-                                        <small className="text-muted">OFFLINE</small>
-                                    </div>
-                                    { /* END list title */ }
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/09.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Lawrence Robinson</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-warning circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                    <div className="list-group-item list-group-item-action border-0">
-                                        <div className="media">
-                                            <img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/10.jpg" alt="User avatar" />
-                                            <div className="media-body text-truncate">
-                                                <a href="">
-                                                    <strong>Tyrone Owens</strong>
-                                                </a>
-                                                <br/>
-                                                <small className="text-muted">Designeer</small>
-                                            </div>
-                                            <div className="ml-auto">
-                                                <span className="circle bg-warning circle-lg"></span>
-                                            </div>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div className="px-3 py-4 text-center">
-                                    { /* Optional link to list more users */ }
-                                    <a className="btn btn-purple btn-sm" href="" title="See more contacts">
-                                        <strong>Load more..</strong>
-                                    </a>
-                                </div>
-                                { /* Extra items */ }
-                                <div className="px-3 py-2">
-                                    <p>
-                                        <small className="text-muted">Tasks completion</small>
-                                    </p>
-                                    <div className="progress progress-xs m-0">
-                                        <div className="progress-bar bg-success" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style={{width: '80%'}}>
-                                            <span className="sr-only">80% Complete</span>
-                                        </div>
-                                    </div>
-                                </div>
-                                <div className="px-3 py-2">
-                                    <p>
-                                        <small className="text-muted">Upload quota</small>
-                                    </p>
-                                    <div className="progress progress-xs m-0">
-                                        <div className="progress-bar bg-warning" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style={{width: '40%'}}>
-                                            <span className="sr-only">40% Complete</span>
-                                        </div>
-                                    </div>
-                                </div>
-                            </TabPane>
-                        </TabContent>
-                    </div>
-                </nav>
-                { /* END Off Sidebar (right) */ }
-            </aside>
-        );
-    }
-
+                            </NavItem> */}
+							</Nav>
+							{/* Tab panes */}
+							<TabContent activeTab={this.state.activeTab}>
+								<TabPane tabId="settings">
+									<h3 className="text-center text-thin mt-4">Settings</h3>
+									<div className="p-2">
+										<h4 className="text-muted text-thin">Themes</h4>
+										<div className="row row-flush mb-2">
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-a"} value="theme-a" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-info"></span>
+															<span className="color bg-info-light"></span>
+														</span>
+														<span className="color bg-white"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-b"} value="theme-b" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-green"></span>
+															<span className="color bg-green-light"></span>
+														</span>
+														<span className="color bg-white"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-c"} value="theme-c" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-purple"></span>
+															<span className="color bg-purple-light"></span>
+														</span>
+														<span className="color bg-white"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-d"} value="theme-d" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-danger"></span>
+															<span className="color bg-danger-light"></span>
+														</span>
+														<span className="color bg-white"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-e"} value="theme-e" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-info-dark"></span>
+															<span className="color bg-info"></span>
+														</span>
+														<span className="color bg-gray-dark"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-f"} value="theme-f" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-green-dark"></span>
+															<span className="color bg-green"></span>
+														</span>
+														<span className="color bg-gray-dark"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-g"} value="theme-g" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-purple-dark"></span>
+															<span className="color bg-purple"></span>
+														</span>
+														<span className="color bg-gray-dark"></span>
+													</label>
+												</div>
+											</div>
+											<div className="col-3 mb-3">
+												<div className="setting-color">
+													<label>
+														<input type="radio" name="setting-theme" checked={this.props.theme.name === "theme-h"} value="theme-h" onChange={this.handleThemeRadio} />
+														<span className="icon-check"></span>
+														<span className="split">
+															<span className="color bg-danger-dark"></span>
+															<span className="color bg-danger"></span>
+														</span>
+														<span className="color bg-gray-dark"></span>
+													</label>
+												</div>
+											</div>
+										</div>
+									</div>
+									<div className="p-2">
+										<h4 className="text-muted text-thin">Layout</h4>
+										<div className="clearfix">
+											<p className="float-left">Fixed</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-fixed" type="checkbox" name="isFixed" checked={this.props.settings.isFixed} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+										<div className="clearfix">
+											<p className="float-left">Boxed</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-boxed" type="checkbox" name="isBoxed" checked={this.props.settings.isBoxed} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+									</div>
+									<div className="p-2">
+										<h4 className="text-muted text-thin">Aside</h4>
+										<div className="clearfix">
+											<p className="float-left">Collapsed</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-collapsed" type="checkbox" name="isCollapsed" checked={this.props.settings.isCollapsed} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+										<div className="clearfix">
+											<p className="float-left">Collapsed Text</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-collapsed-text" type="checkbox" name="isCollapsedText" checked={this.props.settings.isCollapsedText} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+										<div className="clearfix">
+											<p className="float-left">Float</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-float" type="checkbox" name="isFloat" checked={this.props.settings.isFloat} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+										<div className="clearfix">
+											<p className="float-left">Hover</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-hover" type="checkbox" name="asideHover" checked={this.props.settings.asideHover} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+										<div className="clearfix">
+											<p className="float-left">Show Scrollbar</p>
+											<div className="float-right">
+												<label className="switch">
+													<input id="chk-scrollbar" type="checkbox" name="asideScrollbar" checked={this.props.settings.asideScrollbar} onChange={this.handleSettingCheckbox} />
+													<span></span>
+												</label>
+											</div>
+										</div>
+									</div>
+								</TabPane>
+								<TabPane tabId="chat">
+									<h3 className="text-center text-thin mt-4">Connections</h3>
+									<div className="list-group">
+										{/* START list title */}
+										<div className="list-group-item border-0">
+											<small className="text-muted">ONLINE</small>
+										</div>
+										{/* END list title */}
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/05.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Juan Sims</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-success circle-lg"></span>
+												</div>
+											</div>
+										</div>
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/06.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Maureen Jenkins</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-success circle-lg"></span>
+												</div>
+											</div>
+										</div>
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/07.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Billie Dunn</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-danger circle-lg"></span>
+												</div>
+											</div>
+										</div>
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/08.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Tomothy Roberts</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-warning circle-lg"></span>
+												</div>
+											</div>
+										</div>
+										{/* START list title */}
+										<div className="list-group-item border-0">
+											<small className="text-muted">OFFLINE</small>
+										</div>
+										{/* END list title */}
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/09.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Lawrence Robinson</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-warning circle-lg"></span>
+												</div>
+											</div>
+										</div>
+										<div className="list-group-item list-group-item-action border-0">
+											<div className="media">
+												<img className="align-self-center mr-3 rounded-circle thumb48" src="/static/img/user/10.jpg" alt="User avatar" />
+												<div className="media-body text-truncate">
+													<a href="">
+														<strong>Tyrone Owens</strong>
+													</a>
+													<br />
+													<small className="text-muted">Designeer</small>
+												</div>
+												<div className="ml-auto">
+													<span className="circle bg-warning circle-lg"></span>
+												</div>
+											</div>
+										</div>
+									</div>
+									<div className="px-3 py-4 text-center">
+										{/* Optional link to list more users */}
+										<a className="btn btn-purple btn-sm" href="" title="See more contacts">
+											<strong>Load more..</strong>
+										</a>
+									</div>
+									{/* Extra items */}
+									<div className="px-3 py-2">
+										<p>
+											<small className="text-muted">Tasks completion</small>
+										</p>
+										<div className="progress progress-xs m-0">
+											<div className="progress-bar bg-success" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style={{ width: "80%" }}>
+												<span className="sr-only">80% Complete</span>
+											</div>
+										</div>
+									</div>
+									<div className="px-3 py-2">
+										<p>
+											<small className="text-muted">Upload quota</small>
+										</p>
+										<div className="progress progress-xs m-0">
+											<div className="progress-bar bg-warning" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style={{ width: "40%" }}>
+												<span className="sr-only">40% Complete</span>
+											</div>
+										</div>
+									</div>
+								</TabPane>
+							</TabContent>
+						</div>
+					</nav>
+					{/* END Off Sidebar (right) */}
+				</aside>
+			)
+		);
+	}
 }
 
 Offsidebar.propTypes = {
-    actions: PropTypes.object,
-    settings: PropTypes.object,
-    theme: PropTypes.object
+	actions: PropTypes.object,
+	settings: PropTypes.object,
+	theme: PropTypes.object,
 };
 
-const mapStateToProps = state => ({ settings: state.settings, theme: state.theme })
-const mapDispatchToProps = dispatch => ({ actions: bindActionCreators(actions, dispatch) })
+const mapStateToProps = (state) => ({ settings: state.settings, theme: state.theme });
+const mapDispatchToProps = (dispatch) => ({ actions: bindActionCreators(actions, dispatch) });
 
-export default connect(
-    mapStateToProps,
-    mapDispatchToProps
-)(Offsidebar);
+export default connect(mapStateToProps, mapDispatchToProps)(Offsidebar);

+ 277 - 318
components/Layout/Sidebar.js

@@ -1,103 +1,101 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { withTranslation, Trans } from '@/components/Common/Translate';
-import Link from 'next/link';
-import Router, { withRouter } from 'next/router';
-import { Collapse, Badge } from 'reactstrap';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { withTranslation, Trans } from "@/components/Common/Translate";
+import Link from "next/link";
+import Router, { withRouter } from "next/router";
+import { Collapse, Badge } from "reactstrap";
 
-import { connect } from 'react-redux';
-import { bindActionCreators } from 'redux';
-import * as actions from '../../store/actions/actions';
+import { connect } from "react-redux";
+import { bindActionCreators } from "redux";
+import * as actions from "../../store/actions/actions";
 
-import SidebarUserBlock from './SidebarUserBlock';
+import SidebarUserBlock from "./SidebarUserBlock";
+import { getUser } from "@/actions/auth";
 
-import Menu from './Menu.js';
+import Menu from "./Menu.js";
+import MenuPT from "./MenuPT.js";
+// localStorage.getItem("user");
+// import Menu from './MenuPT.js';
 
 // Helper to check for parrent of an given elements
 const parents = (element, selector) => {
-    if (typeof selector !== 'string') {
-        return null;
-    }
-
-    const parents = [];
-    let ancestor = element.parentNode;
-
-    while (
-        ancestor &&
-        ancestor.nodeType === Node.ELEMENT_NODE &&
-        ancestor.nodeType !== 3 /*NODE_TEXT*/
-    ) {
-        if (ancestor.matches(selector)) {
-            parents.push(ancestor);
-        }
-
-        ancestor = ancestor.parentNode;
-    }
-    return parents;
+	if (typeof selector !== "string") {
+		return null;
+	}
+
+	const parents = [];
+	let ancestor = element.parentNode;
+
+	while (ancestor && ancestor.nodeType === Node.ELEMENT_NODE && ancestor.nodeType !== 3 /*NODE_TEXT*/) {
+		if (ancestor.matches(selector)) {
+			parents.push(ancestor);
+		}
+
+		ancestor = ancestor.parentNode;
+	}
+	return parents;
 };
 // Helper to get outerHeight of a dom element
 const outerHeight = (elem, includeMargin) => {
-    const style = getComputedStyle(elem);
-    const margins = includeMargin
-        ? parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10)
-        : 0;
-    return elem.offsetHeight + margins;
+	const style = getComputedStyle(elem);
+	const margins = includeMargin ? parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10) : 0;
+	return elem.offsetHeight + margins;
 };
 
 /**
     Component to display headings on sidebar
 */
 const SidebarItemHeader = ({ item }) => (
-    <li className="nav-heading">
-        <span>
-            <Trans i18nKey={item.translate}>{item.heading}</Trans>
-        </span>
-    </li>
+	<li className="nav-heading">
+		<span>
+			<Trans i18nKey={item.translate}>{item.heading}</Trans>
+		</span>
+	</li>
 );
 
 /**
     Normal items for the sidebar
 */
 const SidebarItem = ({ item, isActive, className, onMouseEnter }) => (
-    <li className={isActive ? 'active' : ''} onMouseEnter={onMouseEnter}>
-        <Link href={item.path} as={item.as}>
-            <a title={item.name}>
-                {item.label && (
-                    <Badge tag="div" className="float-right" color={item.label.color}>
-                        {item.label.value}
-                    </Badge>
-                )}
-                {item.icon && <em className={item.icon} />}
-                <span>
-                    <Trans i18nKey={item.translate}>{item.name}</Trans>
-                </span>
-            </a>
-        </Link>
-    </li>
+	<li className={isActive ? "active" : ""} onMouseEnter={onMouseEnter}>
+		<Link href={item.path} as={item.as}>
+			<a title={item.name}>
+				{item.label && (
+					<Badge tag="div" className="float-right" color={item.label.color}>
+						{item.label.value}
+					</Badge>
+				)}
+				{item.icon && <em className={item.icon} />}
+				<span>
+					<Trans i18nKey={item.translate}>{item.name}</Trans>
+				</span>
+			</a>
+		</Link>
+	</li>
 );
 
 /**
     Build a sub menu with items inside and attach collapse behavior
 */
 const SidebarSubItem = ({ item, isActive, handler, children, isOpen, onMouseEnter }) => (
-    <li className={isActive ? 'active' : ''}>
-        <div className="nav-item" onClick={handler} onMouseEnter={onMouseEnter}>
-            {item.label && (
-                <Badge tag="div" className="float-right" color={item.label.color}>
-                    {item.label.value}
-                </Badge>
-            )}
-            {item.icon && <em className={item.icon} />}
-            <span>
-                <Trans i18nKey={item.translate}>{item.name}</Trans>
-            </span>
-        </div>
-        <Collapse isOpen={isOpen}>
-            <ul id={item.path} className="sidebar-nav sidebar-subnav">
-                {children}
-            </ul>
-        </Collapse>
-    </li>
+	<li className={isActive ? "active" : ""}>
+		<div className="nav-item" onClick={handler} onMouseEnter={onMouseEnter}>
+			{item.label && (
+				<Badge tag="div" className="float-right" color={item.label.color}>
+					{item.label.value}
+				</Badge>
+			)}
+			{item.icon && <em className={item.icon} />}
+			<span>
+				<Trans i18nKey={item.translate}>{item.name}</Trans>
+			</span>
+		</div>
+		<Collapse isOpen={isOpen}>
+			<ul id={item.path} className="sidebar-nav sidebar-subnav">
+				{children}
+			</ul>
+		</Collapse>
+	</li>
 );
 
 /**
@@ -105,263 +103,224 @@ const SidebarSubItem = ({ item, isActive, handler, children, isOpen, onMouseEnte
 */
 const SidebarSubHeader = ({ item }) => <li className="sidebar-subnav-header">{item.name}</li>;
 
-const SidebarBackdrop = ({ closeFloatingNav }) => (
-    <div className="sidebar-backdrop" onClick={closeFloatingNav} />
-);
+const SidebarBackdrop = ({ closeFloatingNav }) => <div className="sidebar-backdrop" onClick={closeFloatingNav} />;
 
 const FloatingNav = ({ item, target, routeActive, isFixed, closeFloatingNav }) => {
-    let asideContainer = document.querySelector('.aside-container');
-    let asideInner = asideContainer.firstElementChild; /*('.aside-inner')*/
-    let sidebar = asideInner.firstElementChild; /*('.sidebar')*/
-
-    let mar =
-        parseInt(getComputedStyle(asideInner)['padding-top'], 0) +
-        parseInt(getComputedStyle(asideContainer)['padding-top'], 0);
-    let itemTop = target.parentElement.offsetTop + mar - sidebar.scrollTop;
-    let vwHeight = document.body.clientHeight;
-
-    const setPositionStyle = el => {
-        if (!el) return;
-        el.style.position = isFixed ? 'fixed' : 'absolute';
-        el.style.top = itemTop + 'px';
-        el.style.bottom = outerHeight(el, true) + itemTop > vwHeight ? 0 : 'auto';
-    };
-
-    return (
-        <ul
-            id={item.path}
-            ref={setPositionStyle}
-            className="sidebar-nav sidebar-subnav nav-floating"
-            onMouseLeave={closeFloatingNav}
-        >
-            <SidebarSubHeader item={item} />
-            {item.submenu.map((subitem, i) => (
-                <SidebarItem key={i} item={subitem} isActive={routeActive(subitem.path)} />
-            ))}
-        </ul>
-    );
+	let asideContainer = document.querySelector(".aside-container");
+	let asideInner = asideContainer.firstElementChild; /*('.aside-inner')*/
+	let sidebar = asideInner.firstElementChild; /*('.sidebar')*/
+
+	let mar = parseInt(getComputedStyle(asideInner)["padding-top"], 0) + parseInt(getComputedStyle(asideContainer)["padding-top"], 0);
+	let itemTop = target.parentElement.offsetTop + mar - sidebar.scrollTop;
+	let vwHeight = document.body.clientHeight;
+
+	const setPositionStyle = (el) => {
+		if (!el) return;
+		el.style.position = isFixed ? "fixed" : "absolute";
+		el.style.top = itemTop + "px";
+		el.style.bottom = outerHeight(el, true) + itemTop > vwHeight ? 0 : "auto";
+	};
+
+	return (
+		<ul id={item.path} ref={setPositionStyle} className="sidebar-nav sidebar-subnav nav-floating" onMouseLeave={closeFloatingNav}>
+			<SidebarSubHeader item={item} />
+			{item.submenu.map((subitem, i) => (
+				<SidebarItem key={i} item={subitem} isActive={routeActive(subitem.path)} />
+			))}
+		</ul>
+	);
 };
 
 /**
     The main sidebar component
 */
 class Sidebar extends Component {
-    state = {
-        collapse: {},
-        showSidebarBackdrop: false,
-        currentFloatingItem: null,
-        currentFloatingItemTarget: null,
-        pathname: this.props.router.pathname
-    };
-
-    componentDidMount() {
-        // prepare the flags to handle menu collapsed states
-        this.buildCollapseList();
-
-        // Listen for routes changes in order to hide the sidebar on mobile
-        Router.events.on('routeChangeStart', this.handleRouteChange);
-        Router.events.on('routeChangeComplete', this.handleRouteComplete);
-
-        // Attach event listener to automatically close sidebar when click outside
-        document.addEventListener('click', this.closeSidebarOnExternalClicks);
-    }
-
-    handleRouteComplete = (pathname) => {
-        this.setState({
-            pathname
-        })
-    }
-
-    handleRouteChange = () => {
-        this.closeFloatingNav();
-        this.closeSidebar();
-    };
-
-    componentWillUnmount() {
-        document.removeEventListener('click', this.closeSidebarOnExternalClicks);
-        Router.events.off('routeChangeStart', this.handleRouteChange);
-        Router.events.off('routeChangeComplete', this.handleRouteComplete);
-    }
-
-    closeSidebar = () => {
-        this.props.actions.toggleSetting('asideToggled');
-    };
-
-    closeSidebarOnExternalClicks = e => {
-        // don't check if sidebar not visible
-        if (!this.props.settings.asideToggled) return;
-
-        if (
-            !parents(e.target, '.aside-container').length && // if not child of sidebar
-            !parents(e.target, '.topnavbar-wrapper').length && // if not child of header
-            !e.target.matches('#user-block-toggle') && // user block toggle anchor
-            !e.target.parentElement.matches('#user-block-toggle') // user block toggle icon
-        ) {
-            this.closeSidebar();
-        }
-    };
-
-    /** prepare initial state of collapse menus.*/
-    buildCollapseList = () => {
-        let collapse = {};
-        Menu.filter(({ heading }) => !heading).forEach(({ name, path, submenu }) => {
-            collapse[name] = this.routeActive(submenu ? submenu.map(({ path }) => path) : path);
-        });
-        this.setState({ collapse });
-    };
-
-    routeActive = paths => {
-        const currpath = this.state.pathname;
-        paths = Array.isArray(paths) ? paths : [paths];
-        return paths.some(p => (p === '/' ? currpath === p : currpath.indexOf(p) > -1));
-    };
-
-    toggleItemCollapse = stateName => () => {
-        for (let c in this.state.collapse) {
-            if (this.state.collapse[c] === true && c !== stateName)
-                this.setState({
-                    collapse: {
-                        [c]: false
-                    }
-                });
-        }
-        this.setState({
-            collapse: {
-                [stateName]: !this.state.collapse[stateName]
-            }
-        });
-    };
-
-    getSubRoutes = item => item.submenu.map(({ path }) => path);
-
-    /** map menu config to string to determine which element to render */
-    itemType = item => {
-        if (item.heading) return 'heading';
-        if (!item.submenu) return 'menu';
-        if (item.submenu) return 'submenu';
-    };
-
-    shouldUseFloatingNav = () => {
-        return (
-            this.props.settings.isCollapsed ||
-            this.props.settings.isCollapsedText ||
-            this.props.settings.asideHover
-        );
-    };
-
-    showFloatingNav = item => e => {
-        if (this.shouldUseFloatingNav())
-            this.setState({
-                currentFloatingItem: item,
-                currentFloatingItemTarget: e.currentTarget,
-                showSidebarBackdrop: true
-            });
-    };
-
-    closeFloatingNav = () => {
-        this.setState({
-            currentFloatingItem: null,
-            currentFloatingItemTarget: null,
-            showSidebarBackdrop: false
-        });
-    };
-
-    render() {
-        return (
-            <>
-                <aside className="aside-container">
-                    {/* START Sidebar (left) */}
-                    <div className="aside-inner">
-                        <nav
-                            className={
-                                'sidebar ' +
-                                (this.props.settings.asideScrollbar ? 'show-scrollbar' : '')
-                            }
-                        >
-                            {/* START sidebar nav */}
-                            <ul className="sidebar-nav">
-                                {/* START user info */}
-                                <li className="has-user-block">
-                                    <SidebarUserBlock />
-                                </li>
-                                {/* END user info */}
-
-                                {/* Iterates over all sidebar items */}
-                                {Menu.map((item, i) => {
-                                    // heading
-                                    if (this.itemType(item) === 'heading')
-                                        return <SidebarItemHeader item={item} key={i} />;
-                                    else {
-                                        if (this.itemType(item) === 'menu')
-                                            return (
-                                                <SidebarItem
-                                                    isActive={this.routeActive(item.path)}
-                                                    item={item}
-                                                    key={i}
-                                                    onMouseEnter={this.closeFloatingNav}
-                                                />
-                                            );
-                                        if (this.itemType(item) === 'submenu')
-                                            return [
-                                                <SidebarSubItem
-                                                    item={item}
-                                                    isOpen={this.state.collapse[item.name]}
-                                                    handler={this.toggleItemCollapse(item.name)}
-                                                    isActive={this.routeActive(
-                                                        this.getSubRoutes(item)
-                                                    )}
-                                                    key={i}
-                                                    onMouseEnter={this.showFloatingNav(item)}
-                                                >
-                                                    <SidebarSubHeader item={item} key={i} />
-                                                    {item.submenu.map((subitem, i) => (
-                                                        <SidebarItem
-                                                            key={i}
-                                                            item={subitem}
-                                                            isActive={this.routeActive(
-                                                                subitem.path
-                                                            )}
-                                                        />
-                                                    ))}
-                                                </SidebarSubItem>
-                                            ];
-                                    }
-                                    return null; // unrecognized item
-                                })}
-                            </ul>
-                            {/* END sidebar nav */}
-                        </nav>
-                    </div>
-                    {/* END Sidebar (left) */}
-                    {this.state.currentFloatingItem && this.state.currentFloatingItem.submenu && (
-                        <FloatingNav
-                            item={this.state.currentFloatingItem}
-                            target={this.state.currentFloatingItemTarget}
-                            routeActive={this.routeActive}
-                            isFixed={this.props.settings.isFixed}
-                            closeFloatingNav={this.closeFloatingNav}
-                        />
-                    )}
-                </aside>
-                {this.state.showSidebarBackdrop && (
-                    <SidebarBackdrop closeFloatingNav={this.closeFloatingNav} />
-                )}
-            </>
-        );
-    }
+	menu = [];
+	state = {
+		collapse: {},
+		showSidebarBackdrop: false,
+		currentFloatingItem: null,
+		currentFloatingItemTarget: null,
+		pathname: this.props.router.pathname,
+	};
+
+	async componentDidMount() {
+		// this.menu = JSON.parse(sessionStorage.getItem("user")).peran[0].peran.id === 2 ? MenuPT : Menu;
+		const user = await getUser();
+		// dataUser.data.peran[0].peran.id === 2;
+		this.menu = user.data.peran[0].peran.id === 2 ? MenuPT : Menu;
+		// prepare the flags to handle menu collapsed states
+		this.buildCollapseList();
+
+		// Listen for routes changes in order to hide the sidebar on mobile
+		Router.events.on("routeChangeStart", this.handleRouteChange);
+		Router.events.on("routeChangeComplete", this.handleRouteComplete);
+
+		// Attach event listener to automatically close sidebar when click outside
+		document.addEventListener("click", this.closeSidebarOnExternalClicks);
+	}
+
+	handleRouteComplete = (pathname) => {
+		this.setState({
+			pathname,
+		});
+	};
+
+	handleRouteChange = () => {
+		this.closeFloatingNav();
+		this.closeSidebar();
+	};
+
+	componentWillUnmount() {
+		document.removeEventListener("click", this.closeSidebarOnExternalClicks);
+		Router.events.off("routeChangeStart", this.handleRouteChange);
+		Router.events.off("routeChangeComplete", this.handleRouteComplete);
+	}
+
+	closeSidebar = () => {
+		this.props.actions.toggleSetting("asideToggled");
+	};
+
+	closeSidebarOnExternalClicks = (e) => {
+		// don't check if sidebar not visible
+		if (!this.props.settings.asideToggled) return;
+
+		if (
+			!parents(e.target, ".aside-container").length && // if not child of sidebar
+			!parents(e.target, ".topnavbar-wrapper").length && // if not child of header
+			!e.target.matches("#user-block-toggle") && // user block toggle anchor
+			!e.target.parentElement.matches("#user-block-toggle") // user block toggle icon
+		) {
+			this.closeSidebar();
+		}
+	};
+
+	/** prepare initial state of collapse menus.*/
+	buildCollapseList = () => {
+		let collapse = {};
+		this.menu
+			.filter(({ heading }) => !heading)
+			.forEach(({ name, path, submenu }) => {
+				collapse[name] = this.routeActive(submenu ? submenu.map(({ path }) => path) : path);
+			});
+		this.setState({ collapse });
+	};
+
+	routeActive = (paths) => {
+		const currpath = this.state.pathname;
+		paths = Array.isArray(paths) ? paths : [paths];
+		return paths.some((p) => (p === "/" ? currpath === p : currpath.indexOf(p) > -1));
+	};
+
+	toggleItemCollapse = (stateName) => () => {
+		for (let c in this.state.collapse) {
+			if (this.state.collapse[c] === true && c !== stateName)
+				this.setState({
+					collapse: {
+						[c]: false,
+					},
+				});
+		}
+		this.setState({
+			collapse: {
+				[stateName]: !this.state.collapse[stateName],
+			},
+		});
+	};
+
+	getSubRoutes = (item) => item.submenu.map(({ path }) => path);
+
+	/** map menu config to string to determine which element to render */
+	itemType = (item) => {
+		if (item.heading) return "heading";
+		if (!item.submenu) return "menu";
+		if (item.submenu) return "submenu";
+	};
+
+	shouldUseFloatingNav = () => {
+		return this.props.settings.isCollapsed || this.props.settings.isCollapsedText || this.props.settings.asideHover;
+	};
+
+	showFloatingNav = (item) => (e) => {
+		if (this.shouldUseFloatingNav())
+			this.setState({
+				currentFloatingItem: item,
+				currentFloatingItemTarget: e.currentTarget,
+				showSidebarBackdrop: true,
+			});
+	};
+
+	closeFloatingNav = () => {
+		this.setState({
+			currentFloatingItem: null,
+			currentFloatingItemTarget: null,
+			showSidebarBackdrop: false,
+		});
+	};
+
+	render() {
+		return (
+			<>
+				<aside className="aside-container">
+					{/* START Sidebar (left) */}
+					<div className="aside-inner">
+						<nav className={"sidebar " + (this.props.settings.asideScrollbar ? "show-scrollbar" : "")}>
+							{/* START sidebar nav */}
+							<ul className="sidebar-nav">
+								{/* START user info */}
+								<li className="has-user-block">
+									<SidebarUserBlock />
+								</li>
+								{/* END user info */}
+
+								{/* Iterates over all sidebar items */}
+								{this.menu.map((item, i) => {
+									// heading
+									if (this.itemType(item) === "heading") return <SidebarItemHeader item={item} key={i} />;
+									else {
+										if (this.itemType(item) === "menu") return <SidebarItem isActive={this.routeActive(item.path)} item={item} key={i} onMouseEnter={this.closeFloatingNav} />;
+										if (this.itemType(item) === "submenu")
+											return [
+												<SidebarSubItem
+													item={item}
+													isOpen={this.state.collapse[item.name]}
+													handler={this.toggleItemCollapse(item.name)}
+													isActive={this.routeActive(this.getSubRoutes(item))}
+													key={i}
+													onMouseEnter={this.showFloatingNav(item)}
+												>
+													<SidebarSubHeader item={item} key={i} />
+													{item.submenu.map((subitem, i) => (
+														<SidebarItem key={i} item={subitem} isActive={this.routeActive(subitem.path)} />
+													))}
+												</SidebarSubItem>,
+											];
+									}
+									return null; // unrecognized item
+								})}
+							</ul>
+							{/* END sidebar nav */}
+						</nav>
+					</div>
+					{/* END Sidebar (left) */}
+					{this.state.currentFloatingItem && this.state.currentFloatingItem.submenu && (
+						<FloatingNav item={this.state.currentFloatingItem} target={this.state.currentFloatingItemTarget} routeActive={this.routeActive} isFixed={this.props.settings.isFixed} closeFloatingNav={this.closeFloatingNav} />
+					)}
+				</aside>
+				{this.state.showSidebarBackdrop && <SidebarBackdrop closeFloatingNav={this.closeFloatingNav} />}
+			</>
+		);
+	}
 }
 
 Sidebar.propTypes = {
-    actions: PropTypes.object,
-    settings: PropTypes.object
+	actions: PropTypes.object,
+	settings: PropTypes.object,
 };
 
-const mapStateToProps = state => ({ settings: state.settings });
-const mapDispatchToProps = dispatch => ({
-    actions: bindActionCreators(actions, dispatch)
+const mapStateToProps = (state) => ({ settings: state.settings });
+const mapDispatchToProps = (dispatch) => ({
+	actions: bindActionCreators(actions, dispatch),
 });
 
-export default connect(
-    mapStateToProps,
-    mapDispatchToProps
-)(withRouter(withTranslation(Sidebar)));
+export default connect(mapStateToProps, mapDispatchToProps)(withRouter(withTranslation(Sidebar)));

+ 48 - 42
components/Layout/SidebarUserBlock.js

@@ -1,51 +1,57 @@
-import React, { Component } from 'react';
-import PropTypes from 'prop-types';
-import { Collapse } from 'reactstrap';
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { Collapse } from "reactstrap";
+import { getUser } from "@/actions/auth";
 
-import { connect } from 'react-redux';
+import { connect } from "react-redux";
 
 class SidebarUserBlock extends Component {
-
-    state = {
-        showUserBlock: false
-    }
-
-    componentDidUpdate(oldProps) {
-        if (oldProps.showUserBlock !== this.props.showUserBlock) {
-            this.setState({ showUserBlock: this.props.showUserBlock })
-        }
-    }
-
-    render() {
-        return (
-            <Collapse id="user-block" isOpen={ this.state.showUserBlock }>
-                <div>
-                    <div className="item user-block">
-                       {/* User picture */}
-                       <div className="user-block-picture">
-                          <div className="user-block-status">
-                             <img className="img-thumbnail rounded-circle" src="/static/img/user/02.jpg" alt="Avatar" width="60" height="60" />
-                             <div className="circle bg-success circle-lg"></div>
-                          </div>
-                       </div>
-                       {/* Name and Job */}
-                       <div className="user-block-info">
-                          <span className="user-block-name">Hello, Mike</span>
-                          <span className="user-block-role">Designer</span>
-                       </div>
-                    </div>
-                </div>
-            </Collapse>
-        )
-    }
+	state = {
+		showUserBlock: true,
+		user: {},
+		role: "",
+	};
+
+	async componentDidMount() {
+		const user = await getUser();
+		this.setState({ user: user.data, role: user.data.peran[0].peran.nama });
+	}
+
+	componentDidUpdate(oldProps) {
+		if (oldProps.showUserBlock !== this.props.showUserBlock) {
+			this.setState({ showUserBlock: this.props.showUserBlock });
+		}
+	}
+
+	render() {
+		const { user, role } = this.state;
+		return (
+			<Collapse id="user-block" isOpen={this.state.showUserBlock}>
+				<div>
+					<div className="item user-block">
+						{/* User picture */}
+						<div className="user-block-picture">
+							<div className="user-block-status">
+								<img className="img-thumbnail rounded-circle" src="/static/img/logo-single.png" alt="Avatar" width="60" height="60" />
+								<div className="circle bg-success circle-lg"></div>
+							</div>
+						</div>
+						{/* Name and Job */}
+						<div className="user-block-info">
+							<span className="user-block-name">{user.nama}</span>
+							<span className="user-block-role">{role}</span>
+						</div>
+					</div>
+				</div>
+			</Collapse>
+		);
+	}
 }
 
 SidebarUserBlock.propTypes = {
-    showUserBlock: PropTypes.bool
+	showUserBlock: PropTypes.bool,
 };
 
-const mapStateToProps = state => ({ showUserBlock: state.settings.showUserBlock })
+const mapStateToProps = (state) => ({ showUserBlock: state.settings.showUserBlock });
 
-export default connect(
-    mapStateToProps
-)(SidebarUserBlock);
+export default connect(mapStateToProps)(SidebarUserBlock);

+ 1 - 1
components/Main/DetailSanksi.js

@@ -77,7 +77,7 @@ function DetailSanksi({ data, noTitle = false }) {
 															<div>
 																<p>{jp.pelanggaran}</p>
 																<p>TMT : {jp.tmt_bulan} Bulan</p>
-																<p>Level Pelanggaran : {jp.label_sanksi}</p>
+																<p>Jenis Sanksi Administratif : {jp.label_sanksi}</p>
 															</div>
 														</div>
 													</div>

+ 2 - 2
components/Main/PermohonanPT.js

@@ -1,10 +1,10 @@
 import Scrollable from "@/components/Common/Scrollable";
 import { Col, FormGroup } from "reactstrap";
 
-function PermohonanPT({ data }) {
+function PermohonanPT({ data, title = null }) {
 	return (
 		<>
-			<p className="lead bb">Permohonan dari PT</p>
+			<p className="lead bb">{title || "Permohonan dari PT"}</p>
 			<form className="form-horizontal">
 				<FormGroup row>
 					<Col md="4">Dokumen Permohonan:</Col>

+ 33 - 31
components/Main/TableSanksi.js

@@ -18,38 +18,40 @@ function TableSanksi({ listData, to, linkName }) {
 							</tr>
 						</thead>
 						<tbody>
-							{listData.map((data) => {
-								return (
-									<tr key={data._id}>
-										<td>{data.sanksi.no_sanksi}</td>
-										<td>
-											<div className="media align-items-center">
-												<div className="media-body d-flex">
-													<div>
-														<h4 className="m-0">Universitas Satyagama</h4>
-														<p>{data.sanksi.description}</p>
+							{listData.length
+								? listData.map((data) => {
+										return (
+											<tr key={data._id}>
+												<td>{data.sanksi.no_sanksi}</td>
+												<td>
+													<div className="media align-items-center">
+														<div className="media-body d-flex">
+															<div>
+																<h4 className="m-0">Universitas Satyagama</h4>
+																<p>{data.sanksi.description}</p>
+															</div>
+														</div>
 													</div>
-												</div>
-											</div>
-										</td>
-										<td>{moment(data.sanksi.createdAt).fromNow()}</td>
-										<td>
-											<div className="ml-auto">
-												<Link
-													href={{
-														pathname: to,
-														query: { noSanksi: data.sanksi.no_sanksi, ptId: data.pt_id },
-													}}
-												>
-													<Button color="primary" size="sm">
-														{linkName}
-													</Button>
-												</Link>
-											</div>
-										</td>
-									</tr>
-								);
-							})}
+												</td>
+												<td>{moment(data.sanksi.createdAt).fromNow()}</td>
+												<td>
+													<div className="ml-auto">
+														<Link
+															href={{
+																pathname: to,
+																query: { noSanksi: data.sanksi.no_sanksi, ptId: data.pt_id },
+															}}
+														>
+															<Button color="primary" size="sm">
+																{linkName}
+															</Button>
+														</Link>
+													</div>
+												</td>
+											</tr>
+										);
+								  })
+								: ""}
 						</tbody>
 					</table>
 				</Datatable>

+ 67 - 0
components/Main/Timeline.js

@@ -0,0 +1,67 @@
+import moment from "moment";
+
+function Timeline({ data }) {
+	const date = [...new Set(data.data.map((e) => moment(e.createdAt).format("DD MMMM YYYY")))];
+	return (
+		<ul className="timeline">
+			{date.map((value) => (
+				<>
+					<li className="timeline-separator" data-datetime={value}></li>
+					{data.data
+						.filter((e) => moment(e.createdAt).format("DD MMMM YYYY") === value)
+						.map((data, i) => (
+							<>
+								<li className={data.role === "PT" ? "timeline-inverted" : ""}>
+									<div className="timeline-badge info">
+										<em className="far fa-file"></em>
+									</div>
+
+									<div className="timeline-card">
+										<div className="popover right">
+											<div className="arrow"></div>
+											<div className="popover-body">
+												<div className="d-flex align-items-center mb-3">
+													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
+													<p className="m-0">
+														<strong>{data.role}</strong>
+														<br />
+														{data.description}
+													</p>
+												</div>
+												{data.data.files ? (
+													<>
+														<p className="text-muted my-2">Dokumen</p>
+														{data.data.files.map((e) => (
+															<div className="media bb p-2">
+																<div className="media-body">
+																	<p className="m-0">
+																		<a href={`data:${e.type};base64, ${Buffer.from(e.data).toString("base64")}`} download={e.name}>
+																			<strong>{e.name}</strong>
+																		</a>
+																	</p>
+																</div>
+															</div>
+														))}
+													</>
+												) : (
+													""
+												)}
+											</div>
+										</div>
+									</div>
+								</li>
+							</>
+						))}
+				</>
+			))}
+
+			<li className="timeline-end">
+				<a className="timeline-badge">
+					<em className="fa fa-plus"></em>
+				</a>
+			</li>
+		</ul>
+	);
+}
+
+export default Timeline;

+ 7 - 9
components/PT/JawabanKeberatan/ModalPermohonan.js

@@ -72,16 +72,14 @@ export class ModalPermohonan extends Component {
 			this.state.files.forEach((e) => {
 				formdata.append("files", e);
 			});
-		}
 
-		const added = await addBanding({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
-		formdata.append("banding", added.add.sanksi.banding._id);
-		await addDocPerbaikan({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
+			const added = await addBanding({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
 
-		if (added) {
-			Router.push({
-				pathname: "/app/pt/jawaban-keberatan",
-			});
+			if (added) {
+				Router.push({
+					pathname: "/app/pt/jawaban-keberatan",
+				});
+			}
 		}
 	};
 
@@ -118,7 +116,7 @@ export class ModalPermohonan extends Component {
 					<ModalBody>
 						<form className="form-horizontal" method="get" action="/" onSubmit={this.onSubmit}>
 							<FormGroup>
-								<label>Dokumen Banding</label>
+								<label>Dalam hal mengajukan permohonan banding maka wajib mengunggah surat permohonan banding & dokumen pendukungnya</label>
 								<div>
 									<DropzoneWrapper className="" onDrop={this.onDrop}>
 										{({ getRootProps, getInputProps, isDragActive }) => {

+ 13 - 12
components/PT/Keberatan/ModalPermohonan.js

@@ -72,17 +72,18 @@ export class ModalPermohonan extends Component {
 			this.state.files.forEach((e) => {
 				formdata.append("files", e);
 			});
-		}
-		const added = await addKeberatan({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
-		// formdata.append("keberatan", added.add.sanksi.keberatan._id);
-		// formdata.append("data", added.add.sanksi.keberatan._id);
-		// formdata.append("model", "Keberatan");
-		// await addDocPerbaikan({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
-		// console.log(added);
-		if (added) {
-			Router.push({
-				pathname: "/app/pt/keberatan",
-			});
+
+			const added = await addKeberatan({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
+			// formdata.append("keberatan", added.add.sanksi.keberatan._id);
+			// formdata.append("data", added.add.sanksi.keberatan._id);
+			// formdata.append("model", "Keberatan");
+			// await addDocPerbaikan({ noSanksi, ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" }, formdata);
+			// console.log(added);
+			if (added) {
+				Router.push({
+					pathname: "/app/pt/keberatan",
+				});
+			}
 		}
 	};
 
@@ -119,7 +120,7 @@ export class ModalPermohonan extends Component {
 					<ModalBody>
 						<form className="form-horizontal" method="get" action="/" onSubmit={this.onSubmit}>
 							<FormGroup>
-								<label>Dalam hal mengajukan permohonan keberatan maka wajib mengunggah dokumen pendukungnya</label>
+								<label>Dalam hal mengajukan permohonan keberatan maka wajib mengunggah surat permohonan keberatan atas pengenaan sanksi administratif & dokumen pendukungnya</label>
 								<div>
 									<DropzoneWrapper className="" onDrop={this.onDrop}>
 										{({ getRootProps, getInputProps, isDragActive }) => {

+ 0 - 1
components/PT/Riwayat.js

@@ -3,7 +3,6 @@ import moment from "moment";
 import { Card, CardHeader, CardBody, CardTitle } from "reactstrap";
 
 function Riwayat({ data }) {
-	console.log(data);
 	return (
 		<Card className="card-default">
 			<CardHeader>

+ 1 - 1
components/PT/TableSanksi.js

@@ -32,7 +32,7 @@ function TableSanksi({ listData, to, linkName }) {
 											</div>
 										</div>
 									</td>
-									<td>{moment(data.sanksi.createAt).fromNow()}</td>
+									<td>{moment(data.sanksi.createAt).format("DD MMMM YYYY")}</td>
 									<td>
 										<Link href={{ pathname: to, query: { noSanksi: data.sanksi.no_sanksi } }}>
 											<Button color="primary">{linkName}</Button>

+ 68 - 0
components/PT/Timeline.js

@@ -0,0 +1,68 @@
+import moment from "moment";
+
+function Timeline({ data, dataPelaporan }) {
+	const jadwal = dataPelaporan;
+	const date = [...new Set(data.data.map((e) => moment(e.createdAt).format("DD MMMM YYYY")))];
+	return (
+		<ul className="timeline">
+			{date.map((value) => (
+				<>
+					<li className="timeline-separator" data-datetime={value}></li>
+					{data.data
+						.filter((e) => e.for_pt && moment(e.createdAt).format("DD MMMM YYYY") === value)
+						.map((data, i) => (
+							<>
+								<li className={data.role === "PT" ? "timeline-inverted" : ""}>
+									<div className="timeline-badge info">
+										<em className="far fa-file"></em>
+									</div>
+
+									<div className="timeline-card">
+										<div className="popover right">
+											<div className="arrow"></div>
+											<div className="popover-body">
+												<div className="d-flex align-items-center mb-3">
+													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
+													<p className="m-0">
+														<strong>{data.role}</strong>
+														<br />
+														{data.description}
+													</p>
+												</div>
+												{data.data.files ? (
+													<>
+														<p className="text-muted my-2">Dokumen</p>
+														{data.data.files.map((e) => (
+															<div className="media bb p-2">
+																<div className="media-body">
+																	<p className="m-0">
+																		<a href={`data:${e.type};base64, ${Buffer.from(e.data).toString("base64")}`} download={e.name}>
+																			<strong>{e.name}</strong>
+																		</a>
+																	</p>
+																</div>
+															</div>
+														))}
+													</>
+												) : (
+													""
+												)}
+											</div>
+										</div>
+									</div>
+								</li>
+							</>
+						))}
+				</>
+			))}
+
+			<li className="timeline-end">
+				<a className="timeline-badge">
+					<em className="fa fa-plus"></em>
+				</a>
+			</li>
+		</ul>
+	);
+}
+
+export default Timeline;

+ 3 - 1
components/Pemeriksaan/TableRiwayat.js

@@ -6,7 +6,8 @@ function TableRiwayat({ data }) {
 			<table className="table table-striped my-4 w-100">
 				<thead>
 					<tr>
-						<th>Tanggal</th>
+                        <th>Tanggal Dibuat</th>
+						<th>Tanggal Dokumen</th>
 						<th>Judul Dokumen</th>
 						<th>File Pendukung</th>
 					</tr>
@@ -15,6 +16,7 @@ function TableRiwayat({ data }) {
 					{data.penjadwalan.pemeriksaan.map((e) => (
 						<tr>
 							<td>{moment(e.createdAt).format("D MMMM YYYY")}</td>
+							<td>{moment(e.date).format("D MMMM YYYY")}</td>
 							<td>{e.title}</td>
 							<td>
 								{e.files.map((e) => (

+ 1 - 1
components/Sanksi/TablePenetapanSanksi.js

@@ -52,7 +52,7 @@ export class TablePenetapanSanksi extends Component {
 													<div>
 														<p>{jp.pelanggaran}</p>
 														<p>TMT : {jp.tmt_bulan} Bulan</p>
-														<p>Level Pelanggaran : {jp.label_sanksi}</p>
+														<p>Jenis Sanksi Administratif : {jp.label_sanksi}</p>
 													</div>
 												</div>
 											</div>

+ 27 - 0
config/axios.js

@@ -0,0 +1,27 @@
+import axios from "axios";
+import { refreshToken } from "@/actions/auth";
+// import jwt_decode from "jwt-decode";
+
+const axiosJWT = axios.create();
+
+axiosJWT.interceptors.request.use(
+	async (config) => {
+		// const response = await refreshToken();
+		// const decoded = jwt_decode(response.access_token);
+		// const expire = decoded.exp;
+		// const currentDate = Date.now();
+		// if (expire * 1000 < currentDate) {
+		const response = await refreshToken();
+		config.headers = {
+			Authorization: `Bearer ${response.access_token}`,
+		};
+		config.withCredentials = true;
+		return config;
+		// }
+	},
+	(error) => {
+		return Promise.reject(error);
+	}
+);
+
+export default axiosJWT;

+ 56 - 0
json/dataUser.js

@@ -0,0 +1,56 @@
+module.exports = [
+	{
+		id: "2A080F42-AE7F-407B-976E-DE5FA87BD277",
+		username: "dikti",
+		password: "123",
+		nama: "Dikti Ristek/LLDIKTI",
+		no_telp: "0211111222233",
+		no_hp: "197903302008011007",
+		jabatan: null,
+		alamat: "Jln. Jenderal Sudirman Pintu 1, Senayan",
+		id_sdm_pengguna: null,
+		peran: [
+			{
+				id: "96EBA4CC-5DE1-4429-A836-56E32A63FC67",
+				organisasi: {
+					id: "86942CDF-44F1-446E-8E9E-CB37BBBB16E6",
+					nama: "Semua Unit",
+					id_lembaga_asal: "86942CDF-44F1-446E-8E9E-CB37BBBB16E6",
+					id_jenis_lembaga: 21,
+				},
+				peran: {
+					id: 1,
+					nama: "Admin Dikti",
+					menu: null,
+				},
+			},
+		],
+	},
+	{
+		id: "2A080F42-AE7F-407B-976E-DE5FA87BD278",
+		username: "satyagama",
+		password: "123",
+		nama: "Universitas Satyagama",
+		no_telp: "02157946063",
+		no_hp: "197903302008011007",
+		jabatan: null,
+		alamat: "Jln. Jenderal Sudirman Pintu 1, Senayan",
+		id_sdm_pengguna: null,
+		peran: [
+			{
+				id: "96EBA4CC-5DE1-4429-A836-56E32A63FC69",
+				organisasi: {
+					id: "86942CDF-44F1-446E-8E9E-CB37BBBB16E6",
+					nama: "Semua Unit",
+					id_lembaga_asal: "86942CDF-44F1-446E-8E9E-CB37BBBB16E6",
+					id_jenis_lembaga: 21,
+				},
+				peran: {
+					id: 2,
+					nama: "Perguruan Tinggi",
+					menu: null,
+				},
+			},
+		],
+	},
+];

+ 5 - 0
package-lock.json

@@ -6405,6 +6405,11 @@
         "set-immediate-shim": "~1.0.1"
       }
     },
+    "jwt-decode": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
+      "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
+    },
     "kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",

+ 1 - 0
package.json

@@ -59,6 +59,7 @@
 		"jquery.flot.spline": "themicon/jquery.flot.spline",
 		"jquery.flot.tooltip": "krzysu/flot.tooltip",
 		"jszip": "3.6.0",
+		"jwt-decode": "^3.1.2",
 		"loaders.css": "0.1.2",
 		"matchmedia": "0.1.2",
 		"moment": "^2.29.1",

+ 8 - 0
pages/app/_middleware.js

@@ -0,0 +1,8 @@
+import { NextResponse, NextRequest } from "next/server";
+
+export async function middleware(req, ev) {
+	if (!req.session.user) {
+		return NextResponse.redirect("/login");
+	}
+	return NextResponse.next();
+}

+ 2 - 3
pages/app/banding/detail.js

@@ -125,7 +125,7 @@ class JawabanBanding extends Component {
 									<Row>
 										<Col lg={12}>
 											<DetailSanksi data={sanksi.data[0]} />
-											<PermohonanPT data={sanksi.data[0]} />
+											<PermohonanPT data={sanksi.data[0].sanksi.banding} title="Permohonan Banding" />
 											<p className="lead bb">Jawaban</p>
 											<form className="form-horizontal" method="get" action="/" onSubmit={this.onSubmit}>
 												<FormGroup>
@@ -137,8 +137,7 @@ class JawabanBanding extends Component {
 															onChange={this.handleChangeSelect}
 															options={[
 																{ value: "Ditolak", label: "Ditolak", className: "State-ACT" },
-																{ value: "Mengubah Keputusan Sanksi", label: "Mengubah Keputusan Sanksi", className: "State-ACT" },
-																{ value: "Membatalkan Keputusan Sanksi", label: "Membatalkan Keputusan Sanksi", className: "State-ACT" },
+																{ value: "Dikabulkan", label: "Dikabulkan", className: "State-ACT" },
 															]}
 															required
 														/>

+ 4 - 4
pages/app/keberatan/detail.js

@@ -131,7 +131,7 @@ class DetailKeberatan extends Component {
 									</Row>
 									<Row>
 										<Col lg={12}>
-											<PermohonanPT data={sanksi.data[0]} />
+											<PermohonanPT data={sanksi.data[0].sanksi.keberatan} />
 										</Col>
 									</Row>
 									<Row>
@@ -146,9 +146,9 @@ class DetailKeberatan extends Component {
 															value={this.state.selectedOption}
 															onChange={this.handleChangeSelect}
 															options={[
-																{ value: "ditolak", label: "Ditolak", className: "State-ACT" },
-																{ value: "mengubah sanksi", label: "Mengubah Sanksi", className: "State-ACT" },
-																{ value: "mencabut sanksi", label: "Mencabut Sanksi", className: "State-ACT" },
+																{ value: "Menolak", label: "Menolak", className: "State-ACT" },
+																{ value: "Mengubah Keputusan", label: "Mengubah Keputusan", className: "State-ACT" },
+																{ value: "Membatalkan Keputusan", label: "Membatalkan Keputusan", className: "State-ACT" },
 															]}
 															required
 														/>

+ 1 - 1
pages/app/pemantauan-perbaikan/index.js

@@ -19,7 +19,7 @@ class PemantauanPerbaikan extends Component {
 		const { sanksi } = this.props;
 		return (
 			<ContentWrapper>
-				<div className="content-heading">Banding</div>
+				<div className="content-heading">Pemantauan Perbaikan</div>
 				<Row>
 					<Col lg="4">
 						<CaseProgress />

+ 17 - 314
pages/app/pemantauan/timeline.js

@@ -1,330 +1,33 @@
 import React, { Component } from "react";
 import ContentWrapper from "@/components/Layout/ContentWrapper";
-import {
-	Row,
-	Col,
-	Card,
-	Button,
-	CardHeader,
-	CardFooter,
-	Table,
-	Nav,
-	NavItem,
-	NavLink,
-	TabContent,
-	TabPane,
-	Pagination,
-	PaginationItem,
-	PaginationLink,
-	ListGroup,
-	ListGroupItem,
-	Dropdown,
-	DropdownMenu,
-	DropdownToggle,
-	DropdownItem,
-} from "reactstrap";
-//import { Row, Col, Card, CardHeader, CardFooter, Table, Pagination, PaginationItem, PaginationLink } from 'reactstrap';
-
-// import { Row, Col, Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
-import Select from "react-select";
-import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";
-
-import { GetServerSideProps, NextPage } from "next";
-import ErrorPage from "next/error";
-import fetch from "node-fetch";
-
-import https from "https";
-
-const containerStyle = {
-	width: "100%",
-	height: "155px",
-};
-
-
-var jenisPelanggaran = [];
-
-//const qpt_id = {};
-
-//http://localhost:3000/app/profile?ptId=0BCE4DB7-B207-445D-8D03-0C54B7688252
-
-// Demo with custom style
-const DemoMapCustomStyle = (props) => (
-	<GoogleMap mapContainerStyle={containerStyle} zoom={14} center={props.location} options={{ styles: props.mapStyles }}>
-		<Marker position={props.location} />
-	</GoogleMap>
-);
-
-const styleHeaderText = {
-	color: "brown",
-};
-
-class Profile extends Component {
-	toggleTab = (tab) => {
-		if (this.state.activeTab !== tab) {
-			this.setState({
-				activeTab: tab,
-			});
-		}
-	};
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import { getLog } from "@/actions/log";
+import { Row, Col } from "reactstrap";
+import Timeline from "@/components/Main/Timeline";
+
+class Pemantauan extends Component {
+	constructor(props) {
+		super(props);
+	}
 
 	static async getInitialProps({ query }) {
-		const httpsAgent = new https.Agent({
-			rejectUnauthorized: false,
-		});
-		const json = [
-			{
-				id: "0BCE4DB7-B207-445D-8D03-0C54B7688252",
-				kode: "031031",
-				kode_satker: null,
-				nama: "Universitas Satyagama",
-				nama_singkat: "USG",
-				sk_pendirian: "0742/O/1990",
-				tgl_sk_pendirian: "1990-12-22",
-				sk_operasional: null,
-				tgl_sk_operasional: null,
-				status: "A",
-				alamat: {
-					jalan: "Jalan Kamal Raya No 2-A Cengkareng",
-					rt: null,
-					rw: null,
-					dusun: null,
-					kelurahan: "-",
-					kode_pos: "11730",
-					kab_kota: {
-						id: "016200",
-						nama: "Kota Jakarta Barat",
-					},
-				},
-				propinsi: {
-					id: "010000",
-					nama: "Prov. D.K.I. Jakarta",
-				},
-				telepon: "(021) 5452377-78",
-				faksimile: "(021) 54391325",
-				website: "www.satyagama.ac.id",
-				email: "info@satyagama.ac.id",
-				status_milik: {
-					id: "3",
-					nama: "Yayasan",
-				},
-				pembina: {
-					id: "728989DD-251E-4516-BE2C-BA17A93A5C51",
-					nama: "LLDIKTI III",
-				},
-				bentuk_pendidikan: {
-					id: "23",
-					nama: "Universitas",
-				},
-				last_update: "2021-12-08",
-				negara: {
-					id: "ID",
-					nama: "Indonesia",
-				},
-				pimpinan: {
-					id: "D3D20B3D-0FBE-4706-8A70-67C4C09C8FBE",
-					nama: "DEWI SULISTYANI",
-					tmt_sk_pengangkatan: "2021-03-17",
-					tst_sk_pengangkatan: "2025-03-17",
-				},
-			},
-		];
-		console.log("json : ", json);
-
-		return { data: json[0] };
+		const log = await getLog({ ptId: query.ptId });
+		return { log };
 	}
 
-	state = {
-		dropdownOpen: false,
-		dropdownOpenUpload: false,
-		timelineAlt: false,
-		location: { lat: 33.7906731, lng: -117.8357194 },
-		customStyle: [
-			{ featureType: "water", stylers: [{ visibility: "on" }, { color: "#bdd1f9" }] },
-			{ featureType: "all", elementType: "labels.text.fill", stylers: [{ color: "#334165" }] },
-			{ featureType: "landscape", stylers: [{ color: "#e9ebf1" }] },
-			{ featureType: "road.highway", elementType: "geometry", stylers: [{ color: "#c5c6c6" }] },
-			{ featureType: "road.arterial", elementType: "geometry", stylers: [{ color: "#fff" }] },
-			{ featureType: "road.local", elementType: "geometry", stylers: [{ color: "#fff" }] },
-			{ featureType: "transit", elementType: "geometry", stylers: [{ color: "#d8dbe0" }] },
-			{ featureType: "poi", elementType: "geometry", stylers: [{ color: "#cfd5e0" }] },
-			{ featureType: "administrative", stylers: [{ visibility: "on" }, { lightness: 33 }] },
-			{ featureType: "poi.park", elementType: "labels", stylers: [{ visibility: "on" }, { lightness: 20 }] },
-			{ featureType: "road", stylers: [{ color: "#d8dbe0", lightness: 20 }] },
-		],
-		listA: [],
-		selectedOptionMulti: [],
-		activeTab: "tasks",
-	};
-
-	toggleDD = () =>
-		this.setState({
-			dropdownOpen: !this.state.dropdownOpen,
-		});
-
-	toggleDDUpload = () =>
-		this.setState({
-			dropdownOpenUpload: !this.state.dropdownOpenUpload,
-		});
-
-	toggleTimeline = (e) => {
-		this.setState({
-			timelineAlt: e.target.checked,
-		});
-	};
-
 	render() {
-		const { selectedOptionMulti } = this.state;
-
+		const { log } = this.props;
 		return (
 			<ContentWrapper unwrap>
-				<div className="bg-cover" style={{ backgroundImage: "url(/static/img/profile-bg.png)" }}>
-					<div className="p-4 text-center" style={styleHeaderText}>
-						<img className="img-thumbnail rounded-circle thumb128" src="/static/img/univ-avatar.png" alt="Avatar" />
-						<h3 className="m-0">{this.props.data.nama}</h3>
-						<p>{this.props.data.sk_pendirian}</p>
-						<p>{this.props.data.alamat.jalan}</p>
-					</div>
-				</div>
+				<Header />
 				<div className="p-3">
 					<Row>
 						<Col xl="9">
-							<ul className="timeline">
-								<li className="timeline-separator" data-datetime="Today"></li>
-								<li className="timeline-inverted">
-									<div className="timeline-badge info">
-										<em className="far fa-file"></em>
-									</div>
-									<div className="timeline-card">
-										<div className="popover right">
-											<div className="arrow"></div>
-											<div className="popover-body">
-												<div className="d-flex align-items-center mb-3">
-													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
-													<p className="m-0">
-														{/* <a className="text-muted" href=""> */}
-														<strong>Admin</strong>
-														{/* </a> */}
-														<br />
-														Upload Bukti Perbaikan
-														{/* <em className="fa fa-paperclip"></em> */}
-														<Dropdown isOpen={this.state.dropdownOpenUpload} toggle={this.toggleDDUpload}>
-															{/* <em className="fa fa-graduation-cap fa-fw mr-3"></em>Status */}
-															{/* <p className="m-0"><br/> Upload Bukti Perbaikan </p> */}
-															<DropdownToggle caret color="link">
-																<em className="fa fa-paperclip"></em>
-															</DropdownToggle>
-															<DropdownMenu className="animated fadeInUpShort">
-																<DropdownItem>
-																	<em className="fa fa-lock mr-2"></em>Upload
-																</DropdownItem>
-															</DropdownMenu>
-														</Dropdown>
-													</p>
-													{/* <li> */}
-
-													{/* </li> */}
-												</div>
-												{/* <a href="">
-                                                    <img className="img-fluid img-thumbnail" src="/static/img/mockup.png" alt="Img"/>
-                                                </a> */}
-												<p className="text-muted my-2">3 Logs</p>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File BBB.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">12m ago</small>
-												</div>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File CCC.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">30m ago</small>
-												</div>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File AAA.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">30m ago</small>
-												</div>
-												{/* <form className="mt-2" method="post" action="#">
-                                                    <textarea className="form-control no-resize" placeholder="Comment..." rows="1"></textarea>
-                                                </form> */}
-											</div>
-										</div>
-									</div>
-								</li>
-								<li>
-									<div className="timeline-badge danger">
-										<em className="fas fa-ticket-alt"></em>
-									</div>
-									<div className="timeline-card">
-										<div className="popover left">
-											<div className="arrow"></div>
-											<div className="popover-body">
-												<div className="d-flex align-items-center mb-3">
-													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
-													<p className="m-0">
-														{/* <a className="text-muted" href=""> */}
-														<strong>Admin</strong>
-														{/* </a> */}
-														<br />
-														opened project
-														<a className="ml-2" href="">
-															#548795
-														</a>
-													</p>
-												</div>
-												<p>
-													<em>&mdash; Project description sample</em>
-												</p>
-											</div>
-										</div>
-									</div>
-								</li>
-								<li className="timeline-end">
-									<a className="timeline-badge">
-										<em className="fa fa-plus"></em>
-									</a>
-								</li>
-							</ul>
+							<Timeline data={log} />
 						</Col>
 						<Col xl="3">
-							<div className="card card-default">
-								<div className="card-body">
-									<div className="text-center">
-										<h3 className="mt-0">{this.props.data.nama}</h3>
-										<p>{this.props.data.sk_pendirian}</p>
-									</div>
-									<hr />
-									<ul className="list-unstyled px-4">
-										<li>
-											<em className="fa fa-globe fa-fw mr-3"></em>
-											{this.props.data.website}
-										</li>
-										<li>
-											<em className="fa fa-graduation-cap fa-fw mr-3"></em>Status Pelanggaran : Tidak Ada
-										</li>
-									</ul>
-								</div>
-							</div>
+							<DetailPT />
 						</Col>
 					</Row>
 				</div>
@@ -333,4 +36,4 @@ class Profile extends Component {
 	}
 }
 
-export default Profile;
+export default Pemantauan;

+ 3 - 3
pages/app/pencabutan-sanksi/detail.js

@@ -143,15 +143,15 @@ class JawabanPencabutanSanksi extends Component {
 															value={this.state.selectedOption}
 															onChange={this.handleChangeSelect}
 															options={[
-																{ value: "diterima", label: "Diterima", className: "State-ACT" },
-																{ value: "rekomendasi perbaikan", label: "Rekomendasi Perbaikan", className: "State-ACT" },
+																{ value: "Diterima", label: "Diterima", className: "State-ACT" },
+																{ value: "Rekomendasi Perbaikan", label: "Rekomendasi Perbaikan", className: "State-ACT" },
 															]}
 															required
 														/>
 														{/* <span className="form-text">Pilih Jenis Pelanggaran</span> */}
 													</div>
 												</FormGroup>
-												{selectedOption && selectedOption.value === "rekomendasi perbaikan" ? (
+												{selectedOption && selectedOption.value === "Rekomendasi Perbaikan" ? (
 													<FormGroup>
 														<label className="row-form-label">Keterangan:</label>
 														<div className="row-md-10">

+ 1 - 5
pages/app/pt/dokumen-perbaikan/index.js

@@ -16,15 +16,11 @@ class Pelaporan extends Component {
 
 	render() {
 		const { sanksi } = this.props;
-		const { keberatan, banding } = sanksi.data[0].sanksi.doc_perbaikan;
-		console.log(sanksi.data[0].sanksi.doc_perbaikan);
 		return (
 			<ContentWrapper>
 				<div className="content-heading">Dokumen Perbaikan</div>
 				<Row>
-					<Col lg={12}>
-						<TableSanksi listData={sanksi.data} to="/app/pt/dokumen-perbaikan/detail" linkName="Detail" />
-					</Col>
+					<Col lg={12}>{sanksi.data.length > 0 ? <TableSanksi listData={sanksi.data} to="/app/pt/dokumen-perbaikan/detail" linkName="Detail" /> : ""}</Col>
 				</Row>
 			</ContentWrapper>
 		);

+ 13 - 7
pages/app/pt/jawaban-keberatan/detail.js

@@ -56,13 +56,19 @@ class JawabanKeberatan extends Component {
 										<Col lg={12}>
 											<DetailSanksi data={sanksi.data[0]} />
 											<DetailJawaban data={sanksi.data[0]} />
-											<p>
-												Setelah membaca jawaban permohonan keberatan atas pengenaan sanksi, jika Perguruan Tinggi bermaksud mengajukan permohonan banding kepada atasan pemberi sanksi maka dapat menekan tombol di
-												bawah ini (10 Hari Kerja)
-											</p>
-											<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.banding || false}>
-												Ajukan Banding
-											</Button>
+											{new Date(sanksi.data[0].sanksi.close_banding).getTime() > Date.now() ? (
+												<>
+													<p>
+														Setelah membaca jawaban permohonan keberatan atas pengenaan sanksi, jika Perguruan Tinggi bermaksud mengajukan permohonan banding kepada atasan pemberi sanksi maka dapat menekan tombol
+														di bawah ini paling lambat {moment(sanksi.data[0].sanksi.close_banding).format("DD MMMM YYYY")}
+													</p>
+													<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.banding || false}>
+														Ajukan Banding
+													</Button>
+												</>
+											) : (
+												<p>Pengajuan ditutup</p>
+											)}
 										</Col>
 									</Row>
 								</CardBody>

+ 14 - 4
pages/app/pt/keberatan/detail.js

@@ -7,6 +7,7 @@ import DetailSanksi from "@/components/Main/DetailSanksi";
 import Riwayat from "@/components/PT/Keberatan/Riwayat";
 import ModalPermohonan from "@/components/PT/Keberatan/ModalPermohonan";
 import Link from "next/link";
+import moment from "moment";
 import { Row, Col, Card, CardBody, Button } from "reactstrap";
 
 class Keberatan extends Component {
@@ -51,10 +52,19 @@ class Keberatan extends Component {
 									<Row>
 										<Col lg={12}>
 											<DetailSanksi data={sanksi.data[0]} />
-											<p>Setelah membaca surat keputusan sanksi tersebut, jika Perguruan Tinggi bermaksud mengajukan permohonan keberatan maka dapat menekan tombol di bawah ini (21 Hari Kerja)</p>
-											<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.keberatan || false}>
-												Ajukan Permohonan Keberatan
-											</Button>
+											{new Date(sanksi.data[0].sanksi.close_keberatan).getTime() > Date.now() ? (
+												<>
+													<p>
+														Setelah membaca surat keputusan sanksi tersebut, jika Perguruan Tinggi bermaksud mengajukan permohonan keberatan maka dapat menekan tombol di bawah ini paling lambat{" "}
+														{moment(sanksi.data[0].sanksi.close_keberatan).format("DD MMMM YYYY")}
+													</p>
+													<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.keberatan || false}>
+														Ajukan Permohonan Keberatan
+													</Button>
+												</>
+											) : (
+												<p>Pengajuan ditutup</p>
+											)}
 										</Col>
 									</Row>
 								</CardBody>

+ 15 - 329
pages/app/pt/pemantauan.js

@@ -2,345 +2,31 @@ import React, { Component } from "react";
 import ContentWrapper from "@/components/Layout/ContentWrapper";
 import Header from "@/components/Main/Header";
 import DetailPT from "@/components/Main/DetailPT";
-import {
-	Row,
-	Col,
-	Card,
-	Button,
-	CardHeader,
-	CardFooter,
-	Table,
-	Nav,
-	NavItem,
-	NavLink,
-	TabContent,
-	TabPane,
-	Pagination,
-	PaginationItem,
-	PaginationLink,
-	ListGroup,
-	ListGroupItem,
-	Dropdown,
-	DropdownMenu,
-	DropdownToggle,
-	DropdownItem,
-} from "reactstrap";
-//import { Row, Col, Card, CardHeader, CardFooter, Table, Pagination, PaginationItem, PaginationLink } from 'reactstrap';
-
-// import { Row, Col, Dropdown, DropdownMenu, DropdownToggle, DropdownItem } from 'reactstrap';
-import Select from "react-select";
-import { GoogleMap, LoadScript, Marker } from "@react-google-maps/api";
-
-import { GetServerSideProps, NextPage } from "next";
-import ErrorPage from "next/error";
-import fetch from "node-fetch";
-
-import https from "https";
-
-const containerStyle = {
-	width: "100%",
-	height: "155px",
-};
-
-var jenisPelanggaran = [];
-
-//const qpt_id = {};
-
-//http://localhost:3000/app/profile?ptId=0BCE4DB7-B207-445D-8D03-0C54B7688252
-
-// Demo with custom style
-const DemoMapCustomStyle = (props) => (
-	<GoogleMap mapContainerStyle={containerStyle} zoom={14} center={props.location} options={{ styles: props.mapStyles }}>
-		<Marker position={props.location} />
-	</GoogleMap>
-);
-
-const styleHeaderText = {
-	color: "brown",
-};
-
-class Profile extends Component {
-	toggleTab = (tab) => {
-		if (this.state.activeTab !== tab) {
-			this.setState({
-				activeTab: tab,
-			});
-		}
-	};
+import { getLog } from "@/actions/log";
+import { getPelaporan } from "@/actions/pelaporan";
+import { Row, Col } from "reactstrap";
+import Timeline from "@/components/PT/Timeline";
+
+class Pemantauan extends Component {
+	constructor(props) {
+		super(props);
+	}
 
 	static async getInitialProps({ query }) {
-		const httpsAgent = new https.Agent({
-			rejectUnauthorized: false,
-		});
-		const json = [
-			{
-				id: "0BCE4DB7-B207-445D-8D03-0C54B7688252",
-				kode: "031031",
-				kode_satker: null,
-				nama: "Universitas Satyagama",
-				nama_singkat: "USG",
-				sk_pendirian: "0742/O/1990",
-				tgl_sk_pendirian: "1990-12-22",
-				sk_operasional: null,
-				tgl_sk_operasional: null,
-				status: "A",
-				alamat: {
-					jalan: "Jalan Kamal Raya No 2-A Cengkareng",
-					rt: null,
-					rw: null,
-					dusun: null,
-					kelurahan: "-",
-					kode_pos: "11730",
-					kab_kota: {
-						id: "016200",
-						nama: "Kota Jakarta Barat",
-					},
-				},
-				propinsi: {
-					id: "010000",
-					nama: "Prov. D.K.I. Jakarta",
-				},
-				telepon: "(021) 5452377-78",
-				faksimile: "(021) 54391325",
-				website: "www.satyagama.ac.id",
-				email: "info@satyagama.ac.id",
-				status_milik: {
-					id: "3",
-					nama: "Yayasan",
-				},
-				pembina: {
-					id: "728989DD-251E-4516-BE2C-BA17A93A5C51",
-					nama: "LLDIKTI III",
-				},
-				bentuk_pendidikan: {
-					id: "23",
-					nama: "Universitas",
-				},
-				last_update: "2021-12-08",
-				negara: {
-					id: "ID",
-					nama: "Indonesia",
-				},
-				pimpinan: {
-					id: "D3D20B3D-0FBE-4706-8A70-67C4C09C8FBE",
-					nama: "DEWI SULISTYANI",
-					tmt_sk_pengangkatan: "2021-03-17",
-					tst_sk_pengangkatan: "2025-03-17",
-				},
-			},
-		];
-		console.log("json : ", json);
-
-		return { data: json[0] };
+		const log = await getLog({ ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" });
+		const pelaporan = await getPelaporan({ ptId: "0BCE4DB7-B207-445D-8D03-0C54B7688252" });
+		return { log, pelaporan };
 	}
 
-	state = {
-		dropdownOpen: false,
-		dropdownOpenUpload: false,
-		timelineAlt: false,
-		location: { lat: 33.7906731, lng: -117.8357194 },
-		customStyle: [
-			{ featureType: "water", stylers: [{ visibility: "on" }, { color: "#bdd1f9" }] },
-			{ featureType: "all", elementType: "labels.text.fill", stylers: [{ color: "#334165" }] },
-			{ featureType: "landscape", stylers: [{ color: "#e9ebf1" }] },
-			{ featureType: "road.highway", elementType: "geometry", stylers: [{ color: "#c5c6c6" }] },
-			{ featureType: "road.arterial", elementType: "geometry", stylers: [{ color: "#fff" }] },
-			{ featureType: "road.local", elementType: "geometry", stylers: [{ color: "#fff" }] },
-			{ featureType: "transit", elementType: "geometry", stylers: [{ color: "#d8dbe0" }] },
-			{ featureType: "poi", elementType: "geometry", stylers: [{ color: "#cfd5e0" }] },
-			{ featureType: "administrative", stylers: [{ visibility: "on" }, { lightness: 33 }] },
-			{ featureType: "poi.park", elementType: "labels", stylers: [{ visibility: "on" }, { lightness: 20 }] },
-			{ featureType: "road", stylers: [{ color: "#d8dbe0", lightness: 20 }] },
-		],
-		listA: [],
-		selectedOptionMulti: [],
-		activeTab: "tasks",
-	};
-
-	toggleDD = () =>
-		this.setState({
-			dropdownOpen: !this.state.dropdownOpen,
-		});
-
-	toggleDDUpload = () =>
-		this.setState({
-			dropdownOpenUpload: !this.state.dropdownOpenUpload,
-		});
-
-	toggleTimeline = (e) => {
-		this.setState({
-			timelineAlt: e.target.checked,
-		});
-	};
-
 	render() {
-		const { selectedOptionMulti } = this.state;
-
+		const { log, pelaporan } = this.props;
 		return (
 			<ContentWrapper unwrap>
 				<Header />
 				<div className="p-3">
 					<Row>
 						<Col xl="9">
-							<ul className="timeline">
-								{/* Date */}
-								<li className="timeline-separator" data-datetime="Today"></li>
-								{/* EndDate */}
-								<li className="timeline-inverted">
-									{/* Left Card */}
-									{/* icon */}
-									<div className="timeline-badge info">
-										<em className="far fa-file"></em>
-									</div>
-									{/* endicon */}
-									<div className="timeline-card">
-										<div className="popover right">
-											<div className="arrow"></div>
-											<div className="popover-body">
-												<div className="d-flex align-items-center mb-3">
-													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
-													<p className="m-0">
-														{/* <a className="text-muted" href=""> */}
-														<strong>Admin</strong>
-														{/* </a> */}
-														<br />
-														Upload Bukti Perbaikan
-														{/* <em className="fa fa-paperclip"></em> */}
-														<Dropdown isOpen={this.state.dropdownOpenUpload} toggle={this.toggleDDUpload}>
-															{/* <em className="fa fa-graduation-cap fa-fw mr-3"></em>Status */}
-															{/* <p className="m-0"><br/> Upload Bukti Perbaikan </p> */}
-															<DropdownToggle caret color="link">
-																<em className="fa fa-paperclip"></em>
-															</DropdownToggle>
-															<DropdownMenu className="animated fadeInUpShort">
-																<DropdownItem>
-																	<em className="fa fa-lock mr-2"></em>Upload
-																</DropdownItem>
-															</DropdownMenu>
-														</Dropdown>
-													</p>
-													{/* <li> */}
-
-													{/* </li> */}
-												</div>
-												{/* <a href="">
-                                                    <img className="img-fluid img-thumbnail" src="/static/img/mockup.png" alt="Img"/>
-                                                </a> */}
-												<p className="text-muted my-2">3 Logs</p>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File BBB.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">12m ago</small>
-												</div>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File CCC.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">30m ago</small>
-												</div>
-												<div className="media bb p-2">
-													<img className="mr-2 rounded-circle thumb32" src="/static/img/user/user.png" alt="Avatar" />
-													<div className="media-body">
-														<p className="m-0">
-															<a href="">
-																<strong>Universitas Username</strong>
-															</a>
-														</p>
-														<div className="text-sm text-muted">Uploaded Document File AAA.pdf</div>
-													</div>
-													<small className="ml-auto text-muted">30m ago</small>
-												</div>
-												{/* <form className="mt-2" method="post" action="#">
-                                                    <textarea className="form-control no-resize" placeholder="Comment..." rows="1"></textarea>
-                                                </form> */}
-											</div>
-										</div>
-									</div>
-									{/* EndLeftCard */}
-								</li>
-								<li>
-									{/* rightCard */}
-									{/* icon */}
-									<div className="timeline-badge danger">
-										<em className="fas fa-ticket-alt"></em>
-									</div>
-									{/* endicon */}
-									<div className="timeline-card">
-										<div className="popover left">
-											<div className="arrow"></div>
-											<div className="popover-body">
-												<div className="d-flex align-items-center mb-3">
-													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
-													<p className="m-0">
-														{/* <a className="text-muted" href=""> */}
-														<strong>Admin</strong>
-														{/* </a> */}
-														<br />
-														opened project
-														<a className="ml-2" href="">
-															#548795
-														</a>
-													</p>
-												</div>
-												<p>
-													<em>&mdash; Project description sample</em>
-												</p>
-											</div>
-										</div>
-									</div>
-									{/* endRightCard */}
-								</li>
-								<li>
-									{/* rightCard */}
-									{/* icon */}
-									<div className="timeline-badge danger">
-										<em className="fas fa-ticket-alt"></em>
-									</div>
-									{/* endicon */}
-									<div className="timeline-card">
-										<div className="popover left">
-											<div className="arrow"></div>
-											<div className="popover-body">
-												<div className="d-flex align-items-center mb-3">
-													<img className="mr-3 rounded-circle thumb48" src="/static/img/user/admin.png" alt="Avatar" />
-													<p className="m-0">
-														{/* <a className="text-muted" href=""> */}
-														<strong>Admin</strong>
-														{/* </a> */}
-														<br />
-														opened project
-														<a className="ml-2" href="">
-															#548795
-														</a>
-													</p>
-												</div>
-												<p>
-													<em>&mdash; Project description sample</em>
-												</p>
-											</div>
-										</div>
-									</div>
-									{/* endRightCard */}
-								</li>
-								<li className="timeline-end">
-									<a className="timeline-badge">
-										<em className="fa fa-plus"></em>
-									</a>
-								</li>
-							</ul>
+							<Timeline data={log} dataPelaporan={pelaporan.data[0]} />
 						</Col>
 						<Col xl="3">
 							<DetailPT />
@@ -352,4 +38,4 @@ class Profile extends Component {
 	}
 }
 
-export default Profile;
+export default Pemantauan;

+ 0 - 5
pages/app/sanksi/detail.js

@@ -5,10 +5,6 @@ import classnames from "classnames";
 import ContentWrapper from "@/components/Layout/ContentWrapper";
 import DetailSanksi from "@/components/Main/DetailSanksi";
 import Header from "@/components/Main/Header";
-import TableRiwayat from "@/components/Pemeriksaan/TableRiwayat";
-import UploadSurat from "@/components/Sanksi/UploadSurat";
-import Ringkasan from "@/components/Sanksi/Ringkasan";
-import TablePenetapanSanksi from "@/components/Sanksi/TablePenetapanSanksi";
 import Link from "next/link";
 import { getPelaporan } from "@/actions/pelaporan";
 import { createSanksi } from "@/actions/sanksi";
@@ -71,7 +67,6 @@ class Detail extends Component {
 
 	render() {
 		const { pelaporan } = this.props;
-		const { checkedData, dataUpload } = this.state;
 		return (
 			<ContentWrapper unwrap>
 				<Header />

+ 15 - 15
pages/index.js

@@ -1,21 +1,21 @@
-import React from 'react';
-import Router from 'next/router';
+import React from "react";
+import Router from "next/router";
 
-//const defaultPage = 'login';
+const defaultPage = 'login';
 //const defaultPage = 'app/profile';
-const defaultPage = 'app/search';
+//const defaultPage = "app/pemantauan";
 //const defaultPage = 'singleview';
 
 export default class extends React.Component {
-    static async getInitialProps({ res }) {
-        if (res) {
-            res.writeHead(302, {
-                Location: defaultPage
-            });
-            res.end();
-        } else {
-            Router.push(defaultPage);
-        }
-        return {};
-    }
+	static async getInitialProps({ res }) {
+		if (res) {
+			res.writeHead(302, {
+				Location: defaultPage,
+			});
+			res.end();
+		} else {
+			Router.push(defaultPage);
+		}
+		return {};
+	}
 }

+ 128 - 201
pages/login.js

@@ -1,207 +1,134 @@
-// import React, { Component,useState } from 'react';
-import React, { Component} from 'react';
-import BasePage from '@/components/Layout/BasePage';
-import Link from 'next/link';
-import { Input, CustomInput } from 'reactstrap';
-import * as actions from '../store/actions/actions';
-
-import FormValidator from '@/components/Forms/Validator.js';
-import { dispatch } from 'd3';
-import Router, { withRouter } from 'next/router'
-
-// import useUser from '../lib/useUser';
-// import fetchJson from '../lib/fetchJson';
-
-const year = new Date().getFullYear()
+import { connect } from "react-redux";
+import { login, getUser } from "@/actions/auth";
 
+import React, { Component } from "react";
+import BasePage from "@/components/Layout/BasePage";
+import { Row, Col, Input, Card, CardHeader, CardBody, Button, CardFooter, CustomInput } from "reactstrap";
+import Router from "next/router";
+import FormValidator from "@/components/Forms/Validator.js";
 
 class Login extends Component {
-
-    // mutateUser = useUser({
-    //     redirectTo: '/profile-sg',
-    //     redirectIfFound: true,
-    // })
-
-    // [errorMsg, setErrorMsg] = useState('')
-
-
-    state = {
-        formLogin: {
-            uname: '',
-            password: ''
-        }
-    }
-
-     /**
-      * Validate input using onChange event
-      * @param  {String} formName The name of the form in the state object
-      * @return {Function} a function used for the event
-      */
-    validateOnChange = event => {
-        const input = event.target;
-        const form = input.form
-        const value = input.type === 'checkbox' ? input.checked : input.value;
-
-        const result = FormValidator.validate(input);
-
-        this.setState({
-            [form.name]: {
-                ...this.state[form.name],
-                [input.name]: value,
-                errors: {
-                    ...this.state[form.name].errors,
-                    [input.name]: result
-                }
-            }
-        });
-
-    }
-
-    onSubmit(e)  {
-        const form = e.target;
-        const inputs = [...form.elements].filter(i => ['INPUT', 'SELECT'].includes(i.nodeName))
-
-        const { errors, hasError } = FormValidator.bulkValidate(inputs)
-
-        this.setState({
-            [form.name]: {
-                ...this.state[form.name],
-                errors
-            }
-        });
-
-        console.log(hasError ? 'Form has errors. Check!' : 'Form Submitted!');
-
-
-        e.preventDefault();
-
-        if (!hasError) {
-            //this.props.logged('signin')
-            //Router.push('/singleview');
-
-            // const body = {
-            //     username: this.state.formLogin.uname,
-            //     password: this.state.formLogin.password
-            //   }
-
-            // try {
-            //     mutateUser(
-            //         await fetchJson('/api/login', {
-            //         method: 'POST',
-            //         headers: { 'Content-Type': 'application/json' },
-            //         body: JSON.stringify(body),
-            //         })
-            //     )
-
-
-            // } catch (error) {
-            // console.error('An unexpected error happened:', error)
-            // setErrorMsg(error.data.message)
-            // }
-            
-            //main route
-            Router.push('/app/projects');
-        };
-
-    }
-
-    /* Simplify error check */
-    hasError = (formName, inputName, method) => {
-        return  this.state[formName] &&
-                this.state[formName].errors &&
-                this.state[formName].errors[inputName] &&
-                this.state[formName].errors[inputName][method]
-    }
-
-    render() {
-        return (
-            <div className="block-center mt-4 wd-xl">
-                <div className="card card-flat">
-                    {/* <div className="card-header text-center bg-white">
-                        <a href="">
-                            <img className="block-center " src="/static/img/logo.png" alt="Logo"/>
-                        </a>
-                    </div> */}
-                    <img class="card-img-top" src="/static/img/logo.png" alt="Logo"></img>
-                    <div className="card-body">
-                        <h5 class="card-title text-center py-2 bg-gray">Aplikasi Perguruan Tinggi Bermasalah </h5>
-                        {/* <p className="text-center py-2">Aplikasi Perguruan Tinggi Bermasalah </p> */}
-                        <form className="mb-3" name="formLogin" onSubmit={this.onSubmit}>
-                            <div className="form-group">
-                                <div className="input-group with-focus">
-                                    {/* <Input type="email"
-                                        name="email"
-                                        className="border-right-0"
-                                        placeholder="Enter username"
-                                        invalid={this.hasError('formLogin','email','required')||this.hasError('formLogin','email','email')}
-                                        onChange={this.validateOnChange}
-                                        data-validate='["required", "email"]'
-                                        value={this.state.formLogin.email}/> */}
-
-                                    <Input placeholder="Enter User Name"
-                                    name="uname"
-                                    className="border-right-0"
-                                    invalid={this.hasError('formLogin','uname','required')}
-                                    onChange={this.validateOnChange}
-                                    data-validate='["required"]'
-                                    value={this.state.formLogin.uname}
-                                     />
-                                    <div className="input-group-append">
-                                        <span className="input-group-text text-muted bg-transparent border-left-0">
-                                            <em className="fa fa-user"></em>
-                                        </span>
-                                    </div>
-                                    { this.hasError('formLogin','uname','required') && <span className="invalid-feedback">Field is required</span> }
-                                    {/* { this.hasError('formLogin','email','email') && <span className="invalid-feedback">Field must be valid email</span> } */}
-                                </div>
-                            </div>
-                            <div className="form-group">
-                                <div className="input-group with-focus">
-                                    <Input type="password"
-                                        id="id-password"
-                                        name="password"
-                                        className="border-right-0"
-                                        placeholder="Password"
-                                        invalid={this.hasError('formLogin','password','required')}
-                                        onChange={this.validateOnChange}
-                                        data-validate='["required"]'
-                                        value={this.state.formLogin.password}
-                                    />
-                                    <div className="input-group-append">
-                                        <span className="input-group-text text-muted bg-transparent border-left-0">
-                                            <em className="fa fa-lock"></em>
-                                        </span>
-                                    </div>
-                                    <span className="invalid-feedback">Field is required</span>
-                                </div>
-                            </div>
-                            {/* <div className="clearfix">
-                                <CustomInput type="checkbox" id="rememberme"
-                                    className="float-left mt-0"
-                                    name="remember"
-                                    label="Remember Me">
-                                </CustomInput>
-                                <div className="float-right">
-                                    <Link href="/pages/recover" as="/recover"><a className="text-muted"> </a></Link>
-                                </div>
-                            </div> */}
-                            <button className="btn btn-block btn-primary mt-3" type="submit">Login</button>
-                        </form>
-                    </div>
-                </div>
-                <div className="p-3 text-center">
-                    {/* <span className="mr-2">&copy;</span> */}
-                    <span>&copy; {year} - Dikti</span>
-                    {/* <span className="mx-2">-</span>
-                    <span>Dikti</span> */}
-                    <br/>
-                    <span> </span>
-                </div>
-            </div>
-        );
-    }
+	state = {
+		/* Group each form state in an object.
+           Property name MUST match the form name */
+
+		formLogin: {
+			username: "",
+			password: "",
+		},
+	};
+
+	/**
+	 * Validate input using onChange event
+	 * @param  {String} formName The name of the form in the state object
+	 * @return {Function} a function used for the event
+	 */
+	validateOnChange = (event) => {
+		const input = event.target;
+		const form = input.form;
+		const value = input.type === "checkbox" ? input.checked : input.value;
+
+		const result = FormValidator.validate(input);
+
+		this.setState({
+			[form.name]: {
+				...this.state[form.name],
+				[input.name]: value,
+				errors: {
+					...this.state[form.name].errors,
+					[input.name]: result,
+				},
+			},
+		});
+	};
+
+	onSubmit = async (e) => {
+		const form = e.target;
+		const inputs = [...form.elements].filter((i) => ["INPUT", "SELECT"].includes(i.nodeName));
+
+		const { errors, hasError } = FormValidator.bulkValidate(inputs);
+
+		this.setState({
+			[form.name]: {
+				...this.state[form.name],
+				errors,
+			},
+		});
+
+		console.log(hasError ? "Form has errors. Check!" : "Form Submitted!");
+		e.preventDefault();
+		if (!hasError) {
+			const { username, password } = this.state.formLogin;
+			const auth = await login(username, password);
+			if (auth.success) {
+				const dataUser = await getUser();
+				if (dataUser.data.peran[0].peran.id === 2) {
+					Router.push({ pathname: "/app/pt/pemantauan" });
+				} else {
+					Router.push({ pathname: "/app/pemantauan" });
+				}
+			}
+
+			// let user = dataUser.filter((e) => e.username === username && e.password === password);
+			// if (user.length) {
+			// 	user = user[0];
+
+			// 	sessionStorage.setItem("user", JSON.stringify(user));
+			// 	if (JSON.parse(sessionStorage.getItem("user")).peran[0].peran.id === 2) {
+			// 		Router.push({ pathname: "/app/pt/pemantauan" });
+			// 	} else {
+			// 		Router.push({ pathname: "/app/pemantauan" });
+			// 	}
+			// }
+			// this.dispatch(login(username, password));
+		}
+		// e.preventDefault();
+	};
+
+	/* Simplify error check */
+	hasError = (formName, inputName, method) => {
+		return this.state[formName] && this.state[formName].errors && this.state[formName].errors[inputName] && this.state[formName].errors[inputName][method];
+	};
+
+	render() {
+		return (
+			<div className="block-center mt-4 wd-xl">
+				<Card className="card card-flat">
+					<img className="card-img-top" src="/static/img/logo.png" alt="Logo" />
+					<CardBody className="card-body">
+						{" "}
+						<h5 className="card-title text-center py-2 bg-gray">Aplikasi Perguruan Tinggi Bermasalah </h5>
+						<form onSubmit={this.onSubmit} method="post" name="formLogin">
+							<div className="form-group">
+								<label className="col-form-label">Username *</label>
+								<Input type="text" name="username" invalid={this.hasError("formLogin", "username", "required")} onChange={this.validateOnChange} data-validate='["required"]' value={this.state.formLogin.username} />
+								{this.hasError("formLogin", "username", "required") && <span className="invalid-feedback">Field is required</span>}
+							</div>
+							<div className="form-group">
+								<label className="col-form-label">Password *</label>
+								<Input
+									type="password"
+									id="id-password"
+									name="password"
+									invalid={this.hasError("formLogin", "password", "required")}
+									onChange={this.validateOnChange}
+									data-validate='["required"]'
+									value={this.state.formLogin.password}
+								/>
+								<span className="invalid-feedback">Field is required</span>
+							</div>
+							<div className="required">* Required fields</div>
+							<Button color="primary" type="submit" block className=" mt-3">
+								Login
+							</Button>
+						</form>
+					</CardBody>
+				</Card>
+			</div>
+		);
+	}
 }
-
 Login.Layout = BasePage;
+const mapStateToProps = (state) => ({ user: state.user });
 
-export default Login;
+export default connect(mapStateToProps)(Login);

+ 0 - 58
pages/singleview.js

@@ -1,58 +0,0 @@
-import React from 'react';
-import { Trans } from '@/components/Common/Translate';
-import ContentWrapper from '@/components/Layout/ContentWrapper';
-import { Row, Col, Dropdown, DropdownToggle, DropdownMenu, DropdownItem } from 'reactstrap';
-
-class SingleView extends React.Component {
-
-    state = {
-      dropdownOpen: false
-    }
-
-    changeLanguage = lng => {
-        this.props.changeLanguage(lng);
-    }
-
-    toggle = () => {
-        this.setState({
-            dropdownOpen: !this.state.dropdownOpen
-        });
-    }
-
-    render() {
-        return (
-            <ContentWrapper>
-                <div className="content-heading">
-                   <div>Single View
-                      <small><Trans i18nKey='dashboard.WELCOME'></Trans></small>
-                   </div>
-                    { /* START Language list */ }
-                    <div className="ml-auto">
-                        <Dropdown isOpen={this.state.dropdownOpen} toggle={this.toggle}>
-                            <DropdownToggle>
-                                English
-                            </DropdownToggle>
-                            <DropdownMenu className="dropdown-menu-right-forced animated fadeInUpShort">
-                                <DropdownItem onClick={() => this.changeLanguage('en')}>English</DropdownItem>
-                                <DropdownItem onClick={() => this.changeLanguage('es')}>Spanish</DropdownItem>
-                            </DropdownMenu>
-                        </Dropdown>
-                    </div>
-                    { /* END Language list */ }
-                </div>
-                <Row>
-                    <Col xs={12} className="text-center">
-                        <h2 className="text-thin">Single view content</h2>
-                        <p>
-                            This project is an application skeleton. You can use it to quickly bootstrap your ReactJS webapp projects and dev environment for these projects.
-                            <br/>
-                            The seed app doesn't do much and has most of the feature removed so you can add theme as per your needs just following the demo app examples.
-                        </p>
-                    </Col>
-                </Row>
-            </ContentWrapper>
-        );
-    }
-}
-
-export default SingleView;

+ 12 - 0
store/actions/user.js

@@ -0,0 +1,12 @@
+export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
+export const LOGIN_FAIL = "LOGIN_FAIL";
+
+import dataUser from "@/json/dataUser";
+
+export const login = (username, password) => (dispatch) => {
+	let data = dataUser.filter((value) => value.username === username && value.password === password);
+	if (!data.length) dispatch({ type: LOGIN_FAIL });
+	data = data[0];
+	localStorage.setItem("userInfo", JSON.stringify(data));
+	dispatch({ type: LOGIN_SUCCESS, payload: data });
+};

+ 2 - 0
store/reducers/reducers.js

@@ -5,6 +5,7 @@ import themesReducer from "./themes.reducers.js";
 import isLoggedReducer from "./isLogged.reducer.js";
 import { pelaporanListReducer, pelaporanCreateReducer } from "./pelaporan.reducers.js";
 import { penjadwalanCreateReducer } from "./penjadwalan.reducers.js";
+import { userReducer } from "./user.reducer";
 
 export default combineReducers({
 	settings: settingsReducer,
@@ -13,4 +14,5 @@ export default combineReducers({
 	pelaporanList: pelaporanListReducer,
 	pelaporanCreate: pelaporanCreateReducer,
 	penjadwalanAdd: penjadwalanCreateReducer,
+	user: userReducer,
 });

+ 12 - 0
store/reducers/user.reducer.js

@@ -0,0 +1,12 @@
+import { LOGIN_SUCCESS, LOGIN_FAIL } from "../actions/user";
+
+export const userReducer = (state = {}, action) => {
+	switch (action.type) {
+		case LOGIN_SUCCESS:
+			return { isLogin: true, data: action.payload };
+		case LOGIN_FAIL:
+			return { isLogin: false, data: {} };
+		default:
+			return state;
+	}
+};

+ 6 - 6
store/store.js

@@ -4,14 +4,14 @@ import reducers from "./reducers/reducers";
 import { saveState } from "./persisted.store.cookies.js";
 
 export default function configureStore(initialState) {
-	const enhancers = compose(typeof window !== "undefined" && window.devToolsExtension ? window.devToolsExtension() : (f) => f);
-
+	// const enhancers = compose(typeof window !== "undefined" && window.devToolsExtension ? window.devToolsExtension() : (f) => f);
+	const composeEnhancers = (typeof window !== "undefined" && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
 	const store = createStore(
 		reducers,
-		applyMiddleware(thunk)
-		// {
-		// 	...initialState,
-		// },
+		{
+			...initialState,
+		},
+		composeEnhancers(applyMiddleware(thunk))
 		// enhancers
 	);