| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736 | import React, { Component } from "react";import Router from "next/router";import BasePage from "@/components/Layout/BasePage";import { ptPublic } from "@/actions/PT";import { getPelanggaranPublic } from "@/actions/pelanggaran";import { createLaporanPublic } from "@/actions/pelaporan";import { notifLaporanBaru } from "@/actions/notifikasi";import Select from "react-select";import AsyncSelect from "react-select/async";import { CopyToClipboard } from "react-copy-to-clipboard";import {  Row,  Col,  FormGroup,  Input,  Card,  CardBody,  Button,  CustomInput,  Navbar,  NavItem,  NavLink,  NavbarBrand,  NavbarToggler,  Nav,  Collapse,  Modal,  ModalHeader,  ModalBody,  ModalFooter,} from "reactstrap";import Link from "next/link";import ContentWrapper from "@/components/Layout/ContentWrapper";import { createPublicUser } from "@/actions/user";import { ToastContainer, toast } from "react-toastify";import { Formik, Form, Field, ErrorMessage } from "formik";import * as Yup from "yup";import swal from "sweetalert2";import "react-toastify/dist/ReactToastify.css";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 laporanSchema = Yup.object().shape({  no_laporan: Yup.string().required(),  no_hp: Yup.number().notRequired(),  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(""),  email: Yup.string().email().notRequired(),  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(0, " ")    .notRequired()    .test(      "filesize",      "Maksimal ukuran setiap dokumen 15mb",      checkIfFilesAreTooBig    ),  is_private: Yup.boolean().notRequired(),});const loadOptions = (inputValue, callback) => {  setTimeout(async () => {    const pt = await ptPublic({ search: inputValue });    const data = pt.data.map((e) => ({      value: e.id,      label: e.nama,      className: "State-ACT",    }));    callback(data);  }, 1000);};const menu = [  {    title: "Home",    path: "/app",  },  {    title: "Buat Laporan",    path: "/laporan/new",  },  {    title: "Pemantauan",    path: "/pemantauan",  },];const selectInstanceId = 1;class App extends Component {  constructor(props) {    super(props);    this.state = {      isOpen: false,      inputValue: "",      pelaporanNumber: Math.floor(Date.now() * Math.random()),      nama: "",      alamat: "",      no_hp: "",      email: "",      fileIdentitas: null,      pelanggaran: [],      selectedPerguruanTinggi: {},      selectedJenis: [],      keteranganLaporan: "",      files: [],      isPrivate: false,      confirm: false,      msgError: [],      modal: false,      user: {},      kode: "",      error: null,      data: {},      token: "",      loading: false,    };  }  static getInitialProps = ({ pathname }) => ({ pathname });  componentDidMount = async () => {    const pelanggaran = await getPelanggaranPublic();    this.setState({ pelanggaran });  };  toggleModal = () => {    this.setState({ modal: !this.state.modal });  };  optionsJenisPelanggaran = (pelanggaran) => {    return pelanggaran.data.map((e) => ({      value: e._id,      label: e.pelanggaran,      className: "State-ACT",    }));  };  setKeteranganPelaporan = (e) => {    this.setState({ keteranganLaporan: e.target.value });  };  handleChangeSelectJenis = (selectedJenis) => {    this.setState({ selectedJenis });  };  handleChangeSelectPerguruanTinggi = (selectedPerguruanTinggi) => {    this.setState({ selectedPerguruanTinggi });  };  handleInputChange = (newValue) => {    const inputValue = newValue.replace(/\W/g, "");    this.setState({ inputValue });    return inputValue;  };  handleKirim = async (data, { resetForm }) => {    const formdata = new FormData();    formdata.append("no_laporan", data.no_laporan);    formdata.append("pt_id", data.pt_id);    formdata.append("nama", data.nama);    formdata.append("email", data.email);    formdata.append("no_hp", data.no_hp);    formdata.append("alamat", data.alamat);    formdata.append("is_private", data.is_private);    formdata.append("keterangan", data.keterangan);    formdata.append("pelanggaran_id", data.pelanggaran_id.join(","));    formdata.append("foto", data.foto[0]);    if (data.dokumen.length > 0) {      Array.from(data.dokumen).forEach((e) => {        formdata.append("dokumen", e);      });    }    const toastid = toast.loading("Please wait...");    const success = await createLaporanPublic(formdata);    if (!success) {      swal.fire({        title: "Data tidak berhasil dikirim",        icon: "error",        confirmButtonColor: "#6FB9DE",      });    } else {      swal.fire({        title: "Data berhasil dikirim",        icon: "success",        confirmButtonColor: "#6FB9DE",      });      Router.push("/laporan/new");    }  };  createLaporan = async (token, kode = "") => {    const data = this.state.data;    const formdata = new FormData();    formdata.append("pt_id", data.pt_id);    formdata.append("keterangan", data.keterangan);    formdata.append("pelanggaran_id", data.pelanggaran_id.join(","));    if (kode) {      formdata.append("no_verifikasi", kode);    }    if (data.dokumen.length > 0) {      Array.from(data.dokumen).forEach((e) => {        formdata.append("dokumen", e);      });    }    // const toastid = toast.loading("loading...");    this.setState({ loading: true });    const success = await createLaporanPublic(token, formdata);    if (!success) {      // toast.update(toastid, { render: "All is not good", type: "error", isLoading: false, autoClose: true, closeButton: true });      swal.fire({        title: "Kode verifikasi salah",        icon: "error",        confirmButtonColor: "#3e3a8e",        // isLoading: true,      });      this.setState({ error: "Kode verifikasi tidak valid" });    } else {      // toast.update(toastid, { render: "All is good", type: "success", isLoading: false, autoClose: true, closeButton: true });      swal.fire({        title: "Data berhasil dikirim",        icon: "success",        confirmButtonColor: "#3e3a8e",      });      this.toggleModal();      Router.push("/laporan/new");    }    this.setState({ loading: false });  };  createUser = async (data) => {    const formdata = new FormData();    formdata.append("no_laporan", data.no_laporan);    formdata.append("pt_id", data.pt_id);    if (data.nama) formdata.append("nama", data.nama);    if (data.email) formdata.append("email", data.email);    formdata.append("no_hp", data.no_hp);    if (data.alamat) formdata.append("alamat", data.alamat);    formdata.append("is_private", data.is_private);    if (data.foto.length > 0) formdata.append("foto", data.foto[0]);    return await createPublicUser(formdata);  };  render() {    const { selectedJenis, pelanggaran } = this.state;    return (      <div>        <ToastContainer />        <Navbar className="navbar-color" expand="md" dark>          <NavbarBrand href="/">            <img              className="width-133"              src="/static/img/Logo-Sidali.png"              alt="App Logo"            />          </NavbarBrand>          <NavbarToggler onClick={this.toggleCollapse} />          <Collapse isOpen={this.state.isOpen} navbar>            <Nav className="ml-auto" navbar>              {menu.map((e) => (                <NavItem active={e.path === this.props.pathname ? true : false}>                  <Link href={e.path}>                    <NavLink style={{ cursor: "pointer" }}>{e.title}</NavLink>                  </Link>                </NavItem>              ))}            </Nav>          </Collapse>        </Navbar>        <ContentWrapper>          <Row>            <Col lg={8} className="block-center d-block ">              <Card className="card-default">                <CardBody>                  <Formik                    initialValues={{                      nama: "",                      no_hp: "",                      email: "",                      alamat: "",                      foto: [],                      no_laporan:                        moment(new Date()).format("DDMM") +                        "" +                        Math.floor(Math.random() * 1000000),                      pt_id: "",                      pelanggaran_id: "",                      keterangan: "",                      dokumen: [],                      setuju: false,                      is_private: false,                    }}                    validationSchema={laporanSchema}                    onSubmit={async (data) => {                      this.toggleModal();                      this.setState({ data, no_laporan: data.no_laporan });                      this.setState({ data, no_hp: data.no_hp });                      const user = await this.createUser(data);                      const token = user.data.token;                      this.setState({ user, token });                    }}                  >                    <Form className="form-horizontal">                      <div class="header-1">                        <h2 class="card-title-1">Identitas Pelapor</h2>                      </div>                      <FormGroup row></FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Nama Lengkap                        </label>                        <div className="col-md-10">                          <Field name="nama">                            {({ field }) => <Input type="text" {...field} />}                          </Field>                          <ErrorMessage                            name="nama"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Nomor Aktif                          <span> (opsional)</span>                        </label>                        <div className="col-md-10">                          <Field name="no_hp">                            {({ field, form }) => (                              <Input type="tel" {...field} />                            )}                          </Field>                          <ErrorMessage                            name="no_hp"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">Email</label>                        <div className="col-md-10">                          <Field name="email">                            {({ field }) => <Input type="email" {...field} />}                          </Field>                          <ErrorMessage                            name="email"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Alamat                        </label>                        <div className="col-md-10">                          <Field name="alamat">                            {({ field }) => (                              <Input type="textarea" {...field} />                            )}                          </Field>                          <ErrorMessage                            name="alamat"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Foto Kartu Identitas                        </label>                        <div className="col-md-10">                          <Field name="foto">                            {({ field, form }) => (                              <Input                                type="file"                                onChange={(e) =>                                  form.setFieldValue(                                    field.name,                                    Array.from(e.currentTarget.files)                                  )                                }                              />                            )}                          </Field>                          <ErrorMessage                            name="foto"                            component="div"                            className="form-text text-danger"                          />                          <p className="mrgn-top-5">                            Ukuran setiap dokumen maksimal 15mb                          </p>                        </div>                        <div className="col-xl-10">                          <div className="checkbox c-checkbox">                            <label>                              <Field name="is_private">                                {({ field }) => (                                  <Input type="checkbox" {...field} />                                )}                              </Field>                              <span className="fa fa-check"></span>                              <text>                                Klik jika ingin merahasiakan identitas anda                              </text>                            </label>                          </div>                        </div>                      </FormGroup>                      <div class="header-1">                        <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>                        <label className="col-md-2 col-form-label">                          Nomor Pelaporan                        </label>                        <div className="col-md-10">                          <Field name="no_laporan">                            {({ field }) => (                              <Input disabled type="text" {...field} />                            )}                          </Field>                          <ErrorMessage                            name="no_laporan"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Perguruan Tinggi yang Dilaporkan                          <span className="star-color"></span>                        </label>                        <div className="col-md-10">                          <Field name="pt_id">                            {({ field, form }) => (                              <AsyncSelect                                cacheOptions                                loadOptions={loadOptions}                                defaultOptions                                onChange={(e) => {                                  this.handleChangeSelectPerguruanTinggi(e);                                  form.setFieldValue(field.name, e.value);                                }}                                onInputChange={this.handleInputChange}                              />                            )}                          </Field>                          <ErrorMessage                            name="pt_id"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Jenis Pelanggaran<span className="star-color"></span>                        </label>                        <div className="col-md-10">                          <Field name="pelanggaran_id">                            {({ field, form }) => (                              <Select                                instanceId={selectInstanceId + 1}                                isMulti                                value={selectedJenis}                                onChange={(e) => {                                  this.handleChangeSelectJenis(e);                                  form.setFieldValue(                                    field.name,                                    e.map((e) => e.value)                                  );                                }}                                options={                                  pelanggaran.data                                    ? this.optionsJenisPelanggaran(pelanggaran)                                    : []                                }                                required                              />                            )}                          </Field>                          <ErrorMessage                            name="pelanggaran_id"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          Keterangan Laporan<span className="star-color"></span>                        </label>                        <div className="col-md-10">                          <Field name="keterangan">                            {({ field }) => (                              <Input type="textarea" {...field} />                            )}                          </Field>                          <ErrorMessage                            name="keterangan"                            component="div"                            className="form-text text-danger"                          />                        </div>                      </FormGroup>                      <FormGroup row>                        <label className="col-md-2 col-form-label">                          File Pendukung                        </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>                          <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>                        <div className="col-xl-10">                          <div className="checkbox c-checkbox">                            <label>                              <Field name="setuju">                                {({ field }) => (                                  <Input type="checkbox" {...field} />                                )}                              </Field>                              <span className="fa fa-check"></span>                              <text>                                Klik jika data yang anda laporkan sudah benar                              </text>                              <ErrorMessage                                name="setuju"                                component="div"                                className="form-text text-danger"                              />                            </label>                          </div>                        </div>                      </FormGroup>                      <FormGroup row>                        <div className="posisi-btn-1 btn-radius">                          <Button                            className="button-kirimlaporan"                            color                            type="submit"                          >                            <h3 className="text-kirimlaporan font-color-white">                              Kirim Laporan                            </h3>                          </Button>                        </div>                      </FormGroup>                    </Form>                  </Formik>                </CardBody>              </Card>            </Col>          </Row>          <Modal isOpen={this.state.modal}>            <form className="form-horizontal">              <ModalBody>                <FormGroup>                  <div className="">                    <label className="modals-verifikasi font-color-white">                      Masukkan Kode Verifikasi                    </label>                    <div className="border-2">                      <Input                        className="border-2"                        onChange={(e) =>                          this.setState({ kode: e.target.value })                        }                        type="text"                      />                    </div>                    <p>                      *Kode verifikasi terkirim ke nomor WA {this.state.no_hp}                    </p>                  </div>                  <p className="font-color-black">                    NOTE : Diharapkan pelapor dapat mencatat ataupun mengingat                    nomor laporan di bawah ini untuk mempermudah proses                    selanjutnya.                  </p>                  <div className="modals">                    <label className="modals font-color-white font-20 ">                      Nomor Laporan : {this.state.no_laporan}                    </label>                    <CopyToClipboard                      text={this.state.no_laporan}                      options={{ asHtml: true }}                    >                      <Button color className="btn-verif">                        <img                          src="/static/img/icon-copy.png"                          alt="icon-copy"                          width="20"                        />                      </Button>                    </CopyToClipboard>                  </div>                  {this.state.error && (                    <div className="form-text text-danger">                      {this.state.error}                    </div>                  )}                </FormGroup>              </ModalBody>              <ModalFooter>                <Button                  className="color-3e3a8e ml-auto"                  color                  type="cancel"                >                  <span className="font-color-white">cancel</span>                </Button>                <Button                  className="btn-login"                  color                  onClick={async () => {                    await this.createLaporan(this.state.token);                  }}                >                  {this.state.loading ?                    (                      <div class="d-flex justify-content-center">                        <span                          class="spinner-border spinner-border-sm text-white"                          role="status"                        ></span>                        <span className="font-color-white">                            Diproses...                        </span>                      </div>                    ) : (                      <span className="font-color-white">                        Buat Laporan Tanpa Kode Verifikasi                      </span>                    )}                </Button>                <Button                  className="color-3e3a8e"                  color                  onClick={async () => {                    if (this.state.kode) {                      await this.createLaporan(                        this.state.token,                        this.state.kode                      );                    } else {                      this.setState({ error: "Kode verifikasi harus diisi" });                    }                  }}                >                  <span className="font-color-white">Kirim</span>                </Button>              </ModalFooter>            </form>          </Modal>        </ContentWrapper>      </div>    );  }}App.Layout = BasePage;export default App;
 |