yazid138 3 年之前
父節點
當前提交
26548e7dd9

+ 4 - 1
actions/pelaporan.js

@@ -5,7 +5,7 @@ export const getPelaporan = async (token, query = {}) => {
 	try {
 		let url = "/laporan";
 		if (query != null) {
-			const { jadwal, evaluasi } = query;
+			const { jadwal, evaluasi, pt_id } = query;
 			url += "?";
 			const parseURL = [];
 			if (jadwal) {
@@ -13,6 +13,9 @@ export const getPelaporan = async (token, query = {}) => {
 			} else if (evaluasi) {
 				parseURL.push(`evaluasi=true`);
 			}
+			if (pt_id) {
+				parseURL.push(`pt_id=${pt_id}`);
+			}
 
 			url += parseURL.join("&");
 		}

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

@@ -178,7 +178,7 @@ class Calendar extends Component {
 		return (
 			<ContentWrapper>
 				<div className="content-heading">
-					<div>Jadwal Pemeriksaan</div>
+					<div>Membuat Jadwal Pemeriksaan</div>
 					<div className="ml-auto">
 						<Link href="/app/penjadwalan">
 							<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>

+ 10 - 8
components/Main/Login.js

@@ -12,7 +12,7 @@ class Login extends Component {
 		super(props);
 		this.state = {
 			/* Group each form state in an object.
-           Property name MUST match the form name */
+		   Property name MUST match the form name */
 			error: null,
 			formLogin: {
 				username: "",
@@ -99,14 +99,14 @@ class Login extends Component {
 					<form onSubmit={this.onSubmit} method="post" name="formLogin">
 						<div className="form-group">
 							<label className="col-form-label">
-								Username<span className="text-warning">*</span>
+								Username <span className="star-color">*</span>
 							</label>
 							<Input type="text" name="username" invalid={this.hasError("formLogin", "username", "required")} onChange={this.validateOnChange} data-validate='["required"]' value={this.state.formLogin.username} />
 							{this.hasError("formLogin", "username", "required") && <span className="invalid-feedback">Field is required</span>}
 						</div>
 						<div className="form-group">
 							<label className="col-form-label">
-								Password<span className="text-warning">*</span>
+								Password <span className="star-color">*</span>
 							</label>
 							<Input
 								type="password"
@@ -121,11 +121,13 @@ class Login extends Component {
 						</div>
 						{/* <div className="required">* Required fields</div>
 						<span>Login Menggunakan Akun PDDIKTI</span> */}
-						<Button color="info" type="submit" block className=" mt-3 btn-login">
-							<text className="text-login">
-								<b>Login</b>
-							</text>
-						</Button>
+						<div className="btn-radius">
+							<Button color="info" type="submit" block className=" mt-3 btn-login">
+								<text className="text-login">
+									<b>Login</b>
+								</text>
+							</Button>
+						</div>
 					</form>
 				</CardBody>
 			</Card>

+ 6 - 5
components/Pelaporan/InputData.js

@@ -51,10 +51,10 @@ const checkIfFilesAreCorrectType = (files) => {
 
 const selectInstanceId = 1;
 const laporanSchema = Yup.object().shape({
-	no_laporan: Yup.string().required("Harap Diisi"),
-	keterangan: Yup.string().min(3).max(200).required("Harap Diisi"),
-	pelanggaran: Yup.array().min(1).required("Harap Diisi"),
-	dokumen: Yup.array().notRequired().test("filesize", "Maksimal ukuran dokumen 15mb", checkIfFilesAreTooBig),
+	no_laporan: Yup.string().required(""),
+	keterangan: Yup.string().min(3, "Minimal 3 Huruf").max(200).required(""),
+	pelanggaran: Yup.array().min(1, " ").required(),
+	dokumen: Yup.array().min(1, " ").required().test("filesize", "Maksimal ukuran dokumen 15mb", checkIfFilesAreTooBig),
 });
 export class InputData extends Component {
 	constructor(props) {
@@ -256,6 +256,7 @@ export class InputData extends Component {
 									)}
 								</Field>
 								<ErrorMessage name="dokumen" component="div" className="form-text text-danger" />
+								<p className="mrgn-top-5">Ukuran setiap dokumen maksimal 15mb</p>
 							</div>
 						</FormGroup>
 
@@ -274,4 +275,4 @@ export class InputData extends Component {
 }
 
 const mapStateToProps = (state) => ({ user: state.user, token: state.token });
-export default connect(mapStateToProps)(InputData);
+export default connect(mapStateToProps)(InputData);

+ 17 - 13
pages/app/index.js

@@ -40,7 +40,7 @@ class App extends Component {
 			<div>
 				<Navbar className="navbar-color" expand="md" dark>
 					<NavbarBrand href="/">
-						<img className="img-fluid logo-nav" src="/static/img/Logo-vputih.png" alt="App Logo" />
+						<img className="img-fluid" src="/static/img/Logo-vputih.png" alt="App Logo" />
 						<img className="img-text-vputih" src="/static/img/Logo-text-vputih.png" alt="App Logo" />
 					</NavbarBrand>
 					<NavbarToggler onClick={this.toggleCollapse} />
@@ -69,20 +69,24 @@ class App extends Component {
 										<button className="btn btn-info btn-lg"><img className="icon-buatlaporan" src="/static/img/icon-buat-laporan.png" alt="icon"/>Buat Laporan</button>
 									</Link> */}
 									<Link href="/laporan/new">
-										<Button color="info" className="btn-labeled">
-											<span className="btn-label">
-												<img className="icon-buatlaporan" src="/static/img/icon-buat-laporan.png" alt="icon" />
-											</span>
-											<text className="text-button-home-1">Buat Laporan</text>
-										</Button>
+										<span className="btn-radius">
+											<Button color="info" className="btn-labeled">
+												<span className="btn-label">
+													<img className="icon-buatlaporan" src="/static/img/icon-buat-laporan.png" alt="icon" />
+												</span>
+												<text className="text-button-home-1">Buat Laporan</text>
+											</Button>
+										</span>
 									</Link>
 									<Link href="/pemantauan">
-										<Button color="info" className="btn-labeled-2">
-											<span className="btn-label">
-												<img className="icon-pemantauan" src="/static/img/icon-pemantauan.png" alt="icon" />
-											</span>
-											<text className="text-button-home-1">Pemantauan</text>
-										</Button>
+										<span className="btn-radius">
+											<Button color="info" className="btn-labeled-2">
+												<span className="btn-label">
+													<img className="icon-pemantauan" src="/static/img/icon-pemantauan.png" alt="icon" />
+												</span>
+												<text className="text-button-home-1">Pemantauan</text>
+											</Button>
+										</span>
 									</Link>
 								</p>
 								<div>

+ 5 - 6
pages/app/pelaporan/index.js

@@ -26,12 +26,11 @@ class Pelaporan extends Component {
 		return (
 			<ContentWrapper>
 				<div className="content-heading">
-					<div>Pelaporan</div>
-					<div className="ml-auto">
-						<Link href="/app/penjadwalan">
-							<button className="btn btn-sm btn-secondary text-sm">next &gt;</button>
-						</Link>
-					</div>
+					Pelaporan
+					<div className="ml-auto"></div>
+					<Link href="/app/penjadwalan">
+						<button className="btn btn-sm btn-secondary text-sm">next &gt;</button>
+					</Link>
 				</div>
 				<Row>
 					<Col lg="4">

+ 1 - 1
pages/app/pelaporan/new.js

@@ -50,7 +50,7 @@ class PelaporanNew extends Component {
 								<CardBody>
 									<Row>
 										<Col lg={12}>
-											<p className="lead bb">Informasi Laporan</p>
+											<p className="lead bb">Informasi Laporan<span className="font-20">(wajib diisi)</span></p>
 											<InputData query={this.props.query} />
 										</Col>
 									</Row>

+ 197 - 0
pages/app/pt/dokumen-perbaikan/detail.js

@@ -0,0 +1,197 @@
+import React, { Component } from "react";
+import Router from "next/router";
+import { getSanksi } from "@/actions/sanksi";
+import { addDocPerbaikan } from "@/actions/docPerbaikan";
+import Link from "next/link";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import Riwayat from "@/components/PT/DocPerbaikan/Riwayat";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col, Card, CardBody, FormGroup, Button, Input } from "reactstrap";
+import { connect } from "react-redux";
+import { notifDocPerbaikan } from "@/actions/notifikasi";
+import Loader from "@/components/Common/Loader";
+import { toast } from "react-toastify";
+
+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 DetailPerbaikanDoc extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			files: [],
+			sanksi: {},
+			keterangan: "",
+		};
+	}
+
+	static getInitialProps = ({ query }) => ({ query });
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		this.setState({ sanksi });
+	};
+
+	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: [],
+		});
+	};
+
+	handleKirim = async (e) => {
+		e.preventDefault();
+		const { keterangan, sanksi } = this.state;
+		const { noSanksi } = this.props.query;
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const formdata = new FormData();
+		formdata.append("description", keterangan);
+		if (this.state.files.length > 0) {
+			this.state.files.forEach((e) => {
+				formdata.append("files", e);
+			});
+			const id = toast.loading("Please wait...");
+			const added = await addDocPerbaikan({ noSanksi, ptId: org_id }, formdata);
+			if (added) {
+				await notifDocPerbaikan({ lembaga: sanksi.data[0].sanksi.user.lembaga, pt_name: user.peran[0].organisasi.nama, no_sanksi: sanksi.data[0].sanksi.no_sanksi });
+				toast.update(id, { render: "All is good", type: "success", isLoading: false, autoClose: true, closeButton: true });
+				Router.push({
+					pathname: "/app/pt/dokumen-perbaikan",
+				});
+			}
+		}
+	};
+
+	render() {
+		const { files, sanksi } = this.state;
+
+		const thumbs = files.map((file, index) => (
+			<Col md={3} key={index}>
+				<img className="img-fluid mb-2" src={file.preview} alt="Item" />
+			</Col>
+		));
+
+		return (
+			<ContentWrapper unwrap>
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Dokumen Perbaikan</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/dokumen-perbaikan">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												<p className="lead bb">Dokumen Perbaikan</p>
+												<form className="form-horizontal" method="get" action="/" onSubmit={this.onSubmit}>
+													<FormGroup>
+														<label className="row-form-label">Keterangan:</label>
+														<div className="row-md-10">
+															<Input type="textarea" value={this.state.keterangan} onChange={(e) => this.setState({ keterangan: e.target.value })} required />
+														</div>
+													</FormGroup>
+													<FormGroup>
+														<label className="row-form-label">Upload Dokumen:</label>
+														<div className="row-md-10">
+															<DropzoneWrapper className="" onDrop={this.onDrop}>
+																{({ getRootProps, getInputProps, isDragActive }) => {
+																	return (
+																		<div {...getRootProps()} className={"dropzone card p-3 " + (isDragActive ? "dropzone-drag-active" : "")}>
+																			<input {...getInputProps()} />
+																			<div className="dropzone-previews flex">
+																				{this.state.files.length > 0 ? <Row>{thumbs}</Row> : <div className="text-center dz-default dz-message">Drop files here to upload</div>}
+																			</div>
+																			<div className="d-flex align-items-center">
+																				<small className="ml-auto">
+																					<button type="button" className="btn btn-link" onClick={this.clearFiles}>
+																						Clear files
+																					</button>
+																				</small>
+																			</div>
+																		</div>
+																	);
+																}}
+															</DropzoneWrapper>
+														</div>
+													</FormGroup>
+													<FormGroup>
+														<div className="row-xl-10">
+															<Button color="primary" onClick={this.handleKirim} type="submit">
+																Kirim
+															</Button>
+														</div>
+													</FormGroup>
+												</form>
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+					{sanksi?.data && (
+						<Row>
+							<Col>
+								<Riwayat data={sanksi.data[0].sanksi.doc_perbaikan} />
+							</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(DetailPerbaikanDoc);

+ 38 - 0
pages/app/pt/dokumen-perbaikan/index.js

@@ -0,0 +1,38 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/TableSanksi";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class Pelaporan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Dokumen Perbaikan</div>
+				<Row>
+					<Col lg={12}>{sanksi.data && sanksi.data.length > 0 ? <TableSanksi listData={sanksi.data} to="/app/pt/dokumen-perbaikan/detail" linkName="Detail" /> : sanksi.data ? 'Tidak ada Sanksi' : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(Pelaporan);

+ 70 - 0
pages/app/pt/jawaban-banding/detail.js

@@ -0,0 +1,70 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { getSanksi } from "@/actions/sanksi";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import DetailJawaban from "@/components/PT/JawabanBanding/DetailJawaban";
+import Link from "next/link";
+import { Row, Col, Card, CardBody, Button } from "reactstrap";
+import { connect } from "react-redux";
+import { withRouter } from "next/router";
+import Loader from "@/components/Common/Loader";
+
+class JawabanBanding extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			modal: false,
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.router.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper unwrap>
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Jawaban Atas Permohonan Banding</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/jawaban-banding">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												<DetailJawaban data={sanksi.data[0]} />
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(withRouter(JawabanBanding));

+ 38 - 0
pages/app/pt/jawaban-banding/index.js

@@ -0,0 +1,38 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/JawabanBanding/TableSanksiJawaban";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class JawabanKeberatan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ banding: true, ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Jawaban Atas Permohonan Banding</div>
+				<Row>
+					<Col lg={12}>{sanksi.data && sanksi.data.length ? <TableSanksi listData={sanksi.data} to="/app/pt/jawaban-banding/detail" linkName="Detail" /> : sanksi.data ? '' : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(JawabanKeberatan);

+ 100 - 0
pages/app/pt/jawaban-keberatan/detail.js

@@ -0,0 +1,100 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { getSanksi } from "@/actions/sanksi";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import DetailJawaban from "@/components/PT/JawabanKeberatan/DetailJawaban";
+import ModalPermohonan from "@/components/PT/JawabanKeberatan/ModalPermohonan";
+import Riwayat from "@/components/PT/JawabanKeberatan/Riwayat";
+import Link from "next/link";
+import { Row, Col, Card, CardBody, Button } from "reactstrap";
+import { connect } from "react-redux";
+import { withRouter } from "next/router";
+import Loader from "@/components/Common/Loader";
+
+class JawabanKeberatan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			modal: false,
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.router.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		this.setState({ sanksi });
+	};
+
+	toggleModal = (value = true) => {
+		if (!value) {
+			this.setState({ modal: false });
+		} else {
+			this.setState({ modal: !this.state.modal });
+		}
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper unwrap>
+				{sanksi?.data && <ModalPermohonan toggleModal={this.toggleModal} modal={this.state.modal} query={this.props.router.query} data={sanksi.data[0]} />}
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Jawaban Atas Permohonan Keberatan</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/jawaban-keberatan">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												<DetailJawaban data={sanksi.data[0]} />
+												{sanksi.data[0].sanksi.keberatan.jawaban.status !== "Membatalkan Keputusan" &&
+													(new Date(sanksi.data[0].sanksi.close_banding).getTime() > Date.now() ? (
+														<>
+															<p>
+																Setelah membaca jawaban permohonan keberatan atas pengenaan sanksi, jika Perguruan Tinggi bermaksud mengajukan permohonan banding kepada atasan pemberi sanksi maka dapat
+																menekan tombol di bawah ini paling lambat {moment(sanksi.data[0].sanksi.close_banding).format("DD MMMM YYYY")}
+															</p>
+															<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.banding || false}>
+																Ajukan Banding
+															</Button>
+														</>
+													) : (
+														<p>Pengajuan ditutup</p>
+													))}
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+					{sanksi?.data && (
+						<Row>
+							<Col>{sanksi.data[0].sanksi.keberatan.jawaban.status !== "Membatalkan Keputusan" && <Riwayat data={sanksi.data[0]} />}</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(withRouter(JawabanKeberatan));

+ 38 - 0
pages/app/pt/jawaban-keberatan/index.js

@@ -0,0 +1,38 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/JawabanKeberatan/TableSanksiJawaban";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class JawabanKeberatan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ keberatan: true, ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Jawaban Atas Permohonan Keberatan</div>
+				<Row>
+					<Col lg={12}>{sanksi.data && sanksi.data.length ? <TableSanksi listData={sanksi.data} to="/app/pt/jawaban-keberatan/detail" linkName="Detail" /> : sanksi.data ? '' : <Loader />} </Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(JawabanKeberatan);

+ 122 - 0
pages/app/pt/jawaban-pencabutan-sanksi/detail.js

@@ -0,0 +1,122 @@
+import React, { Component } from "react";
+import Link from "next/link";
+import { getSanksi } from "@/actions/sanksi";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import Scrollable from "@/components/Common/Scrollable";
+import { Row, Col, Card, CardBody, FormGroup, Button } from "reactstrap";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+import { API_URL } from "@/env";
+class DetailJawabanPencabutanSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	static async getInitialProps({ query }) {
+		return { query };
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		console.log(sanksi);
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		const { jawaban } = (sanksi.data && sanksi.data[0].sanksi.cabut_sanksi) || {};
+		return (
+			<ContentWrapper unwrap>
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Jawaban Permohonan Pencabutan Sanksi</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/jawaban-pencabutan-sanksi">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												<p className="lead bb">Jawaban Permohonan Pencabutan Sanksi</p>
+												<form className="form-horizontal">
+													<FormGroup>
+														<label md="4">Jawaban:</label>
+														<div md="8">
+															<h3>{jawaban && jawaban.status}</h3>
+														</div>
+													</FormGroup>
+													<FormGroup>
+														<label md="4">Keterangan:</label>
+														<div md="8">
+															<p>{jawaban && jawaban.description}</p>
+														</div>
+													</FormGroup>
+													<FormGroup>
+														<label md="4">Dokumen Jawaban:</label>
+														<div md="8">
+															<Scrollable height="120px" className="list-group">
+																<table className="table table-bordered bg-transparent">
+																	<tbody>
+																		{jawaban &&
+																			jawaban.files.map((e) => (
+																				<tr>
+																					<td>
+																						<em className="fa-lg far fa-file-code"></em>
+																					</td>
+																					<td>
+																						<a className="text-muted" href={API_URL + e.path} target="_blank" download={e.name}>
+																							{e.name}
+																						</a>
+																					</td>
+																				</tr>
+																			))}
+																	</tbody>
+																</table>
+															</Scrollable>
+														</div>
+													</FormGroup>
+												</form>
+												{jawaban && jawaban.status === "Rekomendasi Perbaikan" && (
+													<Link
+														href={{
+															pathname: "/app/pt/dokumen-perbaikan/detail",
+															query: { noSanksi: sanksi.data[0].sanksi.no_sanksi },
+														}}
+													>
+														<Button color="primary">Perbaiki Dokumen</Button>
+													</Link>
+												)}
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(DetailJawabanPencabutanSanksi);

+ 38 - 0
pages/app/pt/jawaban-pencabutan-sanksi/index.js

@@ -0,0 +1,38 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/JawabanPencabutanSanksi/TableSanksiJawaban";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class JawabanCabutSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ cabutSanksi: true, ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Jawaban Permohonan Pencabutan Sanksi</div>
+				<Row>
+					<Col lg={12}>{sanksi.data && sanksi.data.length ? <TableSanksi listData={sanksi.data} to="/app/pt/jawaban-pencabutan-sanksi/detail" linkName="Detail" /> : sanksi.data ? '' : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(JawabanCabutSanksi);

+ 97 - 0
pages/app/pt/keberatan/detail.js

@@ -0,0 +1,97 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { getSanksi } from "@/actions/sanksi";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import Riwayat from "@/components/PT/Keberatan/Riwayat";
+import ModalPermohonan from "@/components/PT/Keberatan/ModalPermohonan";
+import Link from "next/link";
+import moment from "moment";
+import { Row, Col, Card, CardBody, Button } from "reactstrap";
+import { connect } from "react-redux";
+import { withRouter } from "next/router";
+import Loader from "@/components/Common/Loader";
+
+class Keberatan extends Component {
+	state = {
+		modal: false,
+		sanksi: {},
+	};
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.router.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		this.setState({ sanksi });
+	};
+
+	toggleModal = (value = true) => {
+		if (!value) {
+			this.setState({ modal: false });
+		} else {
+			this.setState({ modal: !this.state.modal });
+		}
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper unwrap>
+				{sanksi?.data && <ModalPermohonan toggleModal={this.toggleModal} modal={this.state.modal} query={this.props.router.query} data={sanksi.data[0]} />}
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Permohonan Keberatan</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/keberatan">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												{new Date(sanksi.data[0].sanksi.close_keberatan).getTime() > Date.now() ? (
+													<>
+														<p>
+															Setelah membaca surat keputusan sanksi tersebut, jika Perguruan Tinggi bermaksud mengajukan permohonan keberatan maka dapat menekan tombol di bawah ini paling lambat{" "}
+															{moment(sanksi.data[0].sanksi.close_keberatan).format("DD MMMM YYYY")}
+														</p>
+														<Button color="primary" onClick={this.toggleModal} disabled={sanksi.data[0].sanksi.keberatan || false}>
+															Ajukan Permohonan Keberatan
+														</Button>
+													</>
+												) : (
+													<p>Pengajuan ditutup</p>
+												)}
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+					{sanksi?.data && (
+						<Row>
+							<Col>
+								<Riwayat data={sanksi.data[0]} />
+							</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(withRouter(Keberatan));

+ 37 - 0
pages/app/pt/keberatan/index.js

@@ -0,0 +1,37 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/TableSanksi";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+class Keberatan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Permohonan Keberatan</div>
+				<Row>
+					<Col lg={12}>{sanksi.data?.length ? <TableSanksi listData={sanksi.data} to="/app/pt/keberatan/detail" linkName="Detail" /> : sanksi.data ? 'Tidak ada Sanksi' : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(Keberatan);

+ 51 - 0
pages/app/pt/pemantauan.js

@@ -0,0 +1,51 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import { getLog } from "@/actions/log";
+import { getPelaporan } from "@/actions/pelaporan";
+import { Row, Col } from "reactstrap";
+import Timeline from "@/components/PT/Timeline";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class Pemantauan extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			log: [],
+			pelaporan: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const log = await getLog({ ptId: user.peran[0].organisasi.id, isPT: true });
+		const pelaporan = await getPelaporan({ ptId: user.peran[0].organisasi.id });
+		this.setState({ log, pelaporan });
+	};
+
+	render() {
+		const { log, pelaporan } = this.state;
+		return (
+			<ContentWrapper unwrap>
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<Row>
+						{log && pelaporan.data ? (
+							<Col xl="9">
+								<Timeline data={log} dataPelaporan={pelaporan.data[0]} />
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(Pemantauan);

+ 186 - 0
pages/app/pt/pencabutan-sanksi/detail.js

@@ -0,0 +1,186 @@
+import React, { Component } from "react";
+import Router from "next/router";
+import Link from "next/link";
+import { getSanksi } from "@/actions/sanksi";
+import Header from "@/components/Main/Header";
+import DetailPT from "@/components/Main/DetailPT";
+import DetailSanksi from "@/components/Main/DetailSanksi";
+import Riwayat from "@/components/PT/CabutSanksi/Riwayat";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col, Card, CardBody, FormGroup, Button } from "reactstrap";
+import { addCabutSanksi } from "@/actions/cabutSanksi";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+import { toast } from "react-toastify";
+
+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 DetailPencabutanSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			files: [],
+		};
+	}
+
+	static async getInitialProps({ query }) {
+		return { query };
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const { noSanksi } = this.props.query;
+		const sanksi = await getSanksi({ noSanksi, ptId: user.peran[0].organisasi.id });
+		this.setState({ sanksi });
+	};
+
+	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: [],
+		});
+	};
+
+	handleKirim = async (e) => {
+		e.preventDefault();
+		const { noSanksi } = this.props.query;
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const formdata = new FormData();
+		if (this.state.files.length > 0) {
+			this.state.files.forEach((e) => {
+				formdata.append("files", e);
+			});
+			const id = toast.loading("Please wait...");
+			const added = await addCabutSanksi({ noSanksi, ptId: org_id }, formdata);
+			if (added) {
+				toast.update(id, { render: "All is good", type: "success", isLoading: false, autoClose: true, closeButton: true });
+				Router.push({
+					pathname: "/app/pt/pencabutan-sanksi",
+				});
+			}
+		}
+	};
+
+	render() {
+		const { files, sanksi } = this.state;
+
+		const thumbs = files.map((file, index) => (
+			<Col md={3} key={index}>
+				<img className="img-fluid mb-2" src={file.preview} alt="Item" />
+			</Col>
+		));
+		return (
+			<ContentWrapper unwrap>
+				<Header data={this.props.pt[0]} />
+				<div className="p-3">
+					<div className="content-heading">
+						<div>Permohonan Pencabutan Sanksi</div>
+						<div className="ml-auto">
+							<Link href="/app/pt/pencabutan-sanksi">
+								<button className="btn btn-sm btn-secondary text-sm">&lt; back</button>
+							</Link>
+						</div>
+					</div>
+					<Row>
+						{sanksi?.data ? (
+							<Col xl="9">
+								<Card className="card-default">
+									<CardBody>
+										<Row>
+											<Col lg={12}>
+												<DetailSanksi data={sanksi.data[0]} />
+												<p className="lead bb">Permohonan Pencabutan Sanksi</p>
+												<form className="form-horizontal" method="get" action="/" onSubmit={this.onSubmit}>
+													<FormGroup>
+														<label className="row-form-label">Upload Dokumen:</label>
+														<div className="row-md-10">
+															<DropzoneWrapper className="" onDrop={this.onDrop}>
+																{({ getRootProps, getInputProps, isDragActive }) => {
+																	return (
+																		<div {...getRootProps()} className={"dropzone card p-3 " + (isDragActive ? "dropzone-drag-active" : "")}>
+																			<input {...getInputProps()} />
+																			<div className="dropzone-previews flex">
+																				{this.state.files.length > 0 ? <Row>{thumbs}</Row> : <div className="text-center dz-default dz-message">Drop files here to upload</div>}
+																			</div>
+																			<div className="d-flex align-items-center">
+																				<small className="ml-auto">
+																					<button type="button" className="btn btn-link" onClick={this.clearFiles}>
+																						Clear files
+																					</button>
+																				</small>
+																			</div>
+																		</div>
+																	);
+																}}
+															</DropzoneWrapper>
+														</div>
+													</FormGroup>
+													<FormGroup>
+														<div className="row-xl-10">
+															<Button color="primary" onClick={this.handleKirim} disabled={sanksi.data[0].sanksi.cabut_sanksi || false} type="submit">
+																Kirim
+															</Button>
+														</div>
+													</FormGroup>
+												</form>
+											</Col>
+										</Row>
+									</CardBody>
+								</Card>
+							</Col>
+						) : (
+							<Loader />
+						)}
+						<Col xl="3">{this.props.pt && <DetailPT data={this.props.pt[0]} />}</Col>
+					</Row>
+					{sanksi?.data && (
+						<Row>
+							<Col>
+								<Riwayat data={sanksi.data[0]} />
+							</Col>
+						</Row>
+					)}
+				</div>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user, pt: state.pt });
+export default connect(mapStateToProps)(DetailPencabutanSanksi);

+ 38 - 0
pages/app/pt/pencabutan-sanksi/index.js

@@ -0,0 +1,38 @@
+import React, { Component } from "react";
+import ContentWrapper from "@/components/Layout/ContentWrapper";
+import { Row, Col } from "reactstrap";
+import { getSanksi } from "@/actions/sanksi";
+import TableSanksi from "@/components/PT/TableSanksi";
+import { connect } from "react-redux";
+import Loader from "@/components/Common/Loader";
+
+class PencabutanSanksi extends Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			sanksi: {},
+		};
+	}
+
+	componentDidMount = async () => {
+		const { user } = this.props;
+		const org_id = user.peran[0].organisasi.id;
+		const sanksi = await getSanksi({ ptId: org_id });
+		this.setState({ sanksi });
+	};
+
+	render() {
+		const { sanksi } = this.state;
+		return (
+			<ContentWrapper>
+				<div className="content-heading">Permohonan Pencabutan Sanksi</div>
+				<Row>
+					<Col lg={12}>{sanksi.data && sanksi.data.length ? <TableSanksi listData={sanksi.data} to="/app/pt/pencabutan-sanksi/detail" linkName="Detail" /> : sanksi.data ? 'Tidak ada Sanksi' : <Loader />}</Col>
+				</Row>
+			</ContentWrapper>
+		);
+	}
+}
+
+const mapStateToProps = (state) => ({ user: state.user });
+export default connect(mapStateToProps)(PencabutanSanksi);

+ 14 - 14
pages/laporan/new/index.js

@@ -43,17 +43,17 @@ const checkIfFilesAreCorrectType = (files) => {
 };
 
 const laporanSchema = Yup.object().shape({
-	no_laporan: Yup.string().required("Harap Diisi"),
-	no_hp: Yup.number().required("Harap Diisi"),
+	no_laporan: Yup.string().required(),
+	no_hp: Yup.number().required("Wajib Diisi"),
 	nama: Yup.string().notRequired(),
 	setuju: Yup.boolean().isTrue("Harap diceklis"),
 	alamat: Yup.string().min(3, "Minimal 3 huruf").max(200, "Maksimal 200 huruf").notRequired(),
-	keterangan: Yup.string().min(3, "Minimal 3 huruf").max(200, "Maksimal 200 huruf").required("Harap Diisi"),
+	keterangan: Yup.string().min(3, "Minimal 3 huruf").max(200, "Maksimal 200 huruf").required(""),
 	email: Yup.string().email().notRequired(),
-	pelanggaran_id: Yup.array().min(1, "Minimal terdapat 1 jenis pelanggaran").required("Harap Diisi"),
-	pt_id: Yup.string().required("Harap Diisi"),
+	pelanggaran_id: Yup.array().min(1, "Minimal terdapat 1 jenis pelanggaran").required(""),
+	pt_id: Yup.string().required(""),
 	foto: Yup.array().notRequired().test("filesize", "Maksimal ukuran foto 15mb", checkIfFilesAreTooBig).test("type", "harus jpeg/png", checkIfFilesAreCorrectType),
-	dokumen: Yup.array().min(1, "Minimal terdapat 1 dokumen").required().test("filesize", "Maksimal ukuran dokumen 15mb", checkIfFilesAreTooBig),
+	dokumen: Yup.array().min(1, " ").required().test("filesize", "Maksimal ukuran setiap dokumen 15mb", checkIfFilesAreTooBig),
 	is_private: Yup.boolean().notRequired(),
 });
 
@@ -276,7 +276,7 @@ class App extends Component {
 											</FormGroup>
 											<FormGroup row>
 												<label className="col-md-2 col-form-label">
-													Nomor Aktif<span className="text-warning">*</span>
+													Nomor Aktif<span className="star-color">*</span>
 												</label>
 												<div className="col-md-10">
 													<Field name="no_hp">{({ field, form }) => <Input type="tel" {...field} />}</Field>
@@ -314,7 +314,7 @@ class App extends Component {
 												</div>
 											</FormGroup>
 											<div class="header-1">
-												<h2 class="card-title-1">Detail Laporan</h2>
+												<h2 class="card-title-1">Detail Laporan<span className="font-20">(wajib diisi)</span></h2>
 											</div>
 											{/* <p className="lead bb">Detail Laporan</p> */}
 											<FormGroup row>
@@ -326,7 +326,7 @@ class App extends Component {
 											</FormGroup>
 											<FormGroup row>
 												<label className="col-md-2 col-form-label">
-													Perguruan Tinggi yang Dilaporkan<span className="text-warning">*</span>
+													Perguruan Tinggi yang Dilaporkan<span className="star-color"></span>
 												</label>
 												<div className="col-md-10">
 													<Field name="pt_id">
@@ -348,7 +348,7 @@ class App extends Component {
 											</FormGroup>
 											<FormGroup row>
 												<label className="col-md-2 col-form-label">
-													Jenis Pelanggaran<span className="text-warning">*</span>
+													Jenis Pelanggaran<span className="star-color"></span>
 												</label>
 												<div className="col-md-10">
 													<Field name="pelanggaran_id">
@@ -374,7 +374,7 @@ class App extends Component {
 											</FormGroup>
 											<FormGroup row>
 												<label className="col-md-2 col-form-label">
-													Keterangan Laporan<span className="text-warning">*</span>
+													Keterangan Laporan<span className="star-color"></span>
 												</label>
 												<div className="col-md-10">
 													<Field name="keterangan">{({ field }) => <Input type="textarea" {...field} />}</Field>
@@ -383,12 +383,12 @@ class App extends Component {
 											</FormGroup>
 											<FormGroup row>
 												<label className="col-md-2 col-form-label">
-													File Pendukung<span className="text-warning">*</span>
+													File Pendukung<span className="star-color">*</span>
 												</label>
 												<div className="col-md-10">
 													<Field name="dokumen">{({ field, form }) => <Input type="file" multiple onChange={(e) => form.setFieldValue(field.name, Array.from(e.currentTarget.files))} />}</Field>
-													<p>Ukuran maksimal tiap-tiap dokumen adalah 15mb</p>
 													<ErrorMessage name="dokumen" component="div" className="form-text text-danger" />
+													<p className="mrgn-top-5">Ukuran setiap dokumen maksimal 15mb</p>
 												</div>
 											</FormGroup>
 											<FormGroup row>
@@ -453,7 +453,7 @@ class App extends Component {
 						</form>
 					</Modal>
 				</ContentWrapper>
-			</div>
+			</div >
 		);
 	}
 }

+ 30 - 10
styles/bootstrap/_buttons.scss

@@ -136,36 +136,44 @@ input[type="button"] {
 		width: 100%;
 	}
 }
-
+.posisi-btn-1 .button-kirimlaporan{
+	border-radius: 5px;
+}
 .button-kirimlaporan {
 	// background: rgba(0, 0, 0, 0.05);
 	display: inline-block;
 	background-color: #6fb9de;
-	width: 175px;
-	height: 40px;
+	width: 150px;
+	height: 33px;
+	margin-bottom: -15px;
+	
 }
 .text-kirimlaporan {
 	font-weight: 500;
-	font-size: 20px;
+	font-size: 17px;
 	letter-spacing: 0.02em;
 	text-align: center;
 	padding-bottom: 5px;
 }
-.button-lihatpemantauan {
+.posisi-btn-1 .button-lihatpemantauan {
+	border-radius: 5px;
 	position: relative;
 	margin-left: auto;
 	// background: rgba(0, 0, 0, 0.05);
 	display: inline-block;
 	background-color: #6fb9de;
-	width: 200px;
-	height: 40px;
+	width: 160px;
+	height: 35px;
+	margin-bottom: -5px;
+	
 }
 .text-lihatpemantauan {
-	font-weight: 500;
-	font-size: 20px;
+	// font-weight: 500;
+	font-size: 16px;
 	letter-spacing: 0.02em;
 	text-align: center;
-	padding-bottom: 5px;
+	// padding-bottom: 5px;
+	margin: -5px;
 }
 .btn-labeled {
 	padding-top: 0;
@@ -174,6 +182,7 @@ input[type="button"] {
 	margin-top: 3%;
 	background: #6fb9de;
 	display: inline;
+	border-radius: 7px;
 }
 .btn-labeled-2 {
 	padding-top: 0;
@@ -215,3 +224,14 @@ input[type="button"] {
 	margin-top: 20px;
 	margin-bottom: 15px;
 }
+.btn-radius .btn-labeled-2{
+	border-radius: 7px;
+	display: inline;
+}
+.btn-radius .btn-labeled{
+	border-radius: 7px;
+	display: inline;
+}
+.btn-radius .btn-login{
+	border-radius: 7px;
+}

+ 7 - 0
styles/bootstrap/_type.scss

@@ -141,4 +141,11 @@ mark,
   padding: 0;
   font-size: 15px;
   border-radius: 10px;
+}
+.font-20{
+  font-size: 20px;
+  margin-left: 10px;
+}
+.mrgn-top-5{
+  margin-top: 5px;
 }