291 lines
8.8 KiB
TypeScript
291 lines
8.8 KiB
TypeScript
import React, { useEffect, useState } from "react";
|
|
import {
|
|
Dialog,
|
|
DialogClose,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "../ui/dialog";
|
|
import FormSurvey from "./survey";
|
|
import { Controller, useForm } from "react-hook-form";
|
|
import { Textarea } from "../ui/textarea";
|
|
import { Button } from "../ui/button";
|
|
import { z } from "zod";
|
|
import { zodResolver } from "@hookform/resolvers/zod";
|
|
import { Checkbox } from "../ui/checkbox";
|
|
import { createSurveyData } from "@/service/survey/survey";
|
|
import { useTranslations } from "next-intl";
|
|
|
|
const surveySchema = z.object({
|
|
accessFrequency: z.string(),
|
|
uiExperienceDesign: z.string(),
|
|
uiExperienceNavigation: z.string(),
|
|
uiExperienceSpeed: z.string(),
|
|
infoAccuracy: z.string(),
|
|
infoCompleteness: z.string(),
|
|
usefulness: z.string(),
|
|
suggestion: z.string().optional(),
|
|
});
|
|
|
|
type SurveySchema = z.infer<typeof surveySchema>;
|
|
|
|
const UserSurveyBox = () => {
|
|
const [openPolda, setOpenPolda] = useState<any>();
|
|
const [showSurvey, setShowSurvey] = useState(true);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const t = useTranslations("LandingPage");
|
|
|
|
const {
|
|
control,
|
|
handleSubmit,
|
|
formState: { errors },
|
|
} = useForm<SurveySchema>({
|
|
resolver: zodResolver(surveySchema),
|
|
mode: "all",
|
|
defaultValues: {
|
|
accessFrequency: "",
|
|
uiExperienceDesign: "",
|
|
uiExperienceNavigation: "",
|
|
uiExperienceSpeed: "",
|
|
infoAccuracy: "",
|
|
infoCompleteness: "",
|
|
usefulness: "",
|
|
suggestion: "",
|
|
},
|
|
});
|
|
|
|
const options = {
|
|
accessFrequency: [t("everyDay"), t("week"), t("month"), t("firstTime")],
|
|
uiExperienceDesign: [
|
|
t("veryGood"),
|
|
t("good"),
|
|
t("enough"),
|
|
t("notEnough"),
|
|
t("bad"),
|
|
],
|
|
uiExperienceNavigation: [
|
|
t("veryEasy"),
|
|
t("easy"),
|
|
t("enough"),
|
|
t("difficult"),
|
|
t("veryDifficult"),
|
|
],
|
|
uiExperienceSpeed: [
|
|
t("veryFast"),
|
|
t("fast"),
|
|
t("enough"),
|
|
t("slow"),
|
|
t("verySlow"),
|
|
],
|
|
infoAccuracy: [
|
|
t("verySatisfied"),
|
|
t("satisfied"),
|
|
t("enough"),
|
|
t("lessSatisfied"),
|
|
t("notSatisfied"),
|
|
],
|
|
infoCompleteness: [
|
|
t("veryComplete"),
|
|
t("completely"),
|
|
t("enough"),
|
|
t("incomplete"),
|
|
t("notComplete"),
|
|
],
|
|
usefulness: [
|
|
t("veryHelpful"),
|
|
t("helping"),
|
|
t("quiteHelpful"),
|
|
t("lessHelpful"),
|
|
t("notHelpful"),
|
|
],
|
|
};
|
|
|
|
const renderControllerGroup = (
|
|
name: keyof SurveySchema,
|
|
question: string,
|
|
choices: string[]
|
|
) => (
|
|
<div className="space-y-2">
|
|
<p className="font-medium">{question}</p>
|
|
<div className="grid grid-cols-2 gap-2">
|
|
{choices.map((choice, i) => (
|
|
<Controller
|
|
key={i}
|
|
name={name}
|
|
control={control}
|
|
render={({ field }) => (
|
|
<label className="flex items-center space-x-2">
|
|
<Checkbox
|
|
checked={field.value === choice}
|
|
onCheckedChange={() => field.onChange(choice)}
|
|
/>
|
|
<span>{choice}</span>
|
|
</label>
|
|
)}
|
|
/>
|
|
))}
|
|
</div>
|
|
{errors[name] && (
|
|
<p className="text-red-500 text-sm">
|
|
{errors[name]?.message as string}
|
|
</p>
|
|
)}
|
|
</div>
|
|
);
|
|
|
|
const onSubmit = async (data: SurveySchema) => {
|
|
setIsLoading(true);
|
|
try {
|
|
const response = await createSurveyData(data);
|
|
console.log("API Response:", response);
|
|
setShowSurvey(false);
|
|
setOpenPolda(false);
|
|
} catch (error) {
|
|
console.error("Error submitting survey:", error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
};
|
|
return (
|
|
<div className="relative mt-8 rounded-lg bg-white dark:bg-zinc-900 p-6 shadow overflow-hidden">
|
|
{/* Garis menyerong */}
|
|
<div className="hidden lg:block absolute right-64 top-0">
|
|
<img src="/assets/line1.png" alt="line" className="" />
|
|
</div>
|
|
<div className="hidden lg:block absolute right-60 top-0">
|
|
<img src="/assets/line1.png" alt="line" className="" />
|
|
</div>
|
|
<div className="hidden lg:block absolute right-56 top-0">
|
|
<img src="/assets/line1.png" alt="line" className="" />
|
|
</div>
|
|
|
|
{/* Grid konten */}
|
|
<div className="relative z-10 grid grid-cols-1 md:grid-cols-2 gap-4 items-center">
|
|
{/* Kiri: Teks dan tombol */}
|
|
<div>
|
|
<h2 className="text-2xl font-bold mb-2">{t("survey1", { defaultValue: "Survey1" })}</h2>
|
|
<p className="text-sm text-gray-700 dark:text-gray-300 mb-6">
|
|
{t("survey2", { defaultValue: "Survey2" })}
|
|
</p>
|
|
<Dialog open={openPolda} onOpenChange={setOpenPolda}>
|
|
<DialogTrigger asChild>
|
|
<Button
|
|
size="md"
|
|
onClick={() => setOpenPolda(true)}
|
|
className="bg-[#bb3523] hover:bg-[#9e2e1e] text-white font-bold px-6 py-3 rounded shadow-md transition-all duration-300"
|
|
>
|
|
{t("survey3", { defaultValue: "Survey3" })}
|
|
</Button>
|
|
</DialogTrigger>
|
|
<DialogContent
|
|
size="md"
|
|
className="max-h-[90vh] overflow-auto flex flex-col"
|
|
data-lenis-prevent
|
|
>
|
|
<DialogHeader>
|
|
<DialogTitle className="text-lg font-bold">
|
|
{t("survey4", { defaultValue: "Survey4" })}
|
|
</DialogTitle>
|
|
<DialogDescription className="text-sm">
|
|
{t("survey5", { defaultValue: "Survey5" })}
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<form
|
|
onSubmit={handleSubmit(onSubmit)}
|
|
className="space-y-6 mt-4"
|
|
>
|
|
{renderControllerGroup(
|
|
"accessFrequency",
|
|
t("survey6", { defaultValue: "Survey6" }),
|
|
options.accessFrequency
|
|
)}
|
|
|
|
<div>
|
|
<p className="font-medium">{t("survey7", { defaultValue: "Survey7" })}</p>
|
|
<div className="space-y-3 mt-2">
|
|
{renderControllerGroup(
|
|
"uiExperienceDesign",
|
|
t("websiteDesign"),
|
|
options.uiExperienceDesign
|
|
)}
|
|
{renderControllerGroup(
|
|
"uiExperienceNavigation",
|
|
t("easeNavigation"),
|
|
options.uiExperienceNavigation
|
|
)}
|
|
{renderControllerGroup(
|
|
"uiExperienceSpeed",
|
|
t("speed"),
|
|
options.uiExperienceSpeed
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div>
|
|
<p className="font-medium">{t("survey8", { defaultValue: "Survey8" })}</p>
|
|
<div className="space-y-3 mt-2">
|
|
{renderControllerGroup(
|
|
"infoAccuracy",
|
|
t("accurate"),
|
|
options.infoAccuracy
|
|
)}
|
|
{renderControllerGroup(
|
|
"infoCompleteness",
|
|
t("complete"),
|
|
options.infoCompleteness
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{renderControllerGroup(
|
|
"usefulness",
|
|
t("survey9", { defaultValue: "Survey9" }),
|
|
options.usefulness
|
|
)}
|
|
|
|
<div>
|
|
<p className="font-medium">{t("survey10", { defaultValue: "Survey10" })}</p>
|
|
<Controller
|
|
name="suggestion"
|
|
control={control}
|
|
render={({ field }) => (
|
|
<Textarea
|
|
placeholder={t("write")}
|
|
value={field.value}
|
|
onChange={field.onChange}
|
|
/>
|
|
)}
|
|
/>
|
|
</div>
|
|
|
|
<div className="flex justify-end gap-2">
|
|
<Button variant="outline" onClick={() => setOpenPolda(false)}>
|
|
{t("cancel", { defaultValue: "Cancel" })}
|
|
</Button>
|
|
<Button type="submit" disabled={isLoading}>
|
|
{isLoading ? t("sending") : t("send")}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
|
|
{/* Kanan: Gambar survey */}
|
|
<div className="hidden lg:flex justify-center md:justify-end">
|
|
<img
|
|
src="/assets/survey.png"
|
|
alt="Survey Illustration"
|
|
className="w-48 h-auto"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default UserSurveyBox;
|