From 437e20fc708d9c89407cb5ba8c3cdff1606f436e Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Fri, 20 Dec 2024 00:30:43 +0700 Subject: [PATCH] feat:detail communication,internal,escalation --- .../columns.tsx | 13 +- .../escalation-table.tsx | 0 .../escalation/detail/[id]/page.tsx | 19 ++ .../internal/components/columns.tsx | 13 +- .../internal/components/internal-table.tsx | 10 +- .../internal/detail/[id]/page.tsx | 18 ++ .../(protected)/shared/communication/page.tsx | 2 +- .../communication/escalation-detail-form.tsx | 285 +++++++++++++++++ .../communication/internal-detail-form.tsx | 292 ++++++++++++++++++ .../form/communication/internal-form.tsx | 2 +- service/communication/communication.ts | 22 +- 11 files changed, 664 insertions(+), 12 deletions(-) rename app/[locale]/(protected)/shared/communication/escalation/{table-escalation => components}/columns.tsx (90%) rename app/[locale]/(protected)/shared/communication/escalation/{table-escalation => components}/escalation-table.tsx (100%) create mode 100644 app/[locale]/(protected)/shared/communication/escalation/detail/[id]/page.tsx create mode 100644 app/[locale]/(protected)/shared/communication/internal/detail/[id]/page.tsx create mode 100644 components/form/communication/escalation-detail-form.tsx create mode 100644 components/form/communication/internal-detail-form.tsx diff --git a/app/[locale]/(protected)/shared/communication/escalation/table-escalation/columns.tsx b/app/[locale]/(protected)/shared/communication/escalation/components/columns.tsx similarity index 90% rename from app/[locale]/(protected)/shared/communication/escalation/table-escalation/columns.tsx rename to app/[locale]/(protected)/shared/communication/escalation/components/columns.tsx index ede22383..c4c63f71 100644 --- a/app/[locale]/(protected)/shared/communication/escalation/table-escalation/columns.tsx +++ b/app/[locale]/(protected)/shared/communication/escalation/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,14 @@ const columns: ColumnDef[] = [ - - - View - + + + + View + + Edit diff --git a/app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx b/app/[locale]/(protected)/shared/communication/escalation/components/escalation-table.tsx similarity index 100% rename from app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx rename to app/[locale]/(protected)/shared/communication/escalation/components/escalation-table.tsx diff --git a/app/[locale]/(protected)/shared/communication/escalation/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/communication/escalation/detail/[id]/page.tsx new file mode 100644 index 00000000..eaad7e96 --- /dev/null +++ b/app/[locale]/(protected)/shared/communication/escalation/detail/[id]/page.tsx @@ -0,0 +1,19 @@ +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"; +import FormDetailInternal from "@/components/form/communication/internal-detail-form"; +import FormDetailEscalation from "@/components/form/communication/escalation-detail-form"; + +const EscalationDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default EscalationDetailPage; diff --git a/app/[locale]/(protected)/shared/communication/internal/components/columns.tsx b/app/[locale]/(protected)/shared/communication/internal/components/columns.tsx index 59df0665..ac4e763e 100644 --- a/app/[locale]/(protected)/shared/communication/internal/components/columns.tsx +++ b/app/[locale]/(protected)/shared/communication/internal/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[] = [ { @@ -96,10 +97,14 @@ const columns: ColumnDef[] = [ - - - View - + + + + View + + Edit diff --git a/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx b/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx index 5ef7dad3..4cba01b0 100644 --- a/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx +++ b/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx @@ -35,6 +35,7 @@ import { Trash2, TrendingDown, TrendingUp, + UploadIcon, } from "lucide-react"; import { cn, getCookiesDecrypt } from "@/lib/utils"; import { @@ -57,6 +58,7 @@ import { listDataVideo, } from "@/service/content/content"; import { listTicketingInternal } from "@/service/communication/communication"; +import { Link } from "@/components/navigation"; const TableAudio = () => { const router = useRouter(); @@ -151,7 +153,13 @@ const TableAudio = () => { return (
-
+
+ + + diff --git a/app/[locale]/(protected)/shared/communication/internal/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/communication/internal/detail/[id]/page.tsx new file mode 100644 index 00000000..dce21c67 --- /dev/null +++ b/app/[locale]/(protected)/shared/communication/internal/detail/[id]/page.tsx @@ -0,0 +1,18 @@ +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"; +import FormDetailInternal from "@/components/form/communication/internal-detail-form"; + +const InternalDetailPage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default InternalDetailPage; diff --git a/app/[locale]/(protected)/shared/communication/page.tsx b/app/[locale]/(protected)/shared/communication/page.tsx index 2a542701..77104464 100644 --- a/app/[locale]/(protected)/shared/communication/page.tsx +++ b/app/[locale]/(protected)/shared/communication/page.tsx @@ -4,7 +4,7 @@ import InternalTable from "./internal/components/internal-table"; import SiteBreadcrumb from "@/components/site-breadcrumb"; import CollaborationTable from "./collaboration/components/collabroation-table"; -import EscalationTable from "./escalation/table-escalation/escalation-table"; +import EscalationTable from "./escalation/components/escalation-table"; const CommunicationPage = () => { return ( diff --git a/components/form/communication/escalation-detail-form.tsx b/components/form/communication/escalation-detail-form.tsx new file mode 100644 index 00000000..2e5a7e98 --- /dev/null +++ b/components/form/communication/escalation-detail-form.tsx @@ -0,0 +1,285 @@ +"use client"; +"use client"; +import React, { useEffect, 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 } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; +import { + getTicketingDetail, + getTicketingInternalDetail, + getTicketingInternalDiscussion, + saveTicketInternalReply, +} from "@/service/communication/communication"; +import { Textarea } from "@/components/ui/textarea"; + +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 escalationDetail = { + id: number; + title: string; + createdAt: string; + commentFromUserName: string; + message: string; + createdBy: { + id: number; + fullname: string; + }; + sendTo: { + id: number; + fullname: string; + }; + status: { + id: number; + name: string; + }; + priority: { + id: number; + name: string; + }; + description: string; + narration: string; + is_active: string; +}; + +export type replyDetail = { + id: number; + message: string; + createdAt: string; + messageFrom: { + id: number; + fullname: string; + }; + messageTo: { + id: number; + fullname: string; + }; +}; + +export default function FormDetailEscalation() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + + const [detail, setDetail] = useState(); + const [ticketReply, setTicketReply] = useState([]); + const [replyVisible, setReplyVisible] = useState(false); + const [replyMessage, setReplyMessage] = useState(""); + const [selectedPriority, setSelectedPriority] = useState(""); + const [selectedStatus, setSelectedStatus] = useState(""); + + const { + control, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + useEffect(() => { + async function initState() { + if (id) { + const response = await getTicketingDetail(id); + setDetail(response.data?.data); + } + } + initState(); + getTicketReply(); + }, [id]); + + async function getTicketReply() { + const res = await getTicketingInternalDiscussion(id); + if (res.data !== null) { + setTicketReply(res.data?.data); + } + } + + const handleReply = () => { + setReplyVisible((prev) => !prev); // Toggle visibility + }; + + const handleSendReply = async () => { + if (replyMessage.trim() === "") { + MySwal.fire({ + title: "Error", + text: "Pesan tidak boleh kosong!", + icon: "error", + }); + return; + } + + const data = { + ticketId: id, + message: replyMessage, + }; + + try { + const response = await saveTicketInternalReply(data); + + // Tambahkan balasan baru ke daftar balasan + const newReply: replyDetail = { + id: response.data.id, + message: replyMessage, + createdAt: response.data.createdAt, + messageFrom: response.data.messageFrom, + messageTo: response.data.messageTo, + }; + + setTicketReply((prevReplies) => [newReply, ...prevReplies]); + + MySwal.fire({ + title: "Sukses", + text: "Pesan berhasil dikirim.", + icon: "success", + }); + + // Reset input dan sembunyikan form balasan + setReplyMessage(""); + setReplyVisible(false); + } catch (error) { + MySwal.fire({ + title: "Error", + text: "Gagal mengirim balasan.", + icon: "error", + }); + console.error("Error sending reply:", error); + } + }; + + return ( + +
+
+
+ {detail !== undefined && ( +
+

+ Ticket #{detail.id} +

+
+ + + +
+

+ + {detail?.commentFromUserName} + {" "} + mengirimkan pesan untuk{" "} + {detail?.message} +

+

{detail?.createdAt}

+
+
+

{detail.message}

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

+ {errors.title.message} +

+ )} */} +
+
+ + +
+
+ + ( +