feat: update pagination and create image, update login
This commit is contained in:
parent
4b25136c6f
commit
d07e92aa2a
|
|
@ -51,11 +51,17 @@ const useTableColumns = () => {
|
||||||
{
|
{
|
||||||
accessorKey: "categoryName",
|
accessorKey: "categoryName",
|
||||||
header: "Category Name",
|
header: "Category Name",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<span className="whitespace-nowrap">
|
const categoryName = row.getValue("categoryName");
|
||||||
{row.getValue("categoryName")}
|
const categories = row.original.categories;
|
||||||
</span>
|
// Handle new API structure with categories array
|
||||||
),
|
const displayName = categoryName || (categories && categories.length > 0 ? categories[0].title : "-");
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{displayName}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
|
|
@ -77,7 +83,9 @@ const useTableColumns = () => {
|
||||||
accessorKey: "creatorName",
|
accessorKey: "creatorName",
|
||||||
header: "Creator Group",
|
header: "Creator Group",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
<span className="whitespace-nowrap">
|
||||||
|
{row.getValue("creatorName") || row.getValue("createdByName")}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -85,7 +93,7 @@ const useTableColumns = () => {
|
||||||
header: "Source",
|
header: "Source",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">
|
<span className="whitespace-nowrap">
|
||||||
{row.getValue("creatorGroupLevelName")}
|
{row.getValue("creatorGroupLevelName") || "-"}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,13 @@ import columns from "./columns";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import useTableColumns from "./columns";
|
import useTableColumns from "./columns";
|
||||||
import { listEnableCategory, listDataVideo } from "@/service/content";
|
import {
|
||||||
|
listEnableCategory,
|
||||||
|
listDataVideo,
|
||||||
|
listArticles,
|
||||||
|
listArticlesWithFilters,
|
||||||
|
ArticleFilters
|
||||||
|
} from "@/service/content";
|
||||||
import {
|
import {
|
||||||
SortingState,
|
SortingState,
|
||||||
ColumnFiltersState,
|
ColumnFiltersState,
|
||||||
|
|
@ -169,32 +175,39 @@ const TableVideo = () => {
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
try {
|
try {
|
||||||
const isForSelf = Number(roleId) === 4;
|
// Using the new interface-based approach for video content
|
||||||
const res = await listDataVideo(
|
const filters: ArticleFilters = {
|
||||||
showData,
|
page: page,
|
||||||
page - 1,
|
totalPage: Number(showData),
|
||||||
isForSelf,
|
title: search || undefined,
|
||||||
!isForSelf,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
categoryFilter,
|
typeId: 2, // video content type
|
||||||
statusFilter,
|
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
statusFilter?.sort().join(",").includes("1") ? userLevelId : "",
|
startDate: formattedStartDate || undefined,
|
||||||
filterByCreator,
|
endDate: formattedEndDate || undefined,
|
||||||
filterBySource,
|
};
|
||||||
formattedStartDate, // Pastikan format sesuai
|
|
||||||
formattedEndDate, // Pastikan format sesuai
|
const res = await listArticlesWithFilters(filters);
|
||||||
search,
|
|
||||||
filterByCreatorGroup
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
// Handle new articles API response structure
|
||||||
contentData.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(contentData);
|
setDataTable(data);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data.length);
|
||||||
setTotalPage(data?.totalPages);
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,17 @@ const useTableColumns = () => {
|
||||||
{
|
{
|
||||||
accessorKey: "categoryName",
|
accessorKey: "categoryName",
|
||||||
header: "Category Name",
|
header: "Category Name",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<span className="whitespace-nowrap">
|
const categoryName = row.getValue("categoryName");
|
||||||
{row.getValue("categoryName")}
|
const categories = row.original.categories;
|
||||||
</span>
|
// Handle new API structure with categories array
|
||||||
),
|
const displayName = categoryName || (categories && categories.length > 0 ? categories[0].title : "-");
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{displayName}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
|
|
@ -77,7 +83,9 @@ const useTableColumns = () => {
|
||||||
accessorKey: "creatorName",
|
accessorKey: "creatorName",
|
||||||
header: "Creator Group",
|
header: "Creator Group",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
<span className="whitespace-nowrap">
|
||||||
|
{row.getValue("creatorName") || row.getValue("createdByName")}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -85,7 +93,7 @@ const useTableColumns = () => {
|
||||||
header: "Source",
|
header: "Source",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">
|
<span className="whitespace-nowrap">
|
||||||
{row.getValue("creatorGroupLevelName")}
|
{row.getValue("creatorGroupLevelName") || "-"}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,10 @@ import {
|
||||||
listDataAudio,
|
listDataAudio,
|
||||||
listDataImage,
|
listDataImage,
|
||||||
listDataVideo,
|
listDataVideo,
|
||||||
|
listArticles,
|
||||||
|
listArticlesWithFilters,
|
||||||
listEnableCategory,
|
listEnableCategory,
|
||||||
|
ArticleFilters,
|
||||||
} from "@/service/content/content";
|
} from "@/service/content/content";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
@ -176,32 +179,39 @@ const TableAudio = () => {
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
try {
|
try {
|
||||||
const isForSelf = Number(roleId) === 4;
|
// Using the new interface-based approach for audio content
|
||||||
const res = await listDataAudio(
|
const filters: ArticleFilters = {
|
||||||
showData,
|
page: page,
|
||||||
page - 1,
|
totalPage: Number(showData),
|
||||||
isForSelf,
|
title: search || undefined,
|
||||||
!isForSelf,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
categoryFilter,
|
typeId: 4, // audio content type
|
||||||
statusFilter,
|
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
statusFilter?.sort().join(",").includes("1") ? userLevelId : "",
|
startDate: formattedStartDate || undefined,
|
||||||
filterByCreator,
|
endDate: formattedEndDate || undefined,
|
||||||
filterBySource,
|
};
|
||||||
formattedStartDate, // Pastikan format sesuai
|
|
||||||
formattedEndDate, // Pastikan format sesuai
|
const res = await listArticlesWithFilters(filters);
|
||||||
search,
|
|
||||||
filterByCreatorGroup
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
// Handle new articles API response structure
|
||||||
contentData.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(contentData);
|
setDataTable(data);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data.length);
|
||||||
setTotalPage(data?.totalPages);
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,17 @@ const useTableColumns = () => {
|
||||||
{
|
{
|
||||||
accessorKey: "categoryName",
|
accessorKey: "categoryName",
|
||||||
header: "Category Name",
|
header: "Category Name",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<span className="whitespace-nowrap">
|
const categoryName = row.getValue("categoryName");
|
||||||
{row.getValue("categoryName")}
|
const categories = row.original.categories;
|
||||||
</span>
|
// Handle new API structure with categories array
|
||||||
),
|
const displayName = categoryName || (categories && categories.length > 0 ? categories[0].title : "-");
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{displayName}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
|
|
@ -77,7 +83,9 @@ const useTableColumns = () => {
|
||||||
accessorKey: "creatorName",
|
accessorKey: "creatorName",
|
||||||
header: "Creator Group",
|
header: "Creator Group",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
<span className="whitespace-nowrap">
|
||||||
|
{row.getValue("creatorName") || row.getValue("createdByName")}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -85,7 +93,7 @@ const useTableColumns = () => {
|
||||||
header: "Source",
|
header: "Source",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">
|
<span className="whitespace-nowrap">
|
||||||
{row.getValue("creatorGroupLevelName")}
|
{row.getValue("creatorGroupLevelName") || "-"}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,10 @@ import columns from "./columns";
|
||||||
import {
|
import {
|
||||||
listDataImage,
|
listDataImage,
|
||||||
listDataTeks,
|
listDataTeks,
|
||||||
|
listArticles,
|
||||||
|
listArticlesWithFilters,
|
||||||
listEnableCategory,
|
listEnableCategory,
|
||||||
|
ArticleFilters,
|
||||||
} from "@/service/content/content";
|
} from "@/service/content/content";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
|
|
@ -175,32 +178,39 @@ const TableTeks = () => {
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
try {
|
try {
|
||||||
const isForSelf = Number(roleId) === 4;
|
// Using the new interface-based approach for cleaner code
|
||||||
const res = await listDataTeks(
|
const filters: ArticleFilters = {
|
||||||
showData,
|
page: page,
|
||||||
page - 1,
|
totalPage: Number(showData),
|
||||||
isForSelf,
|
title: search || undefined,
|
||||||
!isForSelf,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
categoryFilter,
|
typeId: 3, // text content type
|
||||||
statusFilter,
|
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
statusFilter?.sort().join(",").includes("1") ? userLevelId : "",
|
startDate: formattedStartDate || undefined,
|
||||||
filterByCreator,
|
endDate: formattedEndDate || undefined,
|
||||||
filterBySource,
|
};
|
||||||
formattedStartDate, // Pastikan format sesuai
|
|
||||||
formattedEndDate, // Pastikan format sesuai
|
const res = await listArticlesWithFilters(filters);
|
||||||
search,
|
|
||||||
filterByCreatorGroup
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
// Handle new articles API response structure
|
||||||
contentData.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(contentData);
|
setDataTable(data);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data.length);
|
||||||
setTotalPage(data?.totalPages);
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,17 @@ const useTableColumns = () => {
|
||||||
{
|
{
|
||||||
accessorKey: "categoryName",
|
accessorKey: "categoryName",
|
||||||
header: "Category Name",
|
header: "Category Name",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => {
|
||||||
<span className="whitespace-nowrap">
|
const categoryName = row.getValue("categoryName");
|
||||||
{row.getValue("categoryName")}
|
const categories = row.original.categories;
|
||||||
</span>
|
// Handle new API structure with categories array
|
||||||
),
|
const displayName = categoryName || (categories && categories.length > 0 ? categories[0].title : "-");
|
||||||
|
return (
|
||||||
|
<span className="whitespace-nowrap">
|
||||||
|
{displayName}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "createdAt",
|
accessorKey: "createdAt",
|
||||||
|
|
@ -79,7 +85,9 @@ const useTableColumns = () => {
|
||||||
accessorKey: "creatorName",
|
accessorKey: "creatorName",
|
||||||
header: "Creator Group",
|
header: "Creator Group",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">{row.getValue("creatorName")}</span>
|
<span className="whitespace-nowrap">
|
||||||
|
{row.getValue("creatorName") || row.getValue("createdByName")}
|
||||||
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -87,7 +95,7 @@ const useTableColumns = () => {
|
||||||
header: "Source",
|
header: "Source",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<span className="whitespace-nowrap">
|
<span className="whitespace-nowrap">
|
||||||
{row.getValue("creatorGroupLevelName")}
|
{row.getValue("creatorGroupLevelName") || "-"}
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,10 @@ import TablePagination from "@/components/table/table-pagination";
|
||||||
import {
|
import {
|
||||||
deleteMedia,
|
deleteMedia,
|
||||||
listDataImage,
|
listDataImage,
|
||||||
|
listArticles,
|
||||||
|
listArticlesWithFilters,
|
||||||
listEnableCategory,
|
listEnableCategory,
|
||||||
|
ArticleFilters,
|
||||||
} from "@/service/content/content";
|
} from "@/service/content/content";
|
||||||
import { loading } from "@/config/swal";
|
import { loading } from "@/config/swal";
|
||||||
|
|
||||||
|
|
@ -183,33 +186,39 @@ const TableImage = () => {
|
||||||
? format(new Date(endDate), "yyyy-MM-dd")
|
? format(new Date(endDate), "yyyy-MM-dd")
|
||||||
: "";
|
: "";
|
||||||
try {
|
try {
|
||||||
const isForSelf = Number(roleId) === 4;
|
// Using the new interface-based approach for image content
|
||||||
const res = await listDataImage(
|
const filters: ArticleFilters = {
|
||||||
showData,
|
page: page,
|
||||||
page - 1,
|
totalPage: Number(showData),
|
||||||
isForSelf,
|
title: search || undefined,
|
||||||
!isForSelf,
|
categoryId: categoryFilter ? Number(categoryFilter) : undefined,
|
||||||
categoryFilter,
|
typeId: 1, // image content type
|
||||||
statusFilter,
|
statusId: statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined,
|
||||||
statusFilter?.sort().join(",").includes("1") ? userLevelId : "",
|
startDate: formattedStartDate || undefined,
|
||||||
filterByCreator,
|
endDate: formattedEndDate || undefined,
|
||||||
filterBySource,
|
};
|
||||||
formattedStartDate,
|
|
||||||
formattedEndDate,
|
const res = await listArticlesWithFilters(filters);
|
||||||
search,
|
|
||||||
filterByCreatorGroup,
|
|
||||||
locale == "en"
|
|
||||||
);
|
|
||||||
|
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
const contentData = data?.content;
|
// Handle new articles API response structure
|
||||||
contentData.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(contentData);
|
setDataTable(data);
|
||||||
setTotalData(data?.totalElements);
|
setTotalData(data.length);
|
||||||
setTotalPage(data?.totalPages);
|
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) {
|
} catch (error) {
|
||||||
console.error("Error fetching tasks:", error);
|
console.error("Error fetching tasks:", error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ const AuthPage = () => {
|
||||||
setLoginCredentials(data);
|
setLoginCredentials(data);
|
||||||
try {
|
try {
|
||||||
const result = await validateEmail(data);
|
const result = await validateEmail(data);
|
||||||
|
console.log("result : ", result);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case "skip":
|
case "skip":
|
||||||
handleOTPSuccess();
|
handleOTPSuccess();
|
||||||
|
|
|
||||||
|
|
@ -32,9 +32,14 @@ import { Switch } from "@/components/ui/switch";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import {
|
import {
|
||||||
createMedia,
|
createMedia,
|
||||||
|
createArticle,
|
||||||
getTagsBySubCategoryId,
|
getTagsBySubCategoryId,
|
||||||
listEnableCategory,
|
listEnableCategory,
|
||||||
|
listArticleCategories,
|
||||||
uploadThumbnail,
|
uploadThumbnail,
|
||||||
|
uploadArticleFiles,
|
||||||
|
uploadArticleThumbnail,
|
||||||
|
CreateArticleData,
|
||||||
} from "@/service/content/content";
|
} from "@/service/content/content";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
|
|
@ -466,11 +471,30 @@ export default function FormImage() {
|
||||||
|
|
||||||
const getCategories = async () => {
|
const getCategories = async () => {
|
||||||
try {
|
try {
|
||||||
const category = await listEnableCategory(fileTypeId);
|
// Use new Article Categories API
|
||||||
const resCategory: Category[] = category?.data.data.content;
|
const category = await listArticleCategories(1, 100);
|
||||||
|
console.log("Article categories response:", category);
|
||||||
|
|
||||||
|
if (category?.error) {
|
||||||
|
console.error("Failed to fetch article categories:", category.message);
|
||||||
|
// Fallback to old API if new one fails
|
||||||
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
|
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
||||||
|
setCategories(resCategory);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle new API response structure
|
||||||
|
const resCategory: Category[] = category?.data?.data?.map((item: any) => ({
|
||||||
|
id: item.id,
|
||||||
|
name: item.title, // map title to name for backward compatibility
|
||||||
|
title: item.title,
|
||||||
|
description: item.description,
|
||||||
|
...item
|
||||||
|
})) || [];
|
||||||
|
|
||||||
setCategories(resCategory);
|
setCategories(resCategory);
|
||||||
console.log("data category", resCategory);
|
console.log("Article categories loaded:", resCategory);
|
||||||
|
|
||||||
if (scheduleId && scheduleType === "3") {
|
if (scheduleId && scheduleType === "3") {
|
||||||
const findCategory = resCategory.find((o) =>
|
const findCategory = resCategory.find((o) =>
|
||||||
|
|
@ -478,7 +502,6 @@ export default function FormImage() {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (findCategory) {
|
if (findCategory) {
|
||||||
// setValue("categoryId", findCategory.id);
|
|
||||||
setSelectedCategory(findCategory.id);
|
setSelectedCategory(findCategory.id);
|
||||||
const response = await getTagsBySubCategoryId(findCategory.id);
|
const response = await getTagsBySubCategoryId(findCategory.id);
|
||||||
setTags(response?.data?.data);
|
setTags(response?.data?.data);
|
||||||
|
|
@ -486,6 +509,14 @@ export default function FormImage() {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch categories:", error);
|
console.error("Failed to fetch categories:", error);
|
||||||
|
// Fallback to old API if error occurs
|
||||||
|
try {
|
||||||
|
const fallbackCategory = await listEnableCategory(fileTypeId);
|
||||||
|
const resCategory: Category[] = fallbackCategory?.data.data.content || [];
|
||||||
|
setCategories(resCategory);
|
||||||
|
} catch (fallbackError) {
|
||||||
|
console.error("Fallback category fetch also failed:", fallbackError);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -541,6 +572,21 @@ export default function FormImage() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API request data structure
|
||||||
|
const articleData: CreateArticleData = {
|
||||||
|
title: finalTitle,
|
||||||
|
description: htmlToString(finalDescription),
|
||||||
|
htmlDescription: finalDescription,
|
||||||
|
categoryIds: selectedCategory.toString(),
|
||||||
|
typeId: 1, // Image content type
|
||||||
|
tags: finalTags,
|
||||||
|
isDraft: true,
|
||||||
|
isPublish: false,
|
||||||
|
oldId: 0,
|
||||||
|
slug: finalTitle.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, ''),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Keep old structure for backward compatibility if needed
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -580,37 +626,102 @@ export default function FormImage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id == undefined) {
|
if (id == undefined) {
|
||||||
const response = await createMedia(requestData);
|
// Use new Articles API
|
||||||
console.log("Form Data Submitted:", requestData);
|
const response = await createArticle(articleData);
|
||||||
|
console.log("Article Data Submitted:", articleData);
|
||||||
|
console.log("Article API Response:", response);
|
||||||
|
|
||||||
Cookies.set("idCreate", response?.data?.data, { expires: 1 });
|
if (response?.error) {
|
||||||
id = response?.data?.data;
|
MySwal.fire("Error", response.message || "Failed to create article", "error");
|
||||||
const formMedia = new FormData();
|
|
||||||
const thumbnail = files[0];
|
|
||||||
formMedia.append("file", thumbnail);
|
|
||||||
const responseThumbnail = await uploadThumbnail(id, formMedia);
|
|
||||||
if (responseThumbnail?.error == true) {
|
|
||||||
error(responseThumbnail?.message);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const progressInfoArr = files.map((item) => ({
|
|
||||||
percentage: 0,
|
|
||||||
fileName: item.name,
|
|
||||||
}));
|
|
||||||
progressInfo = progressInfoArr;
|
|
||||||
setIsStartUpload(true);
|
|
||||||
setProgressList(progressInfoArr);
|
|
||||||
|
|
||||||
close();
|
// Get the article ID from the new API response
|
||||||
files.map(async (item: any, index: number) => {
|
const articleId = response?.data?.data?.id;
|
||||||
await uploadResumableFile(
|
Cookies.set("idCreate", articleId, { expires: 1 });
|
||||||
index,
|
id = articleId;
|
||||||
String(id),
|
|
||||||
item,
|
// Upload files using new article-files API
|
||||||
fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0"
|
const formData = new FormData();
|
||||||
);
|
|
||||||
});
|
// Add all files to FormData
|
||||||
|
files.forEach((file, index) => {
|
||||||
|
formData.append('files', file);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log("Uploading files to article:", articleId);
|
||||||
|
console.log("Files to upload:", files.length);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const uploadResponse = await uploadArticleFiles(articleId, formData);
|
||||||
|
|
||||||
|
if (uploadResponse?.error) {
|
||||||
|
MySwal.fire("Error", uploadResponse.message || "Failed to upload files", "error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Files uploaded successfully:", uploadResponse);
|
||||||
|
|
||||||
|
// Upload thumbnail using first file as thumbnail
|
||||||
|
if (files.length > 0) {
|
||||||
|
const thumbnailFormData = new FormData();
|
||||||
|
thumbnailFormData.append('files', files[0]); // Use first file as thumbnail
|
||||||
|
|
||||||
|
console.log("Uploading thumbnail for article:", articleId);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const thumbnailResponse = await uploadArticleThumbnail(articleId, thumbnailFormData);
|
||||||
|
|
||||||
|
if (thumbnailResponse?.error) {
|
||||||
|
console.warn("Thumbnail upload failed:", thumbnailResponse.message);
|
||||||
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
|
} else {
|
||||||
|
console.log("Thumbnail uploaded successfully:", thumbnailResponse);
|
||||||
|
}
|
||||||
|
} catch (thumbnailError) {
|
||||||
|
console.warn("Thumbnail upload error:", thumbnailError);
|
||||||
|
// Don't fail the whole process if thumbnail upload fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (uploadError) {
|
||||||
|
console.error("Upload error:", uploadError);
|
||||||
|
MySwal.fire("Error", "Failed to upload files. Please try again.", "error");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show success message
|
||||||
|
MySwal.fire({
|
||||||
|
title: "Sukses",
|
||||||
|
text: "Article dan files berhasil disimpan.",
|
||||||
|
icon: "success",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: "OK",
|
||||||
|
}).then(() => {
|
||||||
|
router.push("/admin/content/image");
|
||||||
|
});
|
||||||
|
|
||||||
|
Cookies.remove("idCreate");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep old upload logic for backward compatibility
|
||||||
|
// const progressInfoArr = files.map((item) => ({
|
||||||
|
// percentage: 0,
|
||||||
|
// fileName: item.name,
|
||||||
|
// }));
|
||||||
|
// progressInfo = progressInfoArr;
|
||||||
|
// setIsStartUpload(true);
|
||||||
|
// setProgressList(progressInfoArr);
|
||||||
|
|
||||||
|
// files.map(async (item: any, index: number) => {
|
||||||
|
// await uploadResumableFile(
|
||||||
|
// index,
|
||||||
|
// String(id),
|
||||||
|
// item,
|
||||||
|
// fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0"
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
Cookies.remove("idCreate");
|
Cookies.remove("idCreate");
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -82,9 +82,7 @@ export const useAuth = (): AuthContextType => {
|
||||||
|
|
||||||
// Attempt login
|
// Attempt login
|
||||||
const response = await doLogin({
|
const response = await doLogin({
|
||||||
...credentials,
|
...credentials
|
||||||
grantType: AUTH_CONSTANTS.GRANT_TYPE,
|
|
||||||
clientId: AUTH_CONSTANTS.CLIENT_ID,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
|
|
@ -92,7 +90,12 @@ export const useAuth = (): AuthContextType => {
|
||||||
throw new Error("Invalid username or password");
|
throw new Error("Invalid username or password");
|
||||||
}
|
}
|
||||||
|
|
||||||
const { access_token, refresh_token } = response?.data || {};
|
console.log("response : ", response?.data);
|
||||||
|
|
||||||
|
const { access_token, refresh_token } = response?.data?.data || {};
|
||||||
|
|
||||||
|
console.log("access_token : ", access_token);
|
||||||
|
console.log("refresh_token : ", refresh_token);
|
||||||
|
|
||||||
if (!access_token || !refresh_token) {
|
if (!access_token || !refresh_token) {
|
||||||
throw new Error("Invalid response from server");
|
throw new Error("Invalid response from server");
|
||||||
|
|
@ -103,7 +106,9 @@ export const useAuth = (): AuthContextType => {
|
||||||
|
|
||||||
// Get user profile
|
// Get user profile
|
||||||
const profileResponse = await getProfile(access_token);
|
const profileResponse = await getProfile(access_token);
|
||||||
const profile: ProfileData = profileResponse?.data?.data;
|
const profile: any = profileResponse?.data?.data;
|
||||||
|
|
||||||
|
console.log("profile : ", profile);
|
||||||
|
|
||||||
if (!profile) {
|
if (!profile) {
|
||||||
throw new Error("Failed to fetch user profile");
|
throw new Error("Failed to fetch user profile");
|
||||||
|
|
@ -124,12 +129,17 @@ export const useAuth = (): AuthContextType => {
|
||||||
|
|
||||||
loginRateLimiter.resetAttempts(credentials.username);
|
loginRateLimiter.resetAttempts(credentials.username);
|
||||||
|
|
||||||
|
|
||||||
|
console.log("navigationPath : ", profile.userRoleId);
|
||||||
|
|
||||||
const navigationPath = getNavigationPath(
|
const navigationPath = getNavigationPath(
|
||||||
profile.roleId,
|
profile.userRoleId,
|
||||||
profile.userLevel?.id,
|
profile.userLevelId,
|
||||||
profile.userLevel?.parentLevelId
|
profile.userLevelGroup
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log("navigationPath : ", navigationPath);
|
||||||
|
|
||||||
setState({
|
setState({
|
||||||
isAuthenticated: true,
|
isAuthenticated: true,
|
||||||
user: profile,
|
user: profile,
|
||||||
|
|
@ -198,7 +208,7 @@ export const useEmailValidation = () => {
|
||||||
throw new Error(response?.message || "Email validation failed");
|
throw new Error(response?.message || "Email validation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
const message = response?.data?.message;
|
const message = response?.data?.messages[0];
|
||||||
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case "Continue to setup email":
|
case "Continue to setup email":
|
||||||
|
|
@ -301,8 +311,12 @@ export const useOTPVerification = () => {
|
||||||
if (otp.length !== 6) {
|
if (otp.length !== 6) {
|
||||||
throw new Error("OTP must be exactly 6 digits");
|
throw new Error("OTP must be exactly 6 digits");
|
||||||
}
|
}
|
||||||
|
const data = {
|
||||||
|
username : username,
|
||||||
|
otpCode : otp,
|
||||||
|
};
|
||||||
|
|
||||||
const response = await verifyOTPByUsername(username, otp);
|
const response = await verifyOTPByUsername(data);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
throw new Error(response.message || "OTP verification failed");
|
throw new Error(response.message || "OTP verification failed");
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export const NAVIGATION_CONFIG: NavigationConfig[] = [
|
||||||
path: "/admin/dashboard/executive",
|
path: "/admin/dashboard/executive",
|
||||||
label: "Executive Dashboard",
|
label: "Executive Dashboard",
|
||||||
},
|
},
|
||||||
{ roleId: 3, path: "/admin/dashboard", label: "Dashboard" },
|
{ roleId: 1, path: "/admin/dashboard", label: "Dashboard" },
|
||||||
{ roleId: 4, path: "/admin/dashboard", label: "Dashboard" },
|
{ roleId: 4, path: "/admin/dashboard", label: "Dashboard" },
|
||||||
{ roleId: 9, path: "/in/supervisor/ticketing", label: "Ticketing" },
|
{ roleId: 9, path: "/in/supervisor/ticketing", label: "Ticketing" },
|
||||||
{ roleId: 10, path: "/admin/dashboard", label: "Dashboard" },
|
{ roleId: 10, path: "/admin/dashboard", label: "Dashboard" },
|
||||||
|
|
@ -49,30 +49,29 @@ export const setAuthCookies = (
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setProfileCookies = (profile: ProfileData): void => {
|
export const setProfileCookies = (profile: any): void => {
|
||||||
Cookies.set("home_path", profile.homePath || "", { expires: 1 });
|
// Cookies.set("home_path", profile.homePath || "", { expires: 1 });
|
||||||
Cookies.set("profile_picture", profile.profilePictureUrl || "", {
|
// Cookies.set("profile_picture", profile.profilePictureUrl || "", {
|
||||||
expires: 1,
|
// expires: 1,
|
||||||
});
|
// });
|
||||||
Cookies.set("state", profile.userLevel?.name || "", { expires: 1 });
|
// Cookies.set("state", profile.userLevel?.name || "", { expires: 1 });
|
||||||
Cookies.set("state-prov", profile.userLevel?.province?.provName || "", {
|
// Cookies.set("state-prov", profile.userLevel?.province?.provName || "", {
|
||||||
expires: 1,
|
// expires: 1,
|
||||||
});
|
// });
|
||||||
|
|
||||||
setCookiesEncrypt("uie", profile.id, { expires: 1 });
|
setCookiesEncrypt("uie", profile.id, { expires: 1 });
|
||||||
setCookiesEncrypt("urie", profile.roleId.toString(), { expires: 1 });
|
setCookiesEncrypt("urie", profile.userRoleId.toString(), { expires: 1 });
|
||||||
setCookiesEncrypt("urne", profile.role?.name || "", { expires: 1 });
|
setCookiesEncrypt("ulie", profile.userLevelId.toString() || "", {
|
||||||
setCookiesEncrypt("ulie", profile.userLevel?.id.toString() || "", {
|
|
||||||
expires: 1,
|
|
||||||
});
|
|
||||||
setCookiesEncrypt(
|
|
||||||
"uplie",
|
|
||||||
profile.userLevel?.parentLevelId?.toString() || "",
|
|
||||||
{ expires: 1 }
|
|
||||||
);
|
|
||||||
setCookiesEncrypt("ulne", profile.userLevel?.levelNumber.toString() || "", {
|
|
||||||
expires: 1,
|
expires: 1,
|
||||||
});
|
});
|
||||||
|
// setCookiesEncrypt(
|
||||||
|
// "uplie",
|
||||||
|
// profile.userLevel?.parentLevelId?.toString() || "",
|
||||||
|
// { expires: 1 }
|
||||||
|
// );
|
||||||
|
// setCookiesEncrypt("ulne", profile.userLevel?.levelNumber.toString() || "", {
|
||||||
|
// expires: 1,
|
||||||
|
// });
|
||||||
setCookiesEncrypt("ufne", profile.fullname, { expires: 1 });
|
setCookiesEncrypt("ufne", profile.fullname, { expires: 1 });
|
||||||
setCookiesEncrypt("ulnae", profile.userLevel?.name || "", { expires: 1 });
|
setCookiesEncrypt("ulnae", profile.userLevel?.name || "", { expires: 1 });
|
||||||
setCookiesEncrypt("uinse", profile.instituteId || "", { expires: 1 });
|
setCookiesEncrypt("uinse", profile.instituteId || "", { expires: 1 });
|
||||||
|
|
@ -130,7 +129,7 @@ export const isSpecialLevel = (
|
||||||
export const getNavigationPath = (
|
export const getNavigationPath = (
|
||||||
roleId: number,
|
roleId: number,
|
||||||
userLevelId?: number,
|
userLevelId?: number,
|
||||||
parentLevelId?: number
|
userLevelGroup?: number
|
||||||
): string => {
|
): string => {
|
||||||
const config = NAVIGATION_CONFIG.find((nav) => nav.roleId === roleId);
|
const config = NAVIGATION_CONFIG.find((nav) => nav.roleId === roleId);
|
||||||
|
|
||||||
|
|
@ -139,12 +138,11 @@ export const getNavigationPath = (
|
||||||
if (config) {
|
if (config) {
|
||||||
// Special handling for role 2 with specific level conditions
|
// Special handling for role 2 with specific level conditions
|
||||||
if (
|
if (
|
||||||
roleId === 2 &&
|
roleId === 1 &&
|
||||||
userLevelId &&
|
userLevelId
|
||||||
parentLevelId &&
|
// isSpecialLevel(userLevelId, parentLevelId)
|
||||||
isSpecialLevel(userLevelId, parentLevelId)
|
|
||||||
) {
|
) {
|
||||||
return "/in/dashboard";
|
return "/admin/dashboard";
|
||||||
}
|
}
|
||||||
return config.path;
|
return config.path;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import type { NextConfig } from "next";
|
||||||
|
|
||||||
const nextConfig = {
|
const nextConfig = {
|
||||||
images: {
|
images: {
|
||||||
domains: ["netidhub.com"],
|
domains: ["kontenhumas.com"],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ export async function login(data: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function doLogin(data: any) {
|
export async function doLogin(data: any) {
|
||||||
const pathUrl = "signin";
|
const pathUrl = "users/login";
|
||||||
return httpPost(pathUrl, data);
|
return httpPost(pathUrl, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -44,7 +44,7 @@ export async function getCsrfToken() {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
};
|
};
|
||||||
return httpGet(pathUrl, headers);
|
return httpGet(pathUrl, headers);
|
||||||
// const url = 'https://netidhub.com/api/csrf';
|
// const url = 'https://kontenhumas.com/api/csrf';
|
||||||
// try {
|
// try {
|
||||||
// const response = await fetch(url, {
|
// const response = await fetch(url, {
|
||||||
// method: 'GET',
|
// method: 'GET',
|
||||||
|
|
@ -69,8 +69,8 @@ export async function getProfile(token: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postEmailValidation(data: any) {
|
export async function postEmailValidation(data: any) {
|
||||||
const url = "public/users/email-validation";
|
const url = "users/email-validation";
|
||||||
return httpPostInterceptor(url, data);
|
return httpPost(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postSetupEmail(data: any) {
|
export async function postSetupEmail(data: any) {
|
||||||
|
|
@ -78,9 +78,9 @@ export async function postSetupEmail(data: any) {
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function verifyOTPByUsername(username: any, otp: any) {
|
export async function verifyOTPByUsername(data: any) {
|
||||||
const url = `public/users/verify-otp?username=${username}&otp=${otp}`;
|
const url = `users/otp-validation`;
|
||||||
return httpPost(url);
|
return httpPost(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getSubjects() {
|
export async function getSubjects() {
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,60 @@ import {
|
||||||
httpPostInterceptor,
|
httpPostInterceptor,
|
||||||
} from "./http-config/http-interceptor-service";
|
} from "./http-config/http-interceptor-service";
|
||||||
|
|
||||||
|
// Interface for Articles API filters
|
||||||
|
export interface ArticleFilters {
|
||||||
|
page?: number;
|
||||||
|
totalPage?: number;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
categoryId?: number;
|
||||||
|
category?: string;
|
||||||
|
typeId?: number;
|
||||||
|
tags?: string;
|
||||||
|
createdById?: number;
|
||||||
|
statusId?: number;
|
||||||
|
isBanner?: boolean;
|
||||||
|
isPublish?: boolean;
|
||||||
|
isDraft?: boolean;
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for creating new article
|
||||||
|
export interface CreateArticleData {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
categoryIds: string;
|
||||||
|
typeId: number;
|
||||||
|
tags: string;
|
||||||
|
isDraft: boolean;
|
||||||
|
isPublish: boolean;
|
||||||
|
oldId: number;
|
||||||
|
slug: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for Article Category
|
||||||
|
export interface ArticleCategory {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
thumbnailUrl: string;
|
||||||
|
slug: string | null;
|
||||||
|
tags: string[];
|
||||||
|
thumbnailPath: string | null;
|
||||||
|
parentId: number;
|
||||||
|
oldCategoryId: number | null;
|
||||||
|
createdById: number;
|
||||||
|
statusId: number;
|
||||||
|
isPublish: boolean;
|
||||||
|
publishedAt: string | null;
|
||||||
|
isEnabled: boolean | null;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
export async function listDataAll(
|
export async function listDataAll(
|
||||||
isForSelf: any,
|
isForSelf: any,
|
||||||
isApproval: any,
|
isApproval: any,
|
||||||
|
|
@ -150,6 +204,12 @@ export async function createMedia(data: any) {
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API - Create Article
|
||||||
|
export async function createArticle(data: CreateArticleData) {
|
||||||
|
const url = "articles";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
export async function uploadThumbnail(id: any, data: any) {
|
export async function uploadThumbnail(id: any, data: any) {
|
||||||
const url = `media/upload?id=${id}&operation=thumbnail`;
|
const url = `media/upload?id=${id}&operation=thumbnail`;
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
@ -158,6 +218,30 @@ export async function uploadThumbnail(id: any, data: any) {
|
||||||
return httpPostInterceptor(url, data, headers);
|
return httpPostInterceptor(url, data, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API - Upload Article Files
|
||||||
|
export async function uploadArticleFiles(articleId: string | number, files: FormData) {
|
||||||
|
const url = `article-files/${articleId}`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
};
|
||||||
|
return httpPostInterceptor(url, files, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Articles API - Upload Article Thumbnail
|
||||||
|
export async function uploadArticleThumbnail(articleId: string | number, thumbnail: FormData) {
|
||||||
|
const url = `articles/thumbnail/${articleId}`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
};
|
||||||
|
return httpPostInterceptor(url, thumbnail, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Articles API - Get Article Categories
|
||||||
|
export async function listArticleCategories(page: number = 1, limit: number = 100) {
|
||||||
|
const url = `article-categories?page=${page}&limit=${limit}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function detailSPIT(id: any) {
|
export async function detailSPIT(id: any) {
|
||||||
const url = `media/spit?id=${id}`;
|
const url = `media/spit?id=${id}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
|
|
@ -211,3 +295,101 @@ export async function postActivityLog(data: any) {
|
||||||
const url = `activity`;
|
const url = `activity`;
|
||||||
return httpPost(url, data);
|
return httpPost(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API function with complete filter support
|
||||||
|
export async function listArticles(
|
||||||
|
page: number = 1,
|
||||||
|
totalPage: number = 10,
|
||||||
|
title?: string,
|
||||||
|
description?: string,
|
||||||
|
categoryId?: number,
|
||||||
|
category?: string,
|
||||||
|
typeId?: number,
|
||||||
|
tags?: string,
|
||||||
|
createdById?: number,
|
||||||
|
statusId?: number,
|
||||||
|
isBanner?: boolean,
|
||||||
|
isPublish?: boolean,
|
||||||
|
isDraft?: boolean,
|
||||||
|
startDate?: string,
|
||||||
|
endDate?: string
|
||||||
|
) {
|
||||||
|
let url = `articles?page=${page}&totalPage=${totalPage}`;
|
||||||
|
|
||||||
|
// Add optional query parameters based on available filters
|
||||||
|
if (title) url += `&title=${encodeURIComponent(title)}`;
|
||||||
|
if (description) url += `&description=${encodeURIComponent(description)}`;
|
||||||
|
if (categoryId !== undefined) url += `&categoryId=${categoryId}`;
|
||||||
|
if (category) url += `&category=${encodeURIComponent(category)}`;
|
||||||
|
if (typeId !== undefined) url += `&typeId=${typeId}`;
|
||||||
|
if (tags) url += `&tags=${encodeURIComponent(tags)}`;
|
||||||
|
if (createdById !== undefined) url += `&createdById=${createdById}`;
|
||||||
|
if (statusId !== undefined) url += `&statusId=${statusId}`;
|
||||||
|
if (isBanner !== undefined) url += `&isBanner=${isBanner}`;
|
||||||
|
if (isPublish !== undefined) url += `&isPublish=${isPublish}`;
|
||||||
|
if (isDraft !== undefined) url += `&isDraft=${isDraft}`;
|
||||||
|
if (startDate) url += `&startDate=${startDate}`;
|
||||||
|
if (endDate) url += `&endDate=${endDate}`;
|
||||||
|
|
||||||
|
return await httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternative function using interface for better type safety
|
||||||
|
export async function listArticlesWithFilters(filters: ArticleFilters) {
|
||||||
|
return await listArticles(
|
||||||
|
filters.page,
|
||||||
|
filters.totalPage,
|
||||||
|
filters.title,
|
||||||
|
filters.description,
|
||||||
|
filters.categoryId,
|
||||||
|
filters.category,
|
||||||
|
filters.typeId,
|
||||||
|
filters.tags,
|
||||||
|
filters.createdById,
|
||||||
|
filters.statusId,
|
||||||
|
filters.isBanner,
|
||||||
|
filters.isPublish,
|
||||||
|
filters.isDraft,
|
||||||
|
filters.startDate,
|
||||||
|
filters.endDate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatible wrapper for listDataTeks with new articles API
|
||||||
|
export async function listDataTeksNew(
|
||||||
|
size: any,
|
||||||
|
page: any,
|
||||||
|
isForSelf: any,
|
||||||
|
isApproval: any,
|
||||||
|
categoryFilter: any,
|
||||||
|
statusFilter: any,
|
||||||
|
needApprovalFromLevel: any,
|
||||||
|
creator: any,
|
||||||
|
source: any,
|
||||||
|
startDate: any,
|
||||||
|
endDate: any,
|
||||||
|
title: string = "",
|
||||||
|
creatorGroup: string = ""
|
||||||
|
) {
|
||||||
|
// Convert old parameters to new API format
|
||||||
|
const categoryId = categoryFilter ? Number(categoryFilter) : undefined;
|
||||||
|
const statusId = statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined;
|
||||||
|
|
||||||
|
return await listArticles(
|
||||||
|
page + 1, // API expects 1-based page
|
||||||
|
Number(size),
|
||||||
|
title,
|
||||||
|
undefined, // description
|
||||||
|
categoryId,
|
||||||
|
undefined, // category name
|
||||||
|
3, // typeId for text content
|
||||||
|
undefined, // tags
|
||||||
|
undefined, // createdById
|
||||||
|
statusId,
|
||||||
|
undefined, // isBanner
|
||||||
|
undefined, // isPublish
|
||||||
|
undefined, // isDraft
|
||||||
|
startDate,
|
||||||
|
endDate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,60 @@ import {
|
||||||
httpPostInterceptor,
|
httpPostInterceptor,
|
||||||
} from "../http-config/http-interceptor-service";
|
} from "../http-config/http-interceptor-service";
|
||||||
|
|
||||||
|
// Interface for Articles API filters
|
||||||
|
export interface ArticleFilters {
|
||||||
|
page?: number;
|
||||||
|
totalPage?: number;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
categoryId?: number;
|
||||||
|
category?: string;
|
||||||
|
typeId?: number;
|
||||||
|
tags?: string;
|
||||||
|
createdById?: number;
|
||||||
|
statusId?: number;
|
||||||
|
isBanner?: boolean;
|
||||||
|
isPublish?: boolean;
|
||||||
|
isDraft?: boolean;
|
||||||
|
startDate?: string;
|
||||||
|
endDate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for creating new article
|
||||||
|
export interface CreateArticleData {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
htmlDescription: string;
|
||||||
|
categoryIds: string;
|
||||||
|
typeId: number;
|
||||||
|
tags: string;
|
||||||
|
isDraft: boolean;
|
||||||
|
isPublish: boolean;
|
||||||
|
oldId: number;
|
||||||
|
slug: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interface for Article Category
|
||||||
|
export interface ArticleCategory {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
thumbnailUrl: string;
|
||||||
|
slug: string | null;
|
||||||
|
tags: string[];
|
||||||
|
thumbnailPath: string | null;
|
||||||
|
parentId: number;
|
||||||
|
oldCategoryId: number | null;
|
||||||
|
createdById: number;
|
||||||
|
statusId: number;
|
||||||
|
isPublish: boolean;
|
||||||
|
publishedAt: string | null;
|
||||||
|
isEnabled: boolean | null;
|
||||||
|
isActive: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
|
||||||
// export async function listDataAll(
|
// export async function listDataAll(
|
||||||
// isForSelf,
|
// isForSelf,
|
||||||
// isApproval,
|
// isApproval,
|
||||||
|
|
@ -171,6 +225,12 @@ export async function createMedia(data: any) {
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API - Create Article
|
||||||
|
export async function createArticle(data: CreateArticleData) {
|
||||||
|
const url = "articles";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
export async function uploadThumbnail(id: any, data: any) {
|
export async function uploadThumbnail(id: any, data: any) {
|
||||||
const url = `media/upload?id=${id}&operation=thumbnail`;
|
const url = `media/upload?id=${id}&operation=thumbnail`;
|
||||||
const headers = {
|
const headers = {
|
||||||
|
|
@ -179,6 +239,30 @@ export async function uploadThumbnail(id: any, data: any) {
|
||||||
return httpPostInterceptor(url, data, headers);
|
return httpPostInterceptor(url, data, headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API - Upload Article Files
|
||||||
|
export async function uploadArticleFiles(articleId: string | number, files: FormData) {
|
||||||
|
const url = `article-files/${articleId}`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
};
|
||||||
|
return httpPostInterceptor(url, files, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Articles API - Upload Article Thumbnail
|
||||||
|
export async function uploadArticleThumbnail(articleId: string | number, thumbnail: FormData) {
|
||||||
|
const url = `articles/thumbnail/${articleId}`;
|
||||||
|
const headers = {
|
||||||
|
"Content-Type": "multipart/form-data",
|
||||||
|
};
|
||||||
|
return httpPostInterceptor(url, thumbnail, headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Articles API - Get Article Categories
|
||||||
|
export async function listArticleCategories(page: number = 1, limit: number = 100) {
|
||||||
|
const url = `article-categories?page=${page}&limit=${limit}`;
|
||||||
|
return httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function detailSPIT(id: any) {
|
export async function detailSPIT(id: any) {
|
||||||
const url = `media/spit?id=${id}`;
|
const url = `media/spit?id=${id}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
|
|
@ -232,3 +316,101 @@ export async function postActivityLog(data: any) {
|
||||||
const url = `activity`;
|
const url = `activity`;
|
||||||
return httpPost(url, data);
|
return httpPost(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// New Articles API function with complete filter support
|
||||||
|
export async function listArticles(
|
||||||
|
page: number = 1,
|
||||||
|
totalPage: number = 10,
|
||||||
|
title?: string,
|
||||||
|
description?: string,
|
||||||
|
categoryId?: number,
|
||||||
|
category?: string,
|
||||||
|
typeId?: number,
|
||||||
|
tags?: string,
|
||||||
|
createdById?: number,
|
||||||
|
statusId?: number,
|
||||||
|
isBanner?: boolean,
|
||||||
|
isPublish?: boolean,
|
||||||
|
isDraft?: boolean,
|
||||||
|
startDate?: string,
|
||||||
|
endDate?: string
|
||||||
|
) {
|
||||||
|
let url = `articles?page=${page}&totalPage=${totalPage}`;
|
||||||
|
|
||||||
|
// Add optional query parameters based on available filters
|
||||||
|
if (title) url += `&title=${encodeURIComponent(title)}`;
|
||||||
|
if (description) url += `&description=${encodeURIComponent(description)}`;
|
||||||
|
if (categoryId !== undefined) url += `&categoryId=${categoryId}`;
|
||||||
|
if (category) url += `&category=${encodeURIComponent(category)}`;
|
||||||
|
if (typeId !== undefined) url += `&typeId=${typeId}`;
|
||||||
|
if (tags) url += `&tags=${encodeURIComponent(tags)}`;
|
||||||
|
if (createdById !== undefined) url += `&createdById=${createdById}`;
|
||||||
|
if (statusId !== undefined) url += `&statusId=${statusId}`;
|
||||||
|
if (isBanner !== undefined) url += `&isBanner=${isBanner}`;
|
||||||
|
if (isPublish !== undefined) url += `&isPublish=${isPublish}`;
|
||||||
|
if (isDraft !== undefined) url += `&isDraft=${isDraft}`;
|
||||||
|
if (startDate) url += `&startDate=${startDate}`;
|
||||||
|
if (endDate) url += `&endDate=${endDate}`;
|
||||||
|
|
||||||
|
return await httpGetInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alternative function using interface for better type safety
|
||||||
|
export async function listArticlesWithFilters(filters: ArticleFilters) {
|
||||||
|
return await listArticles(
|
||||||
|
filters.page,
|
||||||
|
filters.totalPage,
|
||||||
|
filters.title,
|
||||||
|
filters.description,
|
||||||
|
filters.categoryId,
|
||||||
|
filters.category,
|
||||||
|
filters.typeId,
|
||||||
|
filters.tags,
|
||||||
|
filters.createdById,
|
||||||
|
filters.statusId,
|
||||||
|
filters.isBanner,
|
||||||
|
filters.isPublish,
|
||||||
|
filters.isDraft,
|
||||||
|
filters.startDate,
|
||||||
|
filters.endDate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backward compatible wrapper for listDataTeks with new articles API
|
||||||
|
export async function listDataTeksNew(
|
||||||
|
size: any,
|
||||||
|
page: any,
|
||||||
|
isForSelf: any,
|
||||||
|
isApproval: any,
|
||||||
|
categoryFilter: any,
|
||||||
|
statusFilter: any,
|
||||||
|
needApprovalFromLevel: any,
|
||||||
|
creator: any,
|
||||||
|
source: any,
|
||||||
|
startDate: any,
|
||||||
|
endDate: any,
|
||||||
|
title: string = "",
|
||||||
|
creatorGroup: string = ""
|
||||||
|
) {
|
||||||
|
// Convert old parameters to new API format
|
||||||
|
const categoryId = categoryFilter ? Number(categoryFilter) : undefined;
|
||||||
|
const statusId = statusFilter?.length > 0 ? Number(statusFilter[0]) : undefined;
|
||||||
|
|
||||||
|
return await listArticles(
|
||||||
|
page + 1, // API expects 1-based page
|
||||||
|
Number(size),
|
||||||
|
title,
|
||||||
|
undefined, // description
|
||||||
|
categoryId,
|
||||||
|
undefined, // category name
|
||||||
|
3, // typeId for text content
|
||||||
|
undefined, // tags
|
||||||
|
undefined, // createdById
|
||||||
|
statusId,
|
||||||
|
undefined, // isBanner
|
||||||
|
undefined, // isPublish
|
||||||
|
undefined, // isDraft
|
||||||
|
startDate,
|
||||||
|
endDate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const baseURL = "https://netidhub.com/api/";
|
const baseURL = "https://kontenhumas.com/api/";
|
||||||
|
|
||||||
const axiosBaseInstance = axios.create({
|
const axiosBaseInstance = axios.create({
|
||||||
baseURL,
|
baseURL,
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
|
"X-Client-Key": "b1ce6602-07ad-46c2-85eb-0cd6decfefa3",
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import axios from "axios";
|
||||||
import Cookies from "js-cookie";
|
import Cookies from "js-cookie";
|
||||||
import { getCsrfToken, login } from "../auth";
|
import { getCsrfToken, login } from "../auth";
|
||||||
|
|
||||||
const baseURL = "https://netidhub.com/api/";
|
const baseURL = "https://kontenhumas.com/api/";
|
||||||
|
|
||||||
const refreshToken = Cookies.get("refresh_token");
|
const refreshToken = Cookies.get("refresh_token");
|
||||||
|
|
||||||
|
|
@ -10,6 +10,7 @@ const axiosInterceptorInstance = axios.create({
|
||||||
baseURL,
|
baseURL,
|
||||||
headers: {
|
headers: {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
|
"X-Client-Key": "b1ce6602-07ad-46c2-85eb-0cd6decfefa3",
|
||||||
},
|
},
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ export async function getCsrfToken() {
|
||||||
"content-type": "application/json",
|
"content-type": "application/json",
|
||||||
};
|
};
|
||||||
return httpGet(pathUrl, headers);
|
return httpGet(pathUrl, headers);
|
||||||
// const url = 'https://netidhub.com/api/csrf';
|
// const url = 'https://kontenhumas.com/api/csrf';
|
||||||
// try {
|
// try {
|
||||||
// const response = await fetch(url, {
|
// const response = await fetch(url, {
|
||||||
// method: 'GET',
|
// method: 'GET',
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue