From 4cb4cd85c5460a297760a4c38babe4f11fae7662 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Thu, 19 Dec 2024 02:03:22 +0700 Subject: [PATCH] feat:detail,update planning,task schedule,blog,contest,curated content --- .../contributor/blog/components/columns.tsx | 15 +- .../contributor/blog/detail/[id]/page.tsx | 15 + .../schedule/event/components/columns.tsx | 53 ++- .../schedule/event/detail/[id]/page.tsx | 22 + .../schedule/event/update/[id]/page.tsx | 23 + .../press-conference/components/columns.tsx | 36 +- .../press-conference/detail/[id]/page.tsx | 4 +- .../press-conference/update/[id]/page.tsx | 22 + .../press-release/components/columns.tsx | 53 ++- .../press-release/detail/[id]/page.tsx | 17 + .../press-release/update/[id]/page.tsx | 23 + .../contributor/task/detail/[id]/page.tsx | 3 +- .../shared/contest/components/columns.tsx | 15 +- .../shared/contest/detail/[id]/page.tsx | 17 + components/form/blog/blog--detail-form.tsx | 443 ++++++++++++++++++ .../form/contest/contest-detail-form.tsx | 391 ++++++++++++++++ .../form/schedule/event-detail-form.tsx | 320 +++++++++++++ .../form/schedule/event-update-form.tsx | 400 ++++++++++++++++ .../schedule/pers-release--detail-form.tsx | 345 ++++++++++++++ .../schedule/pers-release--update-form.tsx | 424 +++++++++++++++++ .../form/schedule/pers-release-form.tsx | 2 +- .../schedule/press-conference-detail-form.tsx | 89 ++-- .../form/schedule/press-conference-form.tsx | 10 - .../schedule/press-conference-update-form.tsx | 400 ++++++++++++++++ components/form/task/task-detail-form.tsx | 396 ++++++++++++++++ components/form/task/task-form.tsx | 392 +++++++--------- service/blog/blog.ts | 7 +- service/contest/contest.ts | 6 + service/schedule/schedule.ts | 15 +- 29 files changed, 3606 insertions(+), 352 deletions(-) create mode 100644 app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/schedule/event/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/schedule/event/update/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/schedule/press-conference/update/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/schedule/press-release/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/schedule/press-release/update/[id]/page.tsx create mode 100644 app/[locale]/(protected)/shared/contest/detail/[id]/page.tsx create mode 100644 components/form/blog/blog--detail-form.tsx create mode 100644 components/form/contest/contest-detail-form.tsx create mode 100644 components/form/schedule/event-detail-form.tsx create mode 100644 components/form/schedule/event-update-form.tsx create mode 100644 components/form/schedule/pers-release--detail-form.tsx create mode 100644 components/form/schedule/pers-release--update-form.tsx create mode 100644 components/form/schedule/press-conference-update-form.tsx create mode 100644 components/form/task/task-detail-form.tsx diff --git a/app/[locale]/(protected)/contributor/blog/components/columns.tsx b/app/[locale]/(protected)/contributor/blog/components/columns.tsx index 8dd458d6..c69445ed 100644 --- a/app/[locale]/(protected)/contributor/blog/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/blog/components/columns.tsx @@ -12,6 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -95,18 +96,22 @@ const columns: ColumnDef[] = [ - - - View - + + + + View + + + {/* Edit + Delete - + */} ); diff --git a/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx new file mode 100644 index 00000000..1906dc83 --- /dev/null +++ b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx @@ -0,0 +1,15 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormBlogDetail from "@/components/form/blog/blog--detail-form"; + +const BlogDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default BlogDetailPage; diff --git a/app/[locale]/(protected)/contributor/schedule/event/components/columns.tsx b/app/[locale]/(protected)/contributor/schedule/event/components/columns.tsx index 7cf801d5..85734969 100644 --- a/app/[locale]/(protected)/contributor/schedule/event/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/schedule/event/components/columns.tsx @@ -11,6 +11,7 @@ import { } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -54,11 +55,17 @@ const columns: ColumnDef[] = [ ), }, { - accessorKey: "startTime", + accessorKey: "time", header: "Time", - cell: ({ row }) => ( - {row.getValue("startTime")} - ), + cell: ({ row }: { row: { original: any } }) => { + console.log("Row Original Data:", row.original); + const { startTime, endTime } = row.original; + return ( + + {startTime || "N/A"} - {endTime || "N/A"} + + ); + }, }, { accessorKey: "address", @@ -99,11 +106,17 @@ const columns: ColumnDef[] = [ }, }, { - accessorKey: "speakerName", + accessorKey: "speaker", header: "Disampaikan oleh", - cell: ({ row }) => ( - {row.getValue("speakerName")} - ), + cell: ({ row }: { row: { original: any } }) => { + console.log("Row Original Data:", row.original); + const { speakerTitle, speakerName } = row.original; + return ( + + {speakerTitle || ""} {speakerName || ""} + + ); + }, }, { accessorKey: "uploaderName", @@ -131,14 +144,22 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - + + + + View + + + + + + Edit + + Delete diff --git a/app/[locale]/(protected)/contributor/schedule/event/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/event/detail/[id]/page.tsx new file mode 100644 index 00000000..2d763463 --- /dev/null +++ b/app/[locale]/(protected)/contributor/schedule/event/detail/[id]/page.tsx @@ -0,0 +1,22 @@ +"use client"; +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormPressConference from "@/components/form/schedule/press-conference-form"; +import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form"; +import { useParams } from "next/navigation"; +import { id } from "date-fns/locale"; +import FormEventDetail from "@/components/form/schedule/event-detail-form"; + +const EventDetailPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default EventDetailPage; diff --git a/app/[locale]/(protected)/contributor/schedule/event/update/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/event/update/[id]/page.tsx new file mode 100644 index 00000000..8ec63d19 --- /dev/null +++ b/app/[locale]/(protected)/contributor/schedule/event/update/[id]/page.tsx @@ -0,0 +1,23 @@ +"use client"; +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormPressConference from "@/components/form/schedule/press-conference-form"; +import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form"; +import { useParams } from "next/navigation"; +import { id } from "date-fns/locale"; +import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form"; +import FormEventUpdate from "@/components/form/schedule/event-update-form"; + +const EventUpdatePage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default EventUpdatePage; diff --git a/app/[locale]/(protected)/contributor/schedule/press-conference/components/columns.tsx b/app/[locale]/(protected)/contributor/schedule/press-conference/components/columns.tsx index c1cb2775..7e9737aa 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-conference/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-conference/components/columns.tsx @@ -106,11 +106,17 @@ const columns: ColumnDef[] = [ }, }, { - accessorKey: "speakerName", + accessorKey: "speaker", header: "Disampaikan oleh", - cell: ({ row }) => ( - {row.getValue("speakerName")} - ), + cell: ({ row }: { row: { original: any } }) => { + console.log("Row Original Data:", row.original); + const { speakerTitle, speakerName } = row.original; + return ( + + {speakerTitle || ""} {speakerName || ""} + + ); + }, }, { accessorKey: "uploaderName", @@ -138,16 +144,22 @@ const columns: ColumnDef[] = [ - - + + Detail - - - - - Edit - + + + + + + Edit + + Delete diff --git a/app/[locale]/(protected)/contributor/schedule/press-conference/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/press-conference/detail/[id]/page.tsx index f7c5fc34..91ddc013 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-conference/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-conference/detail/[id]/page.tsx @@ -8,13 +8,11 @@ import { useParams } from "next/navigation"; import { id } from "date-fns/locale"; const PressConDetailPage = () => { - const params = useParams(); - const id = params?.id; return (
- +
); diff --git a/app/[locale]/(protected)/contributor/schedule/press-conference/update/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/press-conference/update/[id]/page.tsx new file mode 100644 index 00000000..75f0e4b1 --- /dev/null +++ b/app/[locale]/(protected)/contributor/schedule/press-conference/update/[id]/page.tsx @@ -0,0 +1,22 @@ +"use client"; +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormPressConference from "@/components/form/schedule/press-conference-form"; +import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form"; +import { useParams } from "next/navigation"; +import { id } from "date-fns/locale"; +import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form"; + +const PressConUpdatePage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default PressConUpdatePage; diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/components/columns.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/components/columns.tsx index 7cf801d5..0bfb7dfa 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-release/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-release/components/columns.tsx @@ -11,6 +11,7 @@ import { } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -54,11 +55,17 @@ const columns: ColumnDef[] = [ ), }, { - accessorKey: "startTime", + accessorKey: "time", header: "Time", - cell: ({ row }) => ( - {row.getValue("startTime")} - ), + cell: ({ row }: { row: { original: any } }) => { + console.log("Row Original Data:", row.original); + const { startTime, endTime } = row.original; + return ( + + {startTime || "N/A"} - {endTime || "N/A"} + + ); + }, }, { accessorKey: "address", @@ -99,11 +106,17 @@ const columns: ColumnDef[] = [ }, }, { - accessorKey: "speakerName", + accessorKey: "speaker", header: "Disampaikan oleh", - cell: ({ row }) => ( - {row.getValue("speakerName")} - ), + cell: ({ row }: { row: { original: any } }) => { + console.log("Row Original Data:", row.original); + const { speakerTitle, speakerName } = row.original; + return ( + + {speakerTitle || ""} {speakerName || ""} + + ); + }, }, { accessorKey: "uploaderName", @@ -131,14 +144,22 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - + + + + View + + + + + + Edit + + Delete diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/detail/[id]/page.tsx new file mode 100644 index 00000000..6d5f0765 --- /dev/null +++ b/app/[locale]/(protected)/contributor/schedule/press-release/detail/[id]/page.tsx @@ -0,0 +1,17 @@ +"use client"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form"; +import FormDetailPressRillis from "@/components/form/schedule/pers-release--detail-form"; + +const PressRilisDetailPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default PressRilisDetailPage; diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/update/[id]/page.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/update/[id]/page.tsx new file mode 100644 index 00000000..9fbd61a3 --- /dev/null +++ b/app/[locale]/(protected)/contributor/schedule/press-release/update/[id]/page.tsx @@ -0,0 +1,23 @@ +"use client"; +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormPressConference from "@/components/form/schedule/press-conference-form"; +import FormDetailPressConference from "@/components/form/schedule/press-conference-detail-form"; +import { useParams } from "next/navigation"; +import { id } from "date-fns/locale"; +import FormUpdatePressConference from "@/components/form/schedule/press-conference-update-form"; +import FormUpdatePressRelease from "@/components/form/schedule/pers-release--update-form"; + +const PressRilisUpdatePage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default PressRilisUpdatePage; diff --git a/app/[locale]/(protected)/contributor/task/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/task/detail/[id]/page.tsx index cafd8320..dde3a7ba 100644 --- a/app/[locale]/(protected)/contributor/task/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/contributor/task/detail/[id]/page.tsx @@ -1,13 +1,14 @@ import { Card, CardContent } from "@/components/ui/card"; import SiteBreadcrumb from "@/components/site-breadcrumb"; import FormTask from "@/components/form/task/task-form"; +import FormTaskDetail from "@/components/form/task/task-detail-form"; const TaskDetailPage = async () => { return (
- +
); diff --git a/app/[locale]/(protected)/shared/contest/components/columns.tsx b/app/[locale]/(protected)/shared/contest/components/columns.tsx index 543b90ba..ff85fdcb 100644 --- a/app/[locale]/(protected)/shared/contest/components/columns.tsx +++ b/app/[locale]/(protected)/shared/contest/components/columns.tsx @@ -12,6 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -108,18 +109,20 @@ const columns: ColumnDef[] = [ - - - View - - + + + + View + + + {/* Edit Delete - + */} ); diff --git a/app/[locale]/(protected)/shared/contest/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/contest/detail/[id]/page.tsx new file mode 100644 index 00000000..a5dc7d1e --- /dev/null +++ b/app/[locale]/(protected)/shared/contest/detail/[id]/page.tsx @@ -0,0 +1,17 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormContestDetail from "@/components/form/contest/contest-detail-form"; + +const ContestDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default ContestDetailPage; diff --git a/components/form/blog/blog--detail-form.tsx b/components/form/blog/blog--detail-form.tsx new file mode 100644 index 00000000..6ed692d2 --- /dev/null +++ b/components/form/blog/blog--detail-form.tsx @@ -0,0 +1,443 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { register } from "module"; +import { Switch } from "@/components/ui/switch"; +import Cookies from "js-cookie"; +import { createTask } from "@/config/api"; +import { + createMedia, + getTagsBySubCategoryId, + listEnableCategory, +} from "@/service/content/content"; +import { getBlog, postBlog } from "@/service/blog/blog"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + slug: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + categoryName: z.string().min(1, { message: "Kategori diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +type Detail = { + id: string; + title: string; + description: string; + slug: string; + metadata: string; + categoryName: string; + thumbnailLink: string; +}; + +const initialCategories: Category[] = [ + { + id: "1", + categoryName: "Giat Polri", + }, + { + id: "2", + categoryName: "Giat Pimpinan", + }, + { + id: "3", + categoryName: "Liputan Kegiatan", + }, + { + id: "4", + categoryName: "Seputar Prestasi", + }, +]; + +export default function FormBlogDetail() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type TaskSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + + const [categories] = useState(initialCategories); + const [selectedTarget, setSelectedTarget] = useState(""); + const [selectedCategory, setSelectedCategory] = useState(); + const [tags, setTags] = useState([]); + const [isDraft, setIsDraft] = useState(false); + + const [detail, setDetail] = useState(); + const [refresh, setRefresh] = useState(false); + + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + let fileTypeId = "1"; + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + // const handleKeyDown = (e: any) => { + // const newTag = e.target.value.trim(); // Ambil nilai input + // if (e.key === "Enter" && newTag) { + // e.preventDefault(); // Hentikan submit form + // if (!tags.includes(newTag)) { + // setTags((prevTags) => [...prevTags, newTag]); // Tambah tag baru + // setValue("tags", ""); // Kosongkan input + // } + // } + // }; + + const handleRemoveTag = (index: any) => { + setTags((prevTags) => prevTags.filter((_, i) => i !== index)); + }; + + const handleImageChange = (event: ChangeEvent) => { + if (event.target.files) { + const files = Array.from(event.target.files); + setSelectedFiles((prevImages: any) => [...prevImages, ...files]); + console.log("DATAFILE::", selectedFiles); + } + }; + + const handleRemoveImage = (index: number) => { + setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getBlog(id); + const details = response.data?.data; + + setDetail(details); + + // Set categoryId dari API ke form dan Select + setValue("categoryName", details.categoryName); + setSelectedTarget(details.categoryId); // Untuk dropdown + } + } + initState(); + }, [refresh, setValue]); + + const save = async (data: TaskSchema) => { + const requestData = { + ...data, + title: data.title, + description: data.description, + categoryId: selectedTarget, + slug: data.slug, + metadata: data.meta, + // tags: data.tags, + isDraft, + }; + + const response = await postBlog(requestData); + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/contributor/blog"); + }); + }; + + const onSubmit = (data: TaskSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + const handlePublish = () => { + setIsDraft(false); + }; + + const handleSave = () => { + setIsDraft(true); + }; + + return ( +
+ {detail !== undefined ? ( +
+ +
+

Detail Indeks

+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+ +
+ + ( + + )} + /> + {errors.description?.message && ( +

+ {errors.description.message} +

+ )} +
+
+
+ + ( + + )} + /> + {errors.slug?.message && ( +

+ {errors.slug.message} +

+ )} +
+
+
+
+ + ( + + )} + /> + {errors.meta?.message && ( +

+ {errors.meta.message} +

+ )} +
+
+
+
+
+
+ +
+ + { + // const file = e.target.files[0]; + // if (file) { + // console.log("Selected File:", file); + // // Tambahkan logika jika diperlukan, misalnya upload file ke server + // } + // }} + className="" + /> +
+
+ + + Thumbnail Gambar Utama + +
+
+ + ( + + )} + /> +
+
+ + {/* ( + + )} + /> */} +
+ {tags.length === 0 && "Please add at least one tag."} +
+
+ {tags.map((tag, index) => ( +
+ {tag} + +
+ ))} +
+
+
+ {/*
+
+ +
+
+ +
+
+ +
+
*/} +
+
+ ) : ( + "" + )} +
+ ); +} diff --git a/components/form/contest/contest-detail-form.tsx b/components/form/contest/contest-detail-form.tsx new file mode 100644 index 00000000..bbe69784 --- /dev/null +++ b/components/form/contest/contest-detail-form.tsx @@ -0,0 +1,391 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { createTask, getTask } from "@/service/task"; +import { getContestById } from "@/service/contest/contest"; +import page from "@/app/[locale]/page"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { cn } from "@/lib/utils"; +import { CalendarIcon } from "lucide-react"; +import { format, parseISO } from "date-fns"; +import { Calendar } from "@/components/ui/calendar"; +import { DateRange } from "react-day-picker"; + +const contestSchema = z.object({ + theme: z.string().min(1, { message: "Judul diperlukan" }), + hastagCode: z.string().min(1, { message: "Judul diperlukan" }), + description: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +export type taskDetail = { + id: number; + theme: string; + hastagCode: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + assignmentMainType: { + id: number; + name: string; + }; + + targetOutput: string; + targetParticipantTopLevel: string; + description: string; + is_active: string; +}; + +export default function FormContestDetail() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type ContestSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + + // State for various form fields + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + + // const [assignmentType, setAssignmentType] = useState("mediahub"); + // const [assignmentCategory, setAssignmentCategory] = useState("publication"); + const [mainType, setMainType] = useState("1"); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState(""); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("all"); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [date, setDate] = useState(); + + const [platformTypeVisible, setPlatformTypeVisible] = useState(false); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + const { + control, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(contestSchema), + }); + + // const handleRadioChange = (event: React.ChangeEvent) => { + // const selectedValue = Number(event.target.value); + // setMainType(selectedValue); + + // setPlatformTypeVisible(selectedValue === 2); + // }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getContestById(id); + const details = response.data?.data; + + setDetail(details); + // if (details?.createdAt) { + // // Memisahkan string duration menjadi start dan end date + // const [startDate, endDate] = details.createdAt.split(" - "); + // setDate({ + // from: parseISO(startDate), + // to: parseISO(endDate), + // }); + // } + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.targetOutput) { + const outputSet = new Set(detail.targetOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor + setTaskOutput({ + all: outputSet.has(0), + video: outputSet.has(2), + audio: outputSet.has(4), + image: outputSet.has(1), + text: outputSet.has(3), + }); + } + }, [detail?.targetOutput]); + + useEffect(() => { + if (detail?.targetParticipantTopLevel) { + const outputSet = new Set( + detail.targetParticipantTopLevel.split(",").map(Number) + ); + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.targetParticipantTopLevel]); + + const save = async (data: ContestSchema) => { + const fileTypeMapping = { + all: "1", + video: "2", + audio: "3", + image: "4", + text: "5", + }; + + const selectedOutputs = Object.keys(taskOutput) + .filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true` + .map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string + .join(","); + + const requestData = { + ...data, + // assignmentType, + // assignmentCategory, + target: selectedTarget, + unitSelection, + assignedToRole: "3", + taskType: taskType, + broadcastType: broadcastType, + assignmentMainTypeId: mainType, + assignmentPurpose: "1", + assignmentTypeId: type, + fileTypeOutput: selectedOutputs, + id: null, + description: data.description, + platformType: "", + theme: data.theme, + }; + + const response = await createTask(requestData); + + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/contributor/task"); + }); + }; + + const onSubmit = (data: ContestSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + return ( + +
+

Form Contest

+ {detail !== undefined ? ( +
+
+
+ + ( + + )} + /> + {errors.hastagCode?.message && ( +

+ {errors.hastagCode.message} +

+ )} +
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.theme?.message && ( +

{errors.theme.message}

+ )} +
+
+ + + + + + + + + +
+
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+ +
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
+ +
+ + ( + + )} + /> + {errors.description?.message && ( +

+ {errors.description.message} +

+ )} +
+
+ + {/* Submit Button */} +
+ +
+
+ ) : ( + "" + )} +
+
+ ); +} diff --git a/components/form/schedule/event-detail-form.tsx b/components/form/schedule/event-detail-form.tsx new file mode 100644 index 00000000..57d9c072 --- /dev/null +++ b/components/form/schedule/event-detail-form.tsx @@ -0,0 +1,320 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { Switch } from "@/components/ui/switch"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { cn } from "@/lib/utils"; +import { CalendarIcon } from "lucide-react"; +import { Calendar } from "@/components/ui/calendar"; +import { addDays, format, parseISO, setDate } from "date-fns"; +import { DateRange } from "react-day-picker"; +import TimePicker from "react-time-picker"; +import "react-time-picker/dist/TimePicker.css"; +import "react-clock/dist/Clock.css"; +import MapHome from "@/components/maps/MapHome"; +import { Textarea } from "@/components/ui/textarea"; +import { error, loading } from "@/lib/swal"; +import Cookies from "js-cookie"; +import { detailSchedule, postSchedule } from "@/service/schedule/schedule"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + level: z.string().min(1, { message: "Judul diperlukan" }), + name: z.string().min(1, { message: "Judul diperlukan" }), + location: z.string().min(1, { message: "Judul diperlukan" }), +}); + +interface Detail { + id: number; + title: string; + address: string; + speakerTitle: string; + speakerName: string; + addressLat: number; + addressLong: number; +} + +export default function FormEventDetail() { + const { id } = useParams() as { id: string }; + console.log(id); + const router = useRouter(); + const [isLiveStreamingEnabled, setIsLiveStreamingEnabled] = useState(false); + type TaskSchema = z.infer; + const [startTime, setStartTime] = useState("08:00"); + const [endTime, setEndTime] = useState("09:00"); + const [date, setDate] = useState(); + + const [detail, setDetail] = useState(); + const [refresh, setRefresh] = useState(false); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + defaultValues: { + location: "", + }, + }); + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailSchedule(id); + const details = response.data?.data; + + setDetail(details); + if (details) { + setDate({ + from: parseISO(details.startDate), + to: parseISO(details.endDate), + }); + } + if (details) { + setStartTime(details.startTime); + setEndTime(details.endTime); + } + } + } + initState(); + }, [refresh, setValue]); + + const handleStartTime = (e: React.ChangeEvent) => { + setStartTime(e.target.value); + }; + + const handleEndTime = (e: React.ChangeEvent) => { + setEndTime(e.target.value); + }; + + return ( +
+ +
+

Form Event

+ {detail !== undefined ? ( +
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+
+
+ +
+

Aktifkan fitur live streaming

+ + setIsLiveStreamingEnabled(checked) + } + /> +
+
+
+ + {isLiveStreamingEnabled && ( +
+ ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+ )} + +
+
+ + + + + + + + + +
+
+ +
+
+
+ +
+
+ +
+
+
+
+
+
+ {/* Kirim setValue ke MapHome */} + setValue("location", location)} + /> +
+
+ ( +