From 0deb587a82208ae76594f880dc4e2ea560ca9915 Mon Sep 17 00:00:00 2001 From: Sabda Yagra Date: Tue, 14 Oct 2025 15:17:22 +0700 Subject: [PATCH] fix: detail article in admin page --- .../content/audio/components/columns.tsx | 11 +- .../admin/content/audio/detail/[id]/page.tsx | 4 +- .../admin/content/text/components/columns.tsx | 11 +- .../content/text/components/table-teks.tsx | 22 +- .../admin/content/text/create/page.tsx | 5 +- .../admin/content/text/detail/[id]/page.tsx | 5 +- .../audio-visual/video-detail-form.tsx | 266 +- .../form/content/audio-visual/video-form.tsx | 3275 +++++++++-------- .../form/content/audio/audio-detail-form.tsx | 62 +- .../content/document/teks-detail-form.tsx | 136 +- .../form/content/document/teks-form.tsx | 35 +- components/form/content/file-preview-text.tsx | 97 +- components/landing-page/media-update.tsx | 54 +- 13 files changed, 2171 insertions(+), 1812 deletions(-) diff --git a/app/[locale]/(admin)/admin/content/audio/components/columns.tsx b/app/[locale]/(admin)/admin/content/audio/components/columns.tsx index 78b4b9b..43ba06f 100644 --- a/app/[locale]/(admin)/admin/content/audio/components/columns.tsx +++ b/app/[locale]/(admin)/admin/content/audio/components/columns.tsx @@ -77,12 +77,21 @@ const useTableColumns = () => { return {formattedDate}; }, }, + // { + // accessorKey: "creatorName", + // header: "Creator Group", + // cell: ({ row }) => ( + // + // {row.getValue("creatorName") || row.getValue("createdByName")} + // + // ), + // }, { accessorKey: "creatorName", header: "Creator Group", cell: ({ row }) => ( - {row.getValue("creatorName") || row.getValue("createdByName")} + {row.original.creatorName || row.original.createdByName || "-"} ), }, diff --git a/app/[locale]/(admin)/admin/content/audio/detail/[id]/page.tsx b/app/[locale]/(admin)/admin/content/audio/detail/[id]/page.tsx index c2ab04f..56d1ca3 100644 --- a/app/[locale]/(admin)/admin/content/audio/detail/[id]/page.tsx +++ b/app/[locale]/(admin)/admin/content/audio/detail/[id]/page.tsx @@ -1,9 +1,11 @@ import FormAudioDetail from "@/components/form/content/audio/audio-detail-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; const AudioDetailPage = async () => { return (
-
+ +
diff --git a/app/[locale]/(admin)/admin/content/text/components/columns.tsx b/app/[locale]/(admin)/admin/content/text/components/columns.tsx index 5ea035b..ab78050 100644 --- a/app/[locale]/(admin)/admin/content/text/components/columns.tsx +++ b/app/[locale]/(admin)/admin/content/text/components/columns.tsx @@ -77,12 +77,21 @@ const useTableColumns = () => { return {formattedDate}; }, }, + // { + // accessorKey: "creatorName", + // header: "Creator Group", + // cell: ({ row }) => ( + // + // {row.getValue("creatorName") || row.getValue("createdByName")} + // + // ), + // }, { accessorKey: "creatorName", header: "Creator Group", cell: ({ row }) => ( - {row.getValue("creatorName") || row.getValue("createdByName")} + {row.original.creatorName || row.original.createdByName || "-"} ), }, diff --git a/app/[locale]/(admin)/admin/content/text/components/table-teks.tsx b/app/[locale]/(admin)/admin/content/text/components/table-teks.tsx index 7818ca3..bc8a491 100644 --- a/app/[locale]/(admin)/admin/content/text/components/table-teks.tsx +++ b/app/[locale]/(admin)/admin/content/text/components/table-teks.tsx @@ -66,7 +66,6 @@ import useTableColumns from "./columns"; const TableTeks = () => { const router = useRouter(); const searchParams = useSearchParams(); - const [dataTable, setDataTable] = React.useState([]); const [totalData, setTotalData] = React.useState(1); const [sorting, setSorting] = React.useState([]); @@ -76,18 +75,14 @@ const TableTeks = () => { const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); - const [showData, setShowData] = React.useState("50"); + 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 [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(""); - const userId = getCookiesDecrypt("uie"); - const userLevelId = getCookiesDecrypt("ulie"); - const [categories, setCategories] = React.useState([]); const [selectedCategories, setSelectedCategories] = React.useState( [] @@ -99,7 +94,6 @@ const TableTeks = () => { const [filterByCreator, setFilterByCreator] = React.useState(""); const [filterBySource, setFilterBySource] = React.useState(""); const [filterByCreatorGroup, setFilterByCreatorGroup] = React.useState(""); - const roleId = getCookiesDecrypt("urie"); const columns = useTableColumns(); const table = useReactTable({ @@ -179,13 +173,12 @@ const TableTeks = () => { : ""; try { - // Using the new interface-based approach for video content const filters: ArticleFilters = { - page: page, + page, totalPage: Number(showData), title: search || undefined, categoryId: categoryFilter ? Number(categoryFilter) : undefined, - typeId: 3, + typeId: 3, // ๐Ÿ”น text content statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined, startDate: formattedStartDate || undefined, @@ -194,14 +187,17 @@ const TableTeks = () => { const res = await listArticlesWithFilters(filters); const data = res?.data?.data; + const meta = res?.data?.meta; if (Array.isArray(data)) { data.forEach((item: any, index: number) => { item.no = (page - 1) * Number(showData) + index + 1; }); setDataTable(data); - setTotalData(data.length); - setTotalPage(Math.ceil(data.length / Number(showData))); + setTotalData(meta?.count ?? data.length); + setTotalPage( + meta?.totalPage ?? Math.ceil(data.length / Number(showData)) + ); } else if (Array.isArray(data?.content)) { const contentData = data.content; contentData.forEach((item: any, index: number) => { @@ -218,7 +214,7 @@ const TableTeks = () => { setTotalPage(1); } } catch (error) { - console.error("Error fetching tasks:", error); + console.error("Error fetching text content:", error); setDataTable([]); setTotalData(0); setTotalPage(1); diff --git a/app/[locale]/(admin)/admin/content/text/create/page.tsx b/app/[locale]/(admin)/admin/content/text/create/page.tsx index 83d87e1..b69509f 100644 --- a/app/[locale]/(admin)/admin/content/text/create/page.tsx +++ b/app/[locale]/(admin)/admin/content/text/create/page.tsx @@ -1,10 +1,11 @@ import FormTeks from "@/components/form/content/document/teks-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; const TeksCreatePage = async () => { return (
- {/* */} -
+ +
diff --git a/app/[locale]/(admin)/admin/content/text/detail/[id]/page.tsx b/app/[locale]/(admin)/admin/content/text/detail/[id]/page.tsx index f20a280..38ba463 100644 --- a/app/[locale]/(admin)/admin/content/text/detail/[id]/page.tsx +++ b/app/[locale]/(admin)/admin/content/text/detail/[id]/page.tsx @@ -1,10 +1,11 @@ import FormTeksDetail from "@/components/form/content/document/teks-detail-form"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; const TeksDetailPage = async () => { return (
- {/* */} -
+ +
diff --git a/components/form/content/audio-visual/video-detail-form.tsx b/components/form/content/audio-visual/video-detail-form.tsx index 984858f..b2d4074 100644 --- a/components/form/content/audio-visual/video-detail-form.tsx +++ b/components/form/content/audio-visual/video-detail-form.tsx @@ -21,8 +21,6 @@ import { Checkbox } from "@/components/ui/checkbox"; import Cookies from "js-cookie"; import { getArticleDetail, - getTagsBySubCategoryId, - listEnableCategory, publishMedia, submitApproval, } from "@/service/content/content"; @@ -47,7 +45,6 @@ import { getCookiesDecrypt } from "@/lib/utils"; import { Icon } from "@iconify/react/dist/iconify.js"; import { error } from "@/lib/swal"; import dynamic from "next/dynamic"; -import SuggestionModal from "@/components/modal/suggestions-modal"; import { formatDateToIndonesian } from "@/utils/globals"; import ApprovalHistoryModal from "@/components/modal/approval-history-modal"; import { listArticleCategories } from "@/service/content"; @@ -62,19 +59,13 @@ const ViewEditor = dynamic(() => import("@/components/editor/view-editor"), { ssr: false, }); -type Category = { - id: string; - title: string; -}; - +type Category = { id: string; title: string }; type FileType = { id: number; fileName: string; fileUrl?: string; fileThumbnail?: string; - format?: string; }; - type Detail = { id: number; title: string; @@ -137,46 +128,28 @@ export default function FormVideoDetail() { const MySwal = withReactContent(Swal); const router = useRouter(); const { id } = useParams() as { id: string }; + const userId = getCookiesDecrypt("uie"); const userLevelId = getCookiesDecrypt("ulie"); const userLevelName = Cookies.get("state"); const roleId = getCookiesDecrypt("urie"); + const [detail, setDetail] = useState(null); const [categories, setCategories] = useState([]); const [files, setFiles] = useState([]); const [thumbsSwiper, setThumbsSwiper] = useState(null); const [approval, setApproval] = useState(); const [selectedPublishers, setSelectedPublishers] = useState([]); + const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); const [modalOpen, setModalOpen] = useState(false); const [status, setStatus] = useState(""); const [description, setDescription] = useState(""); const [filePlacements, setFilePlacements] = useState([]); - const [isUserMabesApprover, setIsUserMabesApprover] = useState(false); - const [refresh, setRefresh] = useState(false); - const [detailVideos, setDetailVideos] = useState([]); - const [selectedCategory, setSelectedCategory] = useState(""); - const { - control, - formState: { errors }, - } = useForm({ - resolver: zodResolver(videoSchema), - }); - - const getStatusName = (statusId: number): string => { - const statusMap: { [key: number]: string } = { - 1: "Menunggu Review", - 2: "Diterima", - 3: "Minta Update", - 4: "Ditolak", - }; - return statusMap[statusId] || "Unknown"; - }; + const { control } = useForm({ resolver: zodResolver(videoSchema) }); useEffect(() => { - if (userLevelId == "216" && roleId == "3") { - setIsUserMabesApprover(true); - } + if (userLevelId == "216" && roleId == "3") setIsUserMabesApprover(true); }, [userLevelId, roleId]); useEffect(() => { @@ -193,29 +166,16 @@ export default function FormVideoDetail() { try { const response = await getArticleDetail(Number(id)); const details = response?.data?.data; - setSelectedCategory(String(details.categories[0].id)); const mappedDetail: Detail = { ...details, + statusId: details?.statusId, categoryId: details?.categories?.[0]?.id, htmlDescription: details?.htmlDescription, - statusName: getStatusName(details?.statusId), uploadedById: details?.createdById, files: details?.files || [], - categories: details?.categories || [], }; - - const mappedFiles = - details?.files?.map((f: any) => ({ - id: f.id, - fileName: f.fileName, - fileUrl: f.fileUrl, - fileThumbnail: f.fileThumbnail, - format: f.format || "mp4", - })) || []; - setDetail(mappedDetail); - setFiles(mappedFiles); - setDetailVideos(mappedFiles.map((f: any) => f.fileUrl || "")); + setFiles(details?.files || []); const approvals = await getDataApprovalByMediaUpload(mappedDetail.id); setApproval(approvals?.data?.data); } catch (err) { @@ -223,33 +183,32 @@ export default function FormVideoDetail() { } } fetchDetail(); - }, [id, refresh]); + }, [id]); + + const getStatusName = (statusId: number) => { + const map: Record = { + 1: "Menunggu Review", + 2: "Diterima", + 3: "Minta Update", + 4: "Ditolak", + }; + return map[statusId] || "Unknown"; + }; const handleCheckboxChange = (id: number) => { setSelectedPublishers((prev) => - prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id] + prev.includes(id) ? prev.filter((i) => i !== id) : [...prev, id] ); }; - const actionApproval = (e: string) => { - const temp = []; - for (const element of files) temp.push([]); - setFilePlacements(temp); - setStatus(e); + const actionApproval = (type: string) => { + const placements = files.map(() => []); + setFilePlacements(placements); + setStatus(type); setDescription(""); setModalOpen(true); }; - const submit = async () => { - if ( - (description?.length > 1 && Number(status) == 3) || - Number(status) == 2 || - Number(status) == 4 - ) { - await save(); - } - }; - const save = async () => { const data = { action: status == "2" ? "approve" : status == "3" ? "revision" : "reject", @@ -257,8 +216,8 @@ export default function FormVideoDetail() { }; setModalOpen(false); loading(); - const response = await submitApproval(id, data); - if (response?.error) return error(response.message); + const res = await submitApproval(id, data); + if (res?.error) return error(res.message); close(); MySwal.fire({ title: "Sukses", @@ -272,23 +231,15 @@ export default function FormVideoDetail() { successCallback(); }; - if (!detail) { - return ( -
- Memuat detail video... -
- ); - } + if (!detail) return
Memuat data...
; return (
- {/* LEFT SIDE */}

Form Video

- {/* Title */}
( )} /> - {/* {errors.title?.message && ( -

{errors.title.message}

- )} */}
- {/* Category */}
- - {categories?.map((cat) => ( + {categories.map((cat) => ( {cat.title} @@ -328,29 +270,12 @@ export default function FormVideoDetail() {
- {/*
- - -
*/} - {/* Description */}
- {/* Video Files */}
- {/* RIGHT SIDE */}
- +
Thumbnail @@ -417,10 +337,10 @@ export default function FormVideoDetail() {
- {detail.tags?.split(",").map((tag: string, index: number) => ( + {detail.tags?.split(",").map((tag, i) => ( {tag.trim()} @@ -436,24 +356,18 @@ export default function FormVideoDetail() { id={String(target)} checked={selectedPublishers.includes(target)} onChange={() => handleCheckboxChange(target)} - className="border" />
))}
- {/* */} -

Information:

- {detail.statusName || getStatusName(detail.statusId)} + {detail.statusId && getStatusName(detail.statusId)}

Komentar

{approval?.message}

@@ -471,6 +385,108 @@ export default function FormVideoDetail() {
)} + + {(Number(detail.needApprovalFromLevel || 0) == + Number(userLevelId) || + (detail.isPublish === false && detail.statusId == 1)) && + Number(detail.uploadedById || detail.createdById) != + Number(userId) ? ( +
+ + + +
+ ) : null} + + + + + Leave Comment + + + {status === "2" && + files.map((file, i) => ( +
+
+ ))} + +