From d424eff71a4985e42500953d9e6b58db4e9f44f0 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Thu, 5 Dec 2024 00:28:40 +0700 Subject: [PATCH 1/3] feat:fix table task,indeks,perencanaan,image --- .../blog/table-blog/blog-table.tsx | 72 +++- .../(protected)/content/image/create/page.tsx | 17 + .../(protected)/content/image/page.tsx | 11 +- .../content/image/table-image/index.tsx | 299 +++++++++++++- .../table-mediahub/mediahub-table.tsx | 69 +++- .../table-medsos/medsos-table.tsx | 69 +++- .../(protected)/task/table-task/data.ts | 106 ----- .../task/table-task/task-table.tsx | 140 +++++-- components/form/content/create-form.tsx | 381 ++++++++++++++++++ config/api.ts | 18 +- lib/menus.ts | 2 +- lib/utils.ts | 57 ++- package-lock.json | 252 ++++++------ package.json | 2 + service/blog/blog.ts | 8 + service/content/content-image.ts | 19 + service/http-config/axios-base-instance.ts | 12 + .../http-config/axios-interceptor-instance.ts | 56 +++ service/http-config/http-base-service.ts | 70 ++++ .../http-config/http-interceptor-service.ts | 129 ++++++ service/login-services.ts | 17 + service/media.ts | 77 ---- service/planning/planning.ts | 11 + service/ppid-categories-services.ts | 147 +++++++ service/task.ts | 80 ++++ 25 files changed, 1713 insertions(+), 408 deletions(-) create mode 100644 app/[locale]/(protected)/content/image/create/page.tsx delete mode 100644 app/[locale]/(protected)/task/table-task/data.ts create mode 100644 components/form/content/create-form.tsx create mode 100644 service/blog/blog.ts create mode 100644 service/content/content-image.ts create mode 100644 service/http-config/axios-base-instance.ts create mode 100644 service/http-config/axios-interceptor-instance.ts create mode 100644 service/http-config/http-base-service.ts create mode 100644 service/http-config/http-interceptor-service.ts create mode 100644 service/login-services.ts delete mode 100644 service/media.ts create mode 100644 service/planning/planning.ts create mode 100644 service/ppid-categories-services.ts create mode 100644 service/task.ts diff --git a/app/[locale]/(protected)/blog/table-blog/blog-table.tsx b/app/[locale]/(protected)/blog/table-blog/blog-table.tsx index b7ea563b..9a0426a8 100644 --- a/app/[locale]/(protected)/blog/table-blog/blog-table.tsx +++ b/app/[locale]/(protected)/blog/table-blog/blog-table.tsx @@ -46,17 +46,33 @@ import { } from "@/components/ui/dropdown-menu"; export type CompanyData = { + no: number; title: string; category: string; - date: string; - tag: string; - status: string; + createdAt: string; + tags: string; + statusName: string; }; import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { listTask } from "@/service/ppid-categories-services"; +import { paginationBlog } from "@/service/blog/blog"; export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, { accessorKey: "title", header: "Judul", @@ -71,33 +87,33 @@ export const columns: ColumnDef[] = [ ), }, { - accessorKey: "category", + accessorKey: "categoryName", header: "Kategori ", cell: ({ row }) => ( - {row.getValue("category")} + {row.getValue("categoryName")} ), }, { - accessorKey: "date", + accessorKey: "createdAt", header: "Tanggal Unggah ", cell: ({ row }) => ( - {row.getValue("date")} + {row.getValue("createdAt")} ), }, { - accessorKey: "tag", + accessorKey: "tags", header: "Tag ", cell: ({ row }) => ( - {row.getValue("tag")} + {row.getValue("tags")} ), }, { - accessorKey: "status", + accessorKey: "statusName", header: "Status", cell: ({ row }) => { return ( - {row.getValue("status")} + {row.getValue("statusName")} ); }, @@ -140,6 +156,7 @@ export const columns: ColumnDef[] = [ ]; const BlogTable = () => { + const [blogTable, setBlogTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -148,12 +165,15 @@ const BlogTable = () => { React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 6, + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman }); + const [page, setPage] = React.useState(1); // Halaman aktif + const [totalPage, setTotalPage] = React.useState(1); // Total halaman + const [limit, setLimit] = React.useState(10); const table = useReactTable({ - data, + data: blogTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -173,6 +193,30 @@ const BlogTable = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await paginationBlog(limit, page); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, // Hitung nomor urut + title: item.title, + categoryName: item.categoryName, + tags: item.tags, + assignmentType: item.assignmentType?.name || "-", + createdAt: item.createdAt, + statusName: item.statusName, + })); + + setBlogTable(data); + setTotalPage(res.data.totalPages); // Total halaman + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
diff --git a/app/[locale]/(protected)/content/image/create/page.tsx b/app/[locale]/(protected)/content/image/create/page.tsx new file mode 100644 index 00000000..6b169ce1 --- /dev/null +++ b/app/[locale]/(protected)/content/image/create/page.tsx @@ -0,0 +1,17 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormImage from "@/components/form/content/create-form"; + +const ImageCreatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default ImageCreatePage; diff --git a/app/[locale]/(protected)/content/image/page.tsx b/app/[locale]/(protected)/content/image/page.tsx index 070ef5d1..bbbd5df8 100644 --- a/app/[locale]/(protected)/content/image/page.tsx +++ b/app/[locale]/(protected)/content/image/page.tsx @@ -5,6 +5,7 @@ import TableImage from "./table-image"; import { Newspaper, NewspaperIcon, UploadIcon } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Icon } from "@iconify/react/dist/iconify.js"; +import { Link } from "@/components/navigation"; const ReactTableImagePage = () => { return ( @@ -54,10 +55,12 @@ const ReactTableImagePage = () => { Konten Foto
- + + + +
+ ); + }, + }, + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + return ( + + + + + + + + + View + + + + + Delete + + + + ); + }, + }, +]; const TableImage = () => { + const [imageTable, setImageTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -35,9 +205,29 @@ const TableImage = () => { const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman + }); + const [page, setPage] = React.useState(1); // Halaman aktif + const [totalPage, setTotalPage] = React.useState(1); // Total halaman + const [limit, setLimit] = React.useState(10); // Jumlah baris per halaman + const [search, setSearch] = React.useState(title); + const userId = getCookiesDecrypt("uie"); + const userLevelId = getCookiesDecrypt("ulie"); + + const [categories, setCategories] = React.useState(); + const [categoryFilter, setCategoryFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); + const [startDateString, setStartDateString] = React.useState(""); + const [endDateString, setEndDateString] = React.useState(""); + const [filterByCreator, setFilterByCreator] = React.useState(""); + const [filterBySource, setFilterBySource] = React.useState(""); + + const roleId = getCookiesDecrypt("urie"); const table = useReactTable({ - data, + data: imageTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -55,6 +245,48 @@ const TableImage = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const isForSelf = Number(roleId) == 4; + const res = await listDataImage( + limit, + page, + isForSelf, + !isForSelf, + categoryFilter?.sort().join(","), + statusFilter?.sort().join(",").includes("1") + ? "1,2" + : statusFilter?.sort().join(","), + statusFilter?.sort().join(",").includes("1") ? userLevelId : "", + filterByCreator, + filterBySource, + startDateString, + endDateString + ); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, // Hitung nomor urut + title: item.title, + categoryName: item.categoryName, + creatorGroup: item.creatorGroup, + assignmentType: item.assignmentType?.name || "-", + createdAt: item.createdAt, + isDone: item.isDone, + publishedOn: item.publishedOn, + isPublish: item.isPublish, + isPublishOnPolda: item.isPublishOnPolda, + })); + + setImageTable(data); + setTotalPage(res.data.totalPages); // Total halaman + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
@@ -72,22 +304,20 @@ const TableImage = () => {
- +
{table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ); - })} + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} ))} @@ -97,6 +327,7 @@ const TableImage = () => { {row.getVisibleCells().map((cell) => ( @@ -114,7 +345,41 @@ const TableImage = () => { )}
- +
+ + {table.getPageOptions().map((page, pageIndex) => ( + + ))} + +
); }; diff --git a/app/[locale]/(protected)/planning/mediahub/table-mediahub/mediahub-table.tsx b/app/[locale]/(protected)/planning/mediahub/table-mediahub/mediahub-table.tsx index 1ba02331..506ea04d 100644 --- a/app/[locale]/(protected)/planning/mediahub/table-mediahub/mediahub-table.tsx +++ b/app/[locale]/(protected)/planning/mediahub/table-mediahub/mediahub-table.tsx @@ -46,15 +46,32 @@ import { } from "@/components/ui/dropdown-menu"; export type CompanyData = { + no: number; title: string; date: string; - status: string; + isActive: boolean; }; import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { listTask } from "@/service/ppid-categories-services"; +import page from "../page"; +import { getPlanningSentPagination } from "@/service/planning/planning"; export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, { accessorKey: "title", header: "Judul", @@ -69,20 +86,26 @@ export const columns: ColumnDef[] = [ ), }, { - accessorKey: "date", + accessorKey: "createdAt", header: "Tanggal Unggah ", cell: ({ row }) => ( - {row.getValue("date")} + {row.getValue("createdAt")} ), }, { - accessorKey: "status", + accessorKey: "isActive", header: "Status", cell: ({ row }) => { + const isActive = row.getValue("isActive"); + console.log("isActive value:", isActive); // TypeScript type is inferred correctly return ( - - {row.getValue("status")} - +
+ {isActive ? ( + Terkirim + ) : ( + Belum Terkirim + )} +
); }, }, @@ -124,6 +147,7 @@ export const columns: ColumnDef[] = [ ]; const MediahubTable = () => { + const [mediahubTable, setMediahubTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -132,12 +156,16 @@ const MediahubTable = () => { React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 6, + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman }); + const [page, setPage] = React.useState(1); // Halaman aktif + const [totalPage, setTotalPage] = React.useState(1); // Total halaman + const [limit, setLimit] = React.useState(10); // Jumlah baris per halaman + // const [search, setSearch] = React.useState(title); const table = useReactTable({ - data, + data: mediahubTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -157,6 +185,27 @@ const MediahubTable = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await getPlanningSentPagination(limit, page, 1); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, // Hitung nomor urut + title: item.title, + createdAt: item.createdAt, + isActive: item.isActive === true, + })); + + setMediahubTable(data); + setTotalPage(res.data.totalPages); // Total halaman + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
diff --git a/app/[locale]/(protected)/planning/medsos-mediahub/table-medsos/medsos-table.tsx b/app/[locale]/(protected)/planning/medsos-mediahub/table-medsos/medsos-table.tsx index c6dbda3d..89e53e08 100644 --- a/app/[locale]/(protected)/planning/medsos-mediahub/table-medsos/medsos-table.tsx +++ b/app/[locale]/(protected)/planning/medsos-mediahub/table-medsos/medsos-table.tsx @@ -46,15 +46,32 @@ import { } from "@/components/ui/dropdown-menu"; export type CompanyData = { + no: number; title: string; date: string; - status: string; + isActive: boolean; }; import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { listTask } from "@/service/ppid-categories-services"; +import page from "../page"; +import { getPlanningSentPagination } from "@/service/planning/planning"; export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, { accessorKey: "title", header: "Judul", @@ -69,20 +86,26 @@ export const columns: ColumnDef[] = [ ), }, { - accessorKey: "date", + accessorKey: "createdAt", header: "Tanggal Unggah ", cell: ({ row }) => ( - {row.getValue("date")} + {row.getValue("createdAt")} ), }, { - accessorKey: "status", + accessorKey: "isActive", header: "Status", cell: ({ row }) => { + const isActive = row.getValue("isActive"); + console.log("isActive value:", isActive); // TypeScript type is inferred correctly return ( - - {row.getValue("status")} - +
+ {isActive ? ( + Terkirim + ) : ( + Belum Terkirim + )} +
); }, }, @@ -124,6 +147,7 @@ export const columns: ColumnDef[] = [ ]; const MedsosTable = () => { + const [mediahubTable, setMediahubTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -132,12 +156,16 @@ const MedsosTable = () => { React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 6, + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman }); + const [page, setPage] = React.useState(1); // Halaman aktif + const [totalPage, setTotalPage] = React.useState(1); // Total halaman + const [limit, setLimit] = React.useState(10); // Jumlah baris per halaman + // const [search, setSearch] = React.useState(title); const table = useReactTable({ - data, + data: mediahubTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -157,6 +185,27 @@ const MedsosTable = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await getPlanningSentPagination(limit, page, 2); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, // Hitung nomor urut + title: item.title, + createdAt: item.createdAt, + isActive: item.isActive === true, + })); + + setMediahubTable(data); + setTotalPage(res.data.totalPages); // Total halaman + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
diff --git a/app/[locale]/(protected)/task/table-task/data.ts b/app/[locale]/(protected)/task/table-task/data.ts deleted file mode 100644 index 93d38fe7..00000000 --- a/app/[locale]/(protected)/task/table-task/data.ts +++ /dev/null @@ -1,106 +0,0 @@ -export const data = [ - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "paid", - date: "$231.26", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Liputan Kegiatan", - code: "PNMH-1287", - status: "due", - date: "$432.81", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "due", - date: "$437.65", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Pers Rilis", - code: "PNMH-1287", - status: "canceled", - date: "$387.55", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "canceled", - date: "$489.80", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Liputan Kegiatan", - code: "PNMH-1287", - status: "canceled", - date: "$421.45", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Pers Rilis", - code: "PNMH-1287", - status: "canceled", - date: "$207.61", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "paid", - date: "$392.86", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Pers Rilis", - code: "PNMH-1287", - status: "paid", - date: "$162.87", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "paid", - date: "$268.58", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Liputan Kegiatan", - code: "PNMH-1287", - status: "paid", - date: "$369.19", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Liputan Kegiatan", - code: "PNMH-1287", - status: "paid", - date: "$420.87", - category: "amplifikasi", - typeTask: "Mediahub", - }, - { - title: "Giat Pimpinan", - code: "PNMH-1287", - status: "paid", - date: "$420.26", - category: "amplifikasi", - typeTask: "Mediahub", - }, -]; diff --git a/app/[locale]/(protected)/task/table-task/task-table.tsx b/app/[locale]/(protected)/task/table-task/task-table.tsx index 3a3644a2..b5a7ddee 100644 --- a/app/[locale]/(protected)/task/table-task/task-table.tsx +++ b/app/[locale]/(protected)/task/table-task/task-table.tsx @@ -37,7 +37,6 @@ import { TrendingDown, TrendingUp, } from "lucide-react"; -import { cn } from "@/lib/utils"; import { DropdownMenu, DropdownMenuContent, @@ -45,20 +44,38 @@ import { DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; -export type CompanyData = { - title: string; - code: string; - typeTask: string; - category: string; - date: string; - status: string; -}; -import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; import { Link } from "@/components/navigation"; +import { listTask } from "@/service/ppid-categories-services"; +import { title } from "process"; +import search from "../../app/chat/components/search"; +import { format } from "date-fns"; + +export type CompanyData = { + no: number; + title: string; + uniqueCode: string; + assignmentMainType: string; + assignmentType: string; + createdAt: string; + isDone: string; +}; export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, { accessorKey: "title", header: "Judul", @@ -73,47 +90,65 @@ export const columns: ColumnDef[] = [ ), }, { - accessorKey: "code", + accessorKey: "uniqueCode", header: "Kode ", cell: ({ row }) => ( - {row.getValue("code")} + {row.getValue("uniqueCode")} ), }, { - accessorKey: "typeTask", - header: "Kode ", + accessorKey: "assignmentMainType", + header: "Tipe Tugas ", cell: ({ row }) => ( - {row.getValue("typeTask")} + + {row.getValue("assignmentMainType")} + ), }, { - accessorKey: "category", + accessorKey: "assignmentType", header: "Jenis Tugas ", cell: ({ row }) => ( - {row.getValue("category")} + + {row.getValue("assignmentType")} + ), }, { - accessorKey: "date", - header: "Tanggal Unggah ", - cell: ({ row }) => ( - {row.getValue("date")} - ), + accessorKey: "createdAt", + header: "Tanggal Unggah", + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, }, + { - accessorKey: "status", + accessorKey: "isDone", header: "Status", cell: ({ row }) => { - const statusColors: Record = { - paid: "bg-success/20 text-success", - due: "bg-warning/20 text-warning", - canceled: "bg-destructive/20 text-destructive", - }; - const status = row.getValue("status"); + const isDone = row.getValue("isDone"); return ( - - {status} - +
+ +
); }, }, @@ -154,6 +189,7 @@ export const columns: ColumnDef[] = [ const TaskTable = () => { const [sorting, setSorting] = React.useState([]); + const [taskTable, setTaskTable] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] ); @@ -161,31 +197,55 @@ const TaskTable = () => { React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 6, + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman }); + const [page, setPage] = React.useState(1); // Halaman aktif + const [totalPage, setTotalPage] = React.useState(1); // Total halaman + const [limit, setLimit] = React.useState(10); // Jumlah baris per halaman + const [search, setSearch] = React.useState(title); const table = useReactTable({ - data, + data: taskTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, + onPaginationChange: setPagination, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), getFilteredRowModel: getFilteredRowModel(), - onColumnVisibilityChange: setColumnVisibility, - onRowSelectionChange: setRowSelection, - onPaginationChange: setPagination, state: { sorting, columnFilters, - columnVisibility, - rowSelection, pagination, }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await listTask(limit, page); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, // Hitung nomor urut + title: item.title, + uniqueCode: item.uniqueCode || "-", + assignmentMainType: item.assignmentMainType?.name || "-", + assignmentType: item.assignmentType?.name || "-", + createdAt: item.createdAt, + isDone: item.isDone, + })); + + setTaskTable(data); + setTotalPage(res.data.totalPages); // Total halaman + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
diff --git a/components/form/content/create-form.tsx b/components/form/content/create-form.tsx new file mode 100644 index 00000000..3b695882 --- /dev/null +++ b/components/form/content/create-form.tsx @@ -0,0 +1,381 @@ +"use client"; +import React, { ChangeEvent, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { register } from "module"; +import { Switch } from "@/components/ui/switch"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), + creator: z.string().min(1, { message: "Judul diperlukan" }), + tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +export default function FormImage() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + const [tags, setTags] = useState([]); + const [selectedFiles, setSelectedFiles] = useState([]); + + // State for various form fields + const [output, setOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + + const [assignmentType, setAssignmentType] = useState("mediahub"); + const [assignmentCategory, setAssignmentCategory] = useState("publication"); + + const [selectedTarget, setSelectedTarget] = useState("all"); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + const handleKeyDown = (e: any) => { + const newTag = e.target.value.trim(); // Ambil nilai input + if (e.key === "Enter" && newTag) { + e.preventDefault(); // Hentikan submit form + if (!tags.includes(newTag)) { + setTags((prevTags) => [...prevTags, newTag]); // Tambah tag baru + setValue("tags", ""); // Kosongkan input + } + } + }; + + const handleRemoveTag = (index: any) => { + setTags((prevTags) => prevTags.filter((_, i) => i !== index)); + }; + + const handleImageChange = (event: ChangeEvent) => { + if (event.target.files) { + const files = Array.from(event.target.files); + setSelectedFiles((prevImages: any) => [...prevImages, ...files]); + console.log("DATAFILE::", selectedFiles); + } + }; + + const handleRemoveImage = (index: number) => { + setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + const save = async (data: TaskSchema) => { + const requestData = { + ...data, + output, + assignmentType, + assignmentCategory, + target: selectedTarget, + unitSelection, + }; + + console.log("Form Data Submitted:", requestData); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/content/image"); + }); + }; + + const onSubmit = (data: TaskSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + return ( +
+
+ +
+

Form Konten Foto

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

{errors.title.message}

+ )} +
+
+
+ + +
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

+ )} +
+
+ +
+ +
+
+ +
+ +
+
+ {selectedFiles?.length > 0 ? ( +
+
+ {selectedFiles.map((image, index) => ( +
+ Pratinjau Gambar + +
+ ))} +
+
+ ) : ( + "" + )} +
+
+ + {/* Submit Button */} +
+
+
+ +
+
+ + ( + + )} + /> + {errors.creator?.message && ( +

+ {errors.creator.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+ {tags.length === 0 && "Please add at least one tag."} +
+
+ {tags.map((tag, index) => ( +
+ {tag} + +
+ ))} +
+
+
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+ ); +} diff --git a/config/api.ts b/config/api.ts index 19badfd3..1e2317f1 100644 --- a/config/api.ts +++ b/config/api.ts @@ -124,22 +124,24 @@ export async function getAPIInterceptor(url: any) { }; } -export async function postAPIInterceptor(url: any, data: any) { +// Fungsi postAPIInterceptor +export async function postAPIInterceptor(url: string, data: any) { const response = await axiosInterceptor .post(url, data) .catch((error) => error.response); - if (response?.status == 401) { + + if (response?.status === 401) { Object.keys(Cookies.get()).forEach((cookieName) => { Cookies.remove(cookieName); }); window.location.href = "/"; - } else if (response?.status > 300 && response?.status != 401) { + } else if (response?.status > 300 && response?.status !== 401) { return { error: true, message: response?.data?.message, data: null, }; - } else if (response?.data.success) { + } else if (response?.data?.success) { return { error: false, message: "success", @@ -149,11 +151,17 @@ export async function postAPIInterceptor(url: any, data: any) { return { error: true, - message: response?.data.message, + message: response?.data?.message, data: null, }; } +// Fungsi createTask +export async function createTask(data: any) { + const url = "assignment"; + return postAPIInterceptor(url, data); // Perbaikan: Memisahkan parameter url dan data +} + export async function deleteAPIInterceptor(url: any, data: any) { const response = await axiosInterceptor .delete(url, { data }) diff --git a/lib/menus.ts b/lib/menus.ts index 9f4d6940..881d1242 100644 --- a/lib/menus.ts +++ b/lib/menus.ts @@ -36,7 +36,7 @@ export function getMenuList(pathname: string, t: any): Group[] { menus: [ { id: "dashboard", - href: "/dashboard/tabs", + href: "/dashboard", label: t("dashboard"), active: pathname.includes("/dashboard"), icon: "material-symbols:dashboard", diff --git a/lib/utils.ts b/lib/utils.ts index 542c545b..c1d41a7c 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,8 +1,10 @@ -import { type ClassValue, clsx } from "clsx" -import { twMerge } from "tailwind-merge" +import { type ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; +import Cookies from "js-cookie"; +import CryptoJS from "crypto-js"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } export const hexToRGB = (hex: any, alpha?: number): any => { @@ -15,4 +17,51 @@ export const hexToRGB = (hex: any, alpha?: number): any => { } else { return `rgb(${r}, ${g}, ${b})`; } -}; \ No newline at end of file +}; + +export function checkAuthorization(page: any) { + const roleId = getCookiesDecrypt("urie"); + const levelNumber = getCookiesDecrypt("ulne"); + if ( + (Number(roleId) !== 3 && + Number(roleId) !== 4 && + Number(roleId) !== 11 && + Number(roleId) !== 12 && + Number(roleId) !== 2) || + roleId == undefined + ) { + console.log("Wrong Authentication"); + window.location.href = "/"; + } else if (page == "admin" && Number(levelNumber) !== 1) { + console.log("Wrong Authentication Admin"); + window.location.href = "/"; + } +} + +export function checkLoginSession() { + const userId = getCookiesDecrypt("uie"); + const jwt = Cookies.get("access_token"); + const data = { + userId, + jwt, + }; + // doCheckSession(data); +} + +export function getCookiesDecrypt(param: any) { + const cookiesEncrypt = Cookies.get(param); + try { + if (cookiesEncrypt != undefined) { + const output = CryptoJS.AES.decrypt( + cookiesEncrypt.toString(), + `${param}_EncryptKey@mediahub` + ).toString(CryptoJS.enc.Utf8); + if (output.startsWith('"')) { + return output.slice(1, -1); + } + return output; + } + } catch (e) { + console.log("Error", cookiesEncrypt); + } +} diff --git a/package-lock.json b/package-lock.json index 1b934d68..46dd08ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -54,6 +54,7 @@ "@south-paw/react-vector-maps": "^3.2.0", "@tanstack/react-table": "^8.19.2", "@types/cleave.js": "^1.4.12", + "@types/crypto-js": "^4.2.2", "@types/js-cookie": "^3.0.6", "@types/qs": "^6.9.17", "@types/react-syntax-highlighter": "^15.5.13", @@ -66,6 +67,7 @@ "clsx": "^2.1.1", "cmdk": "^1.0.0", "cookie": "^1.0.2", + "crypto-js": "^4.2.0", "date-fns": "^3.6.0", "dayjs": "^1.11.11", "embla-carousel-autoplay": "^8.1.3", @@ -1082,6 +1084,126 @@ "glob": "10.3.10" } }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", + "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", + "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", + "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", + "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", + "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", + "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", + "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", + "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@next/swc-win32-x64-msvc": { "version": "14.2.3", "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.3.tgz", @@ -2780,6 +2902,11 @@ "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" }, + "node_modules/@types/crypto-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.2.2.tgz", + "integrity": "sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==" + }, "node_modules/@types/d3-array": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", @@ -4022,6 +4149,11 @@ "node": ">= 8" } }, + "node_modules/crypto-js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", + "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==" + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -13382,126 +13514,6 @@ "type": "github", "url": "https://github.com/sponsors/wooorm" } - }, - "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.3.tgz", - "integrity": "sha512-3pEYo/RaGqPP0YzwnlmPN2puaF2WMLM3apt5jLW2fFdXD9+pqcoTzRk+iZsf8ta7+quAe4Q6Ms0nR0SFGFdS1A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-darwin-x64": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.3.tgz", - "integrity": "sha512-6adp7waE6P1TYFSXpY366xwsOnEXM+y1kgRpjSRVI2CBDOcbRjsJ67Z6EgKIqWIue52d2q/Mx8g9MszARj8IEA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.3.tgz", - "integrity": "sha512-cuzCE/1G0ZSnTAHJPUT1rPgQx1w5tzSX7POXSLaS7w2nIUJUD+e25QoXD/hMfxbsT9rslEXugWypJMILBj/QsA==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.3.tgz", - "integrity": "sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.3.tgz", - "integrity": "sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.3.tgz", - "integrity": "sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.3.tgz", - "integrity": "sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.3.tgz", - "integrity": "sha512-vga40n1q6aYb0CLrM+eEmisfKCR45ixQYXuBXxOOmmoV8sYST9k7E3US32FsY+CkkF7NtzdcebiFT4CHuMSyZw==", - "cpu": [ - "ia32" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } } } } diff --git a/package.json b/package.json index 2a6c72b1..b80a2d6a 100644 --- a/package.json +++ b/package.json @@ -55,6 +55,7 @@ "@south-paw/react-vector-maps": "^3.2.0", "@tanstack/react-table": "^8.19.2", "@types/cleave.js": "^1.4.12", + "@types/crypto-js": "^4.2.2", "@types/js-cookie": "^3.0.6", "@types/qs": "^6.9.17", "@types/react-syntax-highlighter": "^15.5.13", @@ -67,6 +68,7 @@ "clsx": "^2.1.1", "cmdk": "^1.0.0", "cookie": "^1.0.2", + "crypto-js": "^4.2.0", "date-fns": "^3.6.0", "dayjs": "^1.11.11", "embla-carousel-autoplay": "^8.1.3", diff --git a/service/blog/blog.ts b/service/blog/blog.ts new file mode 100644 index 00000000..85f9bc16 --- /dev/null +++ b/service/blog/blog.ts @@ -0,0 +1,8 @@ +import { title } from "process"; +import { httpGetInterceptor } from "../http-config/http-interceptor-service"; + +export async function paginationBlog(size: number, page: number) { + return await httpGetInterceptor( + `blog/pagination?enablePage=1&page=${page}&size=${size}` + ); +} diff --git a/service/content/content-image.ts b/service/content/content-image.ts new file mode 100644 index 00000000..93f1f6b6 --- /dev/null +++ b/service/content/content-image.ts @@ -0,0 +1,19 @@ +import { httpGetInterceptor } from "../http-config/http-interceptor-service"; + +export async function listDataImage( + page: any, + limit: any, + isForSelf: any, + isApproval: any, + categoryFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any +) { + return await httpGetInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` + ); +} diff --git a/service/http-config/axios-base-instance.ts b/service/http-config/axios-base-instance.ts new file mode 100644 index 00000000..c1c8fb83 --- /dev/null +++ b/service/http-config/axios-base-instance.ts @@ -0,0 +1,12 @@ +import axios from "axios"; + +const baseURL = "https://netidhub.com/api/"; + +const axiosBaseInstance = axios.create({ + baseURL, + headers: { + "content-type": "application/json", + }, +}); + +export default axiosBaseInstance; diff --git a/service/http-config/axios-interceptor-instance.ts b/service/http-config/axios-interceptor-instance.ts new file mode 100644 index 00000000..09b7b146 --- /dev/null +++ b/service/http-config/axios-interceptor-instance.ts @@ -0,0 +1,56 @@ +import axios from "axios"; +import Cookies from "js-cookie"; +import { login } from "../login-services"; + +const baseURL = "https://netidhub.com/api/"; + +const refreshToken = Cookies.get("refresh_token"); + +const axiosInterceptorInstance = axios.create({ + baseURL, + headers: { + "content-type": "application/json", + }, +}); + +// Request interceptor +axiosInterceptorInstance.interceptors.request.use( + (config) => { + console.log("Config interceptor : ", config); + const accessToken = Cookies.get("access_token"); + if (accessToken) { + if (config.headers) + config.headers.Authorization = "Bearer " + accessToken; + } + return config; + }, + (error) => { + return Promise.reject(error); + } +); + +// Response interceptor +axiosInterceptorInstance.interceptors.response.use( + (response) => { + return response; + }, + async function (error) { + const originalRequest = error.config; + if (error.response.status === 401 && !originalRequest._retry) { + originalRequest._retry = true; + const data = { + refreshToken: refreshToken, + }; + const res = await login(data); + if (res.data?.data?.access_token) { + Cookies.set("access_token", res.data.data.access_token); + Cookies.set("refresh_token", res.data.data.refresh_token); + return axiosInterceptorInstance(originalRequest); + } + } + + return Promise.reject(error); + } +); + +export default axiosInterceptorInstance; diff --git a/service/http-config/http-base-service.ts b/service/http-config/http-base-service.ts new file mode 100644 index 00000000..3af62f08 --- /dev/null +++ b/service/http-config/http-base-service.ts @@ -0,0 +1,70 @@ +import axiosBaseInstance from "./axios-base-instance"; + +export async function httpPost(pathUrl: any, headers: any, data?: any) { + const response = await axiosBaseInstance + .post(pathUrl, data, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpGet(pathUrl: any, headers: any) { + const response = await axiosBaseInstance + .get(pathUrl, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpPut(pathUrl: any, headers: any, data?: any) { + const response = await axiosBaseInstance + .put(pathUrl, data, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} \ No newline at end of file diff --git a/service/http-config/http-interceptor-service.ts b/service/http-config/http-interceptor-service.ts new file mode 100644 index 00000000..1e990160 --- /dev/null +++ b/service/http-config/http-interceptor-service.ts @@ -0,0 +1,129 @@ +import { useRouter } from "next/navigation"; +import axiosInterceptorInstance from "./axios-interceptor-instance"; +import Cookies from "js-cookie"; + +export async function httpGetInterceptor(pathUrl: any) { + const response = await axiosInterceptorInstance + .get(pathUrl) + .catch((error) => error.response); + console.log("Response interceptor : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else if (response?.status == 401) { + Cookies.set("is_logout", "true"); + window.location.href = "/"; + return { + error: true, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpPostInterceptor( + pathUrl: any, + data: any, + headers?: any +) { + const response = await axiosInterceptorInstance + .post(pathUrl, data) + .catch((error) => error.response); + console.log("Response interceptor : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else if (response?.status == 401) { + Cookies.set("is_logout", "true"); + window.location.href = "/"; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpPutInterceptor( + pathUrl: any, + data: any, + headers?: any +) { + const response = await axiosInterceptorInstance + .put(pathUrl, data, { headers }) + .catch((error) => error.response); + console.log("Response interceptor : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else if (response?.status == 401) { + Cookies.set("is_logout", "true"); + window.location.href = "/"; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpDeleteInterceptor(pathUrl: any) { + const response = await axiosInterceptorInstance + .delete(pathUrl) + .catch((error) => error.response); + console.log("Response interceptor : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else if (response?.status == 401) { + Cookies.set("is_logout", "true"); + window.location.href = "/"; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} + +export async function httpGetInterceptorWithToken(pathUrl: any, headers?: any) { + const response = await axiosInterceptorInstance + .get(pathUrl, headers) + .catch((error) => error.response); + console.log("Response interceptor : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else if (response?.status == 401) { + Cookies.set("is_logout", "true"); + window.location.href = "/"; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} diff --git a/service/login-services.ts b/service/login-services.ts new file mode 100644 index 00000000..cd000b52 --- /dev/null +++ b/service/login-services.ts @@ -0,0 +1,17 @@ +import { httpGet, httpPost } from "./http-config/http-base-service"; +import { httpGetInterceptor, httpGetInterceptorWithToken } from "./http-config/http-interceptor-service"; + + +export async function login(data: any) { + const pathUrl = `users/login`; + const headers = { + "content-type": "application/json", + }; + return await httpPost(pathUrl, headers, data); +} + +export async function userInfo(token: any) { + const pathUrl = `users/info`; + return await httpGetInterceptorWithToken(pathUrl, token); +} + diff --git a/service/media.ts b/service/media.ts deleted file mode 100644 index 7d6ea790..00000000 --- a/service/media.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { - deleteAPIInterceptor, - getAPI, - getAPIInterceptor, - postAPIInterceptor, -} from "../config/api"; - -export async function listDataMedia( - page: any, - limit: any, - search: any, - categoryFilter: any, - statusFilter: any -) { - const name = search || ""; - const url = `media/list?isForAdmin=true&title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&categoryId=${categoryFilter}&statusId=${statusFilter}`; - return getAPIInterceptor({ url }); -} - -export async function listDataVideo( - isForSelf: any, - isApproval: any, - page: any, - limit: any, - search: any, - categoryFilter: any, - statusFilter: any, - needApprovalFromLevel: any, - creator: any, - source: any, - startDate: any, - endDate: any -) { - const name = search || ""; - const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=2&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}`; - return getAPIInterceptor({ url }); -} - -export async function listDataImage( - isForSelf: any, - isApproval: any, - page: any, - limit: any, - search: any, - categoryFilter: any, - statusFilter: any, - needApprovalFromLevel: any, - creator: any, - source: any, - startDate: any, - endDate: any -) { - const name = search || ""; - const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}`; - return getAPIInterceptor({ url }); -} - -export async function listDataAll( - isForSelf: any, - isApproval: any, - page: any, - limit: any, - search: any, - fileTypeFilter: any, - statusFilter: any, - startDate: any, - endDate: any, - needApprovalFromLevel: any -) { - const name = search || ""; - const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&isForSelf=${isForSelf}&isApproval=${isApproval}&typeId=${fileTypeFilter}&statusId=${statusFilter}&startDate=${ - startDate == undefined ? "" : startDate - }&endDate=${ - endDate == undefined ? "" : endDate - }&needApprovalFromLevel=${needApprovalFromLevel}`; - return getAPIInterceptor({ url }); -} diff --git a/service/planning/planning.ts b/service/planning/planning.ts new file mode 100644 index 00000000..8f1cde59 --- /dev/null +++ b/service/planning/planning.ts @@ -0,0 +1,11 @@ +import { httpGetInterceptor } from "../http-config/http-interceptor-service"; + +export async function getPlanningSentPagination( + size: number, + page: number, + typeId: number +) { + return await httpGetInterceptor( + `planning/pagination/sent?enablePage=1&size=${size}&page=${page}&typeId=${typeId}` + ); +} diff --git a/service/ppid-categories-services.ts b/service/ppid-categories-services.ts new file mode 100644 index 00000000..5af976a0 --- /dev/null +++ b/service/ppid-categories-services.ts @@ -0,0 +1,147 @@ +import { httpGet, httpPost } from "./http-config/http-base-service"; +import { + httpDeleteInterceptor, + httpGetInterceptor, + httpPostInterceptor, + httpPutInterceptor, +} from "./http-config/http-interceptor-service"; + +export async function getPublicListPpidData(categoryId: number) { + const headers = { + "content-type": "application/json", + }; + return await httpGet(`/ppid-datas?categoryId=${categoryId}`, headers); +} + +export async function getListCategories(size: number, page: number) { + return await httpGetInterceptor( + `/ppid-data-categories?page=${page}&size=${size}&isOnlyTop=true` + ); +} + +export async function listTask(size: number, page: number) { + return await httpGetInterceptor(`assignment/list?size=${size}&page=${page}`); +} + +export async function updateCategoryPosition(category: any) { + const pathUrl = `/ppid-data-categories/position`; + return await httpPostInterceptor(pathUrl, category); +} + +export async function getListSubCategories( + size: number, + page: number, + parentId: number +) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor( + `/ppid-data-categories?page=${page}&size=${size}&parentId=${parentId}` + ); +} + +export async function getPublicListCategoriesByParentId( + id: any, + limit: number, + levelGroup?: string +) { + const headers = { + "content-type": "application/json", + }; + return await httpGet( + `/ppid-data-categories?parentId=${id}&isPpidDataIncluded=true&sort=asc&sortBy=position&limit=${limit}${ + levelGroup ? `&levelGroup=${levelGroup}` : "" + }`, + headers + ); +} + +export async function getListCategoriesByParentId( + id: any, + limit: number, + levelGroup?: string +) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor( + `/ppid-data-categories?parentId=${id}&isPpidDataIncluded=true&sort=asc&sortBy=position&limit=${limit}${ + levelGroup ? `&levelGroup=${levelGroup}` : "" + }` + ); +} + +export async function getListCategoriesById(id: any) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor(`/ppid-data-categories/${id}`); +} + +export async function getListCategoriesBySlug(slug: any) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor(`/ppid-data-categories/slug/${slug}`); +} + +export async function getPublicListCategoriesBySlug(slug: any) { + const headers = { + "content-type": "application/json", + }; + return await httpGet(`/ppid-data-categories/slug/${slug}`, headers); +} + +export async function getList(categoryId: number) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor(`/ppid-datas?categoryId=1`); +} + +export async function createArticle(data: any) { + const pathUrl = `/articles`; + return await httpPostInterceptor(pathUrl, data); +} + +export async function createPublicCategory(request: any) { + const pathUrl = `/ppid-data-categories`; + return await httpPostInterceptor(pathUrl, request); +} + +export async function uploadPublicThumbnail(id: number, data: any) { + const headers = { + "Content-Type": "multipart/form-data", + }; + const pathUrl = `ppid-data-categories/thumbnail/${id}`; + return await httpPost(pathUrl, headers, data); +} + +export async function getPublicCategoryById(id: any) { + const headers = { + "content-type": "application/json", + }; + return await httpGetInterceptor(`/ppid-data-categories/${id}`); +} + +export async function updatePublicCategory(id: any, request: any) { + const headers = { + "content-type": "application/json", + }; + return await httpPutInterceptor(`/ppid-data-categories/${id}`, request); +} + +export async function deletePublicCategory(id: any) { + const headers = { + "content-type": "application/json", + }; + return await httpDeleteInterceptor(`/ppid-data-categories/${id}`); +} + +export async function getParentCategories() { + const headers = { + "content-type": "application/json", + }; + return await httpGet(`ppid-data-categories?isOnlyTop=true`, headers); +} diff --git a/service/task.ts b/service/task.ts new file mode 100644 index 00000000..28d4c863 --- /dev/null +++ b/service/task.ts @@ -0,0 +1,80 @@ +import { + deleteAPIInterceptor, + getAPIInterceptor, + postAPIInterceptor, +} from "../config/api"; + +export async function listTask(page: any, limit: any) { + const url = `assignment/list?enablePage=1&size=${limit}&page=${page}`; + return getAPIInterceptor({ url }); +} + +export async function getTask(id: any) { + const url = `/assignment?id=${id}`; + return getAPIInterceptor({ url }); +} + +export async function createTask(data: any) { + const url = "assignment"; + return postAPIInterceptor(url, data); // Perbaikan: Memisahkan parameter url dan data +} + +export async function forwardTask(data: any) { + const url = "assignment/forward"; + return postAPIInterceptor(url, data); +} + +export async function finishTask(id: any) { + const url = `assignment/finish?id=${id}`; + return postAPIInterceptor(url, id); +} + +export async function deleteTask(id: any) { + const url = `assignment?id=${id}`; + return deleteAPIInterceptor(url, id); +} + +export async function getUserLevelForAssignments() { + const url = "/users/user-levels/assignment"; + return getAPIInterceptor({ url }); +} + +export async function getAssignmentResponseList(id: any) { + const url = `assignment/response?assignmentId=${id}`; + return getAPIInterceptor({ url }); +} + +export async function createAssignmentResponse(data: any) { + const url = "assignment/response"; + return postAPIInterceptor(url, data); +} + +export async function deleteAssignmentResponse(id: any) { + const url = `assignment/response?id=${id}`; + return deleteAPIInterceptor(url, id); +} + +export async function getAcceptance(id: any, isAccept: any) { + const url = `assignment/acceptance?id=${id}&isAccept=${isAccept}`; + return getAPIInterceptor({ url }); +} + +export async function acceptAssignment(id: any, isAccept: any) { + const url = `assignment/acceptance?id=${id}`; + return postAPIInterceptor(url, id); +} + +export async function postFinishAcceptance(id: any) { + const url = `assignment/finish-acceptance?id=${id}`; + return postAPIInterceptor(url, id); +} + +export async function getAcceptanceAssignmentStatus(id: any) { + const url = `assignment/acceptance/status?id=${id}`; + return getAPIInterceptor({ url }); +} + +export async function getListAttachment(assignmentId: any, isForCreator: any) { + const url = `media/list?&enablePage=0&assignmentId=${assignmentId}&isForAdmin=${isForCreator}`; + return getAPIInterceptor({ url }); +} From 8edaedc9d5f80cdbbaa3bb4557cc70269aa2f2f0 Mon Sep 17 00:00:00 2001 From: Anang Yusman Date: Fri, 6 Dec 2024 00:02:06 +0700 Subject: [PATCH 2/3] feat: add form communication,form task, table communication,table contest --- .../collaboration/create/page.tsx | 16 + .../collabroation-table.tsx | 11 +- .../communication/internal/create/page.tsx | 15 + .../table-internal/internal-table.tsx | 79 ++++- .../contest/table-contest/contest-table.tsx | 72 ++++- .../task/table-task/task-table.tsx | 4 +- app/[locale]/auth/page.tsx | 42 ++- app/[locale]/page.tsx | 4 +- .../form/communication/collaboration-form.tsx | 296 ++++++++++++++++++ .../form/communication/internal-form.tsx | 291 +++++++++++++++++ components/form/task/task-form.tsx | 74 +++-- components/landing-page/Navbar.tsx | 236 +++++++++++--- components/landing-page/new-content.tsx | 282 ++++++++++++++--- lib/utils.ts | 40 +++ package-lock.json | 143 ++++++++- package.json | 3 +- public/assets/mediahub-logo.png | Bin 0 -> 339519 bytes public/assets/vector-login.svg | 103 ++++++ service/auth.ts | 94 ++++++ service/communication/communication.ts | 29 ++ service/contest/contest.ts | 15 + service/http-config/axiosCustom.ts | 17 + service/login-services.ts | 22 +- service/ppid-categories-services.ts | 4 - service/task.ts | 19 +- 25 files changed, 1723 insertions(+), 188 deletions(-) create mode 100644 app/[locale]/(protected)/communication/collaboration/create/page.tsx create mode 100644 app/[locale]/(protected)/communication/internal/create/page.tsx create mode 100644 components/form/communication/collaboration-form.tsx create mode 100644 components/form/communication/internal-form.tsx create mode 100644 public/assets/mediahub-logo.png create mode 100644 public/assets/vector-login.svg create mode 100644 service/auth.ts create mode 100644 service/communication/communication.ts create mode 100644 service/contest/contest.ts create mode 100644 service/http-config/axiosCustom.ts diff --git a/app/[locale]/(protected)/communication/collaboration/create/page.tsx b/app/[locale]/(protected)/communication/collaboration/create/page.tsx new file mode 100644 index 00000000..9c51de4c --- /dev/null +++ b/app/[locale]/(protected)/communication/collaboration/create/page.tsx @@ -0,0 +1,16 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormInternal from "@/components/form/communication/internal-form"; +import FormCollaboration from "@/components/form/communication/collaboration-form"; + +const CollaborationCreatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default CollaborationCreatePage; diff --git a/app/[locale]/(protected)/communication/collaboration/table-collaboration/collabroation-table.tsx b/app/[locale]/(protected)/communication/collaboration/table-collaboration/collabroation-table.tsx index b4ad7a59..cd87c78b 100644 --- a/app/[locale]/(protected)/communication/collaboration/table-collaboration/collabroation-table.tsx +++ b/app/[locale]/(protected)/communication/collaboration/table-collaboration/collabroation-table.tsx @@ -56,6 +56,7 @@ export type CompanyData = { import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { Link } from "@/components/navigation"; export const columns: ColumnDef[] = [ { @@ -181,10 +182,12 @@ const CollaborationTable = () => {
- + + +
diff --git a/app/[locale]/(protected)/communication/internal/create/page.tsx b/app/[locale]/(protected)/communication/internal/create/page.tsx new file mode 100644 index 00000000..ddb27415 --- /dev/null +++ b/app/[locale]/(protected)/communication/internal/create/page.tsx @@ -0,0 +1,15 @@ +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormInternal from "@/components/form/communication/internal-form"; + +const InternalCreatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default InternalCreatePage; diff --git a/app/[locale]/(protected)/communication/internal/table-internal/internal-table.tsx b/app/[locale]/(protected)/communication/internal/table-internal/internal-table.tsx index cee3ad8e..db7d14e3 100644 --- a/app/[locale]/(protected)/communication/internal/table-internal/internal-table.tsx +++ b/app/[locale]/(protected)/communication/internal/table-internal/internal-table.tsx @@ -47,16 +47,31 @@ import { } from "@/components/ui/dropdown-menu"; export type CompanyData = { + no: number; title: string; - createBy: string; - sendTo: string; - date: string; + commentFromUserName: string; + commentToUserName: string; + createdAt: string; }; -import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { listTicketingInternal } from "@/service/communication/communication"; +import { Link } from "@/components/navigation"; export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, { accessorKey: "title", header: "Pertanyaan", @@ -71,24 +86,28 @@ export const columns: ColumnDef[] = [ ), }, { - accessorKey: "createBy", + accessorKey: "commentFromUserName", header: "Pengirim ", cell: ({ row }) => ( - {row.getValue("createBy")} + + {row.getValue("commentFromUserName")} + ), }, { - accessorKey: "sendTo", + accessorKey: "commentToUserName", header: "Penerima", cell: ({ row }) => ( - {row.getValue("sendTo")} + + {row.getValue("commentToUserName")} + ), }, { - accessorKey: "date", + accessorKey: "createdAt", header: "Waktu ", cell: ({ row }) => ( - {row.getValue("date")} + {row.getValue("createdAt")} ), }, { @@ -129,6 +148,7 @@ export const columns: ColumnDef[] = [ ]; const InternalTable = () => { + const [internalTable, setInternalTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -140,9 +160,12 @@ const InternalTable = () => { pageIndex: 0, pageSize: 6, }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); const table = useReactTable({ - data, + data: internalTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -162,15 +185,41 @@ const InternalTable = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await listTicketingInternal(page); + + const data = res.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, + title: item.title, + commentFromUserName: item.commentFromUserName, + commentToUserName: item.commentToUserName, + createdAt: item.createdAt, + })); + + setInternalTable(data); + setTotalPage(res.data.totalPages); + console.log(res?.data?.data); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
- + + +
diff --git a/app/[locale]/(protected)/contest/table-contest/contest-table.tsx b/app/[locale]/(protected)/contest/table-contest/contest-table.tsx index 20ef7936..69d672fc 100644 --- a/app/[locale]/(protected)/contest/table-contest/contest-table.tsx +++ b/app/[locale]/(protected)/contest/table-contest/contest-table.tsx @@ -46,20 +46,36 @@ import { } from "@/components/ui/dropdown-menu"; export type CompanyData = { - code: string; - title: string; + no: number; + hastagCode: string; + theme: string; duration: string; targetOutput: string; - targetParticipant: string; - status: string; + targetParticipantTopLevel: string; + isPublishForAll: string; }; import { data } from "./data"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { listTask } from "@/service/task"; +import { listContest } from "@/service/contest/contest"; export const columns: ColumnDef[] = [ { - accessorKey: "code", + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, + { + accessorKey: "hastagCode", header: "Kode", cell: ({ row }) => (
@@ -68,20 +84,20 @@ export const columns: ColumnDef[] = [ className="text-sm font-bold text-default-600 whitespace-nowrap mb-1" > - {row.getValue("code")} + {row.getValue("hastagCode")}
), }, { - accessorKey: "title", + accessorKey: "theme", header: "Judul", cell: ({ row }) => (

- {row.getValue("title")} + {row.getValue("theme")}

@@ -96,27 +112,27 @@ export const columns: ColumnDef[] = [ }, { accessorKey: "targetOutput", - header: "Tanggal Unggah ", + header: "Target Output ", cell: ({ row }) => ( {row.getValue("targetOutput")} ), }, { - accessorKey: "targetParticipant", + accessorKey: "targetParticipantTopLevel", header: "Tag ", cell: ({ row }) => ( - {row.getValue("targetParticipant")} + {row.getValue("targetParticipantTopLevel")} ), }, { - accessorKey: "status", + accessorKey: "isPublishForAll", header: "Status", cell: ({ row }) => { return ( - {row.getValue("status")} + {row.getValue("isPublishForAll")} ); }, @@ -159,6 +175,7 @@ export const columns: ColumnDef[] = [ ]; const ContestTable = () => { + const [contestTable, setContestTable] = React.useState([]); const [sorting, setSorting] = React.useState([]); const [columnFilters, setColumnFilters] = React.useState( [] @@ -170,9 +187,12 @@ const ContestTable = () => { pageIndex: 0, pageSize: 6, }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); const table = useReactTable({ - data, + data: contestTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -192,6 +212,30 @@ const ContestTable = () => { }, }); + React.useEffect(() => { + initState(); + }, [page, limit]); + + async function initState() { + try { + const res = await listContest(limit, page); + const data = res.data.data.content.map((item: any, index: number) => ({ + no: (page - 1) * limit + index + 1, + hastagCode: item.hastagCode, + theme: item.theme, + targetOutput: item.targetOutput, + targetParticipantTopLevel: item.targetParticipantTopLevel, + duration: item.duration, + isDone: item.isDone, + })); + + setContestTable(data); + setTotalPage(res.data.totalPages); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + return (
diff --git a/app/[locale]/(protected)/task/table-task/task-table.tsx b/app/[locale]/(protected)/task/table-task/task-table.tsx index 80646b0d..030651cc 100644 --- a/app/[locale]/(protected)/task/table-task/task-table.tsx +++ b/app/[locale]/(protected)/task/table-task/task-table.tsx @@ -47,10 +47,10 @@ import { import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; import { Link } from "@/components/navigation"; -import { listTask } from "@/service/ppid-categories-services"; import { title } from "process"; import search from "../../app/chat/components/search"; import { format } from "date-fns"; +import { listTask } from "@/service/task"; export type CompanyData = { no: number; @@ -202,7 +202,7 @@ const TaskTable = () => { }); const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); - const [limit, setLimit] = React.useState(10); + const [limit, setLimit] = React.useState(100); const [search, setSearch] = React.useState(title); const table = useReactTable({ diff --git a/app/[locale]/auth/page.tsx b/app/[locale]/auth/page.tsx index 091105ab..2d70506e 100644 --- a/app/[locale]/auth/page.tsx +++ b/app/[locale]/auth/page.tsx @@ -22,17 +22,25 @@ const Login = ({ params: { locale } }: { params: { locale: string } }) => { className="lg:block hidden flex-1 overflow-hidden text-[40px] leading-[48px] text-default-600 relative z-[1] bg-default-50" > -
+
- + -

- Unlock your Project - performance -

- +
@@ -43,20 +51,30 @@ const Login = ({ params: { locale } }: { params: { locale: string } }) => {
-
-

Sign in

-
Sign in to your account to start using Dashcode
+
+

+ Silahkan Masuk Ke akun anda terlebih dahulu +

+
+ Belum punya akun?{" "} + registrasi +
-
Or continue with
+
+ Or continue with +
Don’t have an account?{" "} - + Sign up
diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 8a025143..f9ea7d30 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -1,19 +1,17 @@ "use client"; - import SearchSection from "@/components/landing-page/SearchSection"; import NewContent from "@/components/landing-page/new-content"; import PopularContent from "@/components/landing-page/popular-content"; import ContentCategory from "@/components/landing-page/content-category"; import Coverage from "@/components/landing-page/coverage"; import Navbar from "@/components/landing-page/navbar"; -import Hero from "@/components/landing-page/hero"; +import Hero from "@/components/landing-page/Hero"; import Footer from "@/components/landing-page/footer"; const Home = ({ params: { locale } }: { params: { locale: string } }) => { return ( <> - diff --git a/components/form/communication/collaboration-form.tsx b/components/form/communication/collaboration-form.tsx new file mode 100644 index 00000000..768e9cca --- /dev/null +++ b/components/form/communication/collaboration-form.tsx @@ -0,0 +1,296 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useRouter } from "next/navigation"; + +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { type } from "os"; +import loading from "@/app/[locale]/(protected)/app/projects/loading"; +import { request } from "http"; +import { error } from "@/lib/utils"; +import { createTask } from "@/service/task"; +import { options } from "@fullcalendar/core/preact.js"; +import { setOptions } from "leaflet"; +import { + getCuratorUser, + getTicketingPriority, + saveTicketing, + saveTicketingInternal, +} from "@/service/communication/communication"; +import makeAnimated from "react-select/animated"; +import Select from "react-select"; +import { + SelectTrigger, + SelectValue, + SelectContent, + SelectItem, +} from "@radix-ui/react-select"; +import { SelectGroup } from "@/components/ui/select"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +interface Option { + id: string; + label: string; + value: string; + fullname: string; + userLevel: string; + userLevelId: string; +} + +export default function FormCollaboration() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + + // State for various form fields + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + + const [assignmentType, setAssignmentType] = useState("mediahub"); + const [assignmentCategory, setAssignmentCategory] = useState("publication"); + const [mainType, setMainType] = useState(1); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [options, setOptions] = useState([]); + const [ticketPriority, setTicketPriority] = useState([]); + const [selectedOption, setSelectedOption] = useState
); }; diff --git a/app/[locale]/(protected)/content/teks/table-teks/index.tsx b/app/[locale]/(protected)/content/teks/table-teks/index.tsx index a2b1e4cc..02823c01 100644 --- a/app/[locale]/(protected)/content/teks/table-teks/index.tsx +++ b/app/[locale]/(protected)/content/teks/table-teks/index.tsx @@ -2,7 +2,9 @@ import * as React from "react"; import { + ColumnDef, ColumnFiltersState, + PaginationState, SortingState, VisibilityState, flexRender, @@ -12,7 +14,6 @@ import { getSortedRowModel, useReactTable, } from "@tanstack/react-table"; -import { columns } from "./columns"; import { Input } from "@/components/ui/input"; import { @@ -26,6 +27,175 @@ import { import { data } from "./data"; import TablePagination from "./table-pagination"; +import { Button } from "@/components/ui/button"; +import { format } from "date-fns"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + ChevronLeft, + ChevronRight, + Eye, + MoreVertical, + Trash2, +} from "lucide-react"; +import { title } from "process"; + +import { getCookiesDecrypt } from "@/lib/utils"; +import { listDataImage, listDataTeks } from "@/service/content/content"; +import page from "../page"; + +export type CompanyData = { + no: number; + title: string; + categoryName: string; + createdAt: string; + creatorGroup: string; + publishedOn: string; + isPublish: any; + isPublishOnPolda: any; + isDone: string; +}; + +export const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, + { + accessorKey: "title", + header: "Judul", + cell: ({ row }) => ( +
+
+

+ {row.getValue("title")} +

+
+
+ ), + }, + { + accessorKey: "categoryName", + header: "Kategori", + cell: ({ row }) => ( + {row.getValue("categoryName")} + ), + }, + { + accessorKey: "createdAt", + header: "Tanggal Unggah", + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, + }, + { + accessorKey: "creatorGroup", + header: "Sumber ", + cell: ({ row }) => ( + {row.getValue("creatorGroup")} + ), + }, + { + accessorKey: "publishedOn", + header: "Penempatan File", + cell: ({ row }) => { + const isPublish = row.original.isPublish; + const isPublishOnPolda = row.original.isPublishOnPolda; + + let displayText = "-"; + if (isPublish && !isPublishOnPolda) { + displayText = "Mabes"; + } else if (isPublish && isPublishOnPolda) { + displayText = "Mabes & Polda"; + } else if (!isPublish && isPublishOnPolda) { + displayText = "Polda"; + } + + return ( +
+ {displayText} +
+ ); + }, + }, + + { + accessorKey: "isDone", + header: "Status", + cell: ({ row }) => { + const isDone = row.getValue("isDone"); + return ( +
+ +
+ ); + }, + }, + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + return ( + + + + + + + + + View + + + + + Delete + + + + ); + }, + }, +]; const TableTeks = () => { const [sorting, setSorting] = React.useState([]); @@ -35,9 +205,29 @@ const TableTeks = () => { const [columnVisibility, setColumnVisibility] = React.useState({}); const [rowSelection, setRowSelection] = React.useState({}); + const [imageTable, setImageTable] = React.useState([]); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, // Halaman pertama + pageSize: 10, // Jumlah baris per halaman + }); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); // Jumlah baris per halaman + const [search, setSearch] = React.useState(""); + const userId = getCookiesDecrypt("uie"); + const userLevelId = getCookiesDecrypt("ulie"); + + const [categories, setCategories] = React.useState(); + const [categoryFilter, setCategoryFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); + const [startDateString, setStartDateString] = React.useState(""); + const [endDateString, setEndDateString] = React.useState(""); + const [filterByCreator, setFilterByCreator] = React.useState(""); + const [filterBySource, setFilterBySource] = React.useState(""); + + const roleId = getCookiesDecrypt("urie"); const table = useReactTable({ - data, + data: imageTable, columns, onSortingChange: setSorting, onColumnFiltersChange: setColumnFilters, @@ -55,6 +245,59 @@ const TableTeks = () => { }, }); + React.useEffect(() => { + initState(); + }, [limit]); + + async function initState() { + try { + const isForSelf = Number(roleId) === 4; + const res = await listDataTeks( + pagination.pageSize, // Ambil nilai dari pagination.pageSize + pagination.pageIndex + 1, // API sering menggunakan page 1-based + isForSelf, + !isForSelf, + categoryFilter?.sort().join(","), + statusFilter?.sort().join(",").includes("1") + ? "1,2" + : statusFilter?.sort().join(","), + statusFilter?.sort().join(",").includes("1") ? userLevelId : "", + filterByCreator, + filterBySource, + startDateString, + endDateString + ); + + setupData(res.data?.data); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + function setupData(rawData: { + content: any[]; + totalPages: number; + totalElements: number; + }) { + if (rawData?.content) { + const data: CompanyData[] = rawData.content.map((item, index) => ({ + no: pagination.pageIndex * pagination.pageSize + index + 1, + title: item.title, + categoryName: item.categoryName, + creatorGroup: item.creatorGroup, + createdAt: item.createdAt, + isDone: item.isDone, + publishedOn: item.publishedOn, + isPublish: item.isPublish, + isPublishOnPolda: item.isPublishOnPolda, + })); + + setImageTable(data); + setTotalPage(rawData.totalPages); + console.log(data, "dataImage"); + } + } + return (
@@ -72,22 +315,20 @@ const TableTeks = () => {
- +
{table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ); - })} + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} ))} @@ -97,6 +338,7 @@ const TableTeks = () => { {row.getVisibleCells().map((cell) => ( @@ -114,7 +356,41 @@ const TableTeks = () => { )}
- +
+ + {table.getPageOptions().map((page, pageIndex) => ( + + ))} + +
); }; diff --git a/app/[locale]/(protected)/task/page.tsx b/app/[locale]/(protected)/task/page.tsx index 7b62e7dd..5be51476 100644 --- a/app/[locale]/(protected)/task/page.tsx +++ b/app/[locale]/(protected)/task/page.tsx @@ -1,11 +1,23 @@ +"use client"; import { Card, CardContent } from "@/components/ui/card"; import TaskTable from "./table-task/task-table"; import { Button } from "@/components/ui/button"; import { UploadIcon } from "lucide-react"; import SiteBreadcrumb from "@/components/site-breadcrumb"; import { Link } from "@/components/navigation"; +import { checkAuthorization, checkLoginSession } from "@/lib/utils"; +import React, { useEffect } from "react"; + +const TaskPage = () => { + useEffect(() => { + function initState() { + checkAuthorization("admin"); // Specify the page, e.g., "admin" or another value + checkLoginSession(); + } + + initState(); + }, []); -const TaskPage = async () => { return (
diff --git a/app/[locale]/(protected)/task/table-task/task-table.tsx b/app/[locale]/(protected)/task/table-task/task-table.tsx index 030651cc..d4593b2a 100644 --- a/app/[locale]/(protected)/task/table-task/task-table.tsx +++ b/app/[locale]/(protected)/task/table-task/task-table.tsx @@ -51,6 +51,13 @@ import { title } from "process"; import search from "../../app/chat/components/search"; import { format } from "date-fns"; import { listTask } from "@/service/task"; +import { getCookiesDecrypt } from "@/lib/utils"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, +} from "@/components/ui/select"; export type CompanyData = { no: number; @@ -202,9 +209,13 @@ const TaskTable = () => { }); const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); - const [limit, setLimit] = React.useState(100); + const [limit, setLimit] = React.useState(10); const [search, setSearch] = React.useState(title); + const userId = getCookiesDecrypt("uie"); + const userLevelNumber = getCookiesDecrypt("ulne"); + const userRoleId = getCookiesDecrypt("urie"); + const table = useReactTable({ data: taskTable, columns, @@ -261,6 +272,18 @@ const TaskTable = () => { />
+
+ {/* */} +
{ @@ -8,10 +13,15 @@ const SearchSection = () => {
{/* Heading */}

- Eksplorasi dan Download Liputan Resmi Kami + Eksplorasiii{" "} + dan Download{" "} + Liputan Resmi Kami

-

Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda seluruh Indonesia

+

+ Liputan resmi yang bersumber dari kegiatan Polri di Mabes dan Polda + seluruh Indonesia +

{/* Search Form */}
@@ -20,19 +30,39 @@ const SearchSection = () => { - + Konten - - + + - + @@ -64,18 +94,29 @@ const SearchSection = () => { {/* Search Input */}
- + - +
{/* Button */} - +
diff --git a/components/partials/auth/login-form.tsx b/components/partials/auth/login-form.tsx index 5e8f39aa..37ff1abc 100644 --- a/components/partials/auth/login-form.tsx +++ b/components/partials/auth/login-form.tsx @@ -4,65 +4,184 @@ import { Button } from "@/components/ui/button"; import { Checkbox } from "@/components/ui/checkbox"; import { Input } from "@/components/ui/input"; import { Label } from "@/components/ui/label"; -import { Link } from "@/i18n/routing"; +import Cookies from "js-cookie"; import { Icon } from "@/components/ui/icon"; import { useForm, SubmitHandler } from "react-hook-form"; import { zodResolver } from "@hookform/resolvers/zod"; import { z } from "zod"; -import { cn } from "@/lib/utils"; +import { cn, setCookiesEncrypt } from "@/lib/utils"; import { Loader2 } from "lucide-react"; -import { loginUser } from "@/action/auth-action"; +import { getProfile, setLogin } from "@/service/auth"; import { toast } from "sonner"; -import { useRouter } from "@/components/navigation"; +import { Link, useRouter } from "@/components/navigation"; +import { warning } from "@/lib/swal"; +// Schema validasi menggunakan zod const schema = z.object({ - email: z.string().email({ message: "Your email is invalid." }), - password: z.string().min(4), + username: z.string().min(1, { message: "Judul diperlukan" }), + password: z + .string() + .min(4, { message: "Password must be at least 4 characters." }), }); + +// Tipe untuk form values +type LoginFormValues = { + username: string; + password: string; +}; + const LoginForm = () => { const [isPending, startTransition] = React.useTransition(); const router = useRouter(); const [passwordType, setPasswordType] = React.useState("password"); const togglePasswordType = () => { - if (passwordType === "text") { - setPasswordType("password"); - } else if (passwordType === "password") { - setPasswordType("text"); - } + setPasswordType((prevType) => + prevType === "password" ? "text" : "password" + ); }; + const { register, handleSubmit, - reset, formState: { errors }, - } = useForm({ + } = useForm({ resolver: zodResolver(schema), mode: "all", - defaultValues: { - email: "dashcode@codeshaper.net", - password: "password", - }, }); - const [isVisible, setIsVisible] = React.useState(false); - const toggleVisibility = () => setIsVisible(!isVisible); - - const onSubmit = (data: z.infer) => { + // Fungsi submit form + const onSubmit: SubmitHandler = async (data) => { startTransition(async () => { try { - const response = await loginUser(data); + const response = await setLogin({ + ...data, + grant_type: "password", + client_id: "mediahub-app", + }); - if (!!response.error) { - toast("Event has been created", { - description: "Sunday, December 03, 2023 at 9:00 AM", - }); + if (response.error) { + toast.error("Username / Password Tidak Sesuai"); } else { - router.push("/dashboard"); - toast.success("Successfully logged in"); + const { access_token } = response.data; + const { refresh_token } = response.data; + const dateTime = new Date(); + const newTime = dateTime.getTime() + 10 * 60 * 1000; + + Cookies.set("access_token", access_token, { + expires: 1, + }); + Cookies.set("refresh_token", refresh_token, { + expires: 1, + }); + Cookies.set("time_refresh", new Date(newTime).toISOString(), { + expires: 1, + }); + + Cookies.set("is_first_login", String(true), { + secure: true, + sameSite: "strict", + }); + const profile = await getProfile(access_token); + console.log("PROFILE : ", profile?.data?.data); + + if ( + profile?.data?.data?.isInternational == true || + profile?.data?.data?.isActive == false || + profile?.data?.data?.isDelete == true + ) { + Object.keys(Cookies.get()).forEach((cookieName) => { + Cookies.remove(cookieName); + }); + warning( + "Akun Anda tidak dapat digunakan untuk masuk ke MediaHub Polri", + "/auth/login" + ); + } else { + Cookies.set("home_path", profile.data?.data?.homePath, { + expires: 1, + }); + Cookies.set( + "profile_picture", + profile.data?.data?.profilePictureUrl, + { + expires: 1, + } + ); + Cookies.set("state", profile.data?.data?.userLevel?.name, { + expires: 1, + }); + setCookiesEncrypt("uie", profile.data.data?.id, { + expires: 1, + }); + setCookiesEncrypt("urie", profile.data.data?.roleId, { + expires: 1, + }); + setCookiesEncrypt("urne", profile.data.data?.role?.name, { + expires: 1, + }); + setCookiesEncrypt("ulie", profile.data.data?.userLevel?.id, { + expires: 1, + }); + setCookiesEncrypt( + "ulplie", + profile.data.data?.userLevel?.parentLevelId, + { + expires: 1, + } + ); + setCookiesEncrypt( + "ulne", + profile.data.data?.userLevel?.levelNumber, + { + expires: 1, + } + ); + setCookiesEncrypt("ufne", profile.data.data?.fullname, { + expires: 1, + }); + setCookiesEncrypt("ulnae", profile.data.data?.userLevel?.name, { + expires: 1, + }); + setCookiesEncrypt("uinse", profile.data.data?.instituteId, { + expires: 1, + }); + + if ( + Number(profile.data.data?.roleId) == 2 || + Number(profile.data.data?.roleId) == 3 || + Number(profile.data.data?.roleId) == 4 || + Number(profile.data.data?.roleId) == 9 || + Number(profile.data.data?.roleId) == 10 || + Number(profile.data.data?.roleId) == 11 || + Number(profile.data.data?.roleId) == 12 + ) { + if ( + profile.data.data?.userLevel?.id == 761 || + profile.data.data?.userLevel?.parentLevelId == 761 + ) { + window.location.href = "/admin/welcome"; + // router.push('/admin/dashboard'); + Cookies.set("status", "login", { + expires: 1, + }); + } else { + window.location.href = "/en/dashboard"; + // router.push('/admin/dashboard'); + Cookies.set("status", "login", { + expires: 1, + }); + } + } else { + window.location.href = "/"; + Cookies.set("status", "login", { + expires: 1, + }); + } + } } } catch (err: any) { - toast.error(err.message); + toast.error(err.message || "An unexpected error occurred."); } }); }; @@ -70,41 +189,39 @@ const LoginForm = () => { return (
-
- {errors.email && ( -
- {errors.email.message} -
- )}
-
{ )}
+ {errors.password?.message && ( +
+ {errors.password.message} +
+ )}
- {errors.password && ( -
- {errors.password.message} -
- )}
@@ -145,4 +262,5 @@ const LoginForm = () => { ); }; + export default LoginForm; diff --git a/config/api.ts b/config/api.ts index 1e2317f1..318ee032 100644 --- a/config/api.ts +++ b/config/api.ts @@ -123,7 +123,6 @@ export async function getAPIInterceptor(url: any) { data: null, }; } - // Fungsi postAPIInterceptor export async function postAPIInterceptor(url: string, data: any) { const response = await axiosInterceptor diff --git a/lib/swal.ts b/lib/swal.ts new file mode 100644 index 00000000..965be403 --- /dev/null +++ b/lib/swal.ts @@ -0,0 +1,92 @@ +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; + +const MySwal = withReactContent(Swal); + +const Toast = MySwal.mixin({ + toast: true, + position: "top-end", + showConfirmButton: false, + timer: 3000, + timerProgressBar: true, + didOpen: (toast) => { + toast.addEventListener("mouseenter", Swal.stopTimer); + toast.addEventListener("mouseleave", Swal.resumeTimer); + }, +}); + +export function loading(msg?: any) { + let timerInterval: any; + MySwal.fire({ + title: msg || "Loading...", + allowOutsideClick: false, + timerProgressBar: true, + didOpen: () => { + MySwal.showLoading(); + timerInterval = setInterval(() => {}, 100); + }, + willClose: () => { + clearInterval(timerInterval); + }, + }); +} + +export function error(msg?: any) { + MySwal.fire({ + icon: "error", + title: "Failed...", + text: msg || "Unknown Error", + }); +} + +export function successRouter(redirect: string, router?: any) { + MySwal.fire({ + title: "Success!", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "Ok", + allowOutsideClick: false, + }).then((result) => { + if (result.isConfirmed) { + router.push(redirect); + } + }); +} + +export function success(title: string) { + MySwal.fire({ + title: title || "Success!", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + return true; + } + }); +} + +export function close() { + MySwal.close(); +} + +export function warning(text: string, redirect: string, router?: any) { + MySwal.fire({ + title: text, + icon: "warning", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then((result) => { + if (result.isConfirmed) { + router.push(redirect); + } + }); +} + +export function successToast(title: string, text: string) { + Toast.fire({ + icon: "error", + title: title, + text: text, + }); +} diff --git a/lib/utils.ts b/lib/utils.ts index ab1b1953..23fd63c4 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -36,6 +36,47 @@ export const hexToRGB = (hex: any, alpha?: number): any => { } }; +export function getCookiesDecrypt(param: any) { + const cookiesEncrypt = Cookies.get(param); + try { + if (cookiesEncrypt != undefined) { + const output = CryptoJS.AES.decrypt( + cookiesEncrypt.toString(), + `${param}_EncryptKey@mediahub` + ).toString(CryptoJS.enc.Utf8); + if (output.startsWith('"')) { + return output.slice(1, -1); + } + return output; + } + } catch (e) { + console.log("Error", cookiesEncrypt); + } +} + +export function successToast(title: string, text: string) { + Toast.fire({ + icon: "error", + title: title, + text: text, + }); +} + +export function setCookiesEncrypt( + param: string, + data: any, + options?: Cookies.CookieAttributes +) { + // Enkripsi data + const cookiesEncrypt = CryptoJS.AES.encrypt( + JSON.stringify(data), + `${param}_EncryptKey@mediahub` + ).toString(); // Tambahkan .toString() di sini + + // Simpan data terenkripsi di cookie + Cookies.set(param, cookiesEncrypt, options); +} + export function checkAuthorization(page: any) { const roleId = getCookiesDecrypt("urie"); const levelNumber = getCookiesDecrypt("ulne"); @@ -64,44 +105,3 @@ export function checkLoginSession() { }; // doCheckSession(data); } - -export function getCookiesDecrypt(param: any) { - const cookiesEncrypt = Cookies.get(param); - try { - if (cookiesEncrypt != undefined) { - const output = CryptoJS.AES.decrypt( - cookiesEncrypt.toString(), - `${param}_EncryptKey@mediahub` - ).toString(CryptoJS.enc.Utf8); - if (output.startsWith('"')) { - return output.slice(1, -1); - } - return output; - } - } catch (e) { - console.log("Error", cookiesEncrypt); - } -} - -export function successToast(title: string, text: string) { - Toast.fire({ - icon: "error", - title: title, - text: text, - }); -} - -export function setCookiesEncrypt(param: any, data: any) { - // Enkripsi data - const cookiesEncrypt = CryptoJS.AES.encrypt( - JSON.stringify(data), - `${param}_EncryptKey@mediahub` - ).toString(); // Tambahkan .toString() di sini - - // Simpan data terenkripsi di cookie - Cookies.set(param, cookiesEncrypt, { expires: 1 }); -} - -export function error(msg: any) { - MySwal.fire("Gagal", msg, "error"); -} diff --git a/service/auth.ts b/service/auth.ts index 952742d9..aec9b966 100644 --- a/service/auth.ts +++ b/service/auth.ts @@ -3,92 +3,30 @@ import Cookies from "js-cookie"; import { getAPI, postAPI, postAPIWithJson } from "../config/api"; import { getAPIDummy } from "./http-config/axiosCustom"; -export async function setLogin(data) { - const url = "signin"; - return postAPI({ url, data }); +import { + httpGetInterceptorWithToken, + httpPostInterceptor, +} from "./http-config/http-interceptor-service"; + +export async function setLogin(data: any) { + const pathUrl = "signin"; + return postAPI(pathUrl, data); } -export async function getProfile(token) { +export async function getProfile(token: any) { const url = "users/info"; - return getAPI({ url, token }); + return getAPI(url, token); } -export async function saveSession(data) { - const url = "users/save-session"; - return postAPIWithJson({ url, data }); -} +// export async function setLogin(data: any) { +// const pathUrl = `signin`; +// const headers = { +// "content-type": "application/json", +// }; +// return await httpPost(pathUrl, headers, data); +// } -export async function checkSession(data) { - const url = "users/check-session"; - return postAPIWithJson({ url, data }); -} - -export async function listProvince() { - const url = "public/users/provinces"; - return getAPI({ url }); -} - -export async function listCity(id) { - const url = `public/users/cities?provId=${id}`; - return getAPI({ url }); -} - -export async function listDistricts(id) { - const url = `public/users/districts?cityId=${id}`; - return getAPI({ url }); -} - -export async function listInstitusi(roleId) { - const url = `public/users/institutes?categoryRoleId=${roleId}`; - return getAPI({ url }); -} - -export async function listRole() { - const url = "public/users/roles"; - return getAPI({ url }); -} - -export async function refreshToken() { - const url = "signin"; - const data = { - grant_type: "refresh_token", - client_id: "mediahub-app", - refresh_token: Cookies.get("refresh_token"), - }; - return postAPI({ url, data }); -} - -export async function postRegistration(data) { - const url = "public/users/save"; - return postAPIWithJson({ url, data }); -} - -export async function saveInstitutes(data) { - const url = "public/users/save-institutes"; - return postAPIWithJson({ url, data }); -} - -export async function forgotPassword(username) { - const url = `forgot-password?username=${username}`; - return postAPIWithJson({ url }); -} - -export async function getDataByNIK(reqid, nik) { - const url = `http://spitpolri.com/api/back_end/get_ktp?reqid=${reqid}&nik=${nik}`; - return getAPIDummy({ url }); -} - -export async function getDataByNRP(reqid, nrp) { - const url = `http://spitpolri.com/api/back_end/get_nrp?reqid=${reqid}&nrp=${nrp}`; - return getAPIDummy({ url }); -} - -export async function getDataJournalist(cert) { - const url = `public/users/search-journalist?cert=${cert}`; - return getAPI({ url }); -} - -export async function getDataPersonil(nrp) { - const url = `public/users/search-personil?nrp=${nrp}`; - return getAPI({ url }); +export async function userInfo(token: any) { + const pathUrl = `users/info`; + return await httpGetInterceptorWithToken(pathUrl, token); } diff --git a/service/content/content-image.ts b/service/content/content-image.ts deleted file mode 100644 index 93f1f6b6..00000000 --- a/service/content/content-image.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { httpGetInterceptor } from "../http-config/http-interceptor-service"; - -export async function listDataImage( - page: any, - limit: any, - isForSelf: any, - isApproval: any, - categoryFilter: any, - statusFilter: any, - needApprovalFromLevel: any, - creator: any, - source: any, - startDate: any, - endDate: any -) { - return await httpGetInterceptor( - `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` - ); -} diff --git a/service/content/content.ts b/service/content/content.ts new file mode 100644 index 00000000..c218a2cb --- /dev/null +++ b/service/content/content.ts @@ -0,0 +1,85 @@ +import { getAPIInterceptor } from "@/config/api"; +import { httpGetInterceptor } from "../http-config/http-interceptor-service"; + +export async function listDataImage( + page: any, + limit: any, + isForSelf: any, + isApproval: any, + categoryFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any +) { + return await httpGetInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=1&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` + ); +} + +export async function listDataVideo( + page: any, + limit: any, + isForSelf: any, + isApproval: any, + categoryFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any +) { + return await httpGetInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=2&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` + ); +} + +export async function listDataTeks( + page: any, + limit: any, + isForSelf: any, + isApproval: any, + categoryFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any +) { + return await httpGetInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=3&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` + ); +} + +export async function listDataAudio( + page: any, + limit: any, + isForSelf: any, + isApproval: any, + categoryFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any +) { + return await httpGetInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&typeId=4&isForSelf=${isForSelf}&isApproval=${isApproval}&categoryId=${categoryFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&creatorUserLevelName=${source}&creatorName=${creator}&startDate=${startDate}&endDate=${endDate}` + ); +} + +export async function listSPIT( + page: any, + limit: any, + title = "", + isPublish: any +) { + return await httpGetInterceptor( + `media/spit/pagination?enablePage=1&page=${page}&size=${limit}&sort=desc&sortBy=contentTitleId&title=${title}&isPublish=${isPublish}` + ); +} diff --git a/service/http-config/axios-interceptor-instance.ts b/service/http-config/axios-interceptor-instance.ts index 09b7b146..51fcb1e9 100644 --- a/service/http-config/axios-interceptor-instance.ts +++ b/service/http-config/axios-interceptor-instance.ts @@ -40,6 +40,8 @@ axiosInterceptorInstance.interceptors.response.use( originalRequest._retry = true; const data = { refreshToken: refreshToken, + grant_type: "refresh_token", + client_id: "mediahub-app", }; const res = await login(data); if (res.data?.data?.access_token) { diff --git a/service/http-config/http-base-service.ts b/service/http-config/http-base-service.ts index 3af62f08..d1f22381 100644 --- a/service/http-config/http-base-service.ts +++ b/service/http-config/http-base-service.ts @@ -1,70 +1,100 @@ +import axiosInstance from "@/config/axiosInstance"; import axiosBaseInstance from "./axios-base-instance"; +import axios from "axios"; +import Cookies from "js-cookie"; +import qs from "qs"; -export async function httpPost(pathUrl: any, headers: any, data?: any) { - const response = await axiosBaseInstance - .post(pathUrl, data, { headers }) - .catch(function (error: any) { - console.log(error); - return error.response; - }); - console.log("Response base svc : ", response); - if (response?.status == 200 || response?.status == 201) { - return { - error: false, - message: "success", - data: response?.data, - }; - } else { - return { - error: true, - message: response?.data?.message || response?.data || null, - data: null, - }; - } +// export async function httpPost(pathUrl: any, headers: any, data?: any) { +// const response = await axiosBaseInstance +// .post(pathUrl, data, { headers }) +// .catch(function (error: any) { +// console.log(error); +// return error.response; +// }); +// console.log("Response base svc : ", response); +// if (response?.status == 200 || response?.status == 201) { +// return { +// error: false, +// message: "success", +// data: response?.data, +// }; +// } else { +// return { +// error: true, +// message: response?.data?.message || response?.data || null, +// data: null, +// }; +// } +// } + +const baseURL = "https://netidhub.com/api/"; +const tokenAuth = Cookies.get("access_token") + ? Cookies.get("access_token") + : null; + +export async function postAPI(url: any, data: any) { + const headers = { + Authorization: `Bearer ${tokenAuth}`, + }; + const response = await axiosInstance + .post(url, qs.stringify(data), { headers }) + .catch((error) => error.response); + if (response?.status > 300) { + return { + error: true, + message: response?.data.error_description, + data: null, + }; + } + return { + error: false, + message: "success", + data: response?.data, + }; } export async function httpGet(pathUrl: any, headers: any) { - const response = await axiosBaseInstance - .get(pathUrl, { headers }) - .catch(function (error: any) { - console.log(error); - return error.response; - }); - console.log("Response base svc : ", response); - if (response?.status == 200 || response?.status == 201) { - return { - error: false, - message: "success", - data: response?.data, - }; - } else { - return { - error: true, - message: response?.data?.message || response?.data || null, - data: null, - }; - } + const response = await axiosBaseInstance + .get(pathUrl, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } } export async function httpPut(pathUrl: any, headers: any, data?: any) { - const response = await axiosBaseInstance - .put(pathUrl, data, { headers }) - .catch(function (error: any) { - console.log(error); - return error.response; - }); - console.log("Response base svc : ", response); - if (response?.status == 200 || response?.status == 201) { - return { - error: false, - message: "success", - data: response?.data, - }; - } else { - return { - error: true, - message: response?.data?.message || response?.data || null, - data: null, - }; - } -} \ No newline at end of file + const response = await axiosBaseInstance + .put(pathUrl, data, { headers }) + .catch(function (error: any) { + console.log(error); + return error.response; + }); + console.log("Response base svc : ", response); + if (response?.status == 200 || response?.status == 201) { + return { + error: false, + message: "success", + data: response?.data, + }; + } else { + return { + error: true, + message: response?.data?.message || response?.data || null, + data: null, + }; + } +} diff --git a/service/task.ts b/service/task.ts index d02dbb88..369f407c 100644 --- a/service/task.ts +++ b/service/task.ts @@ -1,3 +1,4 @@ +import { title } from "process"; import { deleteAPIInterceptor, getAPIInterceptor, @@ -8,8 +9,15 @@ import { httpPostInterceptor, } from "./http-config/http-interceptor-service"; -export async function listTask(size: number, page: number) { - return await httpGetInterceptor(`assignment/list?size=${size}&page=${page}`); +// export async function listTask(size: number, page: number) { +// return await httpGetInterceptor( +// `assignment/list?enablePage=1&title=${title}&size=${limit}&page=${page}` +// ); +// } + +export async function listTask(page: any, limit: any) { + const url = `assignment/list?size=${limit}&page=${page}`; + return getAPIInterceptor(url); } export async function createTask(data: any) {