diff --git a/app/[locale]/(protected)/admin/broadcast/email/component/column.tsx b/app/[locale]/(protected)/admin/broadcast/email/component/column.tsx new file mode 100644 index 00000000..e4235b22 --- /dev/null +++ b/app/[locale]/(protected)/admin/broadcast/email/component/column.tsx @@ -0,0 +1,112 @@ +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 { + formatDateToIndonesian, + getOnlyDate, + htmlToString, +} from "@/utils/globals"; +import { Link, useRouter } from "@/i18n/routing"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { Collapsible, CollapsibleContent } from "@/components/ui/collapsible"; + +const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => {row.getValue("no")}, + }, + + { + accessorKey: "title", + header: "Judul", + cell: ({ row }) => {row.getValue("title")}, + }, + { + accessorKey: "fileTypeName", + header: "Konten", + cell: ({ row }) => {row.getValue("fileTypeName")}, + }, + { + accessorKey: "categoryName", + header: "Kategori", + cell: ({ row }) => {row.getValue("categoryName")}, + }, + { + accessorKey: "createdAt", + header: "Tanggal Unggah", + cell: ({ row }) => ( + {formatDateToIndonesian(row.getValue("createdAt"))} + ), + }, + + { + accessorKey: "statusName", + header: "Status", + cell: ({ row }) => {row.getValue("statusName")}, + }, + + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + return ( + + + + + + + + Detail + + + + + Email Blast + + + + + Whatsapp Blast + + + + + ); + }, + }, +]; + +export default columns; diff --git a/app/[locale]/(protected)/admin/broadcast/component/table.tsx b/app/[locale]/(protected)/admin/broadcast/email/component/table.tsx similarity index 97% rename from app/[locale]/(protected)/admin/broadcast/component/table.tsx rename to app/[locale]/(protected)/admin/broadcast/email/component/table.tsx index 6d7fcc2d..151b650e 100644 --- a/app/[locale]/(protected)/admin/broadcast/component/table.tsx +++ b/app/[locale]/(protected)/admin/broadcast/email/component/table.tsx @@ -60,13 +60,16 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; -import { listDataMedia } from "@/service/broadcast/broadcast"; +import { + listDataMedia, + listDataMediaBroadCast, +} from "@/service/broadcast/broadcast"; import { listEnableCategory } from "@/service/content/content"; import { Checkbox } from "@/components/ui/checkbox"; import { close, loading } from "@/config/swal"; import { Link } from "@/i18n/routing"; -const BroadcastTable = () => { +const BroadcastEmailTable = () => { const router = useRouter(); const searchParams = useSearchParams(); const [search, setSearch] = React.useState(""); @@ -144,7 +147,7 @@ const BroadcastTable = () => { async function fetchData() { try { loading(); - const res = await listDataMedia( + const res = await listDataMediaBroadCast( page - 1, showData, search, @@ -202,17 +205,13 @@ const BroadcastTable = () => { return (
-
-

Brodcast

- +
+ -
- -
{ ); }; -export default BroadcastTable; +export default BroadcastEmailTable; diff --git a/app/[locale]/(protected)/admin/broadcast/page.tsx b/app/[locale]/(protected)/admin/broadcast/page.tsx index dcd756ee..d3dd5505 100644 --- a/app/[locale]/(protected)/admin/broadcast/page.tsx +++ b/app/[locale]/(protected)/admin/broadcast/page.tsx @@ -1,11 +1,51 @@ +"use client"; import SiteBreadcrumb from "@/components/site-breadcrumb"; -import BroadcastTable from "./component/table"; +import BroadcastTable from "./email/component/table"; +import { PlusIcon } from "lucide-react"; + +import EscalationTable from "../../shared/communication/escalation/components/escalation-table"; +import InternalTable from "../../shared/communication/internal/components/internal-table"; +import { useState } from "react"; +import { Link } from "@/i18n/routing"; +import { Button } from "@/components/ui/button"; +import BroadcastEmailTable from "./email/component/table"; +import BroadcastWhatsAppTable from "./whatsapp/component/table"; export default function AdminBroadcast() { + const [tab, setTab] = useState("Email Blast"); return (
- +
+
+ + +
+ {tab === "Email Blast" && } + {tab === "WhatsApp Blast" && } +
); } diff --git a/app/[locale]/(protected)/admin/broadcast/component/column.tsx b/app/[locale]/(protected)/admin/broadcast/whatsapp/component/column.tsx similarity index 100% rename from app/[locale]/(protected)/admin/broadcast/component/column.tsx rename to app/[locale]/(protected)/admin/broadcast/whatsapp/component/column.tsx diff --git a/app/[locale]/(protected)/admin/broadcast/whatsapp/component/table.tsx b/app/[locale]/(protected)/admin/broadcast/whatsapp/component/table.tsx new file mode 100644 index 00000000..0c6b79ab --- /dev/null +++ b/app/[locale]/(protected)/admin/broadcast/whatsapp/component/table.tsx @@ -0,0 +1,403 @@ +"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, + UserIcon, +} from "lucide-react"; +import { cn } 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 { useRouter, useSearchParams } from "next/navigation"; +import TablePagination from "@/components/table/table-pagination"; +import columns from "./column"; +import { getPlanningPagination } from "@/service/agenda-setting/agenda-setting"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { + listDataMedia, + listDataMediaBroadCast, +} from "@/service/broadcast/broadcast"; +import { listEnableCategory } from "@/service/content/content"; +import { Checkbox } from "@/components/ui/checkbox"; +import { close, loading } from "@/config/swal"; +import { Link } from "@/i18n/routing"; + +const BroadcastWhatsAppTable = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + const [search, setSearch] = React.useState(""); + const [showData, setShowData] = React.useState("10"); + const [categories, setCategories] = React.useState(); + 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 [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: Number(showData), + }); + const [categoryFilter, setCategoryFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + 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, + }, + }); + + let typingTimer: any; + const doneTypingInterval = 1500; + + const handleKeyUp = () => { + clearTimeout(typingTimer); + typingTimer = setTimeout(doneTyping, doneTypingInterval); + }; + + const handleKeyDown = () => { + clearTimeout(typingTimer); + }; + + async function doneTyping() { + fetchData(); + } + + React.useEffect(() => { + const pageFromUrl = searchParams?.get("page"); + if (pageFromUrl) { + setPage(Number(pageFromUrl)); + } + }, [searchParams]); + + React.useEffect(() => { + fetchData(); + setPagination({ + pageIndex: 0, + pageSize: Number(showData), + }); + }, [page, showData]); + + async function fetchData() { + try { + loading(); + const res = await listDataMediaBroadCast( + page - 1, + showData, + search, + categoryFilter?.sort().join(","), + statusFilter?.sort().join(",") + ); + const data = res?.data?.data; + const contentData = data?.content; + contentData.forEach((item: any, index: number) => { + item.no = (page - 1) * Number(showData) + index + 1; + }); + + console.log("contentData : ", data); + + setDataTable(contentData); + setTotalData(data?.totalElements); + setTotalPage(data?.totalPages); + close(); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + React.useEffect(() => { + getCategories(); + }, []); + + async function getCategories() { + const category = await listEnableCategory(""); + const resCategory = category?.data?.data?.content; + setCategories(resCategory); + } + + const handleChange = (type: string, id: number, checked: boolean) => { + if (type === "category") { + if (checked) { + const temp: number[] = [...categoryFilter]; + temp.push(id); + setCategoryFilter(temp); + } else { + const temp = categoryFilter.filter((a) => a !== id); + setCategoryFilter(temp); + } + } else { + if (checked) { + const temp: number[] = [...statusFilter]; + temp.push(id); + setStatusFilter(temp); + } else { + const temp = statusFilter.filter((a) => a !== id); + setStatusFilter(temp); + } + } + }; + + return ( +
+
+ + + + setSearch(e.target.value)} + className="max-w-[300px]" + /> +
+ + + + + + + + 1 - 10 Data + + + 1 - 20 Data + + + 1 - 25 Data + + + 1 - 50 Data + + + + + + + + + +
+ +
+

Kategory

+ {categories?.map((category: any) => ( +
+ + handleChange("category", category.id, Boolean(e)) + } + /> + +
+ ))} +

Status

+
+ + handleChange("status", 1, Boolean(e)) + } + /> + +
+
+ + handleChange("status", 2, Boolean(e)) + } + /> + +
+
+ + handleChange("status", 3, Boolean(e)) + } + /> + +
+
+ + handleChange("status", 4, Boolean(e)) + } + /> + +
+
+
+
+
+
+
+ + + {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 BroadcastWhatsAppTable; diff --git a/components/table/management-user/management-user-internal-table.tsx b/components/table/management-user/management-user-internal-table.tsx index 9b9badfa..4e409c71 100644 --- a/components/table/management-user/management-user-internal-table.tsx +++ b/components/table/management-user/management-user-internal-table.tsx @@ -47,8 +47,6 @@ import { PopoverContent, PopoverTrigger, } from "@/components/ui/popover"; -import { listDataMedia } from "@/service/broadcast/broadcast"; -import { listEnableCategory } from "@/service/content/content"; import { Checkbox } from "@/components/ui/checkbox"; import { close, loading } from "@/config/swal"; import { Link, useRouter } from "@/i18n/routing"; diff --git a/service/broadcast/broadcast.ts b/service/broadcast/broadcast.ts index 4dd58783..325816ba 100644 --- a/service/broadcast/broadcast.ts +++ b/service/broadcast/broadcast.ts @@ -16,6 +16,18 @@ export async function listDataMedia( return httpGetInterceptor(url); } +export async function listDataMediaBroadCast( + page: number, + limit: string, + search: string, + categoryFilter: string, + statusFilter: string +) { + const name = search || ""; + const url = `media/list?isForAdmin=true&title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&categoryId=${categoryFilter}&statusId=${statusFilter}`; + return httpGetInterceptor(url); +} + export async function getMediaBlastCampaignPage(page: number) { const url = `media/blast/campaign/list?enablePage=1&page=${page}`; return httpGetInterceptor(url);