From f474a98a75d8dcc971c7982077d67d1416fe22b9 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Fri, 25 Apr 2025 10:07:20 +0800 Subject: [PATCH] feat:add table survey,form survey --- .../admin/survey/component/column.tsx | 57 ++-- .../admin/survey/component/table.tsx | 5 +- .../admin/survey/detail/[id]/page.tsx | 17 ++ .../contributor/blog/detail/[id]/page.tsx | 3 +- components/form/survey/survey-detail.tsx | 264 ++++++++++++++++++ components/landing-page/hero.tsx | 188 ++----------- components/landing-page/survey.tsx | 236 ++++++++++++++++ service/survey/survey.ts | 19 ++ 8 files changed, 596 insertions(+), 193 deletions(-) create mode 100644 app/[locale]/(protected)/admin/survey/detail/[id]/page.tsx create mode 100644 components/form/survey/survey-detail.tsx create mode 100644 components/landing-page/survey.tsx create mode 100644 service/survey/survey.ts diff --git a/app/[locale]/(protected)/admin/survey/component/column.tsx b/app/[locale]/(protected)/admin/survey/component/column.tsx index dfbf1b9e..e576e68f 100644 --- a/app/[locale]/(protected)/admin/survey/component/column.tsx +++ b/app/[locale]/(protected)/admin/survey/component/column.tsx @@ -13,6 +13,9 @@ import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Link, useRouter } from "@/i18n/routing"; +import { format } from "date-fns"; +import header from "@/components/partials/header"; +import { date } from "zod"; const columns: ColumnDef[] = [ { @@ -23,50 +26,61 @@ const columns: ColumnDef[] = [ { accessorKey: "createdAt", header: "Tanggal", - cell: ({ row }) => ( - {row.getValue("createdAt")} - ), + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, }, { - accessorKey: "account-type", + accessorKey: "createdByCategory", header: "Jenis Akun", cell: ({ row }) => ( - {row.getValue("account-type")} + {row.getValue("createdByCategory")} ), }, { - accessorKey: "userName", + accessorKey: "createdByUsername", header: "UserName", cell: ({ row }) => ( - {row.getValue("userName")} + {row.getValue("createdByUsername")} ), }, { - accessorKey: "accessMediahub", + accessorKey: "accessFrequency", header: "Akses Mediahub", cell: ({ row }) => ( - {row.getValue("accessMediahub")} + {row.getValue("accessFrequency")} ), }, { - accessorKey: "desaignWeb", + accessorKey: "uiExperienceDesign", header: "Tampilan Desain Web", cell: ({ row }) => ( - {row.getValue("desaignWeb")} + {row.getValue("uiExperienceDesign")} ), }, { - accessorKey: "navigation", + accessorKey: "uiExperienceNavigation", header: "Kemudahan Navigasi", cell: ({ row }) => ( - {row.getValue("navigation")} + + {row.getValue("uiExperienceNavigation")} + ), }, { - accessorKey: "fastAccess", + accessorKey: "uiExperienceSpeed", header: "Kecepatan Akses", cell: ({ row }) => ( - {row.getValue("fastAccess")} + {row.getValue("uiExperienceSpeed")} ), }, { @@ -86,13 +100,12 @@ const columns: ColumnDef[] = [ - - - Detail - - + + + + View + + ); diff --git a/app/[locale]/(protected)/admin/survey/component/table.tsx b/app/[locale]/(protected)/admin/survey/component/table.tsx index a6efa990..5e084b5a 100644 --- a/app/[locale]/(protected)/admin/survey/component/table.tsx +++ b/app/[locale]/(protected)/admin/survey/component/table.tsx @@ -90,6 +90,7 @@ import { XAxis, YAxis, } from "recharts"; +import { getSurveyData } from "@/service/survey/survey"; const data = [ { @@ -181,7 +182,7 @@ const SurveyListTable = () => { async function fetchData() { try { loading(); - const res = await getMediaBlastCampaignPage(page - 1); + const res = await getSurveyData(); const data = res?.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -249,7 +250,7 @@ const SurveyListTable = () => { -
+

Survei Kepuasan Pengguna MediaHub Polri

diff --git a/app/[locale]/(protected)/admin/survey/detail/[id]/page.tsx b/app/[locale]/(protected)/admin/survey/detail/[id]/page.tsx new file mode 100644 index 00000000..7b24ff71 --- /dev/null +++ b/app/[locale]/(protected)/admin/survey/detail/[id]/page.tsx @@ -0,0 +1,17 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormBlogDetail from "@/components/form/blog/blog--detail-form"; +import FormSurvey from "@/components/landing-page/survey"; +import FormSurveyDetail from "@/components/form/survey/survey-detail"; + +const SurveyDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default SurveyDetailPage; diff --git a/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx index 1906dc83..c196cb0d 100644 --- a/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx @@ -1,12 +1,13 @@ import SiteBreadcrumb from "@/components/site-breadcrumb"; import FormBlogDetail from "@/components/form/blog/blog--detail-form"; +import FormSurveyDetailPage from "@/components/form/survey/survey-detail"; const BlogDetailPage = async () => { return (
- +
); diff --git a/components/form/survey/survey-detail.tsx b/components/form/survey/survey-detail.tsx new file mode 100644 index 00000000..5307a17d --- /dev/null +++ b/components/form/survey/survey-detail.tsx @@ -0,0 +1,264 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { z } from "zod"; +import { useForm, Controller } from "react-hook-form"; +import { zodResolver } from "@hookform/resolvers/zod"; + +import { createSurveyData, getSurveyById } from "@/service/survey/survey"; + +import { Checkbox } from "@/components/ui/checkbox"; +import { Textarea } from "@/components/ui/textarea"; +import { Button } from "@/components/ui/button"; +import { useParams } from "next/navigation"; + +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; + +export default function FormSurveyDetailPage() { + const [isLoading, setIsLoading] = useState(false); + const [loadingSurvey, setLoadingSurvey] = useState(true); + const [detail, setDetail] = useState(); + const { id } = useParams() as { id: string }; + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(surveySchema), + defaultValues: { + accessFrequency: "", + uiExperienceDesign: "", + uiExperienceNavigation: "", + uiExperienceSpeed: "", + infoAccuracy: "", + infoCompleteness: "", + usefulness: "", + suggestion: "", + }, + }); + + const options = { + accessFrequency: [ + "Setiap hari", + "Beberapa kali seminggu", + "Beberapa kali dalam sebulan", + "Baru pertama kali", + ], + uiExperienceDesign: ["Sangat baik", "Baik", "Cukup", "Kurang", "Buruk"], + uiExperienceNavigation: [ + "Sangat mudah", + "Mudah", + "Cukup", + "Sulit", + "Sangat sulit", + ], + uiExperienceSpeed: [ + "Sangat cepat", + "Cepat", + "Cukup", + "Lambat", + "Sangat lambat", + ], + infoAccuracy: ["Sangat puas", "Puas", "Cukup", "Kurang puas", "Tidak puas"], + infoCompleteness: [ + "Sangat lengkap", + "Lengkap", + "Cukup", + "Kurang lengkap", + "Tidak lengkap", + ], + usefulness: [ + "Sangat membantu", + "Membantu", + "Cukup membantu", + "Kurang membantu", + "Tidak membantu", + ], + }; + + const renderControllerGroup = ( + name: keyof SurveySchema, + question: string, + choices: string[] + ) => ( +
+

{question}

+
+ {choices.map((choice, i) => ( + ( + + )} + /> + ))} +
+ {errors[name] && ( +

+ {errors[name]?.message as string} +

+ )} +
+ ); + + const onSubmit = async (data: SurveySchema) => { + setIsLoading(true); + try { + const response = await createSurveyData(data); + console.log("Survey submitted:", response); + } catch (error) { + console.error("Failed to submit survey:", error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + const fetchSurvey = async () => { + if (id) { + setLoadingSurvey(true); + try { + const response = await getSurveyById(id); + const details = response?.data?.data; + + setDetail(details); + + // Set value dari data detail ke form + if (details) { + setValue("accessFrequency", details.accessFrequency || ""); + setValue("uiExperienceDesign", details.uiExperienceDesign || ""); + setValue( + "uiExperienceNavigation", + details.uiExperienceNavigation || "" + ); + setValue("uiExperienceSpeed", details.uiExperienceSpeed || ""); + setValue("infoAccuracy", details.infoAccuracy || ""); + setValue("infoCompleteness", details.infoCompleteness || ""); + setValue("usefulness", details.usefulness || ""); + setValue("suggestion", details.suggestion || ""); + } + } catch (error) { + console.error("Failed to fetch survey detail:", error); + } finally { + setLoadingSurvey(false); + } + } + }; + + fetchSurvey(); + }, [id, setValue]); + + if (loadingSurvey) { + return
Loading survey data...
; + } + + return ( +
+

+ SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI +

+

+ Kami menghargai pendapat Anda! Survei ini bertujuan untuk meningkatkan + kualitas layanan MediaHub Polri. +

+ +
+ {renderControllerGroup( + "accessFrequency", + "1. Seberapa sering Anda mengakses MediaHub Polri?", + options.accessFrequency + )} + +
+

+ 2. Bagaimana pengalaman Anda dalam mengakses website ini? +

+
+ {renderControllerGroup( + "uiExperienceDesign", + "a) Tampilan dan desain website", + options.uiExperienceDesign + )} + {renderControllerGroup( + "uiExperienceNavigation", + "b) Kemudahan navigasi", + options.uiExperienceNavigation + )} + {renderControllerGroup( + "uiExperienceSpeed", + "c) Kecepatan akses website", + options.uiExperienceSpeed + )} +
+
+ +
+

+ 3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub + Polri? +

+
+ {renderControllerGroup( + "infoAccuracy", + "a) Akurat dan terpercaya", + options.infoAccuracy + )} + {renderControllerGroup( + "infoCompleteness", + "b) Kelengkapan berita dan informasi", + options.infoCompleteness + )} +
+
+ + {renderControllerGroup( + "usefulness", + "4. Apakah Anda merasa website ini membantu dalam mendapatkan informasi terkait Polri?", + options.usefulness + )} + +
+

5. Apa saran atau masukan Anda?

+ ( +