pull main
This commit is contained in:
commit
a6683014c2
|
|
@ -1,4 +1,4 @@
|
||||||
'use client'
|
"use client";
|
||||||
|
|
||||||
import "react-datepicker/dist/react-datepicker.css";
|
import "react-datepicker/dist/react-datepicker.css";
|
||||||
import { Icon } from "@iconify/react";
|
import { Icon } from "@iconify/react";
|
||||||
|
|
@ -35,7 +35,7 @@ import { Button } from "@/components/ui/button";
|
||||||
import TablePagination from "@/components/table/table-pagination";
|
import TablePagination from "@/components/table/table-pagination";
|
||||||
import {
|
import {
|
||||||
getMediaBlastCampaignById,
|
getMediaBlastCampaignById,
|
||||||
getMediaBlastBroadcastList
|
getMediaBlastBroadcastList,
|
||||||
} from "@/service/broadcast/broadcast";
|
} from "@/service/broadcast/broadcast";
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
|
|
@ -69,319 +69,342 @@ interface PageProps {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function BroadcastCampaignDetail({ params, searchParams }: PageProps) {
|
export default function BroadcastCampaignDetail({
|
||||||
const router = useRouter();
|
params,
|
||||||
const pathname = usePathname();
|
searchParams,
|
||||||
const { id, locale } = params;
|
}: PageProps) {
|
||||||
const [getData, setGetData] = useState<CampaignData[]>([]);
|
const router = useRouter();
|
||||||
const [totalPage, setTotalPage] = useState<number>(0);
|
const pathname = usePathname();
|
||||||
const [totalData, setTotalData] = useState<number>(0);
|
const { id, locale } = params;
|
||||||
const [activeTab, setActiveTab] = useState<"sent" | "schedule" | "account-list">("sent");
|
const [getData, setGetData] = useState<CampaignData[]>([]);
|
||||||
const { page, size } = searchParams;
|
const [totalPage, setTotalPage] = useState<number>(0);
|
||||||
|
const [totalData, setTotalData] = useState<number>(0);
|
||||||
|
const [activeTab, setActiveTab] = useState<
|
||||||
|
"sent" | "schedule" | "account-list"
|
||||||
|
>("sent");
|
||||||
|
const { page, size } = searchParams;
|
||||||
|
|
||||||
const [calenderState, setCalenderState] = useState<boolean>(false);
|
const [calenderState, setCalenderState] = useState<boolean>(false);
|
||||||
const [typeFilter, setTypeFilter] = useState<string>("email");
|
const [typeFilter, setTypeFilter] = useState<string>("email");
|
||||||
const [dateRange, setDateRange] = useState<[Date, Date]>([new Date(), new Date()]);
|
const [dateRange, setDateRange] = useState<[Date, Date]>([
|
||||||
const [startDate, endDate] = dateRange;
|
new Date(),
|
||||||
|
new Date(),
|
||||||
|
]);
|
||||||
|
const [startDate, endDate] = dateRange;
|
||||||
|
|
||||||
const [startDateString, setStartDateString] = useState<string | undefined>();
|
const [startDateString, setStartDateString] = useState<string | undefined>();
|
||||||
const [endDateString, setEndDateString] = useState<string | undefined>();
|
const [endDateString, setEndDateString] = useState<string | undefined>();
|
||||||
|
|
||||||
// Table state
|
// Table state
|
||||||
const [sorting, setSorting] = useState<SortingState>([]);
|
const [sorting, setSorting] = useState<SortingState>([]);
|
||||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
||||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
||||||
const [rowSelection, setRowSelection] = useState({});
|
const [rowSelection, setRowSelection] = useState({});
|
||||||
const [pagination, setPagination] = useState<PaginationState>({
|
const [pagination, setPagination] = useState<PaginationState>({
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: parseInt(size || "10"),
|
pageSize: parseInt(size || "10"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const pages = page ? parseInt(page) - 1 : 0;
|
const pages = page ? parseInt(page) - 1 : 0;
|
||||||
const currentPage = page ? parseInt(page) : 1;
|
const currentPage = page ? parseInt(page) : 1;
|
||||||
const pageSize = parseInt(size || "10");
|
const pageSize = parseInt(size || "10");
|
||||||
|
|
||||||
const isFHD = useMediaQuery({
|
const isFHD = useMediaQuery({
|
||||||
minWidth: 1920,
|
minWidth: 1920,
|
||||||
});
|
});
|
||||||
|
|
||||||
const setCurrentPage = (pageNumber: number) => {
|
const setCurrentPage = (pageNumber: number) => {
|
||||||
const params = new URLSearchParams(searchParams);
|
const params = new URLSearchParams(searchParams);
|
||||||
params.set('page', pageNumber.toString());
|
params.set("page", pageNumber.toString());
|
||||||
router.push(`${pathname}?${params.toString()}`);
|
router.push(`${pathname}?${params.toString()}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function getListPaginationData() {
|
async function getListPaginationData() {
|
||||||
loading();
|
loading();
|
||||||
console.log("Type : ", typeFilter);
|
console.log("Type : ", typeFilter);
|
||||||
console.log("Date : ", startDateString, endDateString);
|
console.log("Date : ", startDateString, endDateString);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const res = await getMediaBlastBroadcastList(
|
const res = await getMediaBlastBroadcastList(
|
||||||
pages,
|
pages,
|
||||||
activeTab === "schedule",
|
activeTab === "schedule",
|
||||||
startDateString || "",
|
startDateString || "",
|
||||||
endDateString || "",
|
endDateString || "",
|
||||||
typeFilter,
|
typeFilter,
|
||||||
id
|
id
|
||||||
);
|
);
|
||||||
|
|
||||||
close();
|
close();
|
||||||
if (res?.data?.data) {
|
if (res?.data?.data) {
|
||||||
setupData(res.data.data);
|
setupData(res.data.data);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching data:", error);
|
console.error("Error fetching data:", error);
|
||||||
close();
|
close();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getListPaginationData();
|
getListPaginationData();
|
||||||
}, [currentPage, pageSize, activeTab, endDateString, startDateString, typeFilter]);
|
}, [
|
||||||
|
currentPage,
|
||||||
|
pageSize,
|
||||||
|
activeTab,
|
||||||
|
endDateString,
|
||||||
|
startDateString,
|
||||||
|
typeFilter,
|
||||||
|
]);
|
||||||
|
|
||||||
function setupData(rawData: PaginatedResponse) {
|
function setupData(rawData: PaginatedResponse) {
|
||||||
console.log("raw", rawData);
|
console.log("raw", rawData);
|
||||||
if (rawData !== undefined) {
|
if (rawData !== undefined) {
|
||||||
const dataContent = rawData?.content;
|
const dataContent = rawData?.content;
|
||||||
const data: CampaignData[] = [];
|
const data: CampaignData[] = [];
|
||||||
|
|
||||||
dataContent.forEach((element, i) => {
|
dataContent.forEach((element, i) => {
|
||||||
element.no = (currentPage - 1) * pageSize + i + 1;
|
element.no = (currentPage - 1) * pageSize + i + 1;
|
||||||
data.push(element);
|
data.push(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
setGetData(data);
|
setGetData(data);
|
||||||
setTotalPage(rawData?.totalPages);
|
setTotalPage(rawData?.totalPages);
|
||||||
setTotalData(rawData?.totalElements);
|
setTotalData(rawData?.totalElements);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const columns: ColumnDef<CampaignData>[] = [
|
const columns: ColumnDef<CampaignData>[] = [
|
||||||
{
|
{
|
||||||
accessorKey: "no",
|
accessorKey: "no",
|
||||||
header: "No",
|
header: "No",
|
||||||
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "mediaBlastCampaign.title",
|
accessorKey: "mediaBlastCampaign.title",
|
||||||
header: "Campaign",
|
header: "Campaign",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<Link href={`/${locale}/admin/broadcast/campaign-list/detail/${row.original.mediaBlastCampaignId}`} className="text-dark">
|
<Link
|
||||||
<span className="font-weight-bold">{row.original.mediaBlastCampaign?.title}</span>
|
href={`/${locale}/admin/broadcast/campaign-list/detail/${row.original.mediaBlastCampaignId}`}
|
||||||
</Link>
|
className="text-dark"
|
||||||
),
|
>
|
||||||
},
|
<span className="font-weight-bold">
|
||||||
{
|
{row.original.mediaBlastCampaign?.title}
|
||||||
accessorKey: "subject",
|
</span>
|
||||||
header: "Judul",
|
</Link>
|
||||||
cell: ({ row }) => (
|
),
|
||||||
<Link href={`/${locale}/admin/broadcast/content/detail/${row.original.id}`} className="text-dark">
|
},
|
||||||
<span className="font-weight-bold">{row.getValue("subject")}</span>
|
{
|
||||||
</Link>
|
accessorKey: "subject",
|
||||||
),
|
header: "Judul",
|
||||||
},
|
cell: ({ row }) => (
|
||||||
{
|
<Link
|
||||||
accessorKey: "type",
|
href={`/${locale}/admin/broadcast/content/detail/${row.original.id}`}
|
||||||
header: "Tipe",
|
className="text-dark"
|
||||||
cell: ({ row }) => (
|
>
|
||||||
<div className="text-right text-black">
|
<span className="font-weight-bold">{row.getValue("subject")}</span>
|
||||||
{row.getValue("type")}
|
</Link>
|
||||||
</div>
|
),
|
||||||
)
|
},
|
||||||
},
|
{
|
||||||
{
|
accessorKey: "type",
|
||||||
accessorKey: "status",
|
header: "Tipe",
|
||||||
header: "Status",
|
cell: ({ row }) => (
|
||||||
cell: ({ row }) => (
|
<div className="text-right text-black">{row.getValue("type")}</div>
|
||||||
<div className="text-right text-black">
|
),
|
||||||
{row.getValue("status")}
|
},
|
||||||
</div>
|
{
|
||||||
)
|
accessorKey: "status",
|
||||||
},
|
header: "Status",
|
||||||
{
|
cell: ({ row }) => (
|
||||||
accessorKey: "sendDate",
|
<div className="text-right text-black">{row.getValue("status")}</div>
|
||||||
header: "Tanggal & Waktu",
|
),
|
||||||
cell: ({ row }) => (
|
},
|
||||||
<div className="text-black">
|
{
|
||||||
{row.getValue("sendDate")}
|
accessorKey: "sendDate",
|
||||||
</div>
|
header: "Tanggal & Waktu",
|
||||||
)
|
cell: ({ row }) => (
|
||||||
}
|
<div className="text-black">{row.getValue("sendDate")}</div>
|
||||||
];
|
),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
const table = useReactTable({
|
const table = useReactTable({
|
||||||
data: getData,
|
data: getData,
|
||||||
columns,
|
columns,
|
||||||
onSortingChange: setSorting,
|
onSortingChange: setSorting,
|
||||||
onColumnFiltersChange: setColumnFilters,
|
onColumnFiltersChange: setColumnFilters,
|
||||||
getCoreRowModel: getCoreRowModel(),
|
getCoreRowModel: getCoreRowModel(),
|
||||||
getPaginationRowModel: getPaginationRowModel(),
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
getSortedRowModel: getSortedRowModel(),
|
getSortedRowModel: getSortedRowModel(),
|
||||||
getFilteredRowModel: getFilteredRowModel(),
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
onColumnVisibilityChange: setColumnVisibility,
|
onColumnVisibilityChange: setColumnVisibility,
|
||||||
onRowSelectionChange: setRowSelection,
|
onRowSelectionChange: setRowSelection,
|
||||||
onPaginationChange: setPagination,
|
onPaginationChange: setPagination,
|
||||||
state: {
|
state: {
|
||||||
sorting,
|
sorting,
|
||||||
columnFilters,
|
columnFilters,
|
||||||
columnVisibility,
|
columnVisibility,
|
||||||
rowSelection,
|
rowSelection,
|
||||||
pagination,
|
pagination,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function initState() {
|
function initState() {
|
||||||
if (startDate != null && endDate != null) {
|
if (startDate != null && endDate != null) {
|
||||||
setStartDateString(getOnlyDate(startDate));
|
setStartDateString(getOnlyDate(startDate));
|
||||||
setEndDateString(getOnlyDate(endDate));
|
setEndDateString(getOnlyDate(endDate));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('date range', dateRange);
|
console.log("date range", dateRange);
|
||||||
initState();
|
initState();
|
||||||
}, [calenderState, startDate, endDate]);
|
}, [calenderState, startDate, endDate]);
|
||||||
|
|
||||||
const handleTypeFilter = (type: string) => {
|
const handleTypeFilter = (type: string) => {
|
||||||
setTypeFilter(type);
|
setTypeFilter(type);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-white container-fluid rounded rounded-xl">
|
<div className="bg-white container-fluid rounded ">
|
||||||
<div className="mt-1 p-4">
|
<div className="mt-1 p-4">
|
||||||
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-4">
|
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-4">
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setActiveTab("sent")}
|
onClick={() => setActiveTab("sent")}
|
||||||
size="md"
|
size="md"
|
||||||
className={`hover:text-white ${
|
className={`hover:text-white ${
|
||||||
activeTab === "sent"
|
activeTab === "sent"
|
||||||
? "bg-indigo-600 text-white "
|
? "bg-indigo-600 text-white "
|
||||||
: "bg-white text-black "
|
: "bg-white text-black "
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Sent
|
Sent
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setActiveTab("schedule")}
|
onClick={() => setActiveTab("schedule")}
|
||||||
size="md"
|
size="md"
|
||||||
className={`hover:text-white ${
|
className={`hover:text-white ${
|
||||||
activeTab === "schedule"
|
activeTab === "schedule"
|
||||||
? "bg-indigo-600 text-white "
|
? "bg-indigo-600 text-white "
|
||||||
: "bg-white text-black "
|
: "bg-white text-black "
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Schedule
|
Schedule
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => setActiveTab("account-list")}
|
onClick={() => setActiveTab("account-list")}
|
||||||
size="md"
|
size="md"
|
||||||
className={`hover:text-white ${
|
className={`hover:text-white ${
|
||||||
activeTab === "account-list"
|
activeTab === "account-list"
|
||||||
? "bg-indigo-600 text-white "
|
? "bg-indigo-600 text-white "
|
||||||
: "bg-white text-black "
|
: "bg-white text-black "
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
List Akun
|
List Akun
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
|
||||||
|
|
||||||
{activeTab === "account-list" ? (
|
|
||||||
<AccountListTable />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<div className="broadcast-filter flex flex-column gap-3 mb-4">
|
|
||||||
<div className="flex flex-row gap-1 border-2 rounded-md w-fit h-fit">
|
|
||||||
<Button
|
|
||||||
onClick={() => handleTypeFilter("email")}
|
|
||||||
className={`hover:text-white ${
|
|
||||||
typeFilter === "email"
|
|
||||||
? "bg-black text-white "
|
|
||||||
: "bg-white text-black "
|
|
||||||
}`}
|
|
||||||
size='sm'
|
|
||||||
>
|
|
||||||
Email Blast
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => handleTypeFilter("wa")}
|
|
||||||
className={`hover:text-white ${
|
|
||||||
typeFilter === "wa"
|
|
||||||
? "bg-black text-white "
|
|
||||||
: "bg-white text-black "
|
|
||||||
}`}
|
|
||||||
size='sm'
|
|
||||||
>
|
|
||||||
WhatsApp Blast
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div className="dashboard-date-picker">
|
|
||||||
<div className="mx-6 my-1">
|
|
||||||
<ReactDatePicker
|
|
||||||
selectsRange
|
|
||||||
startDate={startDate}
|
|
||||||
endDate={endDate}
|
|
||||||
onChange={(update) => {
|
|
||||||
setDateRange(update as [Date, Date]);
|
|
||||||
}}
|
|
||||||
placeholderText="Pilih Tanggal"
|
|
||||||
onCalendarClose={() => setCalenderState(!calenderState)}
|
|
||||||
className="form-control rounded-pill"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="w-full overflow-x-auto">
|
|
||||||
<Table className="overflow-hidden mt-3">
|
|
||||||
<TableHeader>
|
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
|
||||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
|
||||||
{headerGroup.headers.map((header) => (
|
|
||||||
<TableHead key={header.id}>
|
|
||||||
{header.isPlaceholder
|
|
||||||
? null
|
|
||||||
: flexRender(
|
|
||||||
header.column.columnDef.header,
|
|
||||||
header.getContext()
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{table.getRowModel().rows?.length ? (
|
|
||||||
table.getRowModel().rows.map((row) => (
|
|
||||||
<TableRow
|
|
||||||
key={row.id}
|
|
||||||
data-state={row.getIsSelected() && "selected"}
|
|
||||||
className="h-[75px]"
|
|
||||||
>
|
|
||||||
{row.getVisibleCells().map((cell) => (
|
|
||||||
<TableCell key={cell.id}>
|
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
||||||
</TableCell>
|
|
||||||
))}
|
|
||||||
</TableRow>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<TableRow>
|
|
||||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
|
||||||
No results.
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
)}
|
|
||||||
</TableBody>
|
|
||||||
</Table>
|
|
||||||
<TablePagination
|
|
||||||
table={table}
|
|
||||||
totalData={totalData}
|
|
||||||
totalPage={totalPage}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
|
||||||
|
{activeTab === "account-list" ? (
|
||||||
|
<AccountListTable />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className="broadcast-filter flex flex-column gap-3 mb-4">
|
||||||
|
<div className="flex flex-row gap-1 border-2 rounded-md w-fit h-fit">
|
||||||
|
<Button
|
||||||
|
onClick={() => handleTypeFilter("email")}
|
||||||
|
className={`hover:text-white ${
|
||||||
|
typeFilter === "email"
|
||||||
|
? "bg-black text-white "
|
||||||
|
: "bg-white text-black "
|
||||||
|
}`}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
Email Blast
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={() => handleTypeFilter("wa")}
|
||||||
|
className={`hover:text-white ${
|
||||||
|
typeFilter === "wa"
|
||||||
|
? "bg-black text-white "
|
||||||
|
: "bg-white text-black "
|
||||||
|
}`}
|
||||||
|
size="sm"
|
||||||
|
>
|
||||||
|
WhatsApp Blast
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
<div className="dashboard-date-picker">
|
||||||
|
<div className="mx-6 my-1">
|
||||||
|
<ReactDatePicker
|
||||||
|
selectsRange
|
||||||
|
startDate={startDate}
|
||||||
|
endDate={endDate}
|
||||||
|
onChange={(update) => {
|
||||||
|
setDateRange(update as [Date, Date]);
|
||||||
|
}}
|
||||||
|
placeholderText="Pilih Tanggal"
|
||||||
|
onCalendarClose={() => setCalenderState(!calenderState)}
|
||||||
|
className="form-control rounded-pill"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="w-full overflow-x-auto">
|
||||||
|
<Table className="overflow-hidden mt-3">
|
||||||
|
<TableHeader>
|
||||||
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
|
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||||
|
{headerGroup.headers.map((header) => (
|
||||||
|
<TableHead key={header.id}>
|
||||||
|
{header.isPlaceholder
|
||||||
|
? null
|
||||||
|
: flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
</TableHead>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableHeader>
|
||||||
|
<TableBody>
|
||||||
|
{table.getRowModel().rows?.length ? (
|
||||||
|
table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
data-state={row.getIsSelected() && "selected"}
|
||||||
|
className="h-[75px]"
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell key={cell.id}>
|
||||||
|
{flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
|
</TableRow>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableRow>
|
||||||
|
<TableCell
|
||||||
|
colSpan={columns.length}
|
||||||
|
className="h-24 text-center"
|
||||||
|
>
|
||||||
|
No results.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
<TablePagination
|
||||||
|
table={table}
|
||||||
|
totalData={totalData}
|
||||||
|
totalPage={totalPage}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
import DetailContentBlast from "@/components/form/broadcast/content-blast--detail-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
export default function DetailEmailBlast() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<DetailContentBlast />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@ const ImageCreatePage = async () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div className="space-y-4">
|
<div className="space-y-4 ">
|
||||||
<FormImage />
|
<FormImage />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import Image from "next/image";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
import { getMediaBlastBroadCast } from "@/service/broadcast/broadcast";
|
||||||
|
import { loading, close } from "@/config/swal";
|
||||||
|
|
||||||
|
interface BroadcastDetail {
|
||||||
|
id: number;
|
||||||
|
body: string;
|
||||||
|
subject: string;
|
||||||
|
sendTime: string;
|
||||||
|
thumbnail: string;
|
||||||
|
contentUrl: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function DetailContentBlast() {
|
||||||
|
const params = useParams();
|
||||||
|
const { id } = params as { id: string };
|
||||||
|
|
||||||
|
const [detail, setDetail] = useState<BroadcastDetail | null>(null);
|
||||||
|
const [notFound, setNotFound] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchDetailData();
|
||||||
|
}, [id]);
|
||||||
|
|
||||||
|
async function fetchDetailData() {
|
||||||
|
loading();
|
||||||
|
try {
|
||||||
|
const res = await getMediaBlastBroadCast(id);
|
||||||
|
close();
|
||||||
|
|
||||||
|
const detailData = res?.data?.data;
|
||||||
|
|
||||||
|
if (detailData && detailData.id === Number(id)) {
|
||||||
|
setDetail({
|
||||||
|
id: detailData.id,
|
||||||
|
body: detailData.body,
|
||||||
|
subject: detailData.subject,
|
||||||
|
sendTime: detailData.sendTime,
|
||||||
|
thumbnail: detailData.thumbnail,
|
||||||
|
contentUrl: detailData.contentUrl,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setNotFound(true);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
close();
|
||||||
|
console.error("Failed to fetch broadcast detail:", error);
|
||||||
|
setNotFound(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notFound) {
|
||||||
|
return <div className="text-red-500 p-4">Data tidak ditemukan.</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!detail) {
|
||||||
|
return <div className="text-gray-500 p-4">Loading preview...</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="bg-white rounded-md w-full p-4">
|
||||||
|
<p className="text-xl font-semibold py-1">Preview</p>
|
||||||
|
<div className="bg-[#ddf7c8] p-4 rounded-xl mx-auto space-y-4">
|
||||||
|
<div className="flex gap-4">
|
||||||
|
<Image
|
||||||
|
src={detail.thumbnail}
|
||||||
|
alt="Media Thumbnail"
|
||||||
|
width={250}
|
||||||
|
height={200}
|
||||||
|
className="rounded-md object-cover"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-sm text-black font-bold">{detail.subject}</div>
|
||||||
|
<p>
|
||||||
|
Selengkapnya silakan cek di sini:{" "}
|
||||||
|
<a
|
||||||
|
href={detail.contentUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-blue-600 underline"
|
||||||
|
>
|
||||||
|
{detail.contentUrl}
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<div className="text-right text-xs text-gray-500">
|
||||||
|
{detail.sendTime}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -117,6 +117,11 @@ export async function getMediaBlastBroadcastList(
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getMediaBlastBroadCast(id: string) {
|
||||||
|
const url = `media/blast/broadcast?id=${id}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function listDataPopUp(
|
export async function listDataPopUp(
|
||||||
page: number,
|
page: number,
|
||||||
limit: string,
|
limit: string,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue