diff --git a/app/[locale]/(protected)/admin/broadcast/campaign-list/detail/[id]/page.tsx b/app/[locale]/(protected)/admin/broadcast/campaign-list/detail/[id]/page.tsx index 76cd9e5e..6208c467 100644 --- a/app/[locale]/(protected)/admin/broadcast/campaign-list/detail/[id]/page.tsx +++ b/app/[locale]/(protected)/admin/broadcast/campaign-list/detail/[id]/page.tsx @@ -1,4 +1,4 @@ -'use client' +"use client"; import "react-datepicker/dist/react-datepicker.css"; import { Icon } from "@iconify/react"; @@ -33,9 +33,9 @@ import { } from "@/components/ui/table"; import { Button } from "@/components/ui/button"; import TablePagination from "@/components/table/table-pagination"; -import { +import { getMediaBlastCampaignById, - getMediaBlastBroadcastList + getMediaBlastBroadcastList, } from "@/service/broadcast/broadcast"; // Types @@ -69,319 +69,342 @@ interface PageProps { }; } -export default function BroadcastCampaignDetail({ params, searchParams }: PageProps) { - const router = useRouter(); - const pathname = usePathname(); - const { id, locale } = params; - const [getData, setGetData] = useState([]); - const [totalPage, setTotalPage] = useState(0); - const [totalData, setTotalData] = useState(0); - const [activeTab, setActiveTab] = useState<"sent" | "schedule" | "account-list">("sent"); - const { page, size } = searchParams; +export default function BroadcastCampaignDetail({ + params, + searchParams, +}: PageProps) { + const router = useRouter(); + const pathname = usePathname(); + const { id, locale } = params; + const [getData, setGetData] = useState([]); + const [totalPage, setTotalPage] = useState(0); + const [totalData, setTotalData] = useState(0); + const [activeTab, setActiveTab] = useState< + "sent" | "schedule" | "account-list" + >("sent"); + const { page, size } = searchParams; - const [calenderState, setCalenderState] = useState(false); - const [typeFilter, setTypeFilter] = useState("email"); - const [dateRange, setDateRange] = useState<[Date, Date]>([new Date(), new Date()]); - const [startDate, endDate] = dateRange; + const [calenderState, setCalenderState] = useState(false); + const [typeFilter, setTypeFilter] = useState("email"); + const [dateRange, setDateRange] = useState<[Date, Date]>([ + new Date(), + new Date(), + ]); + const [startDate, endDate] = dateRange; - const [startDateString, setStartDateString] = useState(); - const [endDateString, setEndDateString] = useState(); + const [startDateString, setStartDateString] = useState(); + const [endDateString, setEndDateString] = useState(); - // Table state - const [sorting, setSorting] = useState([]); - const [columnFilters, setColumnFilters] = useState([]); - const [columnVisibility, setColumnVisibility] = useState({}); - const [rowSelection, setRowSelection] = useState({}); - const [pagination, setPagination] = useState({ - pageIndex: 0, - pageSize: parseInt(size || "10"), - }); + // Table state + const [sorting, setSorting] = useState([]); + const [columnFilters, setColumnFilters] = useState([]); + const [columnVisibility, setColumnVisibility] = useState({}); + const [rowSelection, setRowSelection] = useState({}); + const [pagination, setPagination] = useState({ + pageIndex: 0, + pageSize: parseInt(size || "10"), + }); - const pages = page ? parseInt(page) - 1 : 0; - const currentPage = page ? parseInt(page) : 1; - const pageSize = parseInt(size || "10"); + const pages = page ? parseInt(page) - 1 : 0; + const currentPage = page ? parseInt(page) : 1; + const pageSize = parseInt(size || "10"); - const isFHD = useMediaQuery({ - minWidth: 1920, - }); + const isFHD = useMediaQuery({ + minWidth: 1920, + }); - const setCurrentPage = (pageNumber: number) => { - const params = new URLSearchParams(searchParams); - params.set('page', pageNumber.toString()); - router.push(`${pathname}?${params.toString()}`); - }; + const setCurrentPage = (pageNumber: number) => { + const params = new URLSearchParams(searchParams); + params.set("page", pageNumber.toString()); + router.push(`${pathname}?${params.toString()}`); + }; - async function getListPaginationData() { - loading(); - console.log("Type : ", typeFilter); - console.log("Date : ", startDateString, endDateString); - - try { - const res = await getMediaBlastBroadcastList( - pages, - activeTab === "schedule", - startDateString || "", - endDateString || "", - typeFilter, - id - ); - - close(); - if (res?.data?.data) { - setupData(res.data.data); - } - } catch (error) { - console.error("Error fetching data:", error); - close(); - } + async function getListPaginationData() { + loading(); + console.log("Type : ", typeFilter); + console.log("Date : ", startDateString, endDateString); + + try { + const res = await getMediaBlastBroadcastList( + pages, + activeTab === "schedule", + startDateString || "", + endDateString || "", + typeFilter, + id + ); + + close(); + if (res?.data?.data) { + setupData(res.data.data); + } + } catch (error) { + console.error("Error fetching data:", error); + close(); } + } - useEffect(() => { - getListPaginationData(); - }, [currentPage, pageSize, activeTab, endDateString, startDateString, typeFilter]); + useEffect(() => { + getListPaginationData(); + }, [ + currentPage, + pageSize, + activeTab, + endDateString, + startDateString, + typeFilter, + ]); - function setupData(rawData: PaginatedResponse) { - console.log("raw", rawData); - if (rawData !== undefined) { - const dataContent = rawData?.content; - const data: CampaignData[] = []; + function setupData(rawData: PaginatedResponse) { + console.log("raw", rawData); + if (rawData !== undefined) { + const dataContent = rawData?.content; + const data: CampaignData[] = []; - dataContent.forEach((element, i) => { - element.no = (currentPage - 1) * pageSize + i + 1; - data.push(element); - }); + dataContent.forEach((element, i) => { + element.no = (currentPage - 1) * pageSize + i + 1; + data.push(element); + }); - setGetData(data); - setTotalPage(rawData?.totalPages); - setTotalData(rawData?.totalElements); - } + setGetData(data); + setTotalPage(rawData?.totalPages); + setTotalData(rawData?.totalElements); } + } - const columns: ColumnDef[] = [ - { - accessorKey: "no", - header: "No", - cell: ({ row }) => {row.getValue("no")}, - }, - { - accessorKey: "mediaBlastCampaign.title", - header: "Campaign", - cell: ({ row }) => ( - - {row.original.mediaBlastCampaign?.title} - - ), - }, - { - accessorKey: "subject", - header: "Judul", - cell: ({ row }) => ( - - {row.getValue("subject")} - - ), - }, - { - accessorKey: "type", - header: "Tipe", - cell: ({ row }) => ( -
- {row.getValue("type")} -
- ) - }, - { - accessorKey: "status", - header: "Status", - cell: ({ row }) => ( -
- {row.getValue("status")} -
- ) - }, - { - accessorKey: "sendDate", - header: "Tanggal & Waktu", - cell: ({ row }) => ( -
- {row.getValue("sendDate")} -
- ) - } - ]; + const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => {row.getValue("no")}, + }, + { + accessorKey: "mediaBlastCampaign.title", + header: "Campaign", + cell: ({ row }) => ( + + + {row.original.mediaBlastCampaign?.title} + + + ), + }, + { + accessorKey: "subject", + header: "Judul", + cell: ({ row }) => ( + + {row.getValue("subject")} + + ), + }, + { + accessorKey: "type", + header: "Tipe", + cell: ({ row }) => ( +
{row.getValue("type")}
+ ), + }, + { + accessorKey: "status", + header: "Status", + cell: ({ row }) => ( +
{row.getValue("status")}
+ ), + }, + { + accessorKey: "sendDate", + header: "Tanggal & Waktu", + cell: ({ row }) => ( +
{row.getValue("sendDate")}
+ ), + }, + ]; - const table = useReactTable({ - data: getData, - 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, - }, - }); + const table = useReactTable({ + data: getData, + 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, + }, + }); - useEffect(() => { - function initState() { - if (startDate != null && endDate != null) { - setStartDateString(getOnlyDate(startDate)); - setEndDateString(getOnlyDate(endDate)); - } - } - console.log('date range', dateRange); - initState(); - }, [calenderState, startDate, endDate]); + useEffect(() => { + function initState() { + if (startDate != null && endDate != null) { + setStartDateString(getOnlyDate(startDate)); + setEndDateString(getOnlyDate(endDate)); + } + } + console.log("date range", dateRange); + initState(); + }, [calenderState, startDate, endDate]); - const handleTypeFilter = (type: string) => { - setTypeFilter(type); - }; + const handleTypeFilter = (type: string) => { + setTypeFilter(type); + }; - return ( -
-
-
- - - -
- - {activeTab === "account-list" ? ( - - ) : ( - <> -
-
- - -
-
-
- { - setDateRange(update as [Date, Date]); - }} - placeholderText="Pilih Tanggal" - onCalendarClose={() => setCalenderState(!calenderState)} - className="form-control rounded-pill" - /> -
-
-
- -
- - - {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. - - - )} - -
- -
- - )} -
+ return ( +
+
+
+ + +
- ); + + {activeTab === "account-list" ? ( + + ) : ( + <> +
+
+ + +
+
+
+ { + setDateRange(update as [Date, Date]); + }} + placeholderText="Pilih Tanggal" + onCalendarClose={() => setCalenderState(!calenderState)} + className="form-control rounded-pill" + /> +
+
+
+ +
+ + + {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. + + + )} + +
+ +
+ + )} +
+
+ ); } diff --git a/app/[locale]/(protected)/admin/broadcast/content/detail/[id]/page.tsx b/app/[locale]/(protected)/admin/broadcast/content/detail/[id]/page.tsx new file mode 100644 index 00000000..8940b467 --- /dev/null +++ b/app/[locale]/(protected)/admin/broadcast/content/detail/[id]/page.tsx @@ -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 ( +
+ + +
+ ); +} diff --git a/app/[locale]/(protected)/contributor/content/image/create/page.tsx b/app/[locale]/(protected)/contributor/content/image/create/page.tsx index a05b55ea..78031d44 100644 --- a/app/[locale]/(protected)/contributor/content/image/create/page.tsx +++ b/app/[locale]/(protected)/contributor/content/image/create/page.tsx @@ -8,8 +8,8 @@ const ImageCreatePage = async () => { return (
-
- +
+
); diff --git a/components/auth/login-form.tsx b/components/auth/login-form.tsx index a8c447e8..5668d97f 100644 --- a/components/auth/login-form.tsx +++ b/components/auth/login-form.tsx @@ -8,7 +8,7 @@ import { Checkbox } from "@/components/ui/checkbox"; import { Label } from "@/components/ui/label"; import { Link } from "@/i18n/routing"; import { useTranslations } from "next-intl"; -import { +import { Dialog, DialogContent, DialogFooter, @@ -27,7 +27,7 @@ export const LoginForm: React.FC = ({ }) => { const t = useTranslations("LandingPage"); const { login } = useAuth(); - + const [showPassword, setShowPassword] = useState(false); const [rememberMe, setRememberMe] = useState(true); const [roles, setRoles] = useState([]); @@ -210,4 +210,4 @@ export const LoginForm: React.FC = ({
); -}; \ No newline at end of file +}; diff --git a/components/auth/otp-form.tsx b/components/auth/otp-form.tsx index b5ea3072..5adcd047 100644 --- a/components/auth/otp-form.tsx +++ b/components/auth/otp-form.tsx @@ -94,39 +94,39 @@ export const OTPForm: React.FC = ({ className="gap-2" > - - - - - - @@ -166,4 +166,4 @@ export const OTPForm: React.FC = ({
); -}; \ No newline at end of file +}; diff --git a/components/form/broadcast/content-blast--detail-form.tsx b/components/form/broadcast/content-blast--detail-form.tsx new file mode 100644 index 00000000..b7800873 --- /dev/null +++ b/components/form/broadcast/content-blast--detail-form.tsx @@ -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(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
Data tidak ditemukan.
; + } + + if (!detail) { + return
Loading preview...
; + } + + return ( +
+

Preview

+
+
+ Media Thumbnail +
+ +
{detail.subject}
+

+ Selengkapnya silakan cek di sini:{" "} + + {detail.contentUrl} + +

+
+ {detail.sendTime} +
+
+
+ ); +} diff --git a/service/broadcast/broadcast.ts b/service/broadcast/broadcast.ts index a148bcaa..dc269940 100644 --- a/service/broadcast/broadcast.ts +++ b/service/broadcast/broadcast.ts @@ -106,17 +106,22 @@ export async function saveMediaBlastBroadcast(data: any) { } export async function getMediaBlastBroadcastList( - page: number, - isScheduled: boolean, - startDate: string, - endDate: string, - type: string, + page: number, + isScheduled: boolean, + startDate: string, + endDate: string, + type: string, campaignId: string ) { const url = `media/blast/broadcast/list?enablePage=1&page=${page}&isScheduled=${isScheduled}&type=${type}&startDate=${startDate}&endDate=${endDate}&campaignId=${campaignId}`; return httpGetInterceptor(url); } +export async function getMediaBlastBroadCast(id: string) { + const url = `media/blast/broadcast?id=${id}`; + return httpGetInterceptor(url); +} + export async function listDataPopUp( page: number, limit: string,