فهرست منبع

version 2.1~1.88

andi 2 سال پیش
والد
کامیت
a6cf920405
35فایلهای تغییر یافته به همراه1966 افزوده شده و 90 حذف شده
  1. 27 2
      actions/pelanggaran.js
  2. 8 1
      actions/sanksi.js
  3. 3 2
      components/Delegasi/CaseProgress.js
  4. 1 1
      components/Layout/Footer.js
  5. 8 2
      components/Layout/Menu.js
  6. 2 2
      components/Layout/MenuLLDIKTI.js
  7. 132 0
      components/NaikSanksi/DetailSanksi.js
  8. 395 0
      components/NaikSanksi/InputTanggal.js
  9. 89 0
      components/NaikSanksi/TableLaporan.js
  10. 60 0
      components/NaikSanksi/TableRiwayat.js
  11. 13 3
      components/Pelaporan/CaseProgress.js
  12. 11 4
      components/PelaporanTuntas/CaseProgress.js
  13. 11 4
      components/Pemeriksaan/CaseProgress.js
  14. 12 4
      components/Penjadwalan/CaseProgress.js
  15. 11 4
      components/Sanksi/CaseProgress.js
  16. 132 0
      components/TurunSanksi/DetailSanksi.js
  17. 395 0
      components/TurunSanksi/InputTanggal.js
  18. 89 0
      components/TurunSanksi/TableLaporan.js
  19. 60 0
      components/TurunSanksi/TableRiwayat.js
  20. 1 1
      pages/app/index.js
  21. 89 0
      pages/app/naik-sanksi/detail.js
  22. 45 0
      pages/app/naik-sanksi/index.js
  23. 21 3
      pages/app/pelaporan/index.js
  24. 18 1
      pages/app/pemeriksaan/index.js
  25. 19 1
      pages/app/penjadwalan/index.js
  26. 1 1
      pages/app/perpanjangan-sanksi/detail.js
  27. 1 2
      pages/app/rekomendasi-delegasi/detail.js
  28. 19 1
      pages/app/sanksi/index.js
  29. 25 5
      pages/app/tuntas/index.js
  30. 89 0
      pages/app/turun-sanksi/detail.js
  31. 45 0
      pages/app/turun-sanksi/index.js
  32. 62 0
      pages/app/workflow/index.js
  33. BIN
      public/static/img/workflow.pdf
  34. BIN
      public/static/img/workflow_image.png
  35. 72 46
      styles/bootstrap/_images.scss

+ 27 - 2
actions/pelanggaran.js

@@ -57,12 +57,37 @@ export const getPelanggaranPublic = async (token) => {
 	}
 };
 
-export const getPelanggaranSanksi = async (token) => {
+export const getPelanggaranSanksi = async (token, query = {}) => {
 	try {
-		const res = await axios.get("/pelanggaran/sanksi", {headers: {Authorization: token}});
+		let url = `/pelanggaran/sanksi`;
+		if (query != {}) {
+			const { down } = query;
+			url += "?";
+			const parseURL = [];
+			if (down) parseURL.push(`down=true`);
+			url += parseURL.join("&");
+		}
+		const res = await axios.get(url, { headers: { Authorization: token } });
 		return await res.data;
 	} catch (error) {
 		console.log("error", error);
 		return false;
 	}
 };
+// export const getPelanggaranSanksi = async (token, query = {}) => {
+// 	try {
+// 		let url = `/pelanggaran/sanksi`;
+// 		if (query != {}) {
+// 			const { down } = query;
+// 			url += "?";
+// 			const parseURL = [];
+// 			if (down) parseURL.push(`down=true`);
+// 			url += parseURL.join("&");
+// 		}
+// 		const res = await axiosAPI.get(url, { headers: { Authorization: token } });
+// 		return res.data;
+// 	} catch (error) {
+// 		console.log("error", error);
+// 		return false;
+// 	}
+// };

+ 8 - 1
actions/sanksi.js

@@ -12,7 +12,7 @@ export const getSanksi = async (token, query = {}) => {
 	try {
 		let url = "/sanksi";
 		if (query != {}) {
-			const { keberatan, jawaban, banding, cabutSanksi, perbaikan, aktif, delegasi } = query;
+			const { keberatan, jawaban, banding, cabutSanksi, perbaikan, aktif, delegasi, turunSanksi, naikSanksi } = query;
 			url += "?";
 			const parseURL = [];
 			if (keberatan) parseURL.push(`keberatan=true`);
@@ -21,6 +21,8 @@ export const getSanksi = async (token, query = {}) => {
 			if (perbaikan) parseURL.push(`perbaikan=true`);
 			if (jawaban) parseURL.push(`jawaban=true`);
 			if (delegasi) parseURL.push(`delegasi=true`);
+			if (turunSanksi) parseURL.push(`turunSanksi=true`);
+			if (naikSanksi) parseURL.push(`naikSanksi=true`);
 			if (aktif === false) parseURL.push(`aktif=false`);
 			url += parseURL.join("&");
 		}
@@ -69,3 +71,8 @@ export const editTmt = async (token, id, data) => {
 	await createLog(token, { aktivitas: `Berhasil perpanjangan sanksi, id: ${id}` });
 	return res.data;
 };
+export const update = async (token, id, data) => {
+	const res = await axios.put(`sanksi/update/${id}`, data, { headers: { Authorization: token } });
+	await createLog(token, { aktivitas: `Berhasil Merubah Sanksi, id: ${id}` });
+	return res.data;
+};

+ 3 - 2
components/Delegasi/CaseProgress.js

@@ -7,6 +7,7 @@ import FlotChart from "@/components/Charts/Flot.js";
 import { ChartSpline, ChartArea, ChartBarStacked, ChartDonut, ChartLine } from "@/components/Config/flot.setup.js";
 import Datatable from "@/components/Tables/Datatable";
 import MorrisChart from "@/components/Charts//Morris";
+import Dropdown from 'react-bootstrap/Dropdown';
 
 function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 	const ChartPie = {
@@ -116,9 +117,9 @@ function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" type="submit" onClick={excel}>
+					{/* <Button className="float-right button-hidden icon-eksport" type="submit" onClick={excel}>
 						<img src="/static/img/eksport.png"></img>
-					</Button>
+					</Button> */}
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 1 - 1
components/Layout/Footer.js

@@ -7,7 +7,7 @@ class Footer extends Component {
         return (
             <footer className="footer-container">
                 <span>Sidali Dikti &copy; {year}</span>
-                <span className=' float-right'>Version 1.99 ~ 1.83</span>
+                <span className=' float-right'>Version 2.1 ~ 1.88</span>
             </footer>
         );
     }

+ 8 - 2
components/Layout/Menu.js

@@ -93,11 +93,11 @@ const Menu = [
 		submenu: [
 			{
 				name: "a. Naik Sanksi",
-				path: "/app/perubahan-sanksi/naik-sanksi",
+				path: "/app/naik-sanksi",
 			},
 			{
 				name: "b. Turun Sanksi",
-				path: "/app/perubahan-sanksi/turun-sanksi",
+				path: "/app/turun-sanksi",
 			},
 		],
 	},
@@ -132,6 +132,12 @@ const Menu = [
 		icon: "fas fa-book",
 		translate: "sidebar.nav.Bantuan",
 	},
+	{
+		name: "Workflow Aplikasi SIDALI",
+		path: "/app/workflow",
+		icon: "fas fa-project-diagram",
+		translate: "sidebar.nav.Bantuan",
+	},
 ];
 
 export default Menu;

+ 2 - 2
components/Layout/MenuLLDIKTI.js

@@ -80,11 +80,11 @@ const Menu = [
 		submenu: [
 			{
 				name: "a. Naik Sanksi",
-				path: "/app/perubahan-sanksi/naik-sanksi",
+				path: "/app/naik-sanksi",
 			},
 			{
 				name: "b. Turun Sanksi",
-				path: "/app/perubahan-sanksi/turun-sanksi",
+				path: "/app/turun-sanksi",
 			},
 		],
 	},

+ 132 - 0
components/NaikSanksi/DetailSanksi.js

@@ -0,0 +1,132 @@
+import Scrollable from "@/components/Common/Scrollable";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+import { CardBody, Col, FormGroup, Table, Card } from "reactstrap";
+import { API_URL } from "@/env";
+
+function DetailSanksi({ data, noTitle = false }) {
+	return (
+		<Card className="card-default">
+			<CardBody>
+				{noTitle ? "" : <p className="lead bb">Detail Sanksi</p>}
+				<form className="form-horizontal">
+					<FormGroup row>
+						<Col md="4">Nomor Sanksi:</Col>
+						<Col md="8">
+							<strong>{data.no_sanksi}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Nama Perguruan Tinggi:</Col>
+						<Col md="8">
+							<strong>{data.laporan.pt.nama}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Keterangan:</Col>
+						<Col md="8">
+							<Scrollable height="100px" className="list-group">
+								<p>{data.keterangan}</p>
+							</Scrollable>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Dibuat Pada:</Col>
+						<Col md="8">
+							<strong>{moment(data.createdAt).format("D MMMM YYYY")}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md={12}>
+							<div className="card b">
+								<div className="card-body bb">
+									<Table responsive>
+										<thead>
+											<tr>
+												<th>Jenis Pelanggaran</th>
+												<th>Sanksi</th>
+											</tr>
+										</thead>
+										<tbody>
+											{data.pelanggaran.map((jp, index) => (
+												<tr key={jp._id}>
+													<td width={50}>
+														<div className="media align-items-center">
+															<div className="media-body d-flex">
+																<div>
+																	<p>{jp.pelanggaran}</p>
+																	<p>TMT : {jp.tmt_bulan} Bulan</p>
+																	<p>Jenis Sanksi Administratif : {jp.label_sanksi}</p>
+																</div>
+															</div>
+														</div>
+													</td>
+													<td width={50}>
+														<div className="media align-items-center">
+															<div className="media-body d-flex">
+																<div>
+																	<p>{jp.sanksi}</p>
+																	<p>Keterangan : {jp.keterangan_sanksi}</p>
+																</div>
+															</div>
+														</div>
+													</td>
+												</tr>
+											))}
+										</tbody>
+									</Table>
+								</div>
+							</div>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Nomor Surat:</Col>
+						<Col md="8">
+							<strong>{data.no_sanksi}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">TMT Berlaku:</Col>
+						<Col md="8">
+							{/* <strong>{moment(data.masa_berlaku.from_date).format("D MMMM YYYY")} - {moment(data.masa_berlaku.to_date).format("D MMMM YYYY")} </strong> */}
+							{data.masa_berlaku?.to_date ? (<strong>{moment(data.masa_berlaku?.from_date).format("DD-MMMM-YYYY")} - {moment(data.masa_berlaku?.to_date).format("DD-MMMM-YYYY")}</strong>) : (<strong className="m-0">6 Bulan</strong>)}
+
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Sanksi:</Col>
+						<Col md="8">
+							<strong>{data.pelanggaran.map((e) => e.sanksi)}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Dokumen Sanksi:</Col>
+						<Col md="8">
+							<Scrollable height="120px" className="list-group">
+								<table className="table table-bordered bg-transparent">
+									<tbody>
+										{data.dokumen.map((e) => (
+											<tr>
+												<td>
+													<em className="fa-lg far fa-file-code"></em>
+												</td>
+												<td>
+													<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+														{e.judul}
+													</a>
+												</td>
+											</tr>
+										))}
+									</tbody>
+								</table>
+							</Scrollable>
+						</Col>
+					</FormGroup>
+				</form>
+			</CardBody>
+		</Card>
+	);
+}
+
+export default DetailSanksi;

+ 395 - 0
components/NaikSanksi/InputTanggal.js

@@ -0,0 +1,395 @@
+import React, { Component } from "react";
+import { Row, Col, Card, CardBody, FormGroup, Input, Button, Modal, ModalHeader, ModalBody, ModalFooter, CardHeader, CardTitle } from "reactstrap";
+import { toast } from "react-toastify";
+import { Formik, Form, Field, ErrorMessage } from "formik";
+import * as Yup from "yup";
+import { connect } from "react-redux";
+import { getOneSanksi, update } from "@/actions/sanksi";
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import { addDays, addMonths } from 'date-fns';
+import id from 'date-fns/locale/id';
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+import Router from "next/router";
+import { getPelanggaranSanksi } from "@/actions/pelanggaran";
+import Select from "react-select";
+
+
+const selectInstanceId = 1;
+const checkIfFilesAreTooBig = (files) => {
+    let valid = true;
+    if (files) {
+        files.map((file) => {
+            if (file.size > 15 * 1024 * 1024) {
+                valid = false;
+            }
+        });
+    }
+    return valid;
+};
+
+const checkIfFilesAreCorrectType = (files) => {
+    let valid = true;
+    if (files) {
+        files.map((file) => {
+            if (!["image/jpeg", "image/png"].includes(file.type)) {
+                valid = false;
+            }
+        });
+    }
+    return valid;
+};
+
+const rekomendasiSchema = Yup.object().shape({
+    no_sanksi: Yup.string().required("Wajib isi Nomor Sanksi"),
+    keterangan: Yup.string().min(3, "Minimal 3 Huruf").max(200).required("Wajib isi keterangan"),
+    from_date: Yup.date().required("Wajib diisi"),
+    to_date: Yup.date().required("Wajib diisi"),
+    sanksi: Yup.array().required("Wajib isi pelanggaran"),
+    dokumen: Yup.array().required("Wajib diisi").test("filesize", "Maksimal ukuran dokumen 15mb", checkIfFilesAreTooBig),
+});
+
+let Dropzone = null;
+
+class DropzoneWrapper extends Component {
+    state = {
+        isClient: false,
+    };
+    componentDidMount = () => {
+        Dropzone = require("react-dropzone").default;
+        this.setState({ isClient: true });
+    };
+    render() {
+        return Dropzone ? <Dropzone {...this.props}>{this.props.children}</Dropzone> : null;
+    }
+}
+
+class InputTanggal extends Component {
+    constructor(props) {
+        super(props);
+        const tmt_awal = new Date();
+        this.state = {
+            dropdownOpen: false,
+            splitButtonOpen: false,
+            files: [],
+            sanksi: {},
+            data: {},
+            from_date: "",
+            to_date: "",
+            startDay: tmt_awal,
+            sanksi: {},
+            keteranganLaporan: "",
+            tmtCheck: false,
+            listSanksi: ""
+        };
+    }
+
+    async componentDidMount() {
+        const { token, query } = this.props;
+        const { id } = query;
+        const sanksi = await getOneSanksi(token, id);
+        const { data: listSanksi } = await getPelanggaranSanksi(token)
+        this.setState({ sanksi, listSanksi })
+    }
+
+
+    toggleSplit = () => {
+        this.setState({
+            splitButtonOpen: !this.state.splitButtonOpen,
+        });
+    };
+
+    toggleDropDown = () => {
+        this.setState({
+            dropdownOpen: !this.state.dropdownOpen,
+        });
+    };
+
+    onDrop = (files) => {
+        this.setState({
+            files: files.map((file) =>
+                Object.assign(file, {
+                    preview: URL.createObjectURL(file),
+                })
+            ),
+            stat: "Added " + files.length + " file(s)",
+        });
+    };
+
+    uploadFiles = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        this.setState({
+            stat: this.state.files.length ? "Dropzone ready to upload " + this.state.files.length + " file(s)" : "No files added.",
+        });
+    };
+
+    clearFiles = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        this.setState({
+            stat: this.state.files.length ? this.state.files.length + " file(s) cleared." : "No files to clear.",
+        });
+        this.setState({
+            files: [],
+        });
+    };
+
+    static getInitialProps = async ({ query }) => {
+        return { query };
+    };
+    setKeteranganPelaporan = (e) => {
+        this.setState({ keteranganLaporan: e.target.value });
+    };
+    handleTmtCheck = () => {
+        this.setState({ tmtCheck: !this.state.tmtCheck });
+    };
+
+
+    handelSimpan = async (data) => {
+        const { token, query } = this.props;
+        const { id } = query;
+        const formdata = new FormData();
+        formdata.append("no_sanksi", data.no_sanksi);
+        formdata.append("keterangan", data.keterangan);
+        formdata.append("from_date", data.from_date);
+        formdata.append("to_date", data.to_date);
+        formdata.append("sanksi", JSON.stringify(data.sanksi));
+        this.state.files.forEach((e) => {
+            formdata.append("dokumen", e);
+        });
+        const toastid = toast.loading("Please wait...");
+        const added = await update(token, id, formdata);
+        if (!added) {
+            toast.update(toastid, { render: "All is not good", type: "error", isLoading: false, autoClose: true, closeButton: true });
+        } else {
+            toast.update(toastid, { render: "All is good", type: "success", isLoading: false, autoClose: true, closeButton: true });
+            Router.push("/app/naik-sanksi");
+
+        }
+
+    };
+    render() {
+        const { files } = this.state;
+
+        const thumbs = files.map((file, index) => (
+            <div md={3} key={index}>
+                <span className="text-left">{index + 1}.{file.name}</span>
+            </div>
+        ));
+        return (
+            <Card className="card-default">
+                <CardBody>
+                    <p className="lead bb">Dokumen Surat Naik Sanksi</p>
+                    <Formik
+                        initialValues={{
+                            no_sanksi: "",
+                            keterangan: "",
+                            from_date: "",
+                            to_date: "",
+                            sanksi: [],
+                            dokumen: [],
+                        }}
+                        validationSchema={rekomendasiSchema}
+                        onSubmit={this.handelSimpan}
+                    >
+                        {() => (
+                            <Form className="form-horizontal">
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Nomor Sanksi</label>
+                                    <div className="col-md-10">
+                                        <Field name="no_sanksi">{({ field }) => <Input type="textarea" placeholder="Nomor Sanksi" {...field} />}</Field>
+                                        <ErrorMessage name="no_sanksi" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Keterangan</label>
+                                    <div className="col-md-10">
+                                        <Field name="keterangan">{({ field }) => <Input type="textarea" placeholder="Keterangan" {...field} />}</Field>
+                                        <ErrorMessage name="keterangan" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Tidak Perlu TMT</label>
+                                    <div className="col-md-10 mt-2">
+                                        <div className="checkbox c-checkbox">
+                                            <label>
+                                                <Input type="checkbox" onChange={this.handleTmtCheck} defaultChecked={this.state.tmtCheck} />
+                                                <span className="fa fa-check"></span></label>
+                                        </div>
+                                    </div>
+                                </FormGroup>
+                                {this.state.tmtCheck && (
+                                    <FormGroup row className="mt-3">
+                                        <label className="col-md-2 col-form-label">Tanggal Penetapan Sanksi</label>
+                                        <span className="col-sm-3 float-left">
+                                            <Field name="from_date">
+                                                {({ field, form }) => (
+                                                    <DatePicker
+                                                        selected={this.state.from_date}
+                                                        onChange={(from_date) => {
+                                                            this.setState({ from_date })
+                                                            form.setFieldValue(field.name, from_date);
+                                                        }}
+                                                        dateFormat="dd/MM/yyyy"
+                                                        maxDate={this.state.startDay}
+                                                        placeholderText="Dari Tanggal"
+                                                        locale={id}
+                                                        className="form-control bg-white"
+                                                    />
+                                                )}
+                                            </Field>
+                                            <ErrorMessage name="from_date" component="div" className="form-text text-danger" />
+                                        </span>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-3">
+                                        <label className="col-md-2 col-form-label">Isi TMT :</label>
+                                        <div className="col-md-6">
+                                            <Row >
+                                                <Col>
+                                                    <FormGroup>
+                                                        <Field name="from_date">
+                                                            {({ field, form }) => (
+                                                                <DatePicker
+                                                                    selected={this.state.from_date}
+                                                                    onChange={(from_date) => {
+                                                                        this.setState({ from_date })
+                                                                        form.setFieldValue(field.name, from_date);
+                                                                    }}
+                                                                    dateFormat="dd/MM/yyyy"
+                                                                    maxDate={this.state.startDay}
+                                                                    placeholderText="Dari Tanggal"
+                                                                    locale={id}
+                                                                    className="form-control bg-white"
+                                                                />
+                                                            )}
+                                                        </Field>
+                                                        <ErrorMessage name="from_date" component="div" className="form-text text-danger" />
+                                                    </FormGroup>
+                                                </Col>
+                                                <Col>
+                                                    <FormGroup>
+                                                        <Field name="to_date">
+                                                            {({ field, form }) => (
+                                                                <DatePicker
+                                                                    selected={this.state.to_date}
+                                                                    onChange={(to_date) => {
+                                                                        this.setState({ to_date })
+                                                                        form.setFieldValue(field.name, to_date);
+                                                                    }}
+                                                                    dateFormat="dd/MM/yyyy"
+                                                                    minDate={this.state.from_date}
+                                                                    maxDate={addMonths(new Date(this.state.from_date), 6)}
+                                                                    placeholderText="Sampai tanggal"
+                                                                    locale={id}
+                                                                    className="form-control bg-white"
+                                                                />
+                                                            )}
+                                                        </Field>
+                                                        <ErrorMessage name="to_date" component="div" className="form-text text-danger" />
+                                                    </FormGroup>
+                                                </Col>
+                                            </Row>
+                                        </div>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-1">
+                                        <label className="col-md-2 col-form-label">TMT berlaku</label>
+                                        <div className="col-md-10 mt-2">
+                                            <b>{this.state.from_date ? moment(this.state.from_date).format("DD-MM-YYYY") : "-"}</b> hingga <b>{this.state.to_date ? moment(this.state.to_date).format("DD-MM-YYYY") : "-"}</b>
+                                        </div>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-1">
+                                        <label className="col-md-2 col-form-label">TMT</label>
+                                        <div className="col-md-10 mt-2">
+                                            <b>{this.state.to_date ? moment(this.state.to_date).diff(this.state.from_date, 'month') : "-"} bulan</b>
+                                        </div>
+                                    </FormGroup>
+                                )}
+
+                                <FormGroup row className="mt-3">
+                                    <label className="col-md-2 col-form-label">List sanksi </label>
+                                    <div className="col-md-10">
+                                        <Field name="sanksi">{({ field, form }) => <Select
+                                            options={this.props.listSanksi.map(e => ({ value: e, label: e }))}
+                                            isMulti
+                                            onChange={(e) => {
+                                                form.setFieldValue(field.name, e);
+                                            }}
+                                        />}</Field>
+                                        <ErrorMessage name="sanksi" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row className="mt-3">
+                                    <label className="col-md-2 col-form-label">Dokumen Perpanjangan Sanksi : <span className="text-danger">*</span></label>
+                                    <div className="col-md-10">
+                                        <Field name="dokumen">
+                                            {({ field, form }) => (
+                                                <DropzoneWrapper
+                                                    className=""
+                                                    onDrop={(e) => {
+                                                        this.onDrop(e);
+                                                        form.setFieldValue(field.name, e);
+                                                    }}
+                                                >
+                                                    {({ getRootProps, getInputProps, isDragActive }) => {
+                                                        return (
+                                                            <div {...getRootProps()} className={"dropzone card" + (isDragActive ? "dropzone-drag-active" : "")}>
+                                                                <input {...getInputProps()} />
+                                                                <div className="dropzone-previews flex">
+                                                                    <div className="dropzone-style-1">
+                                                                        <div className="center-ver-hor dropzone-previews flex">{this.state.files.length > 0 ? <Row><span className="text-left">{thumbs}</span></Row> :
+                                                                            <div className="text-center fa-2x icon-cloud-upload mr-2 ">
+                                                                                <h5 className="text-center dz-default dz-message">Upload dokumen rekomendasi delegasi</h5>
+                                                                            </div>
+                                                                        }
+                                                                        </div>
+                                                                    </div>
+                                                                </div>
+                                                                <div className="d-flex align-items-center">
+                                                                    <small className="ml-auto">
+                                                                        <button
+                                                                            type="button"
+                                                                            className="btn btn-link"
+                                                                            onClick={(e) => {
+                                                                                this.clearFiles(e);
+                                                                                form.setFieldValue(field.name, []);
+                                                                            }}
+                                                                        >
+                                                                            Reset dokumen
+                                                                        </button>
+                                                                    </small>
+                                                                </div>
+                                                            </div>
+                                                        );
+                                                    }}
+                                                </DropzoneWrapper>
+                                            )}
+                                        </Field>
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <div className="col-xl-10">
+                                        <Button color className="color-3e3a8e btn-login" type="submit">
+                                            <span className="font-color-white">Kirim</span>
+                                        </Button>
+                                    </div>
+                                </FormGroup>
+                            </Form>
+                        )}
+                    </Formik>
+                </CardBody>
+            </Card>
+        );
+    }
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(InputTanggal);

+ 89 - 0
components/NaikSanksi/TableLaporan.js

@@ -0,0 +1,89 @@
+import Datatable from "@/components/Tables/Datatable";
+import { Button } from "reactstrap";
+import Link from "next/link";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+
+function TableLaporan({ listData, to, linkName, status = false, noBy = false }) {
+	return (
+		<div className="card b ">
+			<div className="card-body card-over">
+				{listData && (
+					<Datatable options={{ responsive: false, ordering: true }}>
+						<table className="table w-100" data-order='[[3, "desc"]]'>
+							<thead>
+								<tr>
+									<th>No.Laporan</th>
+									<th>Deskripsi Laporan</th>
+									{<th>TMT Berlaku</th>}
+									{/* {!noBy && <th>Dibuat Oleh</th>} */}
+									{/* <th>Created</th> */}
+									<th>Aksi</th>
+								</tr>
+							</thead>
+							<tbody>
+								{listData.map((data) => {
+									return (
+										<tr key={data._id}>
+											<td>
+												{/* <td>{data.no_laporan}</td> */}
+												<div className="media align-items-center">
+													<div className="media-body d-flex">
+														<div>
+															<h4>{data.laporan.no_laporan}</h4>
+															<p>{moment(data.createdAt).format("DD-MMMM-YYYY")}</p>
+														</div>
+													</div>
+												</div>
+											</td>
+
+											<td>
+												<div className="table-desc">
+													<div className="media align-items-center">
+														<div className="media-body d-flex">
+															<div>
+																<h4 className="m-0">{data.laporan.pt.nama.length > 64 ? data.laporan.pt.nama.substring(0, 64) + "..." : data.laporan.pt.nama}</h4>
+																<p className="w-105">{data.laporan.keterangan}</p>
+															</div>
+														</div>
+													</div>
+												</div>
+											</td>
+
+
+											<td>
+												{/* {data.sanksi.masa_berlaku?.to_date ? (<h4 className="m-0"> {moment(data.sanksi.masa_berlaku?.from_date).format("DD MMMM YYYY")} - {moment(data.sanksi.masa_berlaku?.to_date).format("DD MMMM YYYY")}</h4>) : (<h4 className="m-0">6 Bulan</h4>)} */}
+												<h4 className="w-105">Sanksi Administratif: {data.pelanggaran.map((e) => e.label_sanksi)}</h4>
+												<p className="w-105">{data.keterangan}</p>
+											</td>
+											{!noBy && <td>{data.user.isPrivate ? "" : data.user.nama}</td>}
+											<td>
+												<div className="ml-auto">
+													<Link
+														href={{
+															pathname: to,
+															query: { id: data?._id },
+														}}
+													>
+														<Button className="btn-login" color>
+															<span className="font-color-white">
+																{linkName}
+															</span>
+														</Button>
+													</Link>
+												</div>
+											</td>
+										</tr>
+									);
+								})}
+							</tbody>
+						</table>
+					</Datatable>
+				)}
+			</div>
+		</div>
+	);
+}
+
+export default TableLaporan;

+ 60 - 0
components/NaikSanksi/TableRiwayat.js

@@ -0,0 +1,60 @@
+import Datatable from "@/components/Tables/Datatable";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+
+function TableRiwayat({ data, perbaikan }) {
+	return (
+		// <Datatable options={{ responsive: true }}>
+		<div className="card-over">
+			<table className="table table-striped my-4 w-100">
+				<thead>
+					<tr>
+						<th>Tanggal</th>
+						<th>Keterangan</th>
+						<th>Nomor Surat Sanksi</th>
+						<th>Dokumen Surat Sanksi</th>
+						<th>Dokumen Perbaikan</th>
+					</tr>
+				</thead>
+				<tbody>{data.map((e) =>
+					<tr>
+						<td>{moment(e.createdAt).format("D MMMM YYYY")}</td>
+						<td>{e.keterangan}</td>
+						<td>{e.no_sanksi}</td>
+						<td>
+							{e.dokumen.map((e, index) => (
+								<>
+									<em key="index" className="fa-lg far fa-file-code"></em>
+									<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+										{e.judul}
+									</a>
+									<br />
+								</>
+							))}
+						</td>
+						{perbaikan.length
+							? perbaikan.map((value) => (
+								<tr>
+									<td>
+										{value.dokumen.map((e) => (
+											<>
+												<em className="fa-lg far fa-file-code"></em>
+												<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+													{e.judul}
+												</a>
+											</>
+										))}
+									</td>
+								</tr>
+							))
+							: ""}
+					</tr>)}
+				</tbody>
+			</table>
+		</div>
+		// </Datatable>
+	);
+}
+
+export default TableRiwayat;

+ 13 - 3
components/Pelaporan/CaseProgress.js

@@ -5,8 +5,9 @@ import FlotChart from "@/components/Charts/Flot.js";
 import { ChartSpline, ChartArea, ChartBar, ChartBarStacked, ChartDonut, ChartLine, ChartPie } from "@/components/Config/flot.setup.js";
 import Datatable from "@/components/Tables/Datatable";
 import { useState, useEffect } from "react";
+import Dropdown from 'react-bootstrap/Dropdown';
 
-function CaseProgress({ data, nextButton, prevButton, tahun, newLaporan, excel }) {
+function CaseProgress({ data, nextButton, prevButton, tahun, newLaporan, excelSemua, excelMenu }) {
 	const laporan_pertahun = data.laporan_perTahun;
 
 	const [chartData, setChartData] = useState([
@@ -117,9 +118,18 @@ function CaseProgress({ data, nextButton, prevButton, tahun, newLaporan, excel }
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" onClick={excel}>
+					<Dropdown className="float-right">
+						<Dropdown.Toggle variant="success" id="dropdown-basic">
+							Unduh
+						</Dropdown.Toggle>
+						<Dropdown.Menu>
+							<Dropdown.Item onClick={excelMenu}>Unduh dokumen pelaporan</Dropdown.Item>
+							<Dropdown.Item onClick={excelSemua}>Unduh dokumen semua menu</Dropdown.Item>
+						</Dropdown.Menu>
+					</Dropdown>
+					{/* <Button className="float-right button-hidden icon-eksport" onClick={excel}>
 						<img src="/static/img/eksport.png"></img>
-					</Button>
+					</Button> */}
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 11 - 4
components/PelaporanTuntas/CaseProgress.js

@@ -7,8 +7,9 @@ import { ChartSpline, ChartArea, ChartBarStacked, ChartDonut, ChartLine } from "
 import Datatable from "@/components/Tables/Datatable";
 import MorrisChart from "@/components/Charts//Morris";
 import { Button } from "reactstrap";
+import Dropdown from 'react-bootstrap/Dropdown';
 
-function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
+function CaseProgress({ data, nextButton, prevButton, tahun, excelSemua, excelMenu }) {
 	const ChartBar = {
 		data: [
 			{
@@ -106,9 +107,15 @@ function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" onClick={excel}>
-						<img src="/static/img/eksport.png"></img>
-					</Button>
+					<Dropdown className="float-right">
+						<Dropdown.Toggle variant="success" id="dropdown-basic">
+							Unduh
+						</Dropdown.Toggle>
+						<Dropdown.Menu>
+							<Dropdown.Item onClick={excelMenu}>Unduh dokumen sanksi</Dropdown.Item>
+							<Dropdown.Item onClick={excelSemua}>Unduh dokumen semua menu</Dropdown.Item>
+						</Dropdown.Menu>
+					</Dropdown>
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 11 - 4
components/Pemeriksaan/CaseProgress.js

@@ -7,8 +7,9 @@ import { ChartSpline, ChartArea, ChartBarStacked, ChartDonut, ChartLine } from "
 import Datatable from "@/components/Tables/Datatable";
 import MorrisChart from "@/components/Charts//Morris";
 import { Button } from "reactstrap";
+import Dropdown from 'react-bootstrap/Dropdown';
 
-function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
+function CaseProgress({ data, nextButton, prevButton, tahun, excelSemua, excelMenu }) {
 	const ChartBar = {
 		data: [
 			{
@@ -106,9 +107,15 @@ function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" onClick={excel}>
-						<img src="/static/img/eksport.png"></img>
-					</Button>
+					<Dropdown className="float-right">
+						<Dropdown.Toggle variant="success" id="dropdown-basic">
+							Unduh
+						</Dropdown.Toggle>
+						<Dropdown.Menu>
+							<Dropdown.Item onClick={excelMenu}>Unduh dokumen pemeriksaan</Dropdown.Item>
+							<Dropdown.Item onClick={excelSemua}>Unduh dokumen semua menu</Dropdown.Item>
+						</Dropdown.Menu>
+					</Dropdown>
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 12 - 4
components/Penjadwalan/CaseProgress.js

@@ -7,8 +7,9 @@ import { ChartSpline, ChartArea, ChartBarStacked, ChartDonut, ChartLine } from "
 import Datatable from "@/components/Tables/Datatable";
 import MorrisChart from "@/components/Charts//Morris";
 import { Button } from "reactstrap";
+import Dropdown from 'react-bootstrap/Dropdown';
 
-function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
+function CaseProgress({ data, nextButton, prevButton, tahun, excelSemua, excelMenu }) {
 	const Perkembangan = {
 		data: [
 			{
@@ -106,9 +107,16 @@ function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" onClick={excel}>
-						<img src="/static/img/eksport.png"></img>
-					</Button>
+					<b className="text-tahun">Tahun {tahun} </b>
+					<Dropdown className="float-right">
+						<Dropdown.Toggle variant="success" id="dropdown-basic">
+							Unduh
+						</Dropdown.Toggle>
+						<Dropdown.Menu>
+							<Dropdown.Item onClick={excelMenu}>Unduh dokumen penjadwalan</Dropdown.Item>
+							<Dropdown.Item onClick={excelSemua}>Unduh dokumen semua menu</Dropdown.Item>
+						</Dropdown.Menu>
+					</Dropdown>
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 11 - 4
components/Sanksi/CaseProgress.js

@@ -7,8 +7,9 @@ import { ChartSpline, ChartArea, ChartBarStacked, ChartDonut, ChartLine } from "
 import Datatable from "@/components/Tables/Datatable";
 import MorrisChart from "@/components/Charts//Morris";
 import { Button } from "reactstrap";
+import Dropdown from 'react-bootstrap/Dropdown';
 
-function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
+function CaseProgress({ data, nextButton, prevButton, tahun, excelSemua, excelMenu }) {
 	const ChartBar = {
 		data: [
 			{
@@ -105,9 +106,15 @@ function CaseProgress({ data, nextButton, prevButton, tahun, excel }) {
 						<img src="/static/img/next.png"></img>
 					</Button>
 					<b className="text-tahun">Tahun {tahun} </b>
-					<Button className="float-right button-hidden icon-eksport" onClick={excel}>
-						<img src="/static/img/eksport.png"></img>
-					</Button>
+					<Dropdown className="float-right">
+						<Dropdown.Toggle variant="success" id="dropdown-basic">
+							Unduh
+						</Dropdown.Toggle>
+						<Dropdown.Menu>
+							<Dropdown.Item onClick={excelMenu}>Unduh dokumen sanksi</Dropdown.Item>
+							<Dropdown.Item onClick={excelSemua}>Unduh dokumen semua menu</Dropdown.Item>
+						</Dropdown.Menu>
+					</Dropdown>
 				</div>
 				<div className="header-1">
 					<h2 className="card-title-1">Perkembangan</h2>

+ 132 - 0
components/TurunSanksi/DetailSanksi.js

@@ -0,0 +1,132 @@
+import Scrollable from "@/components/Common/Scrollable";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+import { CardBody, Col, FormGroup, Table, Card } from "reactstrap";
+import { API_URL } from "@/env";
+
+function DetailSanksi({ data, noTitle = false }) {
+	return (
+		<Card className="card-default">
+			<CardBody>
+				{noTitle ? "" : <p className="lead bb">Detail Sanksi</p>}
+				<form className="form-horizontal">
+					<FormGroup row>
+						<Col md="4">Nomor Sanksi:</Col>
+						<Col md="8">
+							<strong>{data.no_sanksi}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Nama Perguruan Tinggi:</Col>
+						<Col md="8">
+							<strong>{data.laporan.pt.nama}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Keterangan:</Col>
+						<Col md="8">
+							<Scrollable height="100px" className="list-group">
+								<p>{data.keterangan}</p>
+							</Scrollable>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Dibuat Pada:</Col>
+						<Col md="8">
+							<strong>{moment(data.createdAt).format("D MMMM YYYY")}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md={12}>
+							<div className="card b">
+								<div className="card-body bb">
+									<Table responsive>
+										<thead>
+											<tr>
+												<th>Jenis Pelanggaran</th>
+												<th>Sanksi</th>
+											</tr>
+										</thead>
+										<tbody>
+											{data.pelanggaran.map((jp, index) => (
+												<tr key={jp._id}>
+													<td width={50}>
+														<div className="media align-items-center">
+															<div className="media-body d-flex">
+																<div>
+																	<p>{jp.pelanggaran}</p>
+																	<p>TMT : {jp.tmt_bulan} Bulan</p>
+																	<p>Jenis Sanksi Administratif : {jp.label_sanksi}</p>
+																</div>
+															</div>
+														</div>
+													</td>
+													<td width={50}>
+														<div className="media align-items-center">
+															<div className="media-body d-flex">
+																<div>
+																	<p>{jp.sanksi}</p>
+																	<p>Keterangan : {jp.keterangan_sanksi}</p>
+																</div>
+															</div>
+														</div>
+													</td>
+												</tr>
+											))}
+										</tbody>
+									</Table>
+								</div>
+							</div>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Nomor Surat:</Col>
+						<Col md="8">
+							<strong>{data.no_sanksi}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">TMT Berlaku:</Col>
+						<Col md="8">
+							{/* <strong>{moment(data.masa_berlaku.from_date).format("D MMMM YYYY")} - {moment(data.masa_berlaku.to_date).format("D MMMM YYYY")} </strong> */}
+							{data.masa_berlaku?.to_date ? (<strong>{moment(data.masa_berlaku?.from_date).format("DD-MMMM-YYYY")} - {moment(data.masa_berlaku?.to_date).format("DD-MMMM-YYYY")}</strong>) : (<strong className="m-0">6 Bulan</strong>)}
+
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Sanksi:</Col>
+						<Col md="8">
+							<strong>{data.pelanggaran.map((e) => e.sanksi)}</strong>
+						</Col>
+					</FormGroup>
+					<FormGroup row>
+						<Col md="4">Dokumen Sanksi:</Col>
+						<Col md="8">
+							<Scrollable height="120px" className="list-group">
+								<table className="table table-bordered bg-transparent">
+									<tbody>
+										{data.dokumen.map((e) => (
+											<tr>
+												<td>
+													<em className="fa-lg far fa-file-code"></em>
+												</td>
+												<td>
+													<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+														{e.judul}
+													</a>
+												</td>
+											</tr>
+										))}
+									</tbody>
+								</table>
+							</Scrollable>
+						</Col>
+					</FormGroup>
+				</form>
+			</CardBody>
+		</Card>
+	);
+}
+
+export default DetailSanksi;

+ 395 - 0
components/TurunSanksi/InputTanggal.js

@@ -0,0 +1,395 @@
+import React, { Component } from "react";
+import { Row, Col, Card, CardBody, FormGroup, Input, Button, Modal, ModalHeader, ModalBody, ModalFooter, CardHeader, CardTitle } from "reactstrap";
+import { toast } from "react-toastify";
+import { Formik, Form, Field, ErrorMessage } from "formik";
+import * as Yup from "yup";
+import { connect } from "react-redux";
+import { getOneSanksi, update } from "@/actions/sanksi";
+import DatePicker from "react-datepicker";
+import "react-datepicker/dist/react-datepicker.css";
+import { addDays, addMonths } from 'date-fns';
+import id from 'date-fns/locale/id';
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+import Router from "next/router";
+import { getPelanggaranSanksi } from "@/actions/pelanggaran";
+import Select from "react-select";
+
+
+const selectInstanceId = 1;
+const checkIfFilesAreTooBig = (files) => {
+    let valid = true;
+    if (files) {
+        files.map((file) => {
+            if (file.size > 15 * 1024 * 1024) {
+                valid = false;
+            }
+        });
+    }
+    return valid;
+};
+
+const checkIfFilesAreCorrectType = (files) => {
+    let valid = true;
+    if (files) {
+        files.map((file) => {
+            if (!["image/jpeg", "image/png"].includes(file.type)) {
+                valid = false;
+            }
+        });
+    }
+    return valid;
+};
+
+const rekomendasiSchema = Yup.object().shape({
+    no_sanksi: Yup.string().required("Wajib isi Nomor Sanksi"),
+    keterangan: Yup.string().min(3, "Minimal 3 Huruf").max(200).required("Wajib isi keterangan"),
+    from_date: Yup.date().required("Wajib diisi"),
+    to_date: Yup.date().required("Wajib diisi"),
+    sanksi: Yup.array().required("Wajib isi pelanggaran"),
+    dokumen: Yup.array().required("Wajib diisi").test("filesize", "Maksimal ukuran dokumen 15mb", checkIfFilesAreTooBig),
+});
+
+let Dropzone = null;
+
+class DropzoneWrapper extends Component {
+    state = {
+        isClient: false,
+    };
+    componentDidMount = () => {
+        Dropzone = require("react-dropzone").default;
+        this.setState({ isClient: true });
+    };
+    render() {
+        return Dropzone ? <Dropzone {...this.props}>{this.props.children}</Dropzone> : null;
+    }
+}
+
+class InputTanggal extends Component {
+    constructor(props) {
+        super(props);
+        const tmt_awal = new Date();
+        this.state = {
+            dropdownOpen: false,
+            splitButtonOpen: false,
+            files: [],
+            sanksi: {},
+            data: {},
+            from_date: "",
+            to_date: "",
+            startDay: tmt_awal,
+            sanksi: {},
+            keteranganLaporan: "",
+            tmtCheck: false,
+            listSanksi: ""
+        };
+    }
+
+    async componentDidMount() {
+        const { token, query } = this.props;
+        const { id } = query;
+        const sanksi = await getOneSanksi(token, id);
+        const { data: listSanksi } = await getPelanggaranSanksi(token, { down: true })
+        this.setState({ sanksi, listSanksi })
+    }
+
+
+    toggleSplit = () => {
+        this.setState({
+            splitButtonOpen: !this.state.splitButtonOpen,
+        });
+    };
+
+    toggleDropDown = () => {
+        this.setState({
+            dropdownOpen: !this.state.dropdownOpen,
+        });
+    };
+
+    onDrop = (files) => {
+        this.setState({
+            files: files.map((file) =>
+                Object.assign(file, {
+                    preview: URL.createObjectURL(file),
+                })
+            ),
+            stat: "Added " + files.length + " file(s)",
+        });
+    };
+
+    uploadFiles = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        this.setState({
+            stat: this.state.files.length ? "Dropzone ready to upload " + this.state.files.length + " file(s)" : "No files added.",
+        });
+    };
+
+    clearFiles = (e) => {
+        e.preventDefault();
+        e.stopPropagation();
+        this.setState({
+            stat: this.state.files.length ? this.state.files.length + " file(s) cleared." : "No files to clear.",
+        });
+        this.setState({
+            files: [],
+        });
+    };
+
+    static getInitialProps = async ({ query }) => {
+        return { query };
+    };
+    setKeteranganPelaporan = (e) => {
+        this.setState({ keteranganLaporan: e.target.value });
+    };
+    handleTmtCheck = () => {
+        this.setState({ tmtCheck: !this.state.tmtCheck });
+    };
+
+
+    handelSimpan = async (data) => {
+        const { token, query } = this.props;
+        const { id } = query;
+        const formdata = new FormData();
+        formdata.append("no_sanksi", data.no_sanksi);
+        formdata.append("keterangan", data.keterangan);
+        formdata.append("from_date", data.from_date);
+        formdata.append("to_date", data.to_date);
+        formdata.append("sanksi", JSON.stringify(data.sanksi));
+        this.state.files.forEach((e) => {
+            formdata.append("dokumen", e);
+        });
+        const toastid = toast.loading("Please wait...");
+        const added = await update(token, id, formdata);
+        if (!added) {
+            toast.update(toastid, { render: "All is not good", type: "error", isLoading: false, autoClose: true, closeButton: true });
+        } else {
+            toast.update(toastid, { render: "All is good", type: "success", isLoading: false, autoClose: true, closeButton: true });
+            Router.push("/app/turun-sanksi");
+
+        }
+
+    };
+    render() {
+        const { files } = this.state;
+
+        const thumbs = files.map((file, index) => (
+            <div md={3} key={index}>
+                <span className="text-left">{index + 1}.{file.name}</span>
+            </div>
+        ));
+        return (
+            <Card className="card-default">
+                <CardBody>
+                    <p className="lead bb">Dokumen Surat Turun Sanksi</p>
+                    <Formik
+                        initialValues={{
+                            no_sanksi: "",
+                            keterangan: "",
+                            from_date: "",
+                            to_date: "",
+                            sanksi: [],
+                            dokumen: [],
+                        }}
+                        validationSchema={rekomendasiSchema}
+                        onSubmit={this.handelSimpan}
+                    >
+                        {() => (
+                            <Form className="form-horizontal">
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Nomor Sanksi</label>
+                                    <div className="col-md-10">
+                                        <Field name="no_sanksi">{({ field }) => <Input type="textarea" placeholder="Nomor Sanksi" {...field} />}</Field>
+                                        <ErrorMessage name="no_sanksi" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Keterangan</label>
+                                    <div className="col-md-10">
+                                        <Field name="keterangan">{({ field }) => <Input type="textarea" placeholder="Keterangan" {...field} />}</Field>
+                                        <ErrorMessage name="keterangan" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <label className="col-md-2 col-form-label">Tidak Perlu TMT</label>
+                                    <div className="col-md-10 mt-2">
+                                        <div className="checkbox c-checkbox">
+                                            <label>
+                                                <Input type="checkbox" onChange={this.handleTmtCheck} defaultChecked={this.state.tmtCheck} />
+                                                <span className="fa fa-check"></span></label>
+                                        </div>
+                                    </div>
+                                </FormGroup>
+                                {this.state.tmtCheck && (
+                                    <FormGroup row className="mt-3">
+                                        <label className="col-md-2 col-form-label">Tanggal Penetapan Sanksi</label>
+                                        <span className="col-sm-3 float-left">
+                                            <Field name="from_date">
+                                                {({ field, form }) => (
+                                                    <DatePicker
+                                                        selected={this.state.from_date}
+                                                        onChange={(from_date) => {
+                                                            this.setState({ from_date })
+                                                            form.setFieldValue(field.name, from_date);
+                                                        }}
+                                                        dateFormat="dd/MM/yyyy"
+                                                        maxDate={this.state.startDay}
+                                                        placeholderText="Dari Tanggal"
+                                                        locale={id}
+                                                        className="form-control bg-white"
+                                                    />
+                                                )}
+                                            </Field>
+                                            <ErrorMessage name="from_date" component="div" className="form-text text-danger" />
+                                        </span>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-3">
+                                        <label className="col-md-2 col-form-label">Isi TMT :</label>
+                                        <div className="col-md-6">
+                                            <Row >
+                                                <Col>
+                                                    <FormGroup>
+                                                        <Field name="from_date">
+                                                            {({ field, form }) => (
+                                                                <DatePicker
+                                                                    selected={this.state.from_date}
+                                                                    onChange={(from_date) => {
+                                                                        this.setState({ from_date })
+                                                                        form.setFieldValue(field.name, from_date);
+                                                                    }}
+                                                                    dateFormat="dd/MM/yyyy"
+                                                                    maxDate={this.state.startDay}
+                                                                    placeholderText="Dari Tanggal"
+                                                                    locale={id}
+                                                                    className="form-control bg-white"
+                                                                />
+                                                            )}
+                                                        </Field>
+                                                        <ErrorMessage name="from_date" component="div" className="form-text text-danger" />
+                                                    </FormGroup>
+                                                </Col>
+                                                <Col>
+                                                    <FormGroup>
+                                                        <Field name="to_date">
+                                                            {({ field, form }) => (
+                                                                <DatePicker
+                                                                    selected={this.state.to_date}
+                                                                    onChange={(to_date) => {
+                                                                        this.setState({ to_date })
+                                                                        form.setFieldValue(field.name, to_date);
+                                                                    }}
+                                                                    dateFormat="dd/MM/yyyy"
+                                                                    minDate={this.state.from_date}
+                                                                    maxDate={addMonths(new Date(this.state.from_date), 6)}
+                                                                    placeholderText="Sampai tanggal"
+                                                                    locale={id}
+                                                                    className="form-control bg-white"
+                                                                />
+                                                            )}
+                                                        </Field>
+                                                        <ErrorMessage name="to_date" component="div" className="form-text text-danger" />
+                                                    </FormGroup>
+                                                </Col>
+                                            </Row>
+                                        </div>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-1">
+                                        <label className="col-md-2 col-form-label">TMT berlaku</label>
+                                        <div className="col-md-10 mt-2">
+                                            <b>{this.state.from_date ? moment(this.state.from_date).format("DD-MM-YYYY") : "-"}</b> hingga <b>{this.state.to_date ? moment(this.state.to_date).format("DD-MM-YYYY") : "-"}</b>
+                                        </div>
+                                    </FormGroup>
+                                )}
+                                {!this.state.tmtCheck && (
+                                    <FormGroup row className="mt-1">
+                                        <label className="col-md-2 col-form-label">TMT</label>
+                                        <div className="col-md-10 mt-2">
+                                            <b>{this.state.to_date ? moment(this.state.to_date).diff(this.state.from_date, 'month') : "-"} bulan</b>
+                                        </div>
+                                    </FormGroup>
+                                )}
+
+                                <FormGroup row className="mt-3">
+                                    <label className="col-md-2 col-form-label">List sanksi </label>
+                                    <div className="col-md-10">
+                                        <Field name="sanksi">{({ field, form }) => <Select
+                                            options={this.props.listSanksi.map(e => ({ value: e, label: e }))}
+                                            isMulti
+                                            onChange={(e) => {
+                                                form.setFieldValue(field.name, e);
+                                            }}
+                                        />}</Field>
+                                        <ErrorMessage name="sanksi" component="div" className="form-text text-danger" />
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row className="mt-3">
+                                    <label className="col-md-2 col-form-label">Dokumen Perpanjangan Sanksi : <span className="text-danger">*</span></label>
+                                    <div className="col-md-10">
+                                        <Field name="dokumen">
+                                            {({ field, form }) => (
+                                                <DropzoneWrapper
+                                                    className=""
+                                                    onDrop={(e) => {
+                                                        this.onDrop(e);
+                                                        form.setFieldValue(field.name, e);
+                                                    }}
+                                                >
+                                                    {({ getRootProps, getInputProps, isDragActive }) => {
+                                                        return (
+                                                            <div {...getRootProps()} className={"dropzone card" + (isDragActive ? "dropzone-drag-active" : "")}>
+                                                                <input {...getInputProps()} />
+                                                                <div className="dropzone-previews flex">
+                                                                    <div className="dropzone-style-1">
+                                                                        <div className="center-ver-hor dropzone-previews flex">{this.state.files.length > 0 ? <Row><span className="text-left">{thumbs}</span></Row> :
+                                                                            <div className="text-center fa-2x icon-cloud-upload mr-2 ">
+                                                                                <h5 className="text-center dz-default dz-message">Upload dokumen rekomendasi delegasi</h5>
+                                                                            </div>
+                                                                        }
+                                                                        </div>
+                                                                    </div>
+                                                                </div>
+                                                                <div className="d-flex align-items-center">
+                                                                    <small className="ml-auto">
+                                                                        <button
+                                                                            type="button"
+                                                                            className="btn btn-link"
+                                                                            onClick={(e) => {
+                                                                                this.clearFiles(e);
+                                                                                form.setFieldValue(field.name, []);
+                                                                            }}
+                                                                        >
+                                                                            Reset dokumen
+                                                                        </button>
+                                                                    </small>
+                                                                </div>
+                                                            </div>
+                                                        );
+                                                    }}
+                                                </DropzoneWrapper>
+                                            )}
+                                        </Field>
+                                    </div>
+                                </FormGroup>
+                                <FormGroup row>
+                                    <div className="col-xl-10">
+                                        <Button color className="color-3e3a8e btn-login" type="submit">
+                                            <span className="font-color-white">Kirim</span>
+                                        </Button>
+                                    </div>
+                                </FormGroup>
+                            </Form>
+                        )}
+                    </Formik>
+                </CardBody>
+            </Card>
+        );
+    }
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(InputTanggal);

+ 89 - 0
components/TurunSanksi/TableLaporan.js

@@ -0,0 +1,89 @@
+import Datatable from "@/components/Tables/Datatable";
+import { Button } from "reactstrap";
+import Link from "next/link";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+
+function TableLaporan({ listData, to, linkName, status = false, noBy = false }) {
+	return (
+		<div className="card b ">
+			<div className="card-body card-over">
+				{listData && (
+					<Datatable options={{ responsive: false, ordering: true }}>
+						<table className="table w-100" data-order='[[3, "desc"]]'>
+							<thead>
+								<tr>
+									<th>No.Laporan</th>
+									<th>Deskripsi Laporan</th>
+									{<th>TMT Berlaku</th>}
+									{/* {!noBy && <th>Dibuat Oleh</th>} */}
+									{/* <th>Created</th> */}
+									<th>Aksi</th>
+								</tr>
+							</thead>
+							<tbody>
+								{listData.map((data) => {
+									return (
+										<tr key={data._id}>
+											<td>
+												{/* <td>{data.no_laporan}</td> */}
+												<div className="media align-items-center">
+													<div className="media-body d-flex">
+														<div>
+															<h4>{data.laporan.no_laporan}</h4>
+															<p>{moment(data.createdAt).format("DD-MMMM-YYYY")}</p>
+														</div>
+													</div>
+												</div>
+											</td>
+
+											<td>
+												<div className="table-desc">
+													<div className="media align-items-center">
+														<div className="media-body d-flex">
+															<div>
+																<h4 className="m-0">{data.laporan.pt.nama.length > 64 ? data.laporan.pt.nama.substring(0, 64) + "..." : data.laporan.pt.nama}</h4>
+																<p className="w-105">{data.laporan.keterangan}</p>
+															</div>
+														</div>
+													</div>
+												</div>
+											</td>
+
+
+											<td>
+												{/* {data.sanksi.masa_berlaku?.to_date ? (<h4 className="m-0"> {moment(data.sanksi.masa_berlaku?.from_date).format("DD MMMM YYYY")} - {moment(data.sanksi.masa_berlaku?.to_date).format("DD MMMM YYYY")}</h4>) : (<h4 className="m-0">6 Bulan</h4>)} */}
+												<h4 className="w-105">Sanksi Administratif: {data.pelanggaran.map((e) => e.label_sanksi)}</h4>
+												<p className="w-105">{data.sanksi.keterangan}</p>
+											</td>
+											{!noBy && <td>{data.user.isPrivate ? "" : data.user.nama}</td>}
+											<td>
+												<div className="ml-auto">
+													<Link
+														href={{
+															pathname: to,
+															query: { id: data?._id },
+														}}
+													>
+														<Button className="btn-login" color>
+															<span className="font-color-white">
+																{linkName}
+															</span>
+														</Button>
+													</Link>
+												</div>
+											</td>
+										</tr>
+									);
+								})}
+							</tbody>
+						</table>
+					</Datatable>
+				)}
+			</div>
+		</div>
+	);
+}
+
+export default TableLaporan;

+ 60 - 0
components/TurunSanksi/TableRiwayat.js

@@ -0,0 +1,60 @@
+import Datatable from "@/components/Tables/Datatable";
+import moment from "moment";
+import 'moment/min/locales';
+moment.locale('id');
+
+function TableRiwayat({ data, perbaikan }) {
+	return (
+		// <Datatable options={{ responsive: true }}>
+		<div className="card-over">
+			<table className="table table-striped my-4 w-100">
+				<thead>
+					<tr>
+						<th>Tanggal</th>
+						<th>Keterangan</th>
+						<th>Nomor Surat Sanksi</th>
+						<th>Dokumen Surat Sanksi</th>
+						<th>Dokumen Perbaikan</th>
+					</tr>
+				</thead>
+				<tbody>{data.map((e) =>
+					<tr>
+						<td>{moment(e.createdAt).format("D MMMM YYYY")}</td>
+						<td>{e.keterangan}</td>
+						<td>{e.no_sanksi}</td>
+						<td>
+							{e.dokumen.map((e, index) => (
+								<>
+									<em key="index" className="fa-lg far fa-file-code"></em>
+									<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+										{e.judul}
+									</a>
+									<br />
+								</>
+							))}
+						</td>
+						{perbaikan.length
+							? perbaikan.map((value) => (
+								<tr>
+									<td>
+										{value.dokumen.map((e) => (
+											<>
+												<em className="fa-lg far fa-file-code"></em>
+												<a className="text-muted" href={e.path} target="_blank" download={e.judul}>
+													{e.judul}
+												</a>
+											</>
+										))}
+									</td>
+								</tr>
+							))
+							: ""}
+					</tr>)}
+				</tbody>
+			</table>
+		</div>
+		// </Datatable>
+	);
+}
+
+export default TableRiwayat;

+ 1 - 1
pages/app/index.js

@@ -112,7 +112,7 @@ class App extends Component {
               </Col>
             </Row>
           </Jumbotron>
-          <span>Version 1.99 ~ 1.83</span>
+          <span>Version 2.1 ~ 1.88</span>
         </ContentWrapper>
       </div>
     );

+ 89 - 0
pages/app/naik-sanksi/detail.js

@@ -0,0 +1,89 @@
+import React, { Component } from "react";
+import { Row, Col, Card, CardBody, FormGroup, Input, Button, Modal, ModalHeader, ModalBody, ModalFooter, CardHeader, CardTitle } from "reactstrap";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import DetailSanksi from "@/components/PerpanjanganSanksi/DetailSanksi";
+import Link from "next/link";
+import DetailPT from "@/components/Main/DetailPT";
+import { getOneSanksi, addRekomendasiDelegasi } from "@/actions/sanksi";
+import Loader from "@/components/Common/Loader";
+import { connect } from "react-redux";
+import TableRiwayat from "@/components/NaikSanksi/TableRiwayat"
+import InputTanggal from "../../../components/NaikSanksi/InputTanggal";
+import { getPelanggaran, getPelanggaranSanksi } from "@/actions/pelanggaran";
+
+
+
+class Detail extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+			files: [],
+			pt: {},
+			data: {},
+			listSanksi: {},
+		};
+	}
+
+	static getInitialProps = async ({ query }) => {
+		return { query };
+	};
+
+	componentDidMount = async () => {
+		const { query, token } = this.props;
+		const idSanksi = query.id;
+		const sanksi = await getOneSanksi(token, idSanksi, { all: true });
+		const { data: listSanksi } = await getPelanggaranSanksi(token)
+		const pt = sanksi.data.laporan.pt;
+		this.setState({ sanksi, pt, listSanksi });
+
+	};
+
+
+	render() {
+		const { files, sanksi, pt, listSanksi } = this.state;
+		const { query, token } = this.props;
+		return (
+			<ContentWrapper unwrap>
+				{/* <Header /> */}
+				<div className="p-3">
+					<div className="content-heading">
+						<span className="font-color-white">
+							Detail Perubahan Naik Sanksi
+						</span>
+						<div className="ml-auto">
+							<Link href="/app/naik-sanksi">
+								<Button className="color-3e3a8e" color>
+									<span className="font-color-white">
+										&lt; Kembali
+									</span>
+								</Button>
+							</Link>
+						</div>
+					</div>
+					{sanksi.data && (
+						<Row>
+
+							<Col xl="9">
+								<DetailSanksi data={sanksi.data} />
+								<InputTanggal query={query} token={token} data={sanksi.data} listSanksi={this.state.listSanksi} />
+								<Card className="card-default">
+									<CardHeader>
+										<CardTitle>Riwayat</CardTitle>
+									</CardHeader>
+									<CardBody>
+										<TableRiwayat data={sanksi.data.riwayat_sanksi} perbaikan={sanksi.data.perbaikan} />
+									</CardBody>
+								</Card>
+							</Col>
+							<Col lg="3">{pt ? <DetailPT data={pt} /> : <Loader />}</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(Detail);

+ 45 - 0
pages/app/naik-sanksi/index.js

@@ -0,0 +1,45 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getPelaporan } from "@/actions/pelaporan";
+import { getSanksi } from "@/actions/sanksi";
+import TableLaporan from "@/components/NaikSanksi/TableLaporan";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class NaikSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			pelaporan: {},
+			graph: {},
+			tahun: new Date().getFullYear(),
+			sanksi: {}
+		};
+	}
+
+	componentDidMount = async () => {
+		const { token } = this.props;
+		const pelaporan = await getPelaporan(token, { sanksi: true });
+		const sanksi = await getSanksi(token, { naikSanksi: true, perbaikan: true, cabutSanksi: true })
+		this.setState({ pelaporan, sanksi });
+	};
+
+	render() {
+		const { pelaporan, sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">
+					<span className="font-color-white">Perubahan Naik Sanksi</span>
+				</div>
+				<Row>
+					{/* <Col lg="12">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col> */}
+					<Col lg="12">{sanksi?.data ? <TableLaporan status noBy listData={sanksi.data} to="/app/naik-sanksi/detail" linkName="Detail" /> : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(NaikSanksi);

+ 21 - 3
pages/app/pelaporan/index.js

@@ -58,14 +58,32 @@ class Pelaporan extends Component {
 	shouldComponentUpdate = (prevProps, prevState) => {
 		if (prevState.graph !== this.state.graph) return true;
 	};
-
-	excel = () => {
+	excelMenu = () => {
 		const url = getExcel(this.props.token, "Laporan", {
 			tahun: this.state.tahun,
 			pelaporan: true,
 		});
 		Router.push(url);
 	};
+	excelSemua = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			pelaporan: true,
+			penjadwalan: true,
+			pemeriksaan: true,
+			sanksi: true,
+
+		});
+		Router.push(url);
+	};
+
+	// excel = () => {
+	// 	const url = getExcel(this.props.token, "Laporan", {
+	// 		tahun: this.state.tahun,
+	// 		pelaporan: true,
+	// 	});
+	// 	Router.push(url);
+	// };
 
 	render() {
 		const { pelaporan, graph, newLaporan } = this.state;
@@ -82,7 +100,7 @@ class Pelaporan extends Component {
 					</Link>
 				</div>
 				<Row>
-					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} newLaporan={newLaporan} excel={this.excel} /> : <Loader />}</Col>
+					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} newLaporan={newLaporan} excelMenu={this.excelMenu} excelSemua={this.excelSemua} /> : <Loader />}</Col>
 					<Col lg="8">{pelaporan?.data ? <TableLaporan listData={pelaporan.data} to="/app/pelaporan/detail" linkName="Detail" /> : <Loader />}</Col>
 				</Row>
 			</ContentWrapper>

+ 18 - 1
pages/app/pemeriksaan/index.js

@@ -43,7 +43,24 @@ class Pemeriksaan extends Component {
 	shouldComponentUpdate = (prevProps, prevState) => {
 		if (prevState.graph !== this.state.graph) return true;
 	};
+	excelMenu = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			pemeriksaan: true,
+		});
+		Router.push(url);
+	};
+	excelSemua = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			pelaporan: true,
+			penjadwalan: true,
+			pemeriksaan: true,
+			sanksi: true,
 
+		});
+		Router.push(url);
+	};
 	excel = () => {
 		const url = getExcel(this.props.token, "Laporan", { tahun: this.state.tahun });
 		Router.push(url);
@@ -74,7 +91,7 @@ class Pemeriksaan extends Component {
 					</div>
 				</div>
 				<Row>
-					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col>
+					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} excelMenu={this.excelMenu} excelSemua={this.excelSemua} /> : <Loader />}</Col>
 					<Col lg="8">{pelaporan?.data ? <TableLaporan status noBy listData={pelaporan.data} to="/app/pemeriksaan/new" linkName="Evaluasi" /> : <Loader />}</Col>
 				</Row>
 			</ContentWrapper>

+ 19 - 1
pages/app/penjadwalan/index.js

@@ -43,6 +43,24 @@ class Penjadwalan extends Component {
 	shouldComponentUpdate = (prevProps, prevState) => {
 		if (prevState.graph !== this.state.graph) return true;
 	};
+	excelMenu = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			penjadwalan: true,
+		});
+		Router.push(url);
+	};
+	excelSemua = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			pelaporan: true,
+			penjadwalan: true,
+			pemeriksaan: true,
+			sanksi: true,
+
+		});
+		Router.push(url);
+	};
 
 	excel = () => {
 		const url = getExcel(this.props.token, "Laporan", { tahun: this.state.tahun });
@@ -74,7 +92,7 @@ class Penjadwalan extends Component {
 					</div>
 				</div>
 				<Row>
-					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col>
+					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} excelMenu={this.excelMenu} excelSemua={this.excelSemua} /> : <Loader />}</Col>
 					<Col lg="8">{pelaporan?.data ? <TableLaporan listData={pelaporan.data} to="/app/penjadwalan/todo" linkName="Atur Jadwal" /> : <Loader />}</Col>
 				</Row>
 			</ContentWrapper>

+ 1 - 1
pages/app/perpanjangan-sanksi/detail.js

@@ -47,7 +47,7 @@ class Detail extends Component {
 							Perpanjangan Sanksi
 						</span>
 						<div className="ml-auto">
-							<Link href="/app/sanksi">
+							<Link href="/app/perpanjangan-sanksi">
 								<Button className="color-3e3a8e" color>
 									<span className="font-color-white">
 										&lt; Kembali

+ 1 - 2
pages/app/rekomendasi-delegasi/detail.js

@@ -33,7 +33,6 @@ class Detail extends Component {
 		const pt = sanksi.data.laporan.pt;
 		const perbaikan = sanksi.data.perbaikan.map((e) => e.dokumen)
 		this.setState({ sanksi, pt, perbaikan });
-		console.log(perbaikan)
 
 	};
 
@@ -50,7 +49,7 @@ class Detail extends Component {
 							Rekomendasi Delegasi
 						</span>
 						<div className="ml-auto">
-							<Link href="/app/sanksi">
+							<Link href="/app/rekomendasi-delegasi">
 								<Button className="color-3e3a8e" color>
 									<span className="font-color-white">
 										&lt; Kembali

+ 19 - 1
pages/app/sanksi/index.js

@@ -43,6 +43,24 @@ class Sanksi extends Component {
 	shouldComponentUpdate = (prevProps, prevState) => {
 		if (prevState.graph !== this.state.graph) return true;
 	};
+	excelMenu = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			sanksi: true,
+		});
+		Router.push(url);
+	};
+	excelSemua = () => {
+		const url = getExcel(this.props.token, "Laporan", {
+			tahun: this.state.tahun,
+			pelaporan: true,
+			penjadwalan: true,
+			pemeriksaan: true,
+			sanksi: true,
+
+		});
+		Router.push(url);
+	};
 
 	excel = () => {
 		const url = getExcel(this.props.token, "Laporan", { tahun: this.state.tahun });
@@ -66,7 +84,7 @@ class Sanksi extends Component {
 					</div>
 				</div>
 				<Row>
-					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col>
+					<Col lg="4">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} excelMenu={this.excelMenu} excelSemua={this.excelSemua} /> : <Loader />}</Col>
 					<Col lg="8">{pelaporan.data ? <TableLaporan listData={pelaporan.data} /> : <Loader />}</Col>
 				</Row>
 			</ContentWrapper>

+ 25 - 5
pages/app/tuntas/index.js

@@ -2,7 +2,7 @@ import React, { Component } from "react";
 import ContentWrapper from "@/components/Layout/ContentWrapper";
 import { Row, Col } from "reactstrap";
 import { getPelaporan } from "@/actions/pelaporan";
-import { getGraph, getExcel,getlaporanselesai } from "@/actions/graph";
+import { getGraph, getExcel, getlaporanselesai } from "@/actions/graph";
 import CaseProgress from "@/components/PelaporanTuntas/CaseProgress";
 import TableLaporan from "@/components/PelaporanTuntas/TableLaporan";
 import { connect } from "react-redux";
@@ -25,9 +25,11 @@ class PelaporanTuntas extends Component {
     componentDidMount = async () => {
         const { token } = this.props;
         let laporanSelesai = await getlaporanselesai(token);
-        laporanSelesai = {...laporanSelesai, data: {
-            ...laporanSelesai.data, laporan: [...laporanSelesai.data.laporan, ...laporanSelesai.data.sanksi], sanksi: null
-        }}
+        laporanSelesai = {
+            ...laporanSelesai, data: {
+                ...laporanSelesai.data, laporan: [...laporanSelesai.data.laporan, ...laporanSelesai.data.sanksi], sanksi: null
+            }
+        }
         const pelaporan = await getPelaporan(token, { jadwal: true, aktif: false });
         const graph = await getGraph(this.props.token, { evaluasi: true, listJadwal: true, aktif: false });
         this.setState({ pelaporan, graph, laporanSelesai });
@@ -53,6 +55,24 @@ class PelaporanTuntas extends Component {
         const url = getExcel(this.props.token, "Laporan", { tahun: this.state.tahun });
         Router.push(url);
     };
+    excelMenu = () => {
+        const url = getExcel(this.props.token, "Laporan", {
+            tahun: this.state.tahun,
+            pelaporan: true,
+        });
+        Router.push(url);
+    };
+    excelSemua = () => {
+        const url = getExcel(this.props.token, "Laporan", {
+            tahun: this.state.tahun,
+            pelaporan: true,
+            penjadwalan: true,
+            pemeriksaan: true,
+            sanksi: true,
+
+        });
+        Router.push(url);
+    };
 
     render() {
         const { pelaporan, graph, laporanSelesai } = this.state;
@@ -64,7 +84,7 @@ class PelaporanTuntas extends Component {
                     </span>
                 </div>
                 <Row>
-                    <Col lg="4">{laporanSelesai?.data ? <CaseProgress data={laporanSelesai.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col>
+                    <Col lg="4">{laporanSelesai?.data ? <CaseProgress data={laporanSelesai.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} excelMenu={this.excelMenu} excelSemua={this.excelSemua} /> : <Loader />}</Col>
                     <Col lg="8">{laporanSelesai?.data?.laporan ? <TableLaporan status noBy listData={laporanSelesai.data.laporan} to="/app/tuntas/detail" linkName="Detail" /> : <Loader />}</Col>
                 </Row>
             </ContentWrapper>

+ 89 - 0
pages/app/turun-sanksi/detail.js

@@ -0,0 +1,89 @@
+import React, { Component } from "react";
+import { Row, Col, Card, CardBody, FormGroup, Input, Button, Modal, ModalHeader, ModalBody, ModalFooter, CardHeader, CardTitle } from "reactstrap";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import DetailSanksi from "@/components/PerpanjanganSanksi/DetailSanksi";
+import Link from "next/link";
+import DetailPT from "@/components/Main/DetailPT";
+import { getOneSanksi, addRekomendasiDelegasi } from "@/actions/sanksi";
+import Loader from "@/components/Common/Loader";
+import { connect } from "react-redux";
+import TableRiwayat from "@/components/TurunSanksi/TableRiwayat"
+import InputTanggal from "../../../components/TurunSanksi/InputTanggal";
+import { getPelanggaran, getPelanggaranSanksi } from "@/actions/pelanggaran";
+
+
+
+class Detail extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+			files: [],
+			pt: {},
+			data: {},
+			listSanksi: {},
+		};
+	}
+
+	static getInitialProps = async ({ query }) => {
+		return { query };
+	};
+
+	componentDidMount = async () => {
+		const { query, token } = this.props;
+		const idSanksi = query.id;
+		const sanksi = await getOneSanksi(token, idSanksi, { all: true });
+		const { data: listSanksi } = await getPelanggaranSanksi(token, { down: true })
+		const pt = sanksi.data.laporan.pt;
+		this.setState({ sanksi, pt, listSanksi });
+
+	};
+
+
+	render() {
+		const { files, sanksi, pt, listSanksi } = this.state;
+		const { query, token } = this.props;
+		return (
+			<ContentWrapper unwrap>
+				{/* <Header /> */}
+				<div className="p-3">
+					<div className="content-heading">
+						<span className="font-color-white">
+							Detail Perubahan Turun Sanksi
+						</span>
+						<div className="ml-auto">
+							<Link href="/app/turun-sanksi">
+								<Button className="color-3e3a8e" color>
+									<span className="font-color-white">
+										&lt; Kembali
+									</span>
+								</Button>
+							</Link>
+						</div>
+					</div>
+					{sanksi.data && (
+						<Row>
+
+							<Col xl="9">
+								<DetailSanksi data={sanksi.data} />
+								<InputTanggal query={query} token={token} data={sanksi.data} listSanksi={this.state.listSanksi} />
+								<Card className="card-default">
+									<CardHeader>
+										<CardTitle>Riwayat</CardTitle>
+									</CardHeader>
+									<CardBody>
+										<TableRiwayat data={sanksi.data.riwayat_sanksi} perbaikan={sanksi.data.perbaikan} />
+									</CardBody>
+								</Card>
+							</Col>
+							<Col lg="3">{pt ? <DetailPT data={pt} /> : <Loader />}</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(Detail);

+ 45 - 0
pages/app/turun-sanksi/index.js

@@ -0,0 +1,45 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getPelaporan } from "@/actions/pelaporan";
+import { getSanksi } from "@/actions/sanksi";
+import TableLaporan from "@/components/TurunSanksi/TableLaporan";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class NaikSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			pelaporan: {},
+			graph: {},
+			tahun: new Date().getFullYear(),
+			sanksi: {}
+		};
+	}
+
+	componentDidMount = async () => {
+		const { token } = this.props;
+		const pelaporan = await getPelaporan(token, { sanksi: true });
+		const sanksi = await getSanksi(token, { turunSanksi: true, perbaikan: true })
+		this.setState({ pelaporan, sanksi });
+	};
+
+	render() {
+		const { pelaporan, sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">
+					<span className="font-color-white">Perubahan Turun Sanksi</span>
+				</div>
+				<Row>
+					{/* <Col lg="12">{graph?.data ? <CaseProgress data={graph.data} nextButton={this.nextButton} prevButton={this.prevButton} tahun={this.state.tahun} excel={this.excel} /> : <Loader />}</Col> */}
+					<Col lg="12">{sanksi?.data ? <TableLaporan status noBy listData={sanksi.data} to="/app/turun-sanksi/detail" linkName="Detail" /> : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, token: state.token });
+export default connect(mapStateToProps)(NaikSanksi);

+ 62 - 0
pages/app/workflow/index.js

@@ -0,0 +1,62 @@
+import React from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Jumbotron, Col, Button } from "reactstrap";
+import Link from "next/link";
+
+class Bantuan extends React.Component {
+    render() {
+        return (
+            <div>
+                <ContentWrapper>
+                    <div className="content-heading">
+                        <span className="font-color-white">Workflow Aplikasi SIDALI</span>
+                        <div className="ml-auto"></div>
+                    </div>
+                    <Jumbotron>
+                        <Row className="home-1-1">
+                            <Col lg={5} className="d-flex flex-column justify-content-center align-items-start">
+                                <h1 className="display-5 home-2 txt-size">Workflow Aplikasi SIDALI</h1>
+                                {/* <h1 className="display-5 txt-size">Penggunaan Aplikasi SIDALI</h1> */}
+                                <hr className="my-4" />
+                                <p className="txt-size">Workflow ini dapat membantu Anda dalam memahami alur
+                                    Aplikasi SIDALI. Pelajari lebih lanjut Aplikasi SIDALI dengan
+                                    mengunduh workflow dibawah ini.</p>
+                                <p className="lead">
+                                    {/* <Link href="/laporan/new">
+										<button className="btn btn-info btn-lg"><img className="icon-buatlaporan" src="/static/img/icon-buat-laporan.png" alt="icon"/>Buat Laporan</button>
+									</Link> */}
+                                    <a href="/static/img/workflow.pdf" download="Workflow Aplikasi SIDALI">
+                                        <span className="btn-radius">
+                                            <Button color="" className="btn-labeled">
+                                                <h4 className="p-1 font-color-white mt-2">Download</h4>
+                                            </Button>
+                                        </span>
+                                    </a>
+                                    <a target="_blank" rel="noopener noreferrer" href="/static/img/workflow.pdf">
+                                        <span className="btn-radius">
+                                            <Button color className="btn-labeled-3">
+                                                <h4 className="p-0 mt-2">Buka Workflow Aplikasi SIDALI</h4>
+                                            </Button>
+                                        </span>
+                                    </a>
+                                    <div style={{
+                                        marginTop: "20px",
+                                        fontSize: "15px"
+                                    }}>Workflow versi 1.0</div>
+                                </p>
+
+                            </Col>
+                            <Col lg={5}>
+                                <img className="responsive-1" src="/static/img/workflow_image.png" alt="gambar" />
+                            </Col>
+                        </Row>
+                    </Jumbotron>
+                </ContentWrapper>
+
+            </div >
+
+        )
+    }
+}
+
+export default Bantuan;

BIN
public/static/img/workflow.pdf


BIN
public/static/img/workflow_image.png


+ 72 - 46
styles/bootstrap/_images.scss

@@ -41,37 +41,40 @@
   color: $figure-caption-color;
 }
 
-.icon-pemantauan{
+.icon-pemantauan {
   width: 35px;
   height: 35px;
   margin-right: -20px;
 }
 
-.icon-buatlaporan{
+.icon-buatlaporan {
   width: 35px;
   height: 35px;
   margin-right: -20px;
 }
 
-.img-text-vputih{
+.img-text-vputih {
   width: 55px;
   height: 20px;
   margin-left: 10px;
 }
-.icon-triangle{
+
+.icon-triangle {
   width: 20px;
   margin-right: 15px;
   margin-left: 15px;
   border-radius: 5px;
 }
-.identitas-pelapor{
+
+.identitas-pelapor {
   width: 830px;
   height: 50px;
 }
+
 .icon-pemantauan {
   width: 30px;
   height: 30px;
- 
+
   // margin-right: -20px; 
 }
 
@@ -84,68 +87,91 @@
 .img-text-vputih {
   width: 55px;
   height: 20px;
-  margin-left: 10px; }
+  margin-left: 10px;
+}
 
 .icon-triangle {
   width: 20px;
   margin-right: 10px;
-  margin-left: 15px; }
+  margin-left: 15px;
+}
 
 .identitas-pelapor {
   width: 830px;
-  height: 50px; }
+  height: 50px;
+}
 
-  // .img-fluid {
-  //   position: relative;
-  //   max-width: 100%;
-  //   height: auto;
-  //   width: 72px;
-  //   height: 37px; }
-  .ditbaga-logo{
-    margin-top: 55%;
+// .img-fluid {
+//   position: relative;
+//   max-width: 100%;
+//   height: auto;
+//   width: 72px;
+//   height: 37px; }
+.ditbaga-logo {
+  margin-top: 55%;
 
-  }
+}
 
-  .logo-nav{
-    width: 60%;
-  }
-  .img-login-1{
-    width: 97%;
-    margin-left: auto;
-    margin-right: auto;
-  }
-  .icon-next{
-    margin-right: 15px;
-    margin-top: 5px;
-  }
-  .float-rigt{
-    float: right;
-  }
-  .float-left{
-    float: left;
-  }
-  .icon-eksport{
-    margin-top: 5px;
-  }
+.logo-nav {
+  width: 60%;
+}
 
-  .width-133{
-    width: 133px;
-    height: auto;
-  }
-.width-50{
+.img-login-1 {
+  width: 97%;
+  margin-left: auto;
+  margin-right: auto;
+}
+
+.icon-next {
+  margin-right: 15px;
+  margin-top: 5px;
+}
+
+.float-rigt {
+  float: right;
+}
+
+.float-left {
+  float: left;
+}
+
+.icon-eksport {
+  margin-top: 5px;
+}
+
+.width-133 {
+  width: 133px;
+  height: auto;
+}
+
+.width-50 {
   width: 60px;
 }
+
 // .responsive-1{
 //   min-height: 500px;
 //   width: 100%;
 // }
 @media screen and (max-width: 1320px) {
   .responsive-1 {
-      width: 170%
+    width: 170%
   }
+
   @media screen and (max-width: 991px) {
     .responsive-1 {
-        width: 100%
+      width: 100%
+    }
+  }
+}
+
+@media screen and (max-width: 1320px) {
+  .responsive-2 {
+    width: 170%
+  }
+
+  @media screen and (max-width: 991px) {
+    .responsive-2 {
+      width: 100%
     }
   }
 }