From c9c3297851de422996340ec8ae7e33a0dd1a844b Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Wed, 11 Jun 2025 18:18:56 +0800 Subject: [PATCH 1/3] feat:task-ta --- .../task-ta/detail-upload/audio/[id]/page.tsx | 15 +++++++++++++++ .../task-ta/detail-upload/image/[id]/page.tsx | 3 ++- .../task-ta/detail-upload/teks/[id]/page.tsx | 16 ++++++++++++++++ .../task-ta/detail-upload/video/[id]/page.tsx | 16 ++++++++++++++++ .../form/content/task-ta/audio-detail-form.tsx | 2 +- .../form/content/task-ta/image-detail-form.tsx | 2 +- .../form/content/task-ta/teks-detail-form.tsx | 2 +- .../form/content/task-ta/video-detail-form.tsx | 2 +- components/partials/auth/login-form.tsx | 6 +++--- 9 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 app/[locale]/(protected)/contributor/task-ta/detail-upload/audio/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/task-ta/detail-upload/teks/[id]/page.tsx create mode 100644 app/[locale]/(protected)/contributor/task-ta/detail-upload/video/[id]/page.tsx diff --git a/app/[locale]/(protected)/contributor/task-ta/detail-upload/audio/[id]/page.tsx b/app/[locale]/(protected)/contributor/task-ta/detail-upload/audio/[id]/page.tsx new file mode 100644 index 00000000..38d17aa3 --- /dev/null +++ b/app/[locale]/(protected)/contributor/task-ta/detail-upload/audio/[id]/page.tsx @@ -0,0 +1,15 @@ +import FormAudioTaDetail from "@/components/form/content/task-ta/audio-detail-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; + +const AudioDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default AudioDetailPage; diff --git a/app/[locale]/(protected)/contributor/task-ta/detail-upload/image/[id]/page.tsx b/app/[locale]/(protected)/contributor/task-ta/detail-upload/image/[id]/page.tsx index 4713ac39..47aae6f4 100644 --- a/app/[locale]/(protected)/contributor/task-ta/detail-upload/image/[id]/page.tsx +++ b/app/[locale]/(protected)/contributor/task-ta/detail-upload/image/[id]/page.tsx @@ -1,3 +1,4 @@ +import FormImageTaDetail from "@/components/form/content/task-ta/image-detail-form"; import FormImageDetail from "@/components/form/content/task-ta/image-detail-form"; import SiteBreadcrumb from "@/components/site-breadcrumb"; @@ -6,7 +7,7 @@ const ImageDetailPage = async () => {
- +
); diff --git a/app/[locale]/(protected)/contributor/task-ta/detail-upload/teks/[id]/page.tsx b/app/[locale]/(protected)/contributor/task-ta/detail-upload/teks/[id]/page.tsx new file mode 100644 index 00000000..66cfe9e2 --- /dev/null +++ b/app/[locale]/(protected)/contributor/task-ta/detail-upload/teks/[id]/page.tsx @@ -0,0 +1,16 @@ +import FormTeksTaDetail from "@/components/form/content/task-ta/teks-detail-form"; +import FormTeksDetail from "@/components/form/content/task-ta/teks-detail-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; + +const TeksDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default TeksDetailPage; diff --git a/app/[locale]/(protected)/contributor/task-ta/detail-upload/video/[id]/page.tsx b/app/[locale]/(protected)/contributor/task-ta/detail-upload/video/[id]/page.tsx new file mode 100644 index 00000000..15564b7f --- /dev/null +++ b/app/[locale]/(protected)/contributor/task-ta/detail-upload/video/[id]/page.tsx @@ -0,0 +1,16 @@ +import FormVideoTaDetail from "@/components/form/content/task-ta/video-detail-form"; +import FormVideoDetail from "@/components/form/content/task-ta/video-detail-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; + +const VideoDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default VideoDetailPage; diff --git a/components/form/content/task-ta/audio-detail-form.tsx b/components/form/content/task-ta/audio-detail-form.tsx index d3f28fb7..9b354bb6 100644 --- a/components/form/content/task-ta/audio-detail-form.tsx +++ b/components/form/content/task-ta/audio-detail-form.tsx @@ -113,7 +113,7 @@ const ViewEditor = dynamic( { ssr: false } ); -export default function FormAudioDetail() { +export default function FormAudioTaDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const userId = getCookiesDecrypt("uie"); diff --git a/components/form/content/task-ta/image-detail-form.tsx b/components/form/content/task-ta/image-detail-form.tsx index abba006a..4706ca8b 100644 --- a/components/form/content/task-ta/image-detail-form.tsx +++ b/components/form/content/task-ta/image-detail-form.tsx @@ -116,7 +116,7 @@ const ViewEditor = dynamic( { ssr: false } ); -export default function FormImageDetail() { +export default function FormImageTaDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const userId = getCookiesDecrypt("uie"); diff --git a/components/form/content/task-ta/teks-detail-form.tsx b/components/form/content/task-ta/teks-detail-form.tsx index c9d5c6f8..5d808a13 100644 --- a/components/form/content/task-ta/teks-detail-form.tsx +++ b/components/form/content/task-ta/teks-detail-form.tsx @@ -111,7 +111,7 @@ const ViewEditor = dynamic( { ssr: false } ); -export default function FormTeksDetail() { +export default function FormTeksTaDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const userId = getCookiesDecrypt("uie"); diff --git a/components/form/content/task-ta/video-detail-form.tsx b/components/form/content/task-ta/video-detail-form.tsx index 569304b6..ca83d2fd 100644 --- a/components/form/content/task-ta/video-detail-form.tsx +++ b/components/form/content/task-ta/video-detail-form.tsx @@ -113,7 +113,7 @@ const ViewEditor = dynamic( { ssr: false } ); -export default function FormVideoDetail() { +export default function FormVideoTaDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const userId = getCookiesDecrypt("uie"); diff --git a/components/partials/auth/login-form.tsx b/components/partials/auth/login-form.tsx index 1d68e8f5..532d0cf8 100644 --- a/components/partials/auth/login-form.tsx +++ b/components/partials/auth/login-form.tsx @@ -535,10 +535,10 @@ const LoginForm = () => { From cfbc6349cc1f97353e5e63db4dc0c4fdf2024b64 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Thu, 12 Jun 2025 14:43:42 +0800 Subject: [PATCH 2/3] feat:fix komunikasi,indeks --- .../contributor/blog/detail/[id]/page.tsx | 3 +- components/form/blog/blog--detail-form.tsx | 2 +- components/form/blog/blog--update-form.tsx | 19 +- components/form/blog/blog-form.tsx | 19 +- .../communication/escalation-detail-form.tsx | 250 ++++++++--- .../communication/internal-detail-form.tsx | 16 +- .../form/communication/internal-form.tsx | 67 +-- components/form/content/spit-convert-form.tsx | 53 +-- .../content/task-ta/audio-detail-form.tsx | 421 +++++++++--------- .../form/content/task-ta/teks-detail-form.tsx | 20 +- .../content/task-ta/video-detail-form.tsx | 8 +- service/communication/communication.ts | 5 + 12 files changed, 501 insertions(+), 382 deletions(-) diff --git a/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx index c196cb0d..1906dc83 100644 --- a/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/contributor/blog/detail/[id]/page.tsx @@ -1,13 +1,12 @@ 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/blog/blog--detail-form.tsx b/components/form/blog/blog--detail-form.tsx index a16c271e..5c9cbdab 100644 --- a/components/form/blog/blog--detail-form.tsx +++ b/components/form/blog/blog--detail-form.tsx @@ -303,7 +303,7 @@ export default function FormBlogDetail() {
- +
prevImages.filter((_, i) => i !== index)); }; + const titleValue = useWatch({ control, name: "title" }); + + useEffect(() => { + if (titleValue) { + const slugified = titleValue + .toLowerCase() + .trim() + .replace(/\s+/g, "-") + .replace(/[^\w-]+/g, ""); // optional: hapus karakter non-alfanumerik + setValue("slug", slugified); + } + }, [titleValue, setValue]); + useEffect(() => { async function initState() { if (id) { @@ -323,7 +336,7 @@ export default function FormBlogUpdate() { @@ -363,7 +376,7 @@ export default function FormBlogUpdate() {
- +
prevImages.filter((_, i) => i !== index)); }; + const titleValue = useWatch({ control, name: "title" }); + + useEffect(() => { + if (titleValue) { + const slugified = titleValue + .toLowerCase() + .trim() + .replace(/\s+/g, "-") + .replace(/[^\w-]+/g, ""); // optional: hapus karakter non-alfanumerik + setValue("slug", slugified); + } + }, [titleValue, setValue]); + // useEffect(() => { // async function initState() { // getCategories(); @@ -359,8 +372,8 @@ export default function FormBlog() {
- -
+ +
diff --git a/components/form/communication/escalation-detail-form.tsx b/components/form/communication/escalation-detail-form.tsx index db62b637..393109b5 100644 --- a/components/form/communication/escalation-detail-form.tsx +++ b/components/form/communication/escalation-detail-form.tsx @@ -20,10 +20,12 @@ import { } from "@/components/ui/select"; import { Avatar, AvatarImage } from "@/components/ui/avatar"; import { + deleteEscalationDiscussion, getEscalationDiscussion, getTicketingDetail, getTicketingInternalDetail, getTicketingInternalDiscussion, + saveEscalationDiscussion, saveTicketInternalReply, } from "@/service/communication/communication"; import { Textarea } from "@/components/ui/textarea"; @@ -33,6 +35,7 @@ import { loading } from "@/lib/swal"; import { id } from "date-fns/locale"; import { htmlToString } from "@/utils/globals"; import InfoLainnyaModal from "../ticketing/info-lainnya"; +import { PlusIcon } from "lucide-react"; const taskSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -62,25 +65,12 @@ export default function FormDetailEscalation() { const [detail, setDetail] = useState(); const [ticketReply, setTicketReply] = useState([]); const [replyVisible, setReplyVisible] = useState(false); - const [listDiscussion, setListDiscussion] = useState(); - const [message, setMessage] = useState(""); + const [activeReplyId, setActiveReplyId] = useState(null); const [selectedPriority, setSelectedPriority] = useState(""); const [openEmergencyModal, setOpenEmergencyModal] = useState(false); const [replyMessage, setReplyMessage] = useState(""); - const [replies, setReplies] = useState([ - { - id: 1, - name: "Mabes Polri - Approver", - message: "test", - timestamp: "2024-12-20 00:56:10", - }, - { - id: 2, - name: "Mabes Polri - Approver", - message: "balas", - timestamp: "2025-01-18 17:42:48", - }, - ]); + const [listDiscussion, setListDiscussion] = useState([]); + const [message, setMessage] = useState(""); const { control, @@ -109,40 +99,75 @@ export default function FormDetailEscalation() { } const handleReply = () => { - setReplyVisible((prev) => !prev); // Toggle visibility + setReplyVisible((prev) => !prev); }; - // useEffect(() => { - // async function initState() { - // if (id != undefined) { - // loading(); - // const responseGet = await getEscalationDiscussion(id); - // close(); - // console.log("escal data", responseGet?.data); - // setListDiscussion(responseGet?.data?.data); - // } - // } - // initState(); - // }, [id]); - - const handleSendReply = () => { - if (replyMessage.trim() === "") return; - - const newReply = { - id: replies.length + 1, - name: "Mabes Polri - Approver", // Sesuaikan dengan data dinamis jika ada - message: replyMessage, - timestamp: new Date().toISOString().slice(0, 19).replace("T", " "), + useEffect(() => { + const fetchDiscussion = async () => { + const response = await getEscalationDiscussion(id); + setListDiscussion(response?.data?.data || []); }; - setReplies([...replies, newReply]); - setReplyMessage(""); + fetchDiscussion(); + }, []); + + const postData = async () => { + if (!message.trim()) return; + + const payload = { + ticketId: id, + message, + parentId: null, + }; + + try { + await saveEscalationDiscussion(payload); + setMessage(""); + + const response = await getEscalationDiscussion(id); + setListDiscussion(response?.data?.data || []); + } catch (error) { + console.error("Gagal mengirim tanggapan:", error); + } + }; + + const postDataChild = async (parentId: any) => { + const textarea = document.getElementById( + `input-comment-${parentId}` + ) as HTMLTextAreaElement | null; + const replyMessage = textarea?.value; + + if (!replyMessage?.trim()) return; + + const payload = { + ticketId: Number(id), + parentMessageId: parentId, + message: replyMessage, + }; + + try { + await saveEscalationDiscussion(payload); + if (textarea) textarea.value = ""; + + const response = await getEscalationDiscussion(id); + setListDiscussion(response?.data?.data || []); + } catch (error) { + console.error("Gagal mengirim balasan:", error); + } }; const openEmergencyIssueDetail = () => { setOpenEmergencyModal(true); }; + async function deleteDataSuggestion(dataId: any) { + const response = await deleteEscalationDiscussion(dataId); + console.log(response); + + const responseGet = await getEscalationDiscussion(id); + setListDiscussion(responseGet?.data?.data); + } + return (
@@ -273,44 +298,121 @@ export default function FormDetailEscalation() {

Tanggapan

-
- {replies.map((reply) => ( -
-

{reply.name}

-

{reply.message}

-

{reply.timestamp}

+
+ {listDiscussion.map((parent: any) => ( +
+
+
+

+ {parent.messageFrom?.fullname} +

+

{parent.message}

+

+ {parent.createdAt} +

+
+ +
+ + {activeReplyId !== parent.id && ( + + )} + + {activeReplyId === parent.id && ( +
+