feat: add ticketing features and others for supervisor
This commit is contained in:
parent
a82977105e
commit
eebb89212b
|
|
@ -3,7 +3,7 @@ import { Card, CardContent } from "@/components/ui/card";
|
|||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table-blog/blog-table";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -56,7 +56,6 @@ export type CompanyData = {
|
|||
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<CompanyData>[] = [
|
||||
|
|
@ -286,40 +285,46 @@ const BlogTable = () => {
|
|||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
import { Button } from '@/components/ui/button';
|
||||
import { Table } from '@tanstack/react-table';
|
||||
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
||||
import { useSearchParams } from 'next/navigation';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import React from 'react';
|
||||
|
||||
interface DataTablePaginationProps {
|
||||
table: Table<any>;
|
||||
totalPage: number; // Total jumlah halaman
|
||||
totalData: number; // Total jumlah data
|
||||
visiblePageCount?: number; // Jumlah halaman yang ditampilkan (default 5)
|
||||
}
|
||||
|
||||
const TablePagination = ({ table, totalPage, totalData, visiblePageCount = 5 }: DataTablePaginationProps) => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const [currentPageIndex, setCurrentPageIndex] = React.useState<number>(1);
|
||||
|
||||
React.useEffect(() => {
|
||||
const pageFromUrl = searchParams?.get('page');
|
||||
if (pageFromUrl) {
|
||||
setCurrentPageIndex(Number(pageFromUrl));
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
// Hitung startPage dan endPage, disesuaikan untuk dimulai dari 1
|
||||
const startPage = Math.max(1, currentPageIndex - Math.floor(visiblePageCount / 2));
|
||||
const endPage = Math.min(totalPage, startPage + visiblePageCount - 1);
|
||||
|
||||
const handlePageChange = (pageIndex: number) => {
|
||||
// Perbarui query parameter di URL
|
||||
const searchParams = new URLSearchParams(window.location.search);
|
||||
searchParams.set('page', (pageIndex).toString()); // Menyimpan halaman sebagai 1-based index
|
||||
router.push(`${window.location.pathname}?${searchParams.toString()}`);
|
||||
|
||||
// Pindahkan halaman di tabel
|
||||
table.setPageIndex(pageIndex);
|
||||
setCurrentPageIndex(pageIndex + 1); // Update state untuk halaman saat ini
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{totalData} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(1)}
|
||||
disabled={currentPageIndex === 1}
|
||||
className='w-8 h-8'
|
||||
>
|
||||
<ChevronLeft className='w-4 h-4' />
|
||||
</Button>
|
||||
{Array.from({ length: endPage - startPage + 1 }, (_, index) => startPage + index).map((pageIndex) => (
|
||||
<Button
|
||||
key={`page-${pageIndex}`}
|
||||
onClick={() => handlePageChange(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={currentPageIndex === pageIndex ? 'default' : 'outline'}
|
||||
>
|
||||
{pageIndex}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => handlePageChange(totalPage)}
|
||||
disabled={currentPageIndex === totalPage}
|
||||
className='w-8 h-8'
|
||||
>
|
||||
<ChevronRight className='w-4 h-4' />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TablePagination;
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -9,7 +9,7 @@ import RecentActivity from "./routine-task/recent-activity";
|
|||
import CompanyTable from "./routine-task/routine-task-table";
|
||||
import TaskTable from "../task/table-task/task-table";
|
||||
import PressConferenceTable from "../schedule/press-release/table-persrilis/pressrilis-table";
|
||||
import BlogTable from "../blog/table-blog/blog-table";
|
||||
import BlogTable from "../blog/table/blog-table";
|
||||
|
||||
const DashboardPage = () => {
|
||||
const t = useTranslations("AnalyticsDashboard");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Blog",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import MediahubTable from "../planning/mediahub/table-mediahub/mediahub-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import BlogTable from "./table/blog-table";
|
||||
|
||||
const BlogPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Table Indeks
|
||||
</div>
|
||||
<div>
|
||||
<Button color="primary" className="text-white">
|
||||
<UploadIcon />
|
||||
Tambah Indeks
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<BlogTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogPage;
|
||||
|
|
@ -0,0 +1,333 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
Badge,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
export type CompanyData = {
|
||||
no: number;
|
||||
title: string;
|
||||
category: 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 { paginationBlog } from "@/service/blog/blog";
|
||||
|
||||
export const columns: ColumnDef<CompanyData>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("no")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Judul",
|
||||
cell: ({ row }) => (
|
||||
<div className="flex items-center gap-5">
|
||||
<div className="flex-1 text-start">
|
||||
<h4 className="text-sm font-medium text-default-600 whitespace-nowrap mb-1">
|
||||
{row.getValue("title")}
|
||||
</h4>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "categoryName",
|
||||
header: "Kategori ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("categoryName")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "tags",
|
||||
header: "Tag ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("tags")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "statusName",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<span className="whitespace-nowrap text-blue-600">
|
||||
{row.getValue("statusName")}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const BlogTable = () => {
|
||||
const [blogTable, setBlogTable] = React.useState<CompanyData[]>([]);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: blogTable,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
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,
|
||||
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);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<div className="flex items-center justify-end py-4 px-10">
|
||||
<div className="flex-1 text-sm text-muted-foreground">
|
||||
{table.getFilteredSelectedRowModel().rows.length} of{" "}
|
||||
{table.getFilteredRowModel().rows.length} row(s) selected.
|
||||
</div>
|
||||
<div className="flex items-center justify-center py-4 gap-2 flex-none">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.previousPage()}
|
||||
disabled={!table.getCanPreviousPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronLeft className="w-4 h-4" />
|
||||
</Button>
|
||||
{table.getPageOptions().map((page, pageIndex) => (
|
||||
<Button
|
||||
key={`basic-data-table-${pageIndex}`}
|
||||
onClick={() => table.setPageIndex(pageIndex)}
|
||||
size="icon"
|
||||
className="w-8 h-8"
|
||||
variant={
|
||||
table.getState().pagination.pageIndex === pageIndex
|
||||
? "default"
|
||||
: "outline"
|
||||
}
|
||||
>
|
||||
{page + 1}
|
||||
</Button>
|
||||
))}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="icon"
|
||||
onClick={() => table.nextPage()}
|
||||
disabled={!table.getCanNextPage()}
|
||||
className="w-8 h-8"
|
||||
>
|
||||
<ChevronRight className="w-4 h-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BlogTable;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
export const metadata = {
|
||||
title: "Ticketing",
|
||||
};
|
||||
|
||||
const Layout = ({ children }: { children: React.ReactNode }) => {
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { UploadIcon } from "lucide-react";
|
||||
import TicketingTable from "./table/ticketing-table";
|
||||
|
||||
const TicketingPage = async () => {
|
||||
return (
|
||||
<div>
|
||||
<SiteBreadcrumb />
|
||||
<div className="space-y-4">
|
||||
<Card className="py-4 px-3">
|
||||
<div className="flex flex-row justify-between items-center">
|
||||
<div className="flex-1 text-xl font-medium text-default-900">
|
||||
Ticketing Table
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardContent className="p-0">
|
||||
<TicketingTable />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TicketingPage;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
export const data = [
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
status: "Terkirim",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Ops Mantap Praja & Pilkada 2024",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
{
|
||||
title: "Seputar Prestasi",
|
||||
status: "Terkirim",
|
||||
category: "Giat Pimpinan",
|
||||
date: "15/10/2024 9:11",
|
||||
tag: "percobaan",
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,303 @@
|
|||
"use client";
|
||||
|
||||
import * as React from "react";
|
||||
import {
|
||||
ColumnDef,
|
||||
ColumnFiltersState,
|
||||
PaginationState,
|
||||
SortingState,
|
||||
VisibilityState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getSortedRowModel,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
|
||||
import {
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
Eye,
|
||||
MoreVertical,
|
||||
Search,
|
||||
SquarePen,
|
||||
Trash2,
|
||||
TrendingDown,
|
||||
TrendingUp,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/components/ui/dropdown-menu";
|
||||
|
||||
import { data } from "./data";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||
import { paginationBlog } from "@/service/blog/blog";
|
||||
import { ticketingPagination } from "@/service/ticketing/ticketing";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import TablePagination from "../../blog/table/table-pagination";
|
||||
import { useRouter, useSearchParams } from "next/navigation";
|
||||
|
||||
export const columns: ColumnDef<any>[] = [
|
||||
{
|
||||
accessorKey: "no",
|
||||
header: "No",
|
||||
cell: ({ row }) => <span>{row.getValue("no")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "referenceNumber",
|
||||
header: "Ticket Number",
|
||||
cell: ({ row }) => <span>{row.getValue("referenceNumber")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "title",
|
||||
header: "Title",
|
||||
cell: ({ row }) => <span>{row.getValue("title")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "commentFromUserName",
|
||||
header: "Sender",
|
||||
cell: ({ row }) => <span>{row.getValue("commentFromUserName")}</span>,
|
||||
},
|
||||
{
|
||||
accessorKey: "type",
|
||||
header: "Channel",
|
||||
cell: ({ row }) => {
|
||||
const type = row.getValue("type") as { name: string };
|
||||
return <span>{type?.name}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "createdBy",
|
||||
header: "Operator",
|
||||
cell: ({ row }) => {
|
||||
const createdBy = row.getValue("createdBy") as { fullname: string };
|
||||
return <span>{createdBy?.fullname}</span>;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: "createdAt",
|
||||
header: "Tanggal Unggah ",
|
||||
cell: ({ row }) => (
|
||||
<span className="whitespace-nowrap">{row.getValue("createdAt")}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
accessorKey: "status",
|
||||
header: "Status",
|
||||
cell: ({ row }) => {
|
||||
const statusColors: Record<string, string> = {
|
||||
open: "bg-primary/20 text-primary",
|
||||
close: "bg-success/20 text-success",
|
||||
};
|
||||
const status = row.getValue("status") as { id: number, name: string };;
|
||||
const statusName = status?.name?.toLocaleLowerCase();
|
||||
console.log(statusName);
|
||||
const statusStyles = statusColors[statusName] || "default";
|
||||
if (statusName) {
|
||||
return (
|
||||
<Badge
|
||||
className={cn("rounded-full px-5",statusStyles)}
|
||||
>{statusName} </Badge>
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
accessorKey: "action",
|
||||
header: "Actions",
|
||||
enableHiding: false,
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
size="icon"
|
||||
className="bg-transparent ring-offset-transparent hover:bg-transparent hover:ring-0 hover:ring-transparent"
|
||||
>
|
||||
<span className="sr-only">Open menu</span>
|
||||
<MoreVertical className="h-4 w-4 text-default-800" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="p-0" align="end">
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<Eye className="w-4 h-4 me-1.5" />
|
||||
View
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||
<SquarePen className="w-4 h-4 me-1.5" />
|
||||
Edit
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none">
|
||||
<Trash2 className="w-4 h-4 me-1.5" />
|
||||
Delete
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const TicketingTable = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
const [ticketData, setTicketData] = React.useState<any[]>([]);
|
||||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>(
|
||||
[]
|
||||
);
|
||||
const [columnVisibility, setColumnVisibility] =
|
||||
React.useState<VisibilityState>({});
|
||||
const [rowSelection, setRowSelection] = React.useState({});
|
||||
const [pagination, setPagination] = React.useState<PaginationState>({
|
||||
pageIndex: 0,
|
||||
pageSize: 10,
|
||||
});
|
||||
const [page, setPage] = React.useState(1);
|
||||
const [totalPage, setTotalPage] = React.useState(1);
|
||||
const [limit, setLimit] = React.useState(10);
|
||||
|
||||
const table = useReactTable({
|
||||
data: ticketData,
|
||||
columns,
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
onPaginationChange: setPagination,
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
pagination,
|
||||
},
|
||||
});
|
||||
|
||||
React.useEffect(() => {
|
||||
const pageFromUrl = searchParams?.get('page');
|
||||
if (pageFromUrl) {
|
||||
setPage(Number(pageFromUrl));
|
||||
}
|
||||
}, [searchParams]);
|
||||
|
||||
React.useEffect(() => {
|
||||
fetchData();
|
||||
}, [page, limit]);
|
||||
|
||||
async function fetchData() {
|
||||
try {
|
||||
const res = await ticketingPagination('', limit, page-1);
|
||||
const data = res.data?.data;
|
||||
const contentData = data?.content;
|
||||
contentData.forEach((item: any, index: number) => {
|
||||
item.no = (page - 1) * limit + index + 1;
|
||||
});
|
||||
|
||||
console.log("contentData : ", contentData);
|
||||
|
||||
setTicketData(contentData);
|
||||
setTotalData(data?.totalElements);
|
||||
setTotalPage(data?.totalPages);
|
||||
} catch (error) {
|
||||
console.error("Error fetching tasks:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="w-full overflow-x-auto">
|
||||
<div className="flex justify-between items-center py-4 px-5">
|
||||
<div>
|
||||
<InputGroup merged>
|
||||
<InputGroupText className="bg-transparent dark:border-secondary dark:group-focus-within:border-secondary">
|
||||
<Search className=" h-4 w-4 dark:text-white" />
|
||||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
/>
|
||||
</InputGroup>
|
||||
</div>
|
||||
<div className="flex-none">
|
||||
<Input
|
||||
placeholder="Filter Status..."
|
||||
value={
|
||||
(table.getColumn("status")?.getFilterValue() as string) ?? ""
|
||||
}
|
||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
||||
table.getColumn("status")?.setFilterValue(event.target.value)
|
||||
}
|
||||
className="max-w-sm "
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<Table className="overflow-hidden">
|
||||
<TableHeader>
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<TableRow key={headerGroup.id} className="bg-default-200">
|
||||
{headerGroup.headers.map((header) => (
|
||||
<TableHead key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</TableHead>
|
||||
))}
|
||||
</TableRow>
|
||||
))}
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{table.getRowModel().rows?.length ? (
|
||||
table.getRowModel().rows.map((row) => (
|
||||
<TableRow
|
||||
key={row.id}
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="h-[75px]"
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
))
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||
No results.
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</Table>
|
||||
<TablePagination table={table} totalData={totalData} totalPage={totalPage} visiblePageCount={5} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TicketingTable;
|
||||
|
|
@ -11,7 +11,7 @@ const MenuWidget = () => {
|
|||
<div className="dark">
|
||||
<div className="bg-default-50 mb-16 mt-24 p-4 relative text-center rounded-2xl text-white">
|
||||
|
||||
<Image className="mx-auto relative -mt-[73px]" alt="" src="/images/svg/rabit.svg" priority width={99} height={114} />
|
||||
{/* <Image className="mx-auto relative -mt-[73px]" alt="" src="/images/svg/rabit.svg" priority width={99} height={114} />
|
||||
<div className="max-w-[160px] mx-auto mt-6">
|
||||
<div className="">Unlimited Access</div>
|
||||
<div className="text-xs font-light">
|
||||
|
|
@ -22,7 +22,7 @@ const MenuWidget = () => {
|
|||
<Button size="sm" fullWidth className=' bg-white text-default-50 hover:bg-background/90'>
|
||||
Upgrade
|
||||
</Button>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
151
lib/menus.ts
151
lib/menus.ts
|
|
@ -1,3 +1,5 @@
|
|||
import { getCookiesDecrypt } from "./utils";
|
||||
|
||||
export type SubChildren = {
|
||||
href: string;
|
||||
label: string;
|
||||
|
|
@ -29,7 +31,12 @@ export type Group = {
|
|||
};
|
||||
|
||||
export function getMenuList(pathname: string, t: any): Group[] {
|
||||
return [
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
const levelNumber = getCookiesDecrypt("ulne");
|
||||
const userLevelId = getCookiesDecrypt("ulie");
|
||||
|
||||
let menusSelected = [
|
||||
{
|
||||
groupLabel: t("apps"),
|
||||
id: "dashboard",
|
||||
|
|
@ -1373,6 +1380,148 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
|||
],
|
||||
},
|
||||
];
|
||||
|
||||
if (Number(roleId) == 9) {
|
||||
menusSelected = [
|
||||
{
|
||||
groupLabel: t("apps"),
|
||||
id: "dashboard",
|
||||
menus: [
|
||||
{
|
||||
id: "dashboard",
|
||||
href: "/dashboard",
|
||||
label: t("dashboard"),
|
||||
active: pathname.includes("/dashboard"),
|
||||
icon: "material-symbols:dashboard",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "ticketing",
|
||||
menus: [
|
||||
{
|
||||
id: "ticketing",
|
||||
href: "/ticketing",
|
||||
label: t("ticketing"),
|
||||
active: pathname.includes("/ticketing"),
|
||||
icon: "mdi:ticket-outline",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "knowledge-base",
|
||||
menus: [
|
||||
{
|
||||
id: "knowledge-base",
|
||||
href: "/knowledge-base",
|
||||
label: t("knowledge-base"),
|
||||
active: pathname.includes("/knowledge-base"),
|
||||
icon: "hugeicons:knowledge-02",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "faq",
|
||||
menus: [
|
||||
{
|
||||
id: "faq",
|
||||
href: "/frequently-asked-question",
|
||||
label: t("faq"),
|
||||
active: pathname.includes("/frequently-asked-question"),
|
||||
icon: "wpf:faq",
|
||||
submenus: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "communication",
|
||||
menus: [
|
||||
{
|
||||
id: "communication",
|
||||
href: "/communication",
|
||||
label: t("communication"),
|
||||
active: pathname.includes("/communication"),
|
||||
icon: "icon-park-outline:communication",
|
||||
submenus: [
|
||||
{
|
||||
href: "/communication/questions",
|
||||
label: t("questions"),
|
||||
active: pathname.includes("/communication/questions"),
|
||||
icon: "solar:inbox-line-outline",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/communication/internal",
|
||||
label: t("internal"),
|
||||
active: pathname.includes("/communication/internal"),
|
||||
icon: "ri:chat-private-line",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/communication/forward",
|
||||
label: t("forward"),
|
||||
active: pathname.includes("/communication/forward"),
|
||||
icon: "ri:share-forward-2-fill",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/communication/collaboration",
|
||||
label: t("collaboration"),
|
||||
active: pathname.includes("/communication/collaboration"),
|
||||
icon: "clarity:employee-group-line",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/communication/account-report",
|
||||
label: t("account-report"),
|
||||
active: pathname.includes("/communication/account-report"),
|
||||
icon: "uiw:user-delete",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
groupLabel: "",
|
||||
id: "settings",
|
||||
menus: [
|
||||
{
|
||||
id: "settings",
|
||||
href: "/settings",
|
||||
label: t("settings"),
|
||||
active: pathname.includes("/settings"),
|
||||
icon: "uil:setting",
|
||||
submenus: [
|
||||
{
|
||||
href: "/settings/feedback",
|
||||
label: t("feedback"),
|
||||
active: pathname.includes("/settings/feedback"),
|
||||
icon: "clarity:employee-group-line",
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
href: "/settings/social-media",
|
||||
label: t("social-media"),
|
||||
active: pathname.includes("/settings/social-media"),
|
||||
icon: "clarity:employee-group-line",
|
||||
children: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
return menusSelected;
|
||||
}
|
||||
export function getHorizontalMenuList(pathname: string, t: any): Group[] {
|
||||
return [
|
||||
|
|
|
|||
|
|
@ -137,6 +137,17 @@
|
|||
"curated-content": "Curated Content",
|
||||
"communication": "Communication",
|
||||
"contest": "Contest",
|
||||
"ticketing": "Ticketing",
|
||||
"knowledge-base": "Knowledge Base",
|
||||
"faq": "FAQ",
|
||||
"questions": "Questions",
|
||||
"internal": "Internal Questions",
|
||||
"forward": "Forward",
|
||||
"collaboration": "Collaboration",
|
||||
"account-report": "Account Report",
|
||||
"settings": "Settings",
|
||||
"feedback": "Feedback",
|
||||
"social-media": "Social media",
|
||||
"analytics": "Analytics",
|
||||
"banking": "Banking",
|
||||
"crm": "Crm",
|
||||
|
|
@ -167,11 +178,9 @@
|
|||
"utility": "utility",
|
||||
"blankPage": "Blank Page",
|
||||
"blog": "Blog",
|
||||
"faq": "Faq",
|
||||
"invoice": "Invoice",
|
||||
"pricing": "Pricing",
|
||||
"profile": "Profile",
|
||||
"settings": "Settings",
|
||||
"elements": "Elements",
|
||||
"components": "Components",
|
||||
"avatar": "Avatar",
|
||||
|
|
|
|||
|
|
@ -137,6 +137,17 @@
|
|||
"curated-content": "Kurasi Konten",
|
||||
"communication": "Komunikasi",
|
||||
"contest": "Kontes",
|
||||
"ticketing": "Ticketing",
|
||||
"knowledge-base": "Knowledge Base",
|
||||
"faq": "FAQ",
|
||||
"questions": "Questions",
|
||||
"internal": "Internal Questions",
|
||||
"forward": "Forward",
|
||||
"collaboration": "Collaboration",
|
||||
"account-report": "Account Report",
|
||||
"settings": "Settings",
|
||||
"feedback": "Feedback",
|
||||
"social-media": "Social media",
|
||||
"analytics": "Analytics",
|
||||
"banking": "Banking",
|
||||
"crm": "Crm",
|
||||
|
|
@ -167,11 +178,9 @@
|
|||
"utility": "utility",
|
||||
"blankPage": "Blank Page",
|
||||
"blog": "Blog",
|
||||
"faq": "Faq",
|
||||
"invoice": "Invoice",
|
||||
"pricing": "Pricing",
|
||||
"profile": "Profile",
|
||||
"settings": "Settings",
|
||||
"elements": "Elements",
|
||||
"components": "Components",
|
||||
"avatar": "Avatar",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import { title } from "process";
|
||||
import { httpGetInterceptor } from "../http-config/http-interceptor-service";
|
||||
|
||||
export async function ticketingPagination(title: string = '', size: number, page: number) {
|
||||
return await httpGetInterceptor(
|
||||
`/ticketing/pagination?enablePage=1&page=${page}&size=${size}&title=${title}`
|
||||
);
|
||||
}
|
||||
Loading…
Reference in New Issue