From fa35e4d2f5b26052e05668867967fd117409f09e Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Tue, 17 Dec 2024 21:27:47 +0700 Subject: [PATCH] feat:curated-content page,detail, detail planning, detail task --- .../(protected)/contributor/blog/page.tsx | 2 +- .../planning/mediahub/components/columns.tsx | 22 +- .../planning/mediahub/publish/[id]/page.tsx | 17 + .../medsos-mediahub/components/columns.tsx | 18 +- .../medsos-mediahub/publish/[id]/page.tsx | 16 + .../components/pressrilis-table.tsx | 2 +- .../contributor/task/components/columns.tsx | 11 +- app/[locale]/(protected)/dashboard/page.tsx | 27 +- .../giat-routine/audio/audio.tsx | 6 +- .../giat-routine/audio/detail/[id]/page.tsx | 549 +++++++++++++++++ .../document/detail/[id]/page.tsx | 518 ++++++++++++++++ .../giat-routine/document/teks.tsx | 6 +- .../giat-routine/image/detail/[id]/page.tsx | 508 +++++++++++----- .../giat-routine/video/audio-visual.tsx | 58 +- .../giat-routine/video/detail/[id]/page.tsx | 551 ++++++++++++++++++ components/form/planning/mediahub-publish.tsx | 352 +++++++++++ components/form/planning/medsos-publish.tsx | 352 +++++++++++ components/form/task/task-form.tsx | 414 +++++++------ service/curated-content/curated-content.ts | 6 + service/planning/planning.ts | 6 + service/task.ts | 2 +- 21 files changed, 3047 insertions(+), 396 deletions(-) create mode 100644 app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx create mode 100644 app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx create mode 100644 components/form/planning/mediahub-publish.tsx create mode 100644 components/form/planning/medsos-publish.tsx create mode 100644 service/curated-content/curated-content.ts diff --git a/app/[locale]/(protected)/contributor/blog/page.tsx b/app/[locale]/(protected)/contributor/blog/page.tsx index 79d07bb0..6cfc19b4 100644 --- a/app/[locale]/(protected)/contributor/blog/page.tsx +++ b/app/[locale]/(protected)/contributor/blog/page.tsx @@ -19,7 +19,7 @@ const BlogPage = async () => {
- diff --git a/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx b/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx index bf6e2a14..eb08dbd9 100644 --- a/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/planning/mediahub/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[] = [ { @@ -91,15 +92,18 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - - + + + + Publish + + + deletePlan(row.id)} + > Delete diff --git a/app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx b/app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx new file mode 100644 index 00000000..9f25656d --- /dev/null +++ b/app/[locale]/(protected)/contributor/planning/mediahub/publish/[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 PublishMediahub from "@/components/form/planning/mediahub-publish"; + +const MediahubPublishPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default MediahubPublishPage; diff --git a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx index bf6e2a14..f7820c16 100644 --- a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/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[] = [ { @@ -91,14 +92,15 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - + + + + Publish + + + Delete diff --git a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx new file mode 100644 index 00000000..7920fc4e --- /dev/null +++ b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx @@ -0,0 +1,16 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import PublishMedsos from "@/components/form/planning/medsos-publish"; + +const MedsosPublishPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default MedsosPublishPage; diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx index 54ca8b08..a66fb7ec 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx @@ -124,7 +124,7 @@ const PressReleaseTable = () => { return (
-
+
diff --git a/app/[locale]/(protected)/contributor/task/components/columns.tsx b/app/[locale]/(protected)/contributor/task/components/columns.tsx index b998497f..3d7be186 100644 --- a/app/[locale]/(protected)/contributor/task/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/task/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[] = [ { @@ -111,10 +112,12 @@ const columns: ColumnDef[] = [ - - - View - + + + + View + + Edit diff --git a/app/[locale]/(protected)/dashboard/page.tsx b/app/[locale]/(protected)/dashboard/page.tsx index 6ba33d22..b44c2581 100644 --- a/app/[locale]/(protected)/dashboard/page.tsx +++ b/app/[locale]/(protected)/dashboard/page.tsx @@ -10,6 +10,7 @@ import PressConferenceTable from "../contributor/schedule/press-release/componen import BlogTable from "../contributor/blog/components/blog-table"; import ContentTable from "./routine-task/components/content-table"; import RecentActivity from "./routine-task/components/recent-activity"; +import { Link } from "@/components/navigation"; const DashboardPage = () => { const t = useTranslations("AnalyticsDashboard"); @@ -110,14 +111,16 @@ const DashboardPage = () => { Table Penugasan
- + + +
- + @@ -128,7 +131,7 @@ const DashboardPage = () => {
- + @@ -145,14 +148,16 @@ const DashboardPage = () => { Table Indeks
- + + +
- + diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx index 501bfd72..e18d163c 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx @@ -62,8 +62,8 @@ const AudioSliderPage = () => {
{displayAudio?.map((audio: any) => ( - @@ -118,7 +118,7 @@ const AudioSliderPage = () => {
- + ))}
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx new file mode 100644 index 00000000..5e41f378 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx @@ -0,0 +1,549 @@ +"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, CardContent } 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 { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: 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." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailAudio() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

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

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx new file mode 100644 index 00000000..afa89b2b --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx @@ -0,0 +1,518 @@ +"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, CardContent } 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 { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; +import JoditEditor from "jodit-react"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: 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." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailDocument() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

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

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx index 8c3a988c..20e89711 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx @@ -61,8 +61,8 @@ const TeksSliderPage = () => { - + ))}
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx index de23584b..05ad3fff 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx @@ -9,7 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; -import { useRouter } from "next/navigation"; +import { useParams, useRouter } from "next/navigation"; import { Select, SelectContent, @@ -17,25 +17,26 @@ import { 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 { postBlog } from "@/service/blog/blog"; import { Textarea } from "@/components/ui/textarea"; -import { InboxIcon } from "lucide-react"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; -const taskSchema = z.object({ +const detailSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), - slug: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: z.string().min(1, { message: "Judul diperlukan" }), meta: z.string().min(1, { message: "Judul diperlukan" }), description: z .string() @@ -45,130 +46,151 @@ const taskSchema = z.object({ type Category = { id: string; - name: string; + categoryName: string; }; -const initialCategories: Category[] = [ +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ { - id: "1", - name: "Giat Polri", + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan }, { - id: "2", - name: "Giat Pimpinan", + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan }, { - id: "3", - name: "Liputan Kegiatan", - }, - { - id: "4", - name: "Seputar Prestasi", + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan }, ]; export default function DetailImage() { const MySwal = withReactContent(Swal); - const router = useRouter(); + const { id } = useParams() as { id: string }; + console.log(id); const editor = useRef(null); - type TaskSchema = z.infer; + type DetailSchema = 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); // State untuk kategori const [selectedTarget, setSelectedTarget] = useState(""); - const [selectedCategory, setSelectedCategory] = useState(); - const [tags, setTags] = useState([]); - const [isDraft, setIsDraft] = useState(false); - - const [unitSelection, setUnitSelection] = useState({ - allUnit: false, - mabes: false, - polda: false, - polres: false, - }); - - let fileTypeId = "1"; + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); const { control, handleSubmit, setValue, formState: { errors }, - } = useForm({ - resolver: zodResolver(taskSchema), + } = useForm({ + resolver: zodResolver(detailSchema), }); - const handleRemoveTag = (index: any) => { - setTags((prevTags) => prevTags.filter((_, i) => i !== index)); + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); }; - 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 addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); } }; - const handleRemoveImage = (index: number) => { - setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); - }; + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; - 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); + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); } - }); - }; + } + initState(); + }, [id, refresh]); return ( -
-
+
+ {detail !== undefined ? (

Kurasi Detail

-
+
@@ -183,6 +205,7 @@ export default function DetailImage() { value={field.value} onChange={field.onChange} placeholder="Enter Title" + defaultValue={detail.title} /> )} /> @@ -195,27 +218,20 @@ export default function DetailImage() {
- + ( + + )} + />
@@ -223,18 +239,19 @@ export default function DetailImage() { ( +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+
-
- + ) : ( + "" + )} +
); } diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx index 5d4b4804..523f860e 100644 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx @@ -1,8 +1,10 @@ "use client"; +import { Link } from "@/components/navigation"; import { Card, CardContent } from "@/components/ui/card"; import { getListContent } from "@/service/landing/landing"; import { formatDateToIndonesian } from "@/utils/globals"; import { Icon } from "@iconify/react/dist/iconify.js"; +import image from "next/image"; import React, { useEffect, useState } from "react"; const VideoSliderPage = () => { @@ -53,32 +55,36 @@ const VideoSliderPage = () => { key={video?.id} className="hover:scale-110 transition-transform duration-300" > - - -
- {formatDateToIndonesian(new Date(video?.createdAt))}{" "} - {video?.timezone || "WIB"} | - - {video?.clickCount} - - - -
-
- {video?.title} -
-
+ + + +
+ {formatDateToIndonesian(new Date(video?.createdAt))}{" "} + {video?.timezone || "WIB"} | + + {video?.clickCount} + + + +
+
+ {video?.title} +
+
+ ))}
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx new file mode 100644 index 00000000..ce86d7b7 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx @@ -0,0 +1,551 @@ +"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, CardContent } 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 { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: 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." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailImage() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailVideo, setDetailVideo] = useState([]); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { url: string }) => + file.url ? file.url : "default-image.jpg" + ); + setDetailVideo(fileUrls); + const filesDataThumbnail = details.files || []; + const fileUrlsThumbnail = filesDataThumbnail.map( + (file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrlsThumbnail); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

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

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/components/form/planning/mediahub-publish.tsx b/components/form/planning/mediahub-publish.tsx new file mode 100644 index 00000000..49060fa6 --- /dev/null +++ b/components/form/planning/mediahub-publish.tsx @@ -0,0 +1,352 @@ +"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 } from "@/service/task"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; +import { id } from "date-fns/locale"; +import { getPlanningById } from "@/service/planning/planning"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +export type mediahubDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + date: string; + description: string; + is_active: string; +}; + +export default function PublishMediahub() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + const [mainType, setMainType] = useState(1); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState("all"); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("all"); + const [startDate, setStartDate] = useState(new Date()); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + + 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(taskSchema), + }); + + 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 getPlanningById(id); + const details = response.data?.data; + + setDetail(details); + if (details?.date) { + setStartDate(new Date(details.date)); // Konversi string tanggal ke objek Date + } + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.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?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); // Membagi string ke dalam array dan mengonversi ke nomor + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + const save = async (data: TaskSchema) => { + 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, + narration: data.naration, + platformType: "", + title: data.title, + }; + + 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: 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); + } + }); + }; + + return ( + +
+

Perencanaan Mediahub

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

{errors.title.message}

+ )} +
+
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ +
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

+ )} +
+
+ + {/* Submit Button */} +
+ +
+
+ ) : ( + "" + )} +
+
+ ); +} diff --git a/components/form/planning/medsos-publish.tsx b/components/form/planning/medsos-publish.tsx new file mode 100644 index 00000000..5124f4a4 --- /dev/null +++ b/components/form/planning/medsos-publish.tsx @@ -0,0 +1,352 @@ +"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 } from "@/service/task"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; +import { id } from "date-fns/locale"; +import { getPlanningById } from "@/service/planning/planning"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +export type medsosDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + date: string; + description: string; + is_active: string; +}; + +export default function PublishMedsos() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + const [mainType, setMainType] = useState(1); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState("all"); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("all"); + const [startDate, setStartDate] = useState(new Date()); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + + 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(taskSchema), + }); + + 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 getPlanningById(id); + const details = response.data?.data; + + setDetail(details); + if (details?.date) { + setStartDate(new Date(details.date)); // Konversi string tanggal ke objek Date + } + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.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?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); // Membagi string ke dalam array dan mengonversi ke nomor + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + const save = async (data: TaskSchema) => { + 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, + narration: data.naration, + platformType: "", + title: data.title, + }; + + 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: 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); + } + }); + }; + + return ( + +
+

Perencanaan Mediahub

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

{errors.title.message}

+ )} +
+
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ +
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

+ )} +
+
+ + {/* Submit Button */} +
+ +
+
+ ) : ( + "" + )} +
+
+ ); +} diff --git a/components/form/task/task-form.tsx b/components/form/task/task-form.tsx index cee28706..37e5d9fa 100644 --- a/components/form/task/task-form.tsx +++ b/components/form/task/task-form.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useRef, useState } from "react"; +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"; @@ -9,7 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; -import { useRouter } from "next/navigation"; +import { useParams, useRouter } from "next/navigation"; import { Select, SelectContent, @@ -20,7 +20,7 @@ import { import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import JoditEditor from "jodit-react"; -import { createTask } from "@/service/task"; +import { createTask, getTask } from "@/service/task"; const taskSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -29,11 +29,32 @@ const taskSchema = z.object({ }), }); +export type taskDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + assignmentMainType: { + id: number; + name: string; + }; + taskType: string; + broadcastType: string; + narration: string; + is_active: string; +}; + export default function FormTask() { const MySwal = withReactContent(Swal); const router = useRouter(); const editor = useRef(null); type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); // State for various form fields const [taskOutput, setTaskOutput] = useState({ @@ -46,11 +67,13 @@ export default function FormTask() { // const [assignmentType, setAssignmentType] = useState("mediahub"); // const [assignmentCategory, setAssignmentCategory] = useState("publication"); - const [mainType, setMainType] = useState(1); + const [mainType, setMainType] = useState("1"); const [taskType, setTaskType] = useState("atensi-khusus"); - const [broadcastType, setBroadcastType] = useState("all"); // untuk Tipe Penugasan + 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 [platformTypeVisible, setPlatformTypeVisible] = useState(false); const [unitSelection, setUnitSelection] = useState({ @@ -68,12 +91,57 @@ export default function FormTask() { resolver: zodResolver(taskSchema), }); - const handleRadioChange = (event: React.ChangeEvent) => { - const selectedValue = Number(event.target.value); - setMainType(selectedValue); + // const handleRadioChange = (event: React.ChangeEvent) => { + // const selectedValue = Number(event.target.value); + // setMainType(selectedValue); - setPlatformTypeVisible(selectedValue === 2); - }; + // setPlatformTypeVisible(selectedValue === 2); + // }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getTask(id); + const details = response.data?.data; + + setDetail(details); + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.broadcastType) { + setBroadcastType(detail.broadcastType); // Mengatur nilai broadcastType dari API + } + }, [detail?.broadcastType]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.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?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); const save = async (data: TaskSchema) => { const fileTypeMapping = { @@ -144,172 +212,184 @@ export default function FormTask() {

Form Penugasan

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

{errors.title.message}

)} - /> - {errors.title?.message && ( -

{errors.title.message}

- )} -
-
+
+
+
+ + +
+
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
- - + + setMainType(value)} + // value={String(mainType)} + // onValueChange={(value) => setMainType(Number(value))} + className="flex flex-wrap gap-3" + > + + + + +
-
- {Object.keys(unitSelection).map((key) => ( -
- - setUnitSelection({ ...unitSelection, [key]: value }) - } - /> - +
+ + setTaskType(String(value))} + className="flex flex-wrap gap-3" + > + + + + + +
+ {/* RadioGroup Assignment Category */} +
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ +
- ))} -
-
- -
- - setMainType(Number(value))} - className="flex flex-wrap gap-3" - > - - - - - -
-
- - setTaskType(String(value))} - className="flex flex-wrap gap-3" - > - - - - - -
- {/* RadioGroup Assignment Category */} -
- - setType(value)} // Mengubah nilai state ketika pilihan berubah - className="flex flex-wrap gap-3" - > -
- - -
-
- - -
-
- - -
-
-
- -
- -
- {Object.keys(taskOutput).map((key) => ( -
- - setTaskOutput({ ...taskOutput, [key]: value }) - } - /> - +
+ +
- ))} +
+ + +
+
-
-
- - setBroadcastType(String(value))} - className="flex flex-wrap gap-3" - > - - - - - - - -
-
- - ( - +
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+ + setBroadcastType(value)} // Mengatur nilai saat radio berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

)} - /> - {errors.naration?.message && ( -

- {errors.naration.message} -

- )} +
-
- {/* Submit Button */} -
- -
- + {/* Submit Button */} +
+ +
+ + ) : ( + "" + )}
); diff --git a/service/curated-content/curated-content.ts b/service/curated-content/curated-content.ts new file mode 100644 index 00000000..af1628f4 --- /dev/null +++ b/service/curated-content/curated-content.ts @@ -0,0 +1,6 @@ +import { getAPIInterceptor } from "@/config/api"; + +export async function detailMedia(id: any) { + const url = `media?id=${id}`; + return getAPIInterceptor(url); +} diff --git a/service/planning/planning.ts b/service/planning/planning.ts index 09419b25..c0010852 100644 --- a/service/planning/planning.ts +++ b/service/planning/planning.ts @@ -1,3 +1,4 @@ +import { getAPIInterceptor } from "@/config/api"; import { httpGetInterceptor } from "../http-config/http-interceptor-service"; export async function getPlanningSentPagination( @@ -10,3 +11,8 @@ export async function getPlanningSentPagination( `planning/pagination/sent?enablePage=1&size=${size}&page=${page}&typeId=${typeId}&title=${title}` ); } + +export async function getPlanningById(id: any) { + const url = `planning?id=${id}`; + return getAPIInterceptor(url); +} diff --git a/service/task.ts b/service/task.ts index c2afd1c6..4aca8bcd 100644 --- a/service/task.ts +++ b/service/task.ts @@ -38,7 +38,7 @@ export async function createTask(data: any) { export async function getTask(id: any) { const url = `/assignment?id=${id}`; - return getAPIInterceptor({ url }); + return getAPIInterceptor(url); } export async function forwardTask(data: any) {