fixing sabda
This commit is contained in:
parent
9fa3148d48
commit
78a4f6d1f8
|
|
@ -42,7 +42,7 @@ const AudioVisualTabs = () => {
|
||||||
|
|
||||||
<TabsContent value="pending" className="mt-0">
|
<TabsContent value="pending" className="mt-0">
|
||||||
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
||||||
<PendingApprovalTable />
|
<PendingApprovalTable typeId={2} />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,11 @@ import TablePagination from "@/components/table/table-pagination";
|
||||||
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
||||||
import usePendingApprovalColumns from "./pending-approval-columns";
|
import usePendingApprovalColumns from "./pending-approval-columns";
|
||||||
|
|
||||||
const PendingApprovalTable = () => {
|
type PendingApprovalTableProps = {
|
||||||
|
typeId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PendingApprovalTable = ({ typeId }: PendingApprovalTableProps) => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(0);
|
const [totalData, setTotalData] = React.useState<number>(0);
|
||||||
|
|
@ -111,7 +115,7 @@ const PendingApprovalTable = () => {
|
||||||
async function fetchPendingData() {
|
async function fetchPendingData() {
|
||||||
try {
|
try {
|
||||||
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
||||||
const res = await listPendingApproval(page, Number(showData));
|
const res = await listPendingApproval(page, Number(showData), typeId);
|
||||||
|
|
||||||
if (res && !res.error && res.data) {
|
if (res && !res.error && res.data) {
|
||||||
// Filter data based on search if provided
|
// Filter data based on search if provided
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ import {
|
||||||
listDataVideo,
|
listDataVideo,
|
||||||
listArticles,
|
listArticles,
|
||||||
listArticlesWithFilters,
|
listArticlesWithFilters,
|
||||||
ArticleFilters
|
ArticleFilters,
|
||||||
} from "@/service/content";
|
} from "@/service/content";
|
||||||
import {
|
import {
|
||||||
SortingState,
|
SortingState,
|
||||||
|
|
@ -174,6 +174,7 @@ const TableVideo = () => {
|
||||||
const formattedEndDate = endDate
|
const formattedEndDate = endDate
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Using the new interface-based approach for video content
|
// Using the new interface-based approach for video content
|
||||||
const filters: ArticleFilters = {
|
const filters: ArticleFilters = {
|
||||||
|
|
@ -182,15 +183,15 @@ const TableVideo = () => {
|
||||||
title: search || undefined,
|
title: search || undefined,
|
||||||
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
typeId: 2, // video content type
|
typeId: 2, // video content type
|
||||||
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
statusId:
|
||||||
|
statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
startDate: formattedStartDate || undefined,
|
startDate: formattedStartDate || undefined,
|
||||||
endDate: formattedEndDate || undefined,
|
endDate: formattedEndDate || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await listArticlesWithFilters(filters);
|
const res = await listArticlesWithFilters(filters);
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
// Handle new articles API response structure
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
data.forEach((item: any, index: number) => {
|
data.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
|
|
@ -198,21 +199,80 @@ const TableVideo = () => {
|
||||||
setDataTable(data);
|
setDataTable(data);
|
||||||
setTotalData(data.length);
|
setTotalData(data.length);
|
||||||
setTotalPage(Math.ceil(data.length / Number(showData)));
|
setTotalPage(Math.ceil(data.length / Number(showData)));
|
||||||
} else {
|
} else if (Array.isArray(data?.content)) {
|
||||||
// Fallback to old structure if API still returns old format
|
const contentData = data.content;
|
||||||
const contentData = data?.content;
|
|
||||||
contentData.forEach((item: any, index: number) => {
|
contentData.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
});
|
});
|
||||||
setDataTable(contentData);
|
setDataTable(contentData);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data?.totalElements ?? contentData.length);
|
||||||
setTotalPage(data?.totalPages);
|
setTotalPage(
|
||||||
|
data?.totalPages ?? Math.ceil(contentData.length / Number(showData))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// async function fetchData() {
|
||||||
|
// const formattedStartDate = startDate
|
||||||
|
// ? format(new Date(startDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// const formattedEndDate = endDate
|
||||||
|
// ? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// try {
|
||||||
|
// // Using the new interface-based approach for video content
|
||||||
|
// const filters: ArticleFilters = {
|
||||||
|
// page: page,
|
||||||
|
// totalPage: Number(showData),
|
||||||
|
// title: search || undefined,
|
||||||
|
// categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
|
// typeId: 2, // video content type
|
||||||
|
// statusId:
|
||||||
|
// statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
|
// startDate: formattedStartDate || undefined,
|
||||||
|
// endDate: formattedEndDate || undefined,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const res = await listArticlesWithFilters(filters);
|
||||||
|
|
||||||
|
// const data = res?.data?.data;
|
||||||
|
// // Handle new articles API response structure
|
||||||
|
// 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)));
|
||||||
|
// } else {
|
||||||
|
// // Fallback to old structure if API still returns old format
|
||||||
|
// const contentData = data?.content;
|
||||||
|
// contentData.forEach((item: any, index: number) => {
|
||||||
|
// item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
|
// });
|
||||||
|
// setDataTable(contentData);
|
||||||
|
// setTotalData(data?.totalElements ?? contentData.length);
|
||||||
|
// setTotalPage(
|
||||||
|
// data?.totalPages ?? Math.ceil(contentData.length / Number(showData))
|
||||||
|
// );
|
||||||
|
// // setTotalData(data?.totalElements);
|
||||||
|
// // setTotalPage(data?.totalPages);
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error fetching tasks:", error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setSearch(e.target.value); // Perbarui state search
|
setSearch(e.target.value); // Perbarui state search
|
||||||
table.getColumn("title")?.setFilterValue(e.target.value); // Set filter tabel
|
table.getColumn("title")?.setFilterValue(e.target.value); // Set filter tabel
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const AudioTabs = () => {
|
||||||
|
|
||||||
<TabsContent value="pending" className="mt-0">
|
<TabsContent value="pending" className="mt-0">
|
||||||
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
||||||
<PendingApprovalTable />
|
<PendingApprovalTable typeId={4} />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,11 @@ import TablePagination from "@/components/table/table-pagination";
|
||||||
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
||||||
import usePendingApprovalColumns from "./pending-approval-columns";
|
import usePendingApprovalColumns from "./pending-approval-columns";
|
||||||
|
|
||||||
const PendingApprovalTable = () => {
|
type PendingApprovalTableProps = {
|
||||||
|
typeId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PendingApprovalTable = ({ typeId }: PendingApprovalTableProps) => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(0);
|
const [totalData, setTotalData] = React.useState<number>(0);
|
||||||
|
|
@ -111,7 +115,7 @@ const PendingApprovalTable = () => {
|
||||||
async function fetchPendingData() {
|
async function fetchPendingData() {
|
||||||
try {
|
try {
|
||||||
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
||||||
const res = await listPendingApproval(page, Number(showData));
|
const res = await listPendingApproval(page, Number(showData), typeId);
|
||||||
|
|
||||||
if (res && !res.error && res.data) {
|
if (res && !res.error && res.data) {
|
||||||
// Filter data based on search if provided
|
// Filter data based on search if provided
|
||||||
|
|
|
||||||
|
|
@ -171,51 +171,106 @@ const TableAudio = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
const formattedStartDate = startDate
|
const formattedStartDate = startDate
|
||||||
? format(new Date(startDate), "yyyy-MM-dd")
|
? format(new Date(startDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
const formattedEndDate = endDate
|
const formattedEndDate = endDate
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
try {
|
|
||||||
// Using the new interface-based approach for audio content
|
|
||||||
const filters: ArticleFilters = {
|
|
||||||
page: page,
|
|
||||||
totalPage: Number(showData),
|
|
||||||
title: search || undefined,
|
|
||||||
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
|
||||||
typeId: 4, // audio content type
|
|
||||||
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
|
||||||
startDate: formattedStartDate || undefined,
|
|
||||||
endDate: formattedEndDate || undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
const res = await listArticlesWithFilters(filters);
|
try {
|
||||||
|
// Using the new interface-based approach for video content
|
||||||
|
const filters: ArticleFilters = {
|
||||||
|
page: page,
|
||||||
|
totalPage: Number(showData),
|
||||||
|
title: search || undefined,
|
||||||
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
|
typeId: 2, // video content type
|
||||||
|
statusId:
|
||||||
|
statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
|
startDate: formattedStartDate || undefined,
|
||||||
|
endDate: formattedEndDate || undefined,
|
||||||
|
};
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const res = await listArticlesWithFilters(filters);
|
||||||
// Handle new articles API response structure
|
const data = res?.data?.data;
|
||||||
if (Array.isArray(data)) {
|
|
||||||
data.forEach((item: any, index: number) => {
|
if (Array.isArray(data)) {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
data.forEach((item: any, index: number) => {
|
||||||
});
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
setDataTable(data);
|
});
|
||||||
setTotalData(data.length);
|
setDataTable(data);
|
||||||
setTotalPage(Math.ceil(data.length / Number(showData)));
|
setTotalData(data.length);
|
||||||
} else {
|
setTotalPage(Math.ceil(data.length / Number(showData)));
|
||||||
// Fallback to old structure if API still returns old format
|
} else if (Array.isArray(data?.content)) {
|
||||||
const contentData = data?.content;
|
const contentData = data.content;
|
||||||
contentData.forEach((item: any, index: number) => {
|
contentData.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
});
|
});
|
||||||
setDataTable(contentData);
|
setDataTable(contentData);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data?.totalElements ?? contentData.length);
|
||||||
setTotalPage(data?.totalPages);
|
setTotalPage(
|
||||||
|
data?.totalPages ?? Math.ceil(contentData.length / Number(showData))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching tasks:", error);
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching tasks:", error);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// async function fetchData() {
|
||||||
|
// const formattedStartDate = startDate
|
||||||
|
// ? format(new Date(startDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// const formattedEndDate = endDate
|
||||||
|
// ? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// try {
|
||||||
|
// // Using the new interface-based approach for audio content
|
||||||
|
// const filters: ArticleFilters = {
|
||||||
|
// page: page,
|
||||||
|
// totalPage: Number(showData),
|
||||||
|
// title: search || undefined,
|
||||||
|
// categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
|
// typeId: 4, // audio content type
|
||||||
|
// statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
|
// startDate: formattedStartDate || undefined,
|
||||||
|
// endDate: formattedEndDate || undefined,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const res = await listArticlesWithFilters(filters);
|
||||||
|
|
||||||
|
// const data = res?.data?.data;
|
||||||
|
// // Handle new articles API response structure
|
||||||
|
// 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)));
|
||||||
|
// } else {
|
||||||
|
// // Fallback to old structure if API still returns old format
|
||||||
|
// const contentData = data?.content;
|
||||||
|
// contentData.forEach((item: any, index: number) => {
|
||||||
|
// item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
|
// });
|
||||||
|
// setDataTable(contentData);
|
||||||
|
// setTotalData(data?.totalElements);
|
||||||
|
// setTotalPage(data?.totalPages);
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error fetching tasks:", error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setSearch(e.target.value); // Perbarui state search
|
setSearch(e.target.value); // Perbarui state search
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const DocumentTabs = () => {
|
||||||
|
|
||||||
<TabsContent value="pending" className="mt-0">
|
<TabsContent value="pending" className="mt-0">
|
||||||
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
||||||
<PendingApprovalTable />
|
<PendingApprovalTable typeId={3} />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,11 @@ import TablePagination from "@/components/table/table-pagination";
|
||||||
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
import { listPendingApproval, PendingApprovalData } from "@/service/content/content";
|
||||||
import usePendingApprovalColumns from "./pending-approval-columns";
|
import usePendingApprovalColumns from "./pending-approval-columns";
|
||||||
|
|
||||||
const PendingApprovalTable = () => {
|
type PendingApprovalTableProps = {
|
||||||
|
typeId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PendingApprovalTable = ({ typeId }: PendingApprovalTableProps) => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(0);
|
const [totalData, setTotalData] = React.useState<number>(0);
|
||||||
|
|
@ -95,7 +99,7 @@ const PendingApprovalTable = () => {
|
||||||
|
|
||||||
async function fetchPendingData() {
|
async function fetchPendingData() {
|
||||||
try {
|
try {
|
||||||
const res = await listPendingApproval(page, Number(showData));
|
const res = await listPendingApproval(page, Number(showData), typeId);
|
||||||
|
|
||||||
if (res && !res.error && res.data) {
|
if (res && !res.error && res.data) {
|
||||||
// Filter data based on search if provided
|
// Filter data based on search if provided
|
||||||
|
|
|
||||||
|
|
@ -177,23 +177,24 @@ const TableTeks = () => {
|
||||||
const formattedEndDate = endDate
|
const formattedEndDate = endDate
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Using the new interface-based approach for cleaner code
|
// Using the new interface-based approach for video content
|
||||||
const filters: ArticleFilters = {
|
const filters: ArticleFilters = {
|
||||||
page: page,
|
page: page,
|
||||||
totalPage: Number(showData),
|
totalPage: Number(showData),
|
||||||
title: search || undefined,
|
title: search || undefined,
|
||||||
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
typeId: 3, // text content type
|
typeId: 2, // video content type
|
||||||
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
statusId:
|
||||||
|
statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
startDate: formattedStartDate || undefined,
|
startDate: formattedStartDate || undefined,
|
||||||
endDate: formattedEndDate || undefined,
|
endDate: formattedEndDate || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const res = await listArticlesWithFilters(filters);
|
const res = await listArticlesWithFilters(filters);
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
// Handle new articles API response structure
|
|
||||||
if (Array.isArray(data)) {
|
if (Array.isArray(data)) {
|
||||||
data.forEach((item: any, index: number) => {
|
data.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
|
|
@ -201,21 +202,75 @@ const TableTeks = () => {
|
||||||
setDataTable(data);
|
setDataTable(data);
|
||||||
setTotalData(data.length);
|
setTotalData(data.length);
|
||||||
setTotalPage(Math.ceil(data.length / Number(showData)));
|
setTotalPage(Math.ceil(data.length / Number(showData)));
|
||||||
} else {
|
} else if (Array.isArray(data?.content)) {
|
||||||
// Fallback to old structure if API still returns old format
|
const contentData = data.content;
|
||||||
const contentData = data?.content;
|
|
||||||
contentData.forEach((item: any, index: number) => {
|
contentData.forEach((item: any, index: number) => {
|
||||||
item.no = (page - 1) * Number(showData) + index + 1;
|
item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
});
|
});
|
||||||
setDataTable(contentData);
|
setDataTable(contentData);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data?.totalElements ?? contentData.length);
|
||||||
setTotalPage(data?.totalPages);
|
setTotalPage(
|
||||||
|
data?.totalPages ?? Math.ceil(contentData.length / Number(showData))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
|
setDataTable([]);
|
||||||
|
setTotalData(0);
|
||||||
|
setTotalPage(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// async function fetchData() {
|
||||||
|
// const formattedStartDate = startDate
|
||||||
|
// ? format(new Date(startDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// const formattedEndDate = endDate
|
||||||
|
// ? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
|
// : "";
|
||||||
|
// try {
|
||||||
|
// // Using the new interface-based approach for cleaner code
|
||||||
|
// const filters: ArticleFilters = {
|
||||||
|
// page: page,
|
||||||
|
// totalPage: Number(showData),
|
||||||
|
// title: search || undefined,
|
||||||
|
// categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
|
// typeId: 3, // text content type
|
||||||
|
// statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
|
// startDate: formattedStartDate || undefined,
|
||||||
|
// endDate: formattedEndDate || undefined,
|
||||||
|
// };
|
||||||
|
|
||||||
|
// const res = await listArticlesWithFilters(filters);
|
||||||
|
|
||||||
|
// const data = res?.data?.data;
|
||||||
|
// // Handle new articles API response structure
|
||||||
|
// 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)));
|
||||||
|
// } else {
|
||||||
|
// // Fallback to old structure if API still returns old format
|
||||||
|
// const contentData = data?.content;
|
||||||
|
// contentData.forEach((item: any, index: number) => {
|
||||||
|
// item.no = (page - 1) * Number(showData) + index + 1;
|
||||||
|
// });
|
||||||
|
// setDataTable(contentData);
|
||||||
|
// setTotalData(data?.totalElements);
|
||||||
|
// setTotalPage(data?.totalPages);
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// console.error("Error fetching tasks:", error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setSearch(e.target.value); // Perbarui state search
|
setSearch(e.target.value); // Perbarui state search
|
||||||
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
|
table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ const ImageTabs = () => {
|
||||||
|
|
||||||
<TabsContent value="pending" className="mt-0">
|
<TabsContent value="pending" className="mt-0">
|
||||||
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
<div className="bg-white rounded-lg border border-gray-200 shadow-sm">
|
||||||
<PendingApprovalTable />
|
<PendingApprovalTable typeId={1} />
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,11 @@ import { listPendingApproval, PendingApprovalData } from "@/service/content/cont
|
||||||
import usePendingApprovalColumns from "./pending-approval-columns";
|
import usePendingApprovalColumns from "./pending-approval-columns";
|
||||||
import { fi } from "date-fns/locale";
|
import { fi } from "date-fns/locale";
|
||||||
|
|
||||||
const PendingApprovalTable = () => {
|
type PendingApprovalTableProps = {
|
||||||
|
typeId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const PendingApprovalTable = ({ typeId }: PendingApprovalTableProps) => {
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
const [dataTable, setDataTable] = React.useState<PendingApprovalData[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(0);
|
const [totalData, setTotalData] = React.useState<number>(0);
|
||||||
|
|
@ -112,7 +116,7 @@ const PendingApprovalTable = () => {
|
||||||
async function fetchPendingData() {
|
async function fetchPendingData() {
|
||||||
try {
|
try {
|
||||||
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
console.log("fetchPendingData: page =", page, "showData =", showData, "Number(showData) =", Number(showData));
|
||||||
const res = await listPendingApproval(page, Number(showData));
|
const res = await listPendingApproval(page, Number(showData), typeId);
|
||||||
|
|
||||||
if (res && !res.error && res.data.data) {
|
if (res && !res.error && res.data.data) {
|
||||||
// Filter data based on search if provided
|
// Filter data based on search if provided
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,7 @@ export default function FormVideo() {
|
||||||
const [publishedForError, setPublishedForError] = useState<string | null>(
|
const [publishedForError, setPublishedForError] = useState<string | null>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
const userId = Cookies.get("userId");
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
const [articleImages, setArticleImages] = useState<string[]>([]);
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
||||||
|
|
@ -483,19 +484,21 @@ export default function FormVideo() {
|
||||||
console.error("Failed to fetch article categories:", category.message);
|
console.error("Failed to fetch article categories:", category.message);
|
||||||
// Fallback to old API if new one fails
|
// Fallback to old API if new one fails
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle new API response structure
|
// Handle new API response structure
|
||||||
const resCategory: Category[] = category?.data?.data?.map((item: any) => ({
|
const resCategory: Category[] =
|
||||||
id: item.id,
|
category?.data?.data?.map((item: any) => ({
|
||||||
name: item.title, // map title to name for backward compatibility
|
id: item.id,
|
||||||
title: item.title,
|
name: item.title, // map title to name for backward compatibility
|
||||||
description: item.description,
|
title: item.title,
|
||||||
...item
|
description: item.description,
|
||||||
})) || [];
|
...item,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
console.log("Article categories loaded:", resCategory);
|
console.log("Article categories loaded:", resCategory);
|
||||||
|
|
@ -516,7 +519,8 @@ export default function FormVideo() {
|
||||||
// Fallback to old API if error occurs
|
// Fallback to old API if error occurs
|
||||||
try {
|
try {
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
} catch (fallbackError) {
|
} catch (fallbackError) {
|
||||||
console.error("Fallback category fetch also failed:", fallbackError);
|
console.error("Fallback category fetch also failed:", fallbackError);
|
||||||
|
|
@ -577,6 +581,23 @@ export default function FormVideo() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatDateForBackend(date: Date) {
|
||||||
|
const pad = (n: number) => (n < 10 ? "0" + n : n);
|
||||||
|
return (
|
||||||
|
date.getFullYear() +
|
||||||
|
"-" +
|
||||||
|
pad(date.getMonth() + 1) +
|
||||||
|
"-" +
|
||||||
|
pad(date.getDate()) +
|
||||||
|
" " +
|
||||||
|
pad(date.getHours()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getMinutes()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getSeconds())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -618,16 +639,22 @@ export default function FormVideo() {
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
// New Articles API request data structure
|
// New Articles API request data structure
|
||||||
const articleData: CreateArticleData = {
|
const articleData: CreateArticleData = {
|
||||||
title: finalTitle,
|
aiArticleId: 0, // default 0
|
||||||
|
categoryIds: selectedCategory.toString(),
|
||||||
|
createdAt: formatDateForBackend(new Date()), // ✅ format sesuai backend
|
||||||
|
createdById: Number(userId), // isi dengan userId valid
|
||||||
description: htmlToString(finalDescription),
|
description: htmlToString(finalDescription),
|
||||||
htmlDescription: finalDescription,
|
htmlDescription: finalDescription,
|
||||||
categoryIds: selectedCategory.toString(),
|
|
||||||
typeId: 4, // Video content type
|
|
||||||
tags: finalTags,
|
|
||||||
isDraft: true,
|
isDraft: true,
|
||||||
isPublish: false,
|
isPublish: false,
|
||||||
oldId: 0,
|
oldId: 0,
|
||||||
slug: finalTitle.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
|
slug: finalTitle
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
.replace(/[^a-z0-9-]/g, ""),
|
||||||
|
tags: finalTags,
|
||||||
|
title: finalTitle,
|
||||||
|
typeId: 1, // Image content type
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use new Articles API
|
// Use new Articles API
|
||||||
|
|
@ -636,7 +663,11 @@ export default function FormVideo() {
|
||||||
console.log("Article API Response:", response);
|
console.log("Article API Response:", response);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
MySwal.fire("Error", response.message || "Failed to create article", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
response.message || "Failed to create article",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -650,7 +681,7 @@ export default function FormVideo() {
|
||||||
|
|
||||||
// Add all files to FormData
|
// Add all files to FormData
|
||||||
files.forEach((file, index) => {
|
files.forEach((file, index) => {
|
||||||
formData.append('files', file);
|
formData.append("files", file);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Uploading files to article:", articleId);
|
console.log("Uploading files to article:", articleId);
|
||||||
|
|
@ -660,7 +691,11 @@ export default function FormVideo() {
|
||||||
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
||||||
|
|
||||||
if (uploadResponse?.error) {
|
if (uploadResponse?.error) {
|
||||||
MySwal.fire("Error", uploadResponse.message || "Failed to upload files", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
uploadResponse.message || "Failed to upload files",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -669,28 +704,40 @@ export default function FormVideo() {
|
||||||
// Upload thumbnail using first file as thumbnail
|
// Upload thumbnail using first file as thumbnail
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
const thumbnailFormData = new FormData();
|
const thumbnailFormData = new FormData();
|
||||||
thumbnailFormData.append('files', files[0]); // Use first file as thumbnail
|
thumbnailFormData.append("files", files[0]); // Use first file as thumbnail
|
||||||
|
|
||||||
console.log("Uploading thumbnail for article:", articleId);
|
console.log("Uploading thumbnail for article:", articleId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const thumbnailResponse = await uploadArticleThumbnail(articleId, thumbnailFormData);
|
const thumbnailResponse = await uploadArticleThumbnail(
|
||||||
|
articleId,
|
||||||
|
thumbnailFormData
|
||||||
|
);
|
||||||
|
|
||||||
if (thumbnailResponse?.error) {
|
if (thumbnailResponse?.error) {
|
||||||
console.warn("Thumbnail upload failed:", thumbnailResponse.message);
|
console.warn(
|
||||||
|
"Thumbnail upload failed:",
|
||||||
|
thumbnailResponse.message
|
||||||
|
);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
} else {
|
} else {
|
||||||
console.log("Thumbnail uploaded successfully:", thumbnailResponse);
|
console.log(
|
||||||
|
"Thumbnail uploaded successfully:",
|
||||||
|
thumbnailResponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (thumbnailError) {
|
} catch (thumbnailError) {
|
||||||
console.warn("Thumbnail upload error:", thumbnailError);
|
console.warn("Thumbnail upload error:", thumbnailError);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (uploadError) {
|
} catch (uploadError) {
|
||||||
console.error("Upload error:", uploadError);
|
console.error("Upload error:", uploadError);
|
||||||
MySwal.fire("Error", "Failed to upload files. Please try again.", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
"Failed to upload files. Please try again.",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -702,7 +749,7 @@ export default function FormVideo() {
|
||||||
confirmButtonColor: "#3085d6",
|
confirmButtonColor: "#3085d6",
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
router.push("/admin/content/video");
|
router.push("/admin/content/audio-visual");
|
||||||
});
|
});
|
||||||
|
|
||||||
Cookies.remove("idCreate");
|
Cookies.remove("idCreate");
|
||||||
|
|
@ -985,7 +1032,6 @@ export default function FormVideo() {
|
||||||
name="categoryId"
|
name="categoryId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Label>Category</Label>
|
|
||||||
<Select
|
<Select
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,7 @@ export default function FormAudio() {
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
const [fileError, setFileError] = useState<string | null>(null);
|
const [fileError, setFileError] = useState<string | null>(null);
|
||||||
type FileWithPreview = File & { preview: string };
|
type FileWithPreview = File & { preview: string };
|
||||||
|
const userId = Cookies.get("userId");
|
||||||
|
|
||||||
const options: Option[] = [
|
const options: Option[] = [
|
||||||
{ id: "all", label: "SEMUA" },
|
{ id: "all", label: "SEMUA" },
|
||||||
|
|
@ -220,8 +221,7 @@ export default function FormAudio() {
|
||||||
file.size <= 100 * 1024 * 1024
|
file.size <= 100 * 1024 * 1024
|
||||||
),
|
),
|
||||||
{
|
{
|
||||||
message:
|
message: "Hanya file .mp3, .wav, maksimal 100MB yang diperbolehkan.",
|
||||||
"Hanya file .mp3, .wav, maksimal 100MB yang diperbolehkan.",
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
|
categoryId: z.string().min(1, { message: "Kategori wajib dipilih." }),
|
||||||
|
|
@ -485,19 +485,21 @@ export default function FormAudio() {
|
||||||
console.error("Failed to fetch article categories:", category.message);
|
console.error("Failed to fetch article categories:", category.message);
|
||||||
// Fallback to old API if new one fails
|
// Fallback to old API if new one fails
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle new API response structure
|
// Handle new API response structure
|
||||||
const resCategory: Category[] = category?.data?.data?.map((item: any) => ({
|
const resCategory: Category[] =
|
||||||
id: item.id,
|
category?.data?.data?.map((item: any) => ({
|
||||||
name: item.title, // map title to name for backward compatibility
|
id: item.id,
|
||||||
title: item.title,
|
name: item.title, // map title to name for backward compatibility
|
||||||
description: item.description,
|
title: item.title,
|
||||||
...item
|
description: item.description,
|
||||||
})) || [];
|
...item,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
console.log("Article categories loaded:", resCategory);
|
console.log("Article categories loaded:", resCategory);
|
||||||
|
|
@ -518,7 +520,8 @@ export default function FormAudio() {
|
||||||
// Fallback to old API if error occurs
|
// Fallback to old API if error occurs
|
||||||
try {
|
try {
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
} catch (fallbackError) {
|
} catch (fallbackError) {
|
||||||
console.error("Fallback category fetch also failed:", fallbackError);
|
console.error("Fallback category fetch also failed:", fallbackError);
|
||||||
|
|
@ -575,6 +578,23 @@ export default function FormAudio() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatDateForBackend(date: Date) {
|
||||||
|
const pad = (n: number) => (n < 10 ? "0" + n : n);
|
||||||
|
return (
|
||||||
|
date.getFullYear() +
|
||||||
|
"-" +
|
||||||
|
pad(date.getMonth() + 1) +
|
||||||
|
"-" +
|
||||||
|
pad(date.getDate()) +
|
||||||
|
" " +
|
||||||
|
pad(date.getHours()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getMinutes()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getSeconds())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -616,16 +636,22 @@ export default function FormAudio() {
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
// New Articles API request data structure
|
// New Articles API request data structure
|
||||||
const articleData: CreateArticleData = {
|
const articleData: CreateArticleData = {
|
||||||
title: finalTitle,
|
aiArticleId: 0, // default 0
|
||||||
|
categoryIds: selectedCategory.toString(),
|
||||||
|
createdAt: formatDateForBackend(new Date()), // ✅ format sesuai backend
|
||||||
|
createdById: Number(userId), // isi dengan userId valid
|
||||||
description: htmlToString(finalDescription),
|
description: htmlToString(finalDescription),
|
||||||
htmlDescription: finalDescription,
|
htmlDescription: finalDescription,
|
||||||
categoryIds: selectedCategory.toString(),
|
|
||||||
typeId: 3, // Audio content type
|
|
||||||
tags: finalTags,
|
|
||||||
isDraft: true,
|
isDraft: true,
|
||||||
isPublish: false,
|
isPublish: false,
|
||||||
oldId: 0,
|
oldId: 0,
|
||||||
slug: finalTitle.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
|
slug: finalTitle
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
.replace(/[^a-z0-9-]/g, ""),
|
||||||
|
tags: finalTags,
|
||||||
|
title: finalTitle,
|
||||||
|
typeId: 1, // Image content type
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use new Articles API
|
// Use new Articles API
|
||||||
|
|
@ -634,7 +660,11 @@ export default function FormAudio() {
|
||||||
console.log("Article API Response:", response);
|
console.log("Article API Response:", response);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
MySwal.fire("Error", response.message || "Failed to create article", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
response.message || "Failed to create article",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -648,7 +678,7 @@ export default function FormAudio() {
|
||||||
|
|
||||||
// Add all files to FormData
|
// Add all files to FormData
|
||||||
files.forEach((file, index) => {
|
files.forEach((file, index) => {
|
||||||
formData.append('files', file);
|
formData.append("files", file);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Uploading files to article:", articleId);
|
console.log("Uploading files to article:", articleId);
|
||||||
|
|
@ -658,7 +688,11 @@ export default function FormAudio() {
|
||||||
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
||||||
|
|
||||||
if (uploadResponse?.error) {
|
if (uploadResponse?.error) {
|
||||||
MySwal.fire("Error", uploadResponse.message || "Failed to upload files", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
uploadResponse.message || "Failed to upload files",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -667,28 +701,40 @@ export default function FormAudio() {
|
||||||
// Upload thumbnail using first file as thumbnail
|
// Upload thumbnail using first file as thumbnail
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
const thumbnailFormData = new FormData();
|
const thumbnailFormData = new FormData();
|
||||||
thumbnailFormData.append('files', files[0]); // Use first file as thumbnail
|
thumbnailFormData.append("files", files[0]); // Use first file as thumbnail
|
||||||
|
|
||||||
console.log("Uploading thumbnail for article:", articleId);
|
console.log("Uploading thumbnail for article:", articleId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const thumbnailResponse = await uploadArticleThumbnail(articleId, thumbnailFormData);
|
const thumbnailResponse = await uploadArticleThumbnail(
|
||||||
|
articleId,
|
||||||
|
thumbnailFormData
|
||||||
|
);
|
||||||
|
|
||||||
if (thumbnailResponse?.error) {
|
if (thumbnailResponse?.error) {
|
||||||
console.warn("Thumbnail upload failed:", thumbnailResponse.message);
|
console.warn(
|
||||||
|
"Thumbnail upload failed:",
|
||||||
|
thumbnailResponse.message
|
||||||
|
);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
} else {
|
} else {
|
||||||
console.log("Thumbnail uploaded successfully:", thumbnailResponse);
|
console.log(
|
||||||
|
"Thumbnail uploaded successfully:",
|
||||||
|
thumbnailResponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (thumbnailError) {
|
} catch (thumbnailError) {
|
||||||
console.warn("Thumbnail upload error:", thumbnailError);
|
console.warn("Thumbnail upload error:", thumbnailError);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (uploadError) {
|
} catch (uploadError) {
|
||||||
console.error("Upload error:", uploadError);
|
console.error("Upload error:", uploadError);
|
||||||
MySwal.fire("Error", "Failed to upload files. Please try again.", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
"Failed to upload files. Please try again.",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -975,7 +1021,6 @@ export default function FormAudio() {
|
||||||
name="categoryId"
|
name="categoryId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Label>Category</Label>
|
|
||||||
<Select
|
<Select
|
||||||
value={field.value}
|
value={field.value}
|
||||||
onValueChange={(value) => {
|
onValueChange={(value) => {
|
||||||
|
|
|
||||||
|
|
@ -131,7 +131,7 @@ export default function FormTeks() {
|
||||||
polda: false,
|
polda: false,
|
||||||
polres: false,
|
polres: false,
|
||||||
});
|
});
|
||||||
|
const userId = Cookies.get("userId");
|
||||||
let fileTypeId = "2";
|
let fileTypeId = "2";
|
||||||
let progressInfo: any = [];
|
let progressInfo: any = [];
|
||||||
let counterUpdateProgress = 0;
|
let counterUpdateProgress = 0;
|
||||||
|
|
@ -481,19 +481,21 @@ export default function FormTeks() {
|
||||||
console.error("Failed to fetch article categories:", category.message);
|
console.error("Failed to fetch article categories:", category.message);
|
||||||
// Fallback to old API if new one fails
|
// Fallback to old API if new one fails
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle new API response structure
|
// Handle new API response structure
|
||||||
const resCategory: Category[] = category?.data?.data?.map((item: any) => ({
|
const resCategory: Category[] =
|
||||||
id: item.id,
|
category?.data?.data?.map((item: any) => ({
|
||||||
name: item.title, // map title to name for backward compatibility
|
id: item.id,
|
||||||
title: item.title,
|
name: item.title, // map title to name for backward compatibility
|
||||||
description: item.description,
|
title: item.title,
|
||||||
...item
|
description: item.description,
|
||||||
})) || [];
|
...item,
|
||||||
|
})) || [];
|
||||||
|
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
console.log("Article categories loaded:", resCategory);
|
console.log("Article categories loaded:", resCategory);
|
||||||
|
|
@ -514,7 +516,8 @@ export default function FormTeks() {
|
||||||
// Fallback to old API if error occurs
|
// Fallback to old API if error occurs
|
||||||
try {
|
try {
|
||||||
const fallbackCategory = await listEnableCategory(fileTypeId);
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
const resCategory: Category[] =
|
||||||
|
fallbackCategory?.data.data.content || [];
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
} catch (fallbackError) {
|
} catch (fallbackError) {
|
||||||
console.error("Fallback category fetch also failed:", fallbackError);
|
console.error("Fallback category fetch also failed:", fallbackError);
|
||||||
|
|
@ -579,6 +582,23 @@ export default function FormTeks() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatDateForBackend(date: Date) {
|
||||||
|
const pad = (n: number) => (n < 10 ? "0" + n : n);
|
||||||
|
return (
|
||||||
|
date.getFullYear() +
|
||||||
|
"-" +
|
||||||
|
pad(date.getMonth() + 1) +
|
||||||
|
"-" +
|
||||||
|
pad(date.getDate()) +
|
||||||
|
" " +
|
||||||
|
pad(date.getHours()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getMinutes()) +
|
||||||
|
":" +
|
||||||
|
pad(date.getSeconds())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -620,25 +640,34 @@ export default function FormTeks() {
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
// New Articles API request data structure
|
// New Articles API request data structure
|
||||||
const articleData: CreateArticleData = {
|
const articleData: CreateArticleData = {
|
||||||
title: finalTitle,
|
aiArticleId: 0, // default 0
|
||||||
|
categoryIds: selectedCategory.toString(),
|
||||||
|
createdAt: formatDateForBackend(new Date()), // ✅ format sesuai backend
|
||||||
|
createdById: Number(userId), // isi dengan userId valid
|
||||||
description: htmlToString(finalDescription),
|
description: htmlToString(finalDescription),
|
||||||
htmlDescription: finalDescription,
|
htmlDescription: finalDescription,
|
||||||
categoryIds: selectedCategory.toString(),
|
|
||||||
typeId: 2, // Document content type
|
|
||||||
tags: finalTags,
|
|
||||||
isDraft: true,
|
isDraft: true,
|
||||||
isPublish: false,
|
isPublish: false,
|
||||||
oldId: 0,
|
oldId: 0,
|
||||||
slug: finalTitle.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
|
slug: finalTitle
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, "-")
|
||||||
|
.replace(/[^a-z0-9-]/g, ""),
|
||||||
|
tags: finalTags,
|
||||||
|
title: finalTitle,
|
||||||
|
typeId: 1, // Image content type
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use new Articles API
|
// Use new Articles API
|
||||||
const response = await createArticle(articleData);
|
const response = await createArticle(articleData);
|
||||||
console.log("Article Data Submitted:", articleData);
|
console.log("Article Data Submitted:", articleData);
|
||||||
console.log("Article API Response:", response);
|
console.log("Article API Response:", response);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
MySwal.fire("Error", response.message || "Failed to create article", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
response.message || "Failed to create article",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -652,7 +681,7 @@ export default function FormTeks() {
|
||||||
|
|
||||||
// Add all files to FormData
|
// Add all files to FormData
|
||||||
files.forEach((file, index) => {
|
files.forEach((file, index) => {
|
||||||
formData.append('files', file);
|
formData.append("files", file);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("Uploading files to article:", articleId);
|
console.log("Uploading files to article:", articleId);
|
||||||
|
|
@ -662,7 +691,11 @@ export default function FormTeks() {
|
||||||
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
||||||
|
|
||||||
if (uploadResponse?.error) {
|
if (uploadResponse?.error) {
|
||||||
MySwal.fire("Error", uploadResponse.message || "Failed to upload files", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
uploadResponse.message || "Failed to upload files",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -671,28 +704,40 @@ export default function FormTeks() {
|
||||||
// Upload thumbnail using first file as thumbnail
|
// Upload thumbnail using first file as thumbnail
|
||||||
if (files.length > 0) {
|
if (files.length > 0) {
|
||||||
const thumbnailFormData = new FormData();
|
const thumbnailFormData = new FormData();
|
||||||
thumbnailFormData.append('files', files[0]); // Use first file as thumbnail
|
thumbnailFormData.append("files", files[0]); // Use first file as thumbnail
|
||||||
|
|
||||||
console.log("Uploading thumbnail for article:", articleId);
|
console.log("Uploading thumbnail for article:", articleId);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const thumbnailResponse = await uploadArticleThumbnail(articleId, thumbnailFormData);
|
const thumbnailResponse = await uploadArticleThumbnail(
|
||||||
|
articleId,
|
||||||
|
thumbnailFormData
|
||||||
|
);
|
||||||
|
|
||||||
if (thumbnailResponse?.error) {
|
if (thumbnailResponse?.error) {
|
||||||
console.warn("Thumbnail upload failed:", thumbnailResponse.message);
|
console.warn(
|
||||||
|
"Thumbnail upload failed:",
|
||||||
|
thumbnailResponse.message
|
||||||
|
);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
} else {
|
} else {
|
||||||
console.log("Thumbnail uploaded successfully:", thumbnailResponse);
|
console.log(
|
||||||
|
"Thumbnail uploaded successfully:",
|
||||||
|
thumbnailResponse
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (thumbnailError) {
|
} catch (thumbnailError) {
|
||||||
console.warn("Thumbnail upload error:", thumbnailError);
|
console.warn("Thumbnail upload error:", thumbnailError);
|
||||||
// Don't fail the whole process if thumbnail upload fails
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (uploadError) {
|
} catch (uploadError) {
|
||||||
console.error("Upload error:", uploadError);
|
console.error("Upload error:", uploadError);
|
||||||
MySwal.fire("Error", "Failed to upload files. Please try again.", "error");
|
MySwal.fire(
|
||||||
|
"Error",
|
||||||
|
"Failed to upload files. Please try again.",
|
||||||
|
"error"
|
||||||
|
);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -963,42 +1008,41 @@ export default function FormTeks() {
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="py-3 w-full space-y-2">
|
<div className="py-3 w-full space-y-2">
|
||||||
<Label>Category</Label>
|
<Label>Category</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="categoryId"
|
name="categoryId"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<Label>Category</Label>
|
<Select
|
||||||
<Select
|
value={field.value}
|
||||||
value={field.value}
|
onValueChange={(value) => {
|
||||||
onValueChange={(value) => {
|
field.onChange(value);
|
||||||
field.onChange(value);
|
setSelectedCategory(value);
|
||||||
setSelectedCategory(value);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<SelectTrigger>
|
||||||
<SelectTrigger>
|
<SelectValue placeholder="Pilih" />
|
||||||
<SelectValue placeholder="Pilih" />
|
</SelectTrigger>
|
||||||
</SelectTrigger>
|
<SelectContent>
|
||||||
<SelectContent>
|
{categories.map((category) => (
|
||||||
{categories.map((category) => (
|
<SelectItem
|
||||||
<SelectItem
|
key={category.id}
|
||||||
key={category.id}
|
value={category.id.toString()}
|
||||||
value={category.id.toString()}
|
>
|
||||||
>
|
{category.name}
|
||||||
{category.name}
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
|
||||||
|
|
||||||
{errors.categoryId && (
|
{errors.categoryId && (
|
||||||
<p className="text-sm text-red-500 mt-1">
|
<p className="text-sm text-red-500 mt-1">
|
||||||
{errors.categoryId.message}
|
{errors.categoryId.message}
|
||||||
</p>
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
/>
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-row items-center gap-3 py-2">
|
<div className="flex flex-row items-center gap-3 py-2">
|
||||||
|
|
|
||||||
|
|
@ -2338,6 +2338,7 @@
|
||||||
"version": "1.1.13",
|
"version": "1.1.13",
|
||||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz",
|
||||||
"integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
|
"integrity": "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@radix-ui/primitive": "1.1.3",
|
"@radix-ui/primitive": "1.1.3",
|
||||||
"@radix-ui/react-context": "1.1.2",
|
"@radix-ui/react-context": "1.1.2",
|
||||||
|
|
|
||||||
|
|
@ -456,9 +456,10 @@ export interface PendingApprovalResponse {
|
||||||
// Function to fetch pending approval data
|
// Function to fetch pending approval data
|
||||||
export async function listPendingApproval(
|
export async function listPendingApproval(
|
||||||
page: number = 1,
|
page: number = 1,
|
||||||
limit: number = 10
|
limit: number = 10,
|
||||||
|
typeId?: number
|
||||||
) {
|
) {
|
||||||
const url = `articles/pending-approval?page=${page}&limit=${limit}`;
|
const url = `articles/pending-approval?page=${page}&limit=${limit}&typeId=${typeId}`;
|
||||||
return await httpGetInterceptor(url);
|
return await httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue