diff --git a/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/columns.tsx b/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/columns.tsx new file mode 100644 index 00000000..e7a091b5 --- /dev/null +++ b/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/columns.tsx @@ -0,0 +1,164 @@ +import * as React from "react"; +import { ColumnDef } from "@tanstack/react-table"; + +import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { format } from "date-fns"; +import { Link, usePathname, useRouter } from "@/i18n/routing"; +import { useToast } from "@/components/ui/use-toast"; +import { deleteDataFAQ } from "@/service/settings/settings"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { deleteQuestion } from "@/service/communication/communication"; + +const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => {row.getValue("no")}, + }, + { + accessorKey: "message", + header: "Pertanyaan", + cell: ({ row }) => ( + {row.getValue("message")} + ), + }, + { + accessorKey: "commentFromUserName", + header: "Penerima", + cell: ({ row }) => ( + {row.getValue("commentFromUserName")} + ), + }, + { + accessorKey: "type", + header: "Channel", + cell: ({ row }) => { + const type = row.original.type; // Akses properti category + return {type?.name || "N/A"}; + }, + }, + { + accessorKey: "createdAt", + header: "Waktu", + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, + }, + { + accessorKey: "isActive", + header: "Status", + cell: ({ row }) => { + const isActive = row.getValue("isActive") as boolean; // Ambil nilai isActive + const status = isActive ? "Open" : "Closed"; // Tentukan teks berdasarkan isActive + const statusStyles = isActive + ? "bg-green-100 text-green-600" // Gaya untuk "Open" + : "bg-red-100 text-red-600"; // Gaya untuk "Closed" + + return ( + {status} + ); + }, + }, + + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + const pathname = usePathname(); + const router = useRouter(); + const { toast } = useToast(); + const MySwal = withReactContent(Swal); + + const questionDelete = async (id: string) => { + const response = await deleteQuestion(id); + console.log(response); + if (response?.error) { + toast({ + title: "Error", + variant: "destructive", + description: "Gagal Delete", + }); + return false; + } + toast({ + title: "Sukses", + description: "Berhasil Delete", + }); + router.push(`${pathname}?dataChange=true`); + }; + + const deleteValidation = async (id: string) => { + MySwal.fire({ + title: "Delete Data", + text: "Apakah Anda yakin ingin menghapus data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Delete", + }).then((result) => { + if (result.isConfirmed) { + questionDelete(id); + } + }); + }; + return ( + + + + + + + + Jawab + + + + + Eskalasi + + + deleteValidation(row?.original?.id)}> + + Delete + + + + + ); + }, + }, +]; + +export default columns; diff --git a/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/questions-table.tsx b/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/questions-table.tsx new file mode 100644 index 00000000..98efd8e3 --- /dev/null +++ b/app/[locale]/(protected)/supervisor/communications/questions/[title]/components/questions-table.tsx @@ -0,0 +1,320 @@ +"use client"; + +import * as React from "react"; +import { + ColumnDef, + ColumnFiltersState, + PaginationState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; + +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { + ChevronLeft, + ChevronRight, + Eye, + MoreVertical, + Search, + SquarePen, + Trash2, + TrendingDown, + TrendingUp, +} from "lucide-react"; +import { cn, getCookiesDecrypt } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuRadioGroup, + DropdownMenuRadioItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Input } from "@/components/ui/input"; +import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { paginationBlog } from "@/service/blog/blog"; +import { ticketingPagination } from "@/service/ticketing/ticketing"; +import { Badge } from "@/components/ui/badge"; +import { useParams, useSearchParams } from "next/navigation"; +import TablePagination from "@/components/table/table-pagination"; +import columns from "./columns"; +import { + listDataAudio, + listDataImage, + listDataVideo, +} from "@/service/content/content"; +import { + getQuestionPagination, + getTicketingEscalationPagination, + listTicketingInternal, +} from "@/service/communication/communication"; +import { usePathname, useRouter } from "@/i18n/routing"; + +interface statisticType { + incomingTotal: number; + createdTicketTotal: number; + todayIncomingTotal: number; +} + +const QuestionsTable = (props: { + statisticData: (data: statisticType) => void; +}) => { + const router = useRouter(); + const pathname = usePathname(); + const searchParams = useSearchParams(); + const params = useParams(); + const title = params?.title; + const dataChange = searchParams?.get("dataChange"); + const [dataTable, setDataTable] = React.useState([]); + const [totalData, setTotalData] = React.useState(1); + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + const [showData, setShowData] = React.useState("10"); + + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [search, setSearch] = React.useState(""); + + const roleId = getCookiesDecrypt("urie"); + + const table = useReactTable({ + data: dataTable, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + pagination, + }, + }); + + React.useEffect(() => { + if (dataChange) { + router.push(pathname); + } + fetchData(); + }, [dataChange]); + + React.useEffect(() => { + const pageFromUrl = searchParams?.get("page"); + if (pageFromUrl) { + setPage(Number(pageFromUrl)); + } + }, [searchParams]); + + React.useEffect(() => { + fetchData(); + setPagination({ + pageIndex: 0, + pageSize: Number(showData), + }); + }, [page, showData]); + + let typingTimer: any; + const doneTypingInterval = 1500; + + const handleKeyUp = () => { + clearTimeout(typingTimer); + typingTimer = setTimeout(doneTyping, doneTypingInterval); + }; + + const handleKeyDown = () => { + clearTimeout(typingTimer); + }; + + async function doneTyping() { + fetchData(); + } + + async function fetchData() { + const typeNow = + title === "comment" + ? "1" + : title === "facebook" + ? "2" + : title === "instagram" + ? "3" + : title === "x" + ? "4" + : title === "youtube" + ? "5" + : title === "emergency" + ? "6" + : title === "email" + ? "7" + : title === "inbox" + ? "8" + : title === "whatsapp" + ? "9" + : title === "tiktok" + ? "10" + : ""; + + try { + const res = await getQuestionPagination( + search, + page - 1, + typeNow, + showData + ); + const data = res?.data?.data; + const contentData = data?.page?.content; + console.log("contentDatassss : ", data); + + contentData.forEach((item: any, index: number) => { + item.no = (page - 1) * Number(showData) + index + 1; + }); + setDataTable(contentData); + props.statisticData(data?.statistic); + setTotalData(data?.page?.totalElements); + setTotalPage(data?.page?.totalPages); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + return ( +
+
+ {title == "all" + ? "Pertanyaan Masuk" + : title === "inbox" + ? "Pesan Masuk" + : title == "comment" + ? "Komentar Konten" + : title === "emergency" + ? "Emergency Issue" + : title}{" "} + + {totalData} + +
+
+
+ + + + + setSearch(e.target.value)} + onKeyDown={handleKeyDown} + onKeyUp={handleKeyUp} + /> + +
+ + + + + + + + 1 - 10 Data + + + 1 - 20 Data + + + 1 - 25 Data + + + 1 - 50 Data + + + + +
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+ +
+ ); +}; + +export default QuestionsTable; diff --git a/app/[locale]/(protected)/supervisor/communications/questions/[title]/page.tsx b/app/[locale]/(protected)/supervisor/communications/questions/[title]/page.tsx new file mode 100644 index 00000000..6d5d7f86 --- /dev/null +++ b/app/[locale]/(protected)/supervisor/communications/questions/[title]/page.tsx @@ -0,0 +1,136 @@ +"use client"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import { Link } from "@/i18n/routing"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import QuestionsTable from "./components/questions-table"; +import { useState } from "react"; + +interface statisticType { + incomingTotal: number; + createdTicketTotal: number; + todayIncomingTotal: number; +} + +export default function Questions() { + const [statisticData, setStatisticData] = useState({ + incomingTotal: 0, + createdTicketTotal: 0, + todayIncomingTotal: 0, + }); + return ( +
+ +
+
+
+
+ +
+

{statisticData.todayIncomingTotal}

+

Pertanyaan hari ini

+
+
+
+ +
+

{statisticData.incomingTotal}

+

Pertanyaan masuk

+
+
+
+ +
+

{statisticData.createdTicketTotal}

+

Tiket dibuat

+
+
+
+
+

Pertanyaan masuk berdasarkan sumber:

+
+ + + Emergency Issue + + + + Email + + + + Facebook + + + X + + + + Instagram + + + + Whatsapp + + + + Youtube + + + + Pesan Masuk + + + + Komentar Konten + +
+
+
+ setStatisticData(data)} /> +
+
+ ); +} diff --git a/lib/menus.ts b/lib/menus.ts index c9fbef40..d64cb3a7 100644 --- a/lib/menus.ts +++ b/lib/menus.ts @@ -2176,7 +2176,7 @@ export function getMenuList(pathname: string, t: any): Group[] { icon: "icon-park-outline:communication", submenus: [ { - href: "/supervisor/communications/questions", + href: "/supervisor/communications/questions/all", label: t("questions"), active: pathname.includes("/communications/questions"), icon: "solar:inbox-line-outline", diff --git a/service/communication/communication.ts b/service/communication/communication.ts index e58df702..fcb92b6e 100644 --- a/service/communication/communication.ts +++ b/service/communication/communication.ts @@ -100,3 +100,18 @@ export async function deleteCollabDiscussion(id: string | number) { const url = `ticketing/collaboration/discussion?id=${id}`; return httpDeleteInterceptor(url); } + +export async function getQuestionPagination( + title = "", + page: number, + typeId: string, + size: string +) { + const url = `question/pagination?enablePage=1&size=${size}&title=${title}&page=${page}&typeId=${typeId}`; + return httpGetInterceptor(url); +} + +export async function deleteQuestion(id: string | number) { + const url = `/question?id=${id}`; + return httpDeleteInterceptor(url); +}