index.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882
  1. import React, { Component } from "react";
  2. import Router from "next/router";
  3. import BasePage from "@/components/Layout/BasePage";
  4. import { ptPublic } from "@/actions/PT";
  5. import { getPelanggaranPublic } from "@/actions/pelanggaran";
  6. import { createLaporanPublic } from "@/actions/pelaporan";
  7. import { notifLaporanBaru } from "@/actions/notifikasi";
  8. import Select from "react-select";
  9. import AsyncSelect from "react-select/async";
  10. import { CopyToClipboard } from "react-copy-to-clipboard";
  11. import {
  12. Row,
  13. Col,
  14. FormGroup,
  15. Input,
  16. Card,
  17. CardBody,
  18. Button,
  19. CustomInput,
  20. Navbar,
  21. NavItem,
  22. NavLink,
  23. NavbarBrand,
  24. NavbarToggler,
  25. Nav,
  26. Collapse,
  27. Modal,
  28. ModalHeader,
  29. ModalBody,
  30. ModalFooter,
  31. FormFeedback,
  32. } from "reactstrap";
  33. import Link from "next/link";
  34. import ContentWrapper from "@/components/Layout/ContentWrapper";
  35. import { createPublicUser } from "@/actions/user";
  36. import { ToastContainer, toast } from "react-toastify";
  37. import { Formik, Form, Field, ErrorMessage } from "formik";
  38. import * as Yup from "yup";
  39. import swal from "sweetalert2";
  40. import { getCsrf } from "../../../actions/security";
  41. import "react-toastify/dist/ReactToastify.css";
  42. const checkIfFilesAreTooBig = (files) => {
  43. let valid = true;
  44. if (files) {
  45. files.map((file) => {
  46. if (file.size > 15 * 1024 * 1024) {
  47. valid = false;
  48. }
  49. });
  50. }
  51. return valid;
  52. };
  53. const checkIfFilesAreCorrectType = (files) => {
  54. let valid = true;
  55. if (files) {
  56. files.map((file) => {
  57. if (!["image/jpeg", "image/png"].includes(file.type)) {
  58. valid = false;
  59. }
  60. });
  61. }
  62. return valid;
  63. };
  64. const checkIfFilesAreCorrectTypePDF = (files) => {
  65. let valid = true;
  66. if (files) {
  67. files.map((file) => {
  68. if (!["application/pdf", "application/pdf"].includes(file.type)) {
  69. valid = false;
  70. }
  71. });
  72. }
  73. return valid;
  74. };
  75. const laporanSchema = Yup.object().shape({
  76. no_laporan: Yup.string().required(),
  77. no_hp: Yup.number().notRequired(),
  78. nama: Yup.string().notRequired(),
  79. setuju: Yup.boolean().isTrue("Harap diceklis"),
  80. alamat: Yup.string()
  81. .min(3, "Minimal 3 huruf")
  82. .max(200, "Maksimal 200 huruf")
  83. .notRequired(),
  84. keterangan: Yup.string()
  85. .min(3, "Minimal 3 huruf")
  86. .max(200, "Maksimal 200 huruf")
  87. .required("Wajib diisi"),
  88. email: Yup.string().email().notRequired(),
  89. pelanggaran_id: Yup.array()
  90. .min(1, "Minimal terdapat 1 jenis pelanggaran")
  91. .required("Wajib diisi"),
  92. pt_id: Yup.string().required("Wajib diisi"),
  93. foto: Yup.array()
  94. .notRequired()
  95. .test("filesize", "Maksimal ukuran foto 15mb", checkIfFilesAreTooBig)
  96. .test("type", "harus jpeg/png", checkIfFilesAreCorrectType),
  97. dokumen: Yup.array()
  98. .min(0, " ")
  99. .notRequired()
  100. .test(
  101. "filesize",
  102. "Maksimal ukuran setiap dokumen 15mb",
  103. checkIfFilesAreTooBig
  104. )
  105. .test("type", "File harus berformat PDF", checkIfFilesAreCorrectTypePDF),
  106. is_private: Yup.boolean().notRequired(),
  107. });
  108. const loadOptions = (inputValue, callback) => {
  109. setTimeout(async () => {
  110. const pt = await ptPublic({ search: inputValue });
  111. const data = pt.data.map((e) => ({
  112. value: e.id,
  113. label: e.nama,
  114. className: "State-ACT",
  115. }));
  116. callback(data);
  117. }, 1000);
  118. };
  119. const menu = [
  120. {
  121. title: "Home",
  122. path: "/app",
  123. },
  124. {
  125. title: "Buat Laporan",
  126. path: "/laporan/new",
  127. },
  128. {
  129. title: "Pemantauan",
  130. path: "/pemantauan",
  131. },
  132. ];
  133. const selectInstanceId = 1;
  134. class App extends Component {
  135. constructor(props) {
  136. super(props);
  137. this.state = {
  138. isOpen: false,
  139. inputValue: "",
  140. pelaporanNumber: Math.floor(Date.now() * Math.random()),
  141. nama: "",
  142. alamat: "",
  143. no_hp: "",
  144. email: "",
  145. fileIdentitas: null,
  146. pelanggaran: [],
  147. selectedPerguruanTinggi: {},
  148. selectedJenis: [],
  149. keteranganLaporan: "",
  150. files: [],
  151. isPrivate: false,
  152. confirm: false,
  153. msgError: [],
  154. modal: false,
  155. modalNotnoHP: false,
  156. user: {},
  157. kode: "",
  158. error: null,
  159. data: {},
  160. token: "",
  161. loading: false,
  162. disablecancel: false,
  163. disablekirim: false,
  164. disablekirim2: false,
  165. disablekirim3: false,
  166. loading2: false,
  167. kodeVerifNotOK: false,
  168. };
  169. }
  170. static getInitialProps = ({ pathname }) => ({ pathname });
  171. componentDidMount = async () => {
  172. const pelanggaran = await getPelanggaranPublic();
  173. this.setState({ pelanggaran });
  174. };
  175. toggleModal = (no_hp = null) => {
  176. if (no_hp) {
  177. this.setState({ modal: !this.state.modal })
  178. } else {
  179. this.setState({ modalNotnoHP: !this.state.modalNotnoHP });
  180. }
  181. };
  182. // disableKirim = (modalNotnoHP = false) => {
  183. // if (modalNotnoHP == false) {
  184. // this.setState({ disableKirim: true })
  185. // } else {
  186. // this.setState({ disableKirim: false })
  187. // }
  188. // }
  189. optionsJenisPelanggaran = (pelanggaran) => {
  190. return pelanggaran.data.map((e) => ({
  191. value: e._id,
  192. label: e.pelanggaran,
  193. className: "State-ACT",
  194. }));
  195. };
  196. setKeteranganPelaporan = (e) => {
  197. this.setState({ keteranganLaporan: e.target.value });
  198. };
  199. handleChangeSelectJenis = (selectedJenis) => {
  200. this.setState({ selectedJenis });
  201. };
  202. handleChangeSelectPerguruanTinggi = (selectedPerguruanTinggi) => {
  203. this.setState({ selectedPerguruanTinggi });
  204. };
  205. handleInputChange = (newValue) => {
  206. const inputValue = newValue.replace();
  207. this.setState({ inputValue });
  208. return inputValue;
  209. };
  210. handleKirim = async (data, { resetForm }) => {
  211. const getToken = await getCsrf();
  212. const _csrf = getToken.token;
  213. const formdata = new FormData();
  214. formdata.append("no_laporan", data.no_laporan);
  215. formdata.append("pt_id", data.pt_id);
  216. formdata.append("nama", data.nama);
  217. formdata.append("email", data.email);
  218. formdata.append("no_hp", data.no_hp);
  219. formdata.append("alamat", data.alamat);
  220. formdata.append("is_private", data.is_private);
  221. formdata.append("keterangan", data.keterangan);
  222. formdata.append("pelanggaran_id", data.pelanggaran_id.join(","));
  223. formdata.append("foto", data.foto[0]);
  224. if (data.dokumen.length > 0) {
  225. Array.from(data.dokumen).forEach((e) => {
  226. formdata.append("dokumen", e);
  227. });
  228. }
  229. const toastid = toast.loading("Please wait...");
  230. const success = await createLaporanPublic(formdata, _csrf);
  231. if (!success) {
  232. swal.fire({
  233. title: "Data tidak berhasil dikirim",
  234. icon: "error",
  235. confirmButtonColor: "#6FB9DE",
  236. });
  237. } else {
  238. swal.fire({
  239. title: "Data berhasil dikirim",
  240. icon: "success",
  241. confirmButtonColor: "#6FB9DE",
  242. });
  243. Router.push("/laporan/new");
  244. }
  245. };
  246. createLaporan = async (token, kode = "") => {
  247. const getToken = await getCsrf();
  248. const _csrf = getToken.token;
  249. const data = this.state.data;
  250. const formdata = new FormData();
  251. formdata.append("pt_id", data.pt_id);
  252. formdata.append("keterangan", data.keterangan);
  253. formdata.append("pelanggaran_id", data.pelanggaran_id.join(","));
  254. if (kode) {
  255. formdata.append("no_verifikasi", kode);
  256. }
  257. if (data.dokumen.length > 0) {
  258. Array.from(data.dokumen).forEach((e) => {
  259. formdata.append("dokumen", e);
  260. });
  261. }
  262. this.setState({ loading: true });
  263. const response = await createLaporanPublic(token, formdata, _csrf);
  264. if (response.error) {
  265. swal.fire({
  266. title: response.error.message,
  267. icon: "error",
  268. content: response.error.message,
  269. confirmButtonColor: "#3e3a8e",
  270. });
  271. this.setState({ kodeVerifNotOK: true, error: false });
  272. } else {
  273. swal.fire({
  274. title: "Data berhasil dikirim",
  275. icon: "success",
  276. confirmButtonColor: "#3e3a8e",
  277. });
  278. this.toggleModal();
  279. Router.push("/laporan/new");
  280. }
  281. this.setState({ loading: false });
  282. };
  283. createUser = async (data) => {
  284. const getToken = await getCsrf();
  285. const _csrf = getToken.token;
  286. const formdata = new FormData();
  287. formdata.append("no_laporan", data.no_laporan);
  288. formdata.append("pt_id", data.pt_id);
  289. if (data.nama) formdata.append("nama", data.nama);
  290. if (data.email) formdata.append("email", data.email);
  291. formdata.append("no_hp", data.no_hp);
  292. if (data.alamat) formdata.append("alamat", data.alamat);
  293. formdata.append("is_private", data.is_private);
  294. if (data.foto.length > 0) formdata.append("foto", data.foto[0]);
  295. return await createPublicUser(formdata, _csrf);
  296. };
  297. render() {
  298. const { selectedJenis, pelanggaran } = this.state;
  299. return (
  300. <div>
  301. <ToastContainer />
  302. <Navbar className="navbar-color" expand="md" dark>
  303. <NavbarBrand href="/">
  304. <img
  305. className="width-133"
  306. src="/static/img/Logo-Sidali.png"
  307. alt="App Logo"
  308. />
  309. </NavbarBrand>
  310. <NavbarToggler onClick={this.toggleCollapse} />
  311. <Collapse isOpen={this.state.isOpen} navbar>
  312. <Nav className="ml-auto" navbar>
  313. {menu.map((e) => (
  314. <NavItem active={e.path === this.props.pathname ? true : false}>
  315. <Link href={e.path}>
  316. <NavLink style={{ cursor: "pointer" }}>{e.title}</NavLink>
  317. </Link>
  318. </NavItem>
  319. ))}
  320. </Nav>
  321. </Collapse>
  322. </Navbar>
  323. <ContentWrapper>
  324. <Row>
  325. <Col lg={8} className="block-center d-block ">
  326. <Card className="card-default">
  327. <CardBody>
  328. <Formik
  329. initialValues={{
  330. nama: "",
  331. no_hp: "",
  332. email: "",
  333. alamat: "",
  334. foto: [],
  335. no_laporan:
  336. moment(new Date()).format("DDMM") +
  337. "" +
  338. Math.floor(Math.random() * 1000000),
  339. pt_id: "",
  340. pelanggaran_id: "",
  341. keterangan: "",
  342. dokumen: [],
  343. setuju: false,
  344. is_private: false,
  345. }}
  346. validationSchema={laporanSchema}
  347. onSubmit={async (data) => {
  348. this.toggleModal(data.no_hp);
  349. this.setState({ data, no_laporan: data.no_laporan });
  350. this.setState({ data, no_hp: data.no_hp });
  351. const user = await this.createUser(data);
  352. const token = user.data.token;
  353. this.setState({ user, token });
  354. }}
  355. >
  356. <Form className="form-horizontal">
  357. <div class="header-1">
  358. <h2 class="card-title-1">Identitas Pelapor</h2>
  359. </div>
  360. <FormGroup row></FormGroup>
  361. <FormGroup row>
  362. <label className="col-md-2 col-form-label">
  363. Nama Lengkap
  364. </label>
  365. <div className="col-md-10">
  366. <Field name="nama">
  367. {({ field }) => <Input type="text" {...field} />}
  368. </Field>
  369. <ErrorMessage
  370. name="nama"
  371. component="div"
  372. className="form-text text-danger"
  373. />
  374. </div>
  375. </FormGroup>
  376. <FormGroup row>
  377. <label className="col-md-2 col-form-label">
  378. Nomor Aktif
  379. <span> &#40;opsional&#41;</span>
  380. </label>
  381. <div className="col-md-10">
  382. <Field name="no_hp">
  383. {({ field, form }) => (
  384. <Input type="tel" id="phone"
  385. name="phone"
  386. className="invalid-mv"
  387. pattern="[0-9]{10,13}"
  388. // title="Nomor telepon tidak valid"
  389. {...field} />
  390. )}
  391. </Field>
  392. <ErrorMessage
  393. name="no_hp"
  394. component="div"
  395. className="form-text text-danger"
  396. />
  397. </div>
  398. </FormGroup>
  399. <FormGroup row>
  400. <label className="col-md-2 col-form-label">Email</label>
  401. <div className="col-md-10">
  402. <Field name="email">
  403. {({ field }) => <Input type="email" className="invalid-mv" {...field} />}
  404. </Field>
  405. <ErrorMessage
  406. name="email"
  407. component="div"
  408. className="form-text text-danger"
  409. />
  410. </div>
  411. </FormGroup>
  412. <FormGroup row>
  413. <label className="col-md-2 col-form-label">
  414. Alamat
  415. </label>
  416. <div className="col-md-10">
  417. <Field name="alamat">
  418. {({ field }) => (
  419. <Input type="textarea" {...field} />
  420. )}
  421. </Field>
  422. <ErrorMessage
  423. name="alamat"
  424. component="div"
  425. className="form-text text-danger"
  426. />
  427. </div>
  428. </FormGroup>
  429. <FormGroup row>
  430. <label className="col-md-2 col-form-label">
  431. Foto Kartu Identitas
  432. </label>
  433. <div className="col-md-10">
  434. <Field name="foto">
  435. {({ field, form }) => (
  436. <Input
  437. type="file"
  438. accept="image/jpeg, image/png"
  439. onChange={(e) =>
  440. form.setFieldValue(
  441. field.name,
  442. Array.from(e.currentTarget.files)
  443. )
  444. }
  445. />
  446. )}
  447. </Field>
  448. <ErrorMessage
  449. name="foto"
  450. component="div"
  451. className="form-text text-danger"
  452. />
  453. <p className="mrgn-top-5">
  454. Ukuran setiap dokumen maksimal 15mb
  455. </p>
  456. </div>
  457. <div className="col-xl-10">
  458. <div className="checkbox c-checkbox">
  459. <label>
  460. <Field name="is_private">
  461. {({ field }) => (
  462. <Input type="checkbox" {...field} />
  463. )}
  464. </Field>
  465. <span className="fa fa-check"></span>
  466. <text>
  467. Klik jika ingin merahasiakan identitas anda
  468. </text>
  469. </label>
  470. </div>
  471. </div>
  472. </FormGroup>
  473. <div class="header-1">
  474. <h2 class="card-title-1">
  475. Detail Laporan
  476. </h2>
  477. </div>
  478. <FormGroup row>
  479. <label className="col-md-2 col-form-label">
  480. Nomor Pelaporan
  481. </label>
  482. <div className="col-md-10">
  483. <Field name="no_laporan">
  484. {({ field }) => (
  485. <Input disabled type="text" {...field} />
  486. )}
  487. </Field>
  488. <ErrorMessage
  489. name="no_laporan"
  490. component="div"
  491. className="form-text text-danger"
  492. />
  493. </div>
  494. </FormGroup>
  495. <FormGroup row>
  496. <label className="col-md-2 col-form-label">
  497. Perguruan Tinggi yang Dilaporkan
  498. <span className="star-color"></span>
  499. </label>
  500. <div className="col-md-10">
  501. <Field name="pt_id">
  502. {({ field, form }) => (
  503. <AsyncSelect
  504. cacheOptions
  505. loadOptions={loadOptions}
  506. defaultOptions
  507. onChange={(e) => {
  508. this.handleChangeSelectPerguruanTinggi(e);
  509. form.setFieldValue(field.name, e.value);
  510. }}
  511. onInputChange={this.handleInputChange}
  512. />
  513. )}
  514. </Field>
  515. <ErrorMessage
  516. name="pt_id"
  517. component="div"
  518. className="form-text text-danger"
  519. />
  520. </div>
  521. </FormGroup>
  522. <FormGroup row>
  523. <label className="col-md-2 col-form-label">
  524. Jenis Pelanggaran<span className="star-color"></span>
  525. </label>
  526. <div className="col-md-10">
  527. <Field name="pelanggaran_id">
  528. {({ field, form }) => (
  529. <Select
  530. instanceId={selectInstanceId + 1}
  531. isMulti
  532. value={selectedJenis}
  533. onChange={(e) => {
  534. this.handleChangeSelectJenis(e);
  535. form.setFieldValue(
  536. field.name,
  537. e.map((e) => e.value)
  538. );
  539. }}
  540. options={
  541. pelanggaran.data
  542. ? this.optionsJenisPelanggaran(pelanggaran)
  543. : []
  544. }
  545. required
  546. />
  547. )}
  548. </Field>
  549. <ErrorMessage
  550. name="pelanggaran_id"
  551. component="div"
  552. className="form-text text-danger"
  553. />
  554. </div>
  555. </FormGroup>
  556. <FormGroup row>
  557. <label className="col-md-2 col-form-label">
  558. Keterangan Laporan<span className="star-color"></span>
  559. </label>
  560. <div className="col-md-10">
  561. <Field name="keterangan">
  562. {({ field }) => (
  563. <Input type="textarea" {...field} />
  564. )}
  565. </Field>
  566. <ErrorMessage
  567. name="keterangan"
  568. component="div"
  569. className="form-text text-danger"
  570. />
  571. </div>
  572. </FormGroup>
  573. <FormGroup row>
  574. <label className="col-md-2 col-form-label">
  575. File Pendukung
  576. </label>
  577. <div className="col-md-10">
  578. <Field name="dokumen">
  579. {({ field, form }) => (
  580. <Input
  581. type="file"
  582. multiple
  583. accept=".pdf"
  584. onChange={(e) =>
  585. form.setFieldValue(
  586. field.name,
  587. Array.from(e.currentTarget.files)
  588. )
  589. }
  590. />
  591. )}
  592. </Field>
  593. <ErrorMessage
  594. name="dokumen"
  595. component="div"
  596. className="form-text text-danger"
  597. />
  598. <p className="mrgn-top-5">
  599. Ukuran setiap dokumen PDF maksimal 15 Mb
  600. </p>
  601. </div>
  602. </FormGroup>
  603. <FormGroup row>
  604. <div className="col-xl-10">
  605. <div className="checkbox c-checkbox">
  606. <label>
  607. <Field name="setuju">
  608. {({ field }) => (
  609. <Input type="checkbox" {...field} />
  610. )}
  611. </Field>
  612. <span className="fa fa-check"></span>
  613. <text>
  614. Klik jika data yang anda laporkan sudah benar
  615. </text>
  616. <ErrorMessage
  617. name="setuju"
  618. component="div"
  619. className="form-text text-danger"
  620. />
  621. </label>
  622. </div>
  623. </div>
  624. </FormGroup>
  625. <FormGroup row>
  626. <div className="posisi-btn-1 btn-radius">
  627. <Button
  628. className="button-kirimlaporan btn-login"
  629. color
  630. type="submit"
  631. >
  632. <h3 className="text-kirimlaporan font-color-white">
  633. Kirim Laporan
  634. </h3>
  635. </Button>
  636. </div>
  637. </FormGroup>
  638. </Form>
  639. </Formik>
  640. </CardBody>
  641. </Card>
  642. </Col>
  643. </Row>
  644. <Modal isOpen={this.state.modal}>
  645. <form className="form-horizontal">
  646. <ModalBody>
  647. <FormGroup>
  648. <div className="">
  649. <label className=" font-weight-bold h6">
  650. Masukkan Kode Verifikasi :
  651. </label>
  652. <div className="border-2">
  653. <Input
  654. className="border-2 "
  655. invalid={this.state.error}
  656. onChange={(e) =>
  657. this.setState({ kode: e.target.value })
  658. }
  659. type="text"
  660. placeholder={this.state.error}
  661. />
  662. <FormFeedback invalid={this.state.error}>
  663. Kode verifikasi harus diisi
  664. </FormFeedback>
  665. </div>
  666. <p>
  667. *Kode verifikasi terkirim ke nomor WA {this.state.no_hp}
  668. </p>
  669. </div>
  670. <p className="font-color-black">
  671. NOTE : Diharapkan pelapor dapat mencatat ataupun mengingat
  672. nomor laporan di bawah ini untuk mempermudah proses
  673. selanjutnya.
  674. </p>
  675. <div className="modals">
  676. <label className="modals text-white font-20 ">
  677. Nomor Laporan : {this.state.no_laporan}
  678. </label>
  679. <CopyToClipboard
  680. text={this.state.no_laporan}
  681. options={{ asHtml: true }}
  682. >
  683. <Button color className="btn-verif">
  684. <img
  685. src="/static/img/icon-copy.png"
  686. alt="icon-copy"
  687. width="20"
  688. />
  689. </Button>
  690. </CopyToClipboard>
  691. </div>
  692. {/* {this.state.error && (
  693. <div className="form-text text-danger">
  694. {this.state.error}
  695. </div>
  696. )} */}
  697. </FormGroup>
  698. </ModalBody>
  699. <ModalFooter>
  700. <Button
  701. className=" float-lg-left mr-auto btn-login"
  702. color
  703. disabled={this.state.disablekirim3}
  704. onClick={async () => {
  705. this.setState({ disablekirim2: true, disablecancel: true, loading2: true })
  706. await this.createLaporan(this.state.token);
  707. this.setState({ disablekirim2: false, disablecancel: false, loading2: false })
  708. }}
  709. >
  710. {this.state.loading2 ?
  711. (
  712. <div class="d-flex justify-content-center">
  713. <span
  714. class="spinner-border spinner-border-sm text-white"
  715. role="status"
  716. ></span>
  717. <span className="font-color-white">
  718. &nbsp; Diproses...
  719. </span>
  720. </div>
  721. ) : (
  722. <span className="font-color-white">
  723. Buat Laporan Tanpa Kode Verifikasi
  724. </span>
  725. )}
  726. </Button>
  727. <Button
  728. className="bg-danger"
  729. color
  730. disabled={this.state.disablecancel}
  731. onClick={() => this.setState({ modal: false })}
  732. >
  733. <span className="font-color-white">Cancel</span>
  734. </Button>
  735. <Button
  736. className="bg-success float-lg-right"
  737. color
  738. disabled={this.state.disablekirim2}
  739. onClick={async () => {
  740. this.setState({ disablekirim3: true, disablecancel: true })
  741. if (this.state.kode) {
  742. await this.createLaporan(
  743. this.state.token,
  744. this.state.kode
  745. );
  746. } else {
  747. this.setState({ error: true, error: "Harus diisi" });
  748. }
  749. this.setState({ disablekirim3: false, disablecancel: false })
  750. }}
  751. >
  752. {this.state.loading ?
  753. (
  754. <div class="d-flex justify-content-center">
  755. <span
  756. class="spinner-border spinner-border-sm text-white"
  757. role="status"
  758. ></span>
  759. <span className="font-color-white">
  760. &nbsp; Diproses...
  761. </span>
  762. </div>
  763. ) : (
  764. <span className="font-color-white">Kirim</span>
  765. )}
  766. </Button>
  767. </ModalFooter>
  768. </form>
  769. </Modal>
  770. <Modal isOpen={this.state.modalNotnoHP}>
  771. <form className="form-horizontal">
  772. <ModalBody>
  773. <FormGroup>
  774. <p className="font-color-black">
  775. NOTE : Diharapkan pelapor dapat mencatat ataupun mengingat
  776. nomor laporan di bawah ini untuk mempermudah proses
  777. selanjutnya.
  778. </p>
  779. <div className="modals">
  780. <label className="modals font-color-white font-20 ">
  781. Nomor Laporan : {this.state.no_laporan}
  782. </label>
  783. <CopyToClipboard
  784. text={this.state.no_laporan}
  785. options={{ asHtml: true }}
  786. >
  787. <Button color className="btn-verif">
  788. <img
  789. src="/static/img/icon-copy.png"
  790. alt="icon-copy"
  791. width="20"
  792. />
  793. </Button>
  794. </CopyToClipboard>
  795. </div>
  796. {this.state.error && (
  797. <div className="form-text text-danger">
  798. {this.state.error}
  799. </div>
  800. )}
  801. </FormGroup>
  802. </ModalBody>
  803. <ModalFooter>
  804. <Button
  805. className="bg-danger"
  806. color
  807. disabled={this.state.disablecancel}
  808. // disabled={true}
  809. onClick={() => this.setState({ modalNotnoHP: false })}
  810. >
  811. <span className="font-color-white">Cancel</span>
  812. </Button>
  813. <Button
  814. className="bg-success float-lg-right"
  815. color
  816. disabled={this.state.disablekirim}
  817. onClick={async () => {
  818. this.setState({ disablecancel: true, loading2: true })
  819. await this.createLaporan(this.state.token);
  820. this.setState({ disablecancel: false })
  821. }}
  822. >
  823. {this.state.loading2 ?
  824. (
  825. <div class="d-flex justify-content-center">
  826. <span
  827. class="spinner-border spinner-border-sm text-white"
  828. role="status"
  829. ></span>
  830. <span className="font-color-white">
  831. &nbsp; Diproses...
  832. </span>
  833. </div>
  834. ) : (
  835. <span className="font-color-white">
  836. Kirim
  837. </span>
  838. )}
  839. </Button>
  840. </ModalFooter>
  841. </form>
  842. </Modal>
  843. </ContentWrapper>
  844. </div >
  845. );
  846. }
  847. }
  848. App.Layout = BasePage;
  849. export default App;