feat:kritik saran popup
This commit is contained in:
parent
1eede31961
commit
c52c351bf0
|
|
@ -303,7 +303,7 @@ export default function CategorySatker(props: {
|
|||
}}
|
||||
size="5xl"
|
||||
scrollBehavior={scrollBehavior}
|
||||
placement={modalPlacement}
|
||||
placement="center"
|
||||
className="bg-white"
|
||||
>
|
||||
<ModalContent>
|
||||
|
|
|
|||
|
|
@ -182,7 +182,7 @@ export default function PolriApps(props: {
|
|||
}}
|
||||
size="5xl"
|
||||
scrollBehavior={scrollBehavior}
|
||||
placement={modalPlacement}
|
||||
placement={"center"}
|
||||
className="bg-white"
|
||||
>
|
||||
<ModalContent>
|
||||
|
|
|
|||
|
|
@ -310,7 +310,7 @@ export default function RegionalNews(props: {
|
|||
}}
|
||||
size="5xl"
|
||||
scrollBehavior={scrollBehavior}
|
||||
placement={modalPlacement}
|
||||
placement="center"
|
||||
className="bg-white"
|
||||
>
|
||||
<ModalContent>
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default function BannerHumasNew() {
|
|||
</PopoverTrigger>
|
||||
<PopoverContent className="ml-2 w-fit">
|
||||
<div
|
||||
className={` px-1 py-2 text-black grid gap-2 ${
|
||||
className={` px-1 py-2 grid gap-2 ${
|
||||
withImage ? " grid-cols-3" : "grid-cols-1 gap-2"
|
||||
} `}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,14 @@ import RegionalNews from "./RegionalNews";
|
|||
import { useEffect, useState } from "react";
|
||||
import CategorySatker from "./CategorySatker";
|
||||
import PolriApps from "./PolriApps";
|
||||
import Link from "next/link";
|
||||
import SuggestionsModal from "./suggestions";
|
||||
|
||||
export default function DigitalServices() {
|
||||
const [isPoldaOpen, setIsPoldaOpen] = useState(false);
|
||||
const [isSatkerOpen, setIsSatkerOpen] = useState(false);
|
||||
const [isAppsOpen, setIsAppsOpen] = useState(false);
|
||||
const [isSuggestionOpen, setIsSuggestionOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="border-1 rounded-xl py-2 w-[90%] lg:w-[75%] mx-auto bg-white text-black">
|
||||
|
|
@ -73,7 +76,7 @@ export default function DigitalServices() {
|
|||
</p>
|
||||
</a>
|
||||
<a
|
||||
onClick={() => setIsAppsOpen(true)}
|
||||
onClick={() => setIsSuggestionOpen(true)}
|
||||
className="group shadow-lg rounded-lg w-full lg:w-[200px] h-[200px] flex flex-col justify-center items-center hover:border-3 hover:border-red-600 cursor-pointer mx-auto transition duration-300 ease-in-out"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -90,8 +93,8 @@ export default function DigitalServices() {
|
|||
Lihat Selengkapnya
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
onClick={() => setIsAppsOpen(true)}
|
||||
<Link
|
||||
href="https://survey.zohopublic.com/zs/EYCOBO"
|
||||
className="group shadow-lg rounded-lg w-full lg:w-[200px] h-[200px] flex flex-col justify-center items-center hover:border-3 hover:border-red-600 cursor-pointer mx-auto transition duration-300 ease-in-out"
|
||||
>
|
||||
<Image
|
||||
|
|
@ -107,7 +110,7 @@ export default function DigitalServices() {
|
|||
<p className="text-xs text-primary underline transform group-hover:translate-y-2 transition duration-300 ease-in-out">
|
||||
Lihat Selengkapnya
|
||||
</p>
|
||||
</a>
|
||||
</Link>
|
||||
</div>
|
||||
<RegionalNews
|
||||
opened={isPoldaOpen}
|
||||
|
|
@ -121,6 +124,10 @@ export default function DigitalServices() {
|
|||
opened={isAppsOpen}
|
||||
modalStatus={(status) => setIsAppsOpen(status)}
|
||||
/>
|
||||
<SuggestionsModal
|
||||
opened={isSuggestionOpen}
|
||||
modalStatus={(status) => setIsSuggestionOpen(status)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,293 @@
|
|||
"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";
|
||||
|
||||
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 = {
|
||||
name: values.name,
|
||||
description: values.description,
|
||||
email: values.email,
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
// setRefresh(!refresh);
|
||||
// MySwal.fire({
|
||||
// title: "Sukses",
|
||||
// icon: "success",
|
||||
// confirmButtonColor: "#3085d6",
|
||||
// confirmButtonText: "OK",
|
||||
// }).then((result) => {
|
||||
// if (result.isConfirmed) {
|
||||
// }
|
||||
// });
|
||||
};
|
||||
|
||||
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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue