290 lines
9.9 KiB
TypeScript
290 lines
9.9 KiB
TypeScript
"use client";
|
|
import { Button } from "@heroui/button";
|
|
import {
|
|
Image,
|
|
Input,
|
|
InputOtp,
|
|
Modal,
|
|
ModalBody,
|
|
ModalContent,
|
|
ModalFooter,
|
|
ModalHeader,
|
|
ModalProps,
|
|
Textarea,
|
|
useDisclosure,
|
|
} from "@heroui/react";
|
|
import { ChevronLeftWhite, ChevronRightWhite } from "../icons";
|
|
import React, { useEffect, useState } from "react";
|
|
import Link from "next/link";
|
|
import { useTranslations } from "next-intl";
|
|
import * as z from "zod";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { Controller, useForm } from "react-hook-form";
|
|
import { close, error, loading } from "@/config/swal";
|
|
import OTPInput from "react-otp-input";
|
|
import { otpRequest, otpValidation } from "@/service/master-user";
|
|
import Swal from "sweetalert2";
|
|
import withReactContent from "sweetalert2-react-content";
|
|
import { createFeedback } from "@/service/feedbacks";
|
|
|
|
const createArticleSchema = z.object({
|
|
email: z.string().min(2, {
|
|
message: "Email harus diisi",
|
|
}),
|
|
name: z.string().min(2, {
|
|
message: "Nama harus diisi",
|
|
}),
|
|
description: z.string().min(2, {
|
|
message: "Deskripsi harus diisi",
|
|
}),
|
|
});
|
|
|
|
export default function SuggestionsModal(props: {
|
|
opened: boolean;
|
|
modalStatus: (status: boolean) => void;
|
|
}) {
|
|
const { isOpen, onOpen, onOpenChange } = useDisclosure();
|
|
const [needOtp, setNeedOtp] = useState(false);
|
|
const [otpValue, setOtpValue] = useState("");
|
|
const MySwal = withReactContent(Swal);
|
|
|
|
// const t = useTranslations("Landing");
|
|
|
|
useEffect(() => {
|
|
if (props.opened) {
|
|
onOpen();
|
|
}
|
|
}, [props.opened]);
|
|
|
|
const formOptions = {
|
|
resolver: zodResolver(createArticleSchema),
|
|
defaultValues: { name: "", description: "", email: "" },
|
|
};
|
|
|
|
type UserSettingSchema = z.infer<typeof createArticleSchema>;
|
|
const {
|
|
control,
|
|
handleSubmit,
|
|
reset,
|
|
formState: { errors },
|
|
} = useForm<UserSettingSchema>(formOptions);
|
|
|
|
const onSubmit = async (values: z.infer<typeof createArticleSchema>) => {
|
|
if (!needOtp) {
|
|
loading();
|
|
const res = await otpRequest(values.email, values?.name);
|
|
if (res?.error) {
|
|
error(res.message);
|
|
return false;
|
|
}
|
|
close();
|
|
setNeedOtp(true);
|
|
} else {
|
|
const validation = await otpValidation(values.email, otpValue);
|
|
if (validation?.error) {
|
|
error("OTP Tidak Sesuai");
|
|
return false;
|
|
}
|
|
|
|
const req = {
|
|
commentFromName: values.name,
|
|
message: values.description,
|
|
commentFromEmail: values.email,
|
|
};
|
|
|
|
const res = await createFeedback(req);
|
|
if (res?.error) {
|
|
error(res?.message);
|
|
return false;
|
|
}
|
|
|
|
MySwal.fire({
|
|
title: "Berhasil Kirim",
|
|
text: "",
|
|
icon: "success",
|
|
showCancelButton: false,
|
|
confirmButtonColor: "#3085d6",
|
|
confirmButtonText: "Oke",
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
}
|
|
});
|
|
reset();
|
|
setNeedOtp(false);
|
|
setOtpValue("");
|
|
props.modalStatus(!props.opened);
|
|
onOpenChange();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<Modal
|
|
isOpen={isOpen}
|
|
onOpenChange={() => {
|
|
props.modalStatus(!props.opened);
|
|
onOpenChange();
|
|
}}
|
|
size="3xl"
|
|
className="bg-white"
|
|
placement="top-center"
|
|
>
|
|
<ModalContent>
|
|
{(onClose) => (
|
|
<>
|
|
<ModalHeader className="flex flex-col text-black justify-center items-center min-h mb- text-3xl font-semibold">
|
|
<div className="text-xl text-black w-full justify-center flex">
|
|
<p className="border-b-3 border-[#C3170F] py-2 w-fit">
|
|
Kritik & Saran
|
|
</p>
|
|
</div>
|
|
</ModalHeader>
|
|
<ModalBody>
|
|
<form
|
|
onSubmit={handleSubmit(onSubmit)}
|
|
className="flex flex-col gap-3"
|
|
>
|
|
{needOtp ? (
|
|
<div className="flex flex-col gap-1 text-black">
|
|
<p className="text-xs">
|
|
Kode verifikasi sudah dikirmkan. Silahkan cek Email
|
|
Anda!
|
|
</p>
|
|
<p>OTP</p>
|
|
|
|
{/* <OTPInput
|
|
value={otpValue}
|
|
onChange={setOtpValue}
|
|
numInputs={6}
|
|
renderSeparator={<span>-</span>}
|
|
renderInput={(props) => (
|
|
<input
|
|
{...props}
|
|
className="!w-[30px] h-[30px] dark:text-white rounded-sm"
|
|
/>
|
|
)}
|
|
/> */}
|
|
<InputOtp
|
|
length={6}
|
|
value={otpValue}
|
|
onValueChange={setOtpValue}
|
|
className="dark:text-white"
|
|
/>
|
|
</div>
|
|
) : (
|
|
<>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="text-sm text-black">Nama</p>
|
|
<Controller
|
|
control={control}
|
|
name="name"
|
|
render={({ field: { onChange, value } }) => (
|
|
<Input
|
|
type="text"
|
|
id="title"
|
|
placeholder=""
|
|
label=""
|
|
value={value}
|
|
onChange={onChange}
|
|
labelPlacement="outside"
|
|
className="w-full text-black"
|
|
classNames={{
|
|
inputWrapper: [
|
|
"border-1 rounded-lg",
|
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
|
],
|
|
}}
|
|
variant="bordered"
|
|
/>
|
|
)}
|
|
/>
|
|
{errors?.name && (
|
|
<p className="text-red-400 text-sm">
|
|
{errors.name?.message}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="text-sm text-black">Email</p>
|
|
<Controller
|
|
control={control}
|
|
name="email"
|
|
render={({ field: { onChange, value } }) => (
|
|
<Input
|
|
type="email"
|
|
id="email"
|
|
placeholder=""
|
|
label=""
|
|
value={value}
|
|
onChange={onChange}
|
|
labelPlacement="outside"
|
|
className="w-full text-black"
|
|
classNames={{
|
|
inputWrapper: [
|
|
"border-1 rounded-lg !text-black",
|
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400 !text-black",
|
|
"dark:group-data-[focused=true]:!text-black",
|
|
],
|
|
}}
|
|
variant="bordered"
|
|
/>
|
|
)}
|
|
/>
|
|
{errors?.email && (
|
|
<p className="text-red-400 text-sm">
|
|
{errors.email?.message}
|
|
</p>
|
|
)}
|
|
</div>
|
|
<div className="flex flex-col gap-1">
|
|
<p className="text-sm text-black">Kritik & Saran</p>
|
|
<Controller
|
|
control={control}
|
|
name="description"
|
|
render={({ field: { onChange, value } }) => (
|
|
<Textarea
|
|
type="text"
|
|
id="description"
|
|
placeholder=""
|
|
label=""
|
|
value={value}
|
|
onChange={onChange}
|
|
labelPlacement="outside"
|
|
className="w-full text-black"
|
|
classNames={{
|
|
inputWrapper: [
|
|
"border-1 rounded-lg",
|
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
|
],
|
|
}}
|
|
variant="bordered"
|
|
/>
|
|
)}
|
|
/>
|
|
{errors?.description && (
|
|
<p className="text-red-400 text-sm">
|
|
{errors.description?.message}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
|
|
<ModalFooter className="self-end grow items-end">
|
|
<Button color="primary" type="submit">
|
|
Kirim
|
|
</Button>
|
|
<Button color="danger" variant="light" onPress={onClose}>
|
|
Tutup
|
|
</Button>
|
|
</ModalFooter>
|
|
</form>
|
|
</ModalBody>
|
|
</>
|
|
)}
|
|
</ModalContent>
|
|
</Modal>
|
|
</>
|
|
);
|
|
}
|