From 3fee36390d57c5b62c5423cae23f1e6fcdd6f804 Mon Sep 17 00:00:00 2001 From: hanif salafi Date: Mon, 1 Sep 2025 03:30:13 +0700 Subject: [PATCH] feat: update media broadcast, update blogs --- .../account-list/component/column.tsx | 15 +- .../account-list/component/table.tsx | 200 +++++++++++------- components/form/blog/blog-form.tsx | 4 + service/broadcast/broadcast.ts | 6 +- 4 files changed, 134 insertions(+), 91 deletions(-) diff --git a/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/column.tsx b/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/column.tsx index 515d48fc..f8dcfd54 100644 --- a/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/column.tsx +++ b/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/column.tsx @@ -30,34 +30,27 @@ const columns: ColumnDef[] = [ accessorKey: "accountName", header: "Nama", cell: ({ row }) => ( - {row.original.mediaBlastAccount.accountName} + {row.original.mediaBlastAccountName} ), }, { accessorKey: "accountType", header: "Tipe Akun", cell: ({ row }) => ( - {row.original.mediaBlastAccount.accountType} - ), - }, - { - accessorKey: "accountCategory", - header: "Kategory", - cell: ({ row }) => ( - {row.original.mediaBlastAccount.accountCategory} + {row.original.mediaBlastAccountType} ), }, { accessorKey: "emailAddress", header: "Email", cell: ({ row }) => ( - {row.original.mediaBlastAccount.emailAddress} + {row.original.mediaBlastAccountEmail} ), }, { accessorKey: "whatsappNumber", header: "Whatsapp", - cell: ({ row }) => {row.original.mediaBlastAccount.whatsappNumber}, + cell: ({ row }) => {row.original.mediaBlastAccountPhone}, }, { id: "actions", diff --git a/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/table.tsx b/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/table.tsx index c2388f79..f7d3bc28 100644 --- a/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/table.tsx +++ b/app/[locale]/(protected)/admin/broadcast/campaign-list/account-list/component/table.tsx @@ -34,7 +34,7 @@ import { import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import { Label } from "@/components/ui/label"; import { - Select, + Select as UISelect, SelectContent, SelectItem, SelectTrigger, @@ -50,15 +50,17 @@ import { Icon } from "@iconify/react"; import { useParams, useSearchParams } from "next/navigation"; import { Badge } from "@/components/ui/badge"; import { X } from "lucide-react"; +import ReactSelect from "react-select"; import columns from "./column"; import TablePagination from "@/components/table/table-pagination"; import { getMediaBlastCampaignAccountList, deleteMediaBlastCampaignAccount, - saveMediaBlastCampaignAccount, + saveMediaBlastCampaignAccountBulk, } from "@/service/broadcast/broadcast"; -import { close, loading, error, success } from "@/config/swal"; +import { AdministrationUserList } from "@/service/management-user/management-user"; +import { close, loading, error, success, successCallback } from "@/config/swal"; // Mock data for available accounts - replace with actual API call const availableAccounts = [ @@ -97,6 +99,7 @@ const AccountListTable = () => { const [selectedAccount, setSelectedAccount] = React.useState([]); const [selectedCategory, setSelectedCategory] = React.useState(""); const [availableAccountsList, setAvailableAccountsList] = React.useState(availableAccounts); + const [usersList, setUsersList] = React.useState([]); const table = useReactTable({ data: dataTable, @@ -170,53 +173,60 @@ const AccountListTable = () => { loading(); if (accountCategory === "all-account") { - // Handle all accounts selection - const allAccounts = availableAccountsList.map(acc => ({ + // Handle all accounts - send only campaignId and category "all" + const request = { mediaBlastCampaignId: campaignId, - mediaBlastAccountId: acc.id, - })); - - for (const request of allAccounts) { - const response = await saveMediaBlastCampaignAccount(request); - if (response?.error) { - error(response.message); - return; - } + mediaBlastAccountCategory: "all", + }; + const response = await saveMediaBlastCampaignAccountBulk(request); + if (response?.error) { + error(response.message); + return; } } else if (accountCategory === "kategori" && selectedCategory) { - // Handle category selection - const categoryAccounts = availableAccountsList.filter( - acc => acc.category === selectedCategory - ); + // Handle category selection - send campaignId and role-based category + let roleId = ""; + switch (selectedCategory) { + case "umum": + roleId = "5"; + break; + case "jurnalis": + roleId = "6"; + break; + case "polri": + roleId = "7"; + break; + case "ksp": + roleId = "8"; + break; + default: + roleId = "5"; + } - for (const acc of categoryAccounts) { - const request = { - mediaBlastCampaignId: campaignId, - mediaBlastAccountId: acc.id, - }; - const response = await saveMediaBlastCampaignAccount(request); - if (response?.error) { - error(response.message); - return; - } + const request = { + mediaBlastCampaignId: campaignId, + mediaBlastAccountCategory: `role-${roleId}`, + }; + const response = await saveMediaBlastCampaignAccountBulk(request); + if (response?.error) { + error(response.message); + return; } } else if (accountCategory === "custom") { - // Handle custom selection - for (const acc of selectedAccount) { - const request = { - mediaBlastCampaignId: campaignId, - mediaBlastAccountId: acc.id, - }; - const response = await saveMediaBlastCampaignAccount(request); - if (response?.error) { - error(response.message); - return; - } + // Handle custom selection - send campaignId and selected user IDs + const request = { + mediaBlastCampaignId: campaignId, + mediaBlastAccountIds: selectedAccount.map(acc => acc.id), + }; + const response = await saveMediaBlastCampaignAccountBulk(request); + if (response?.error) { + error(response.message); + return; } } - + close(); - success("Akun berhasil ditambahkan ke campaign!"); + successCallback("Akun berhasil ditambahkan ke campaign!"); resetDialogState(); fetchData(); } catch (err) { @@ -229,9 +239,32 @@ const AccountListTable = () => { setAccountCategory(""); setSelectedAccount([]); setSelectedCategory(""); + setUsersList([]); setIsDialogOpen(false); }; + const fetchUsersList = async () => { + try { + loading(); + const response = await AdministrationUserList( + "1", // levelId + 0, // page + "", // name + "100", // size + "1", // featureId + "" // role + ); + + if (response?.data?.data?.content) { + setUsersList(response.data.data.content); + } + close(); + } catch (err) { + close(); + error("Terjadi kesalahan saat mengambil daftar user"); + } + }; + const handleFilter = (id: string, checked: boolean) => { let temp = [...filtered]; if (checked) temp = [...temp, id]; @@ -239,16 +272,7 @@ const AccountListTable = () => { setFiltered(temp); }; - const handleAccountSelection = (accountId: string, checked: boolean) => { - if (checked) { - const account = availableAccountsList.find(acc => acc.id === accountId); - if (account && !selectedAccount.find(acc => acc.id === accountId)) { - setSelectedAccount([...selectedAccount, account]); - } - } else { - setSelectedAccount(selectedAccount.filter(acc => acc.id !== accountId)); - } - }; + const removeSelectedAccount = (accountId: string) => { setSelectedAccount(selectedAccount.filter(acc => acc.id !== accountId)); @@ -274,20 +298,23 @@ const AccountListTable = () => { Pilih Akun - + Pilih Akun Untuk Campaign Ini -
+
{ setAccountCategory(val); setSelectedAccount([]); setSelectedCategory(""); + if (val === "custom") { + fetchUsersList(); + } }} - className="space-y-3" + className="flex space-x-6" >
@@ -299,7 +326,7 @@ const AccountListTable = () => {
- +
@@ -307,7 +334,7 @@ const AccountListTable = () => { {accountCategory === "kategori" && (
- +
)} {/* Custom Account Selection */} {accountCategory === "custom" && (
- -
- {getFilteredAccounts().map((acc) => ( -
- selected.id === acc.id)} - onCheckedChange={(checked) => handleAccountSelection(acc.id, Boolean(checked))} - /> - -
- ))} -
+ + ({ + value: user.id, + label: `${user.fullname} (${user.role?.name})`, + user: user + }))} + value={selectedAccount.map((acc: any) => ({ + value: acc.id, + label: `${acc.fullname} (${acc.role?.name})`, + user: acc + }))} + onChange={(selectedOptions: any) => { + const selectedUsers = selectedOptions ? selectedOptions.map((option: any) => option.user) : []; + setSelectedAccount(selectedUsers); + }} + placeholder="Cari dan pilih user..." + noOptionsMessage={() => "Tidak ada user ditemukan"} + loadingMessage={() => "Memuat..."} + isSearchable={true} + isClearable={true} + className="react-select" + classNamePrefix="select" + /> {/* Selected Accounts Display */} {selectedAccount.length > 0 && (
- +
{selectedAccount.map((acc) => ( - - {acc.accountName} + + {acc.fullname} removeSelectedAccount(acc.id)} @@ -364,7 +401,7 @@ const AccountListTable = () => { {accountCategory === "all-account" && (

- Semua akun ({availableAccountsList.length} akun) akan ditambahkan ke campaign ini. + Semua akun akan ditambahkan ke campaign ini.

)} @@ -373,7 +410,16 @@ const AccountListTable = () => { {accountCategory === "kategori" && selectedCategory && (

- {getFilteredAccounts().length} akun dari kategori "{selectedCategory}" akan ditambahkan. + Semua akun dengan role "{selectedCategory.toUpperCase()}" akan ditambahkan. +

+
+ )} + + {/* Custom Selection Info */} + {accountCategory === "custom" && ( +
+

+ {selectedAccount.length} user terpilih akan ditambahkan ke campaign ini.

)} diff --git a/components/form/blog/blog-form.tsx b/components/form/blog/blog-form.tsx index 687b2d44..25185324 100644 --- a/components/form/blog/blog-form.tsx +++ b/components/form/blog/blog-form.tsx @@ -32,6 +32,7 @@ import { postBlog, uploadThumbnailBlog } from "@/service/blog/blog"; import dynamic from "next/dynamic"; import { error } from "console"; import { loading } from "@/lib/swal"; +import { getCookiesDecrypt } from "@/lib/utils"; const taskSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -92,6 +93,7 @@ export default function FormBlog() { const [thumbnail, setThumbnail] = useState(null); const [preview, setPreview] = useState(null); const inputRef = useRef(null); + const roleName = getCookiesDecrypt("urne"); const [unitSelection, setUnitSelection] = useState({ allUnit: false, @@ -180,6 +182,7 @@ export default function FormBlog() { const save = async (data: TaskSchema) => { loading(); + console.log("roleName", roleName); const finalTags = tags.join(", "); const requestData = { ...data, @@ -190,6 +193,7 @@ export default function FormBlog() { metadata: data.meta, tags: finalTags, isDraft, + isInternational: roleName?.includes("INT") ? true : false, }; const response = await postBlog(requestData); diff --git a/service/broadcast/broadcast.ts b/service/broadcast/broadcast.ts index bd876c60..29bae757 100644 --- a/service/broadcast/broadcast.ts +++ b/service/broadcast/broadcast.ts @@ -63,8 +63,8 @@ export async function saveMediaBlastCampaign(data: { return httpPostInterceptor(url, data); } -export async function saveMediaBlastCampaignAccount(data: any) { - const url = `media/blast/campaign-account`; +export async function saveMediaBlastCampaignAccountBulk(data: any) { + const url = `media/blast/campaign-account-bulk`; return httpPostInterceptor( url, data ); } @@ -111,7 +111,7 @@ export async function getMediaBlastAccount(id: string) { } export async function deleteMediaBlastAccount(id: string) { - const url = `media/blast/account?id=${id}`; + const url = `media/blast/campaign-account?id=${id}`; return httpDeleteInterceptor(url); }