feat:kritik saran popup

This commit is contained in:
Rama Priyanto 2025-03-04 12:53:29 +07:00
parent 1eede31961
commit c52c351bf0
6 changed files with 308 additions and 8 deletions

View File

@ -303,7 +303,7 @@ export default function CategorySatker(props: {
}}
size="5xl"
scrollBehavior={scrollBehavior}
placement={modalPlacement}
placement="center"
className="bg-white"
>
<ModalContent>

View File

@ -182,7 +182,7 @@ export default function PolriApps(props: {
}}
size="5xl"
scrollBehavior={scrollBehavior}
placement={modalPlacement}
placement={"center"}
className="bg-white"
>
<ModalContent>

View File

@ -310,7 +310,7 @@ export default function RegionalNews(props: {
}}
size="5xl"
scrollBehavior={scrollBehavior}
placement={modalPlacement}
placement="center"
className="bg-white"
>
<ModalContent>

View File

@ -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"
} `}
>

View File

@ -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>
);
}

View File

@ -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>
</>
);
}