From 5b3b9e44fa7b49bcc3b2bc7843e8495ff9478323 Mon Sep 17 00:00:00 2001 From: Hafid Nur Date: Fri, 28 Mar 2025 18:50:54 +0700 Subject: [PATCH] feat: Implement DataTable to backoffice pages - Halaman Data Akun - Halaman Validasi Transaksi --- apps/backoffice/src/app/accounts/page.tsx | 153 ++++---------- apps/backoffice/src/app/transactions/page.tsx | 199 ++++++++++-------- 2 files changed, 149 insertions(+), 203 deletions(-) diff --git a/apps/backoffice/src/app/accounts/page.tsx b/apps/backoffice/src/app/accounts/page.tsx index 950d2c2..5191e88 100644 --- a/apps/backoffice/src/app/accounts/page.tsx +++ b/apps/backoffice/src/app/accounts/page.tsx @@ -5,22 +5,19 @@ import { FilterOutlined, SearchOutlined, EditOutlined, - ArrowRightOutlined, - ArrowLeftOutlined, } from '@ant-design/icons'; import { Button, Input } from '@imphnen-frontend-service/ui/atoms'; import { DataTable } from '@imphnen-frontend-service/ui/organisms'; import { ColumnDef, - flexRender, getCoreRowModel, getPaginationRowModel, PaginationState, useReactTable, + RowSelectionState, } from '@tanstack/react-table'; -// Define account interface interface Account { id: number; name: string; @@ -38,7 +35,26 @@ const mockData: Account[] = Array.from({ length: 90 }, (_, i) => ({ address: 'Jl. Pantai Cibaduyut Indonesia', })); -const columns: ColumnDef[] = [ +const columns: ColumnDef[] = [ + { + id: 'select', + header: ({ table }) => ( + + ), + cell: ({ row }) => ( + + ), + }, { header: 'No', accessorKey: 'id', @@ -61,21 +77,19 @@ const columns: ColumnDef[] = [ }, { header: 'Action', - cell: ({ row }) => { - return ( - - ); - }, + cell: ({ row }) => ( + + ), }, ]; @@ -85,15 +99,22 @@ export const Components: FC = (): ReactElement => { pageSize: 9, }); + const [rowSelection, setRowSelection] = React.useState({}); + const table = useReactTable({ data: mockData, columns, state: { pagination, + rowSelection, }, + enableRowSelection: true, + onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), getPaginationRowModel: getPaginationRowModel(), onPaginationChange: setPagination, + pageCount: Math.ceil(mockData.length / pagination.pageSize), + manualPagination: false, }); return ( @@ -129,97 +150,7 @@ export const Components: FC = (): ReactElement => { {/* Table */} - - - {/* Pagination */} - {/* */} -
- - -
- {table.getPageCount() <= 8 ? ( - Array.from({ length: table.getPageCount() }, (_, index) => ( - - )) - ) : ( - // Render ellipsis jika total halaman lebih dari 8 - <> - - {table.getState().pagination.pageIndex > 3 && ...} - {Array.from( - { length: 5 }, - (_, index) => - table.getState().pagination.pageIndex - 2 + index - ) - .filter((page) => page > 0 && page < table.getPageCount() - 1) - .map((page) => ( - - ))} - {table.getState().pagination.pageIndex < - table.getPageCount() - 4 && ...} - - - )} -
- - -
+ ); diff --git a/apps/backoffice/src/app/transactions/page.tsx b/apps/backoffice/src/app/transactions/page.tsx index dd8c82e..fb8428f 100644 --- a/apps/backoffice/src/app/transactions/page.tsx +++ b/apps/backoffice/src/app/transactions/page.tsx @@ -1,18 +1,25 @@ -import { FC, ReactElement, useState } from 'react'; +import * as React from 'react'; + +import { FC, ReactElement } from 'react'; import { FilterOutlined, SearchOutlined, - FileTextOutlined, AuditOutlined, } from '@ant-design/icons'; import { Button, Input } from '@imphnen-frontend-service/ui/atoms'; -import { Pagination } from '@imphnen-frontend-service/ui/molecules'; import { DataTable } from '@imphnen-frontend-service/ui/organisms'; -// Define status type for better type safety +import { + ColumnDef, + getCoreRowModel, + getPaginationRowModel, + PaginationState, + useReactTable, + RowSelectionState, +} from '@tanstack/react-table'; + type TransactionStatus = 'valid' | 'invalid' | 'unchecked'; -// Define transaction interface interface Transaction { id: number; name: string; @@ -32,36 +39,103 @@ const mockTransactions: Transaction[] = Array.from({ length: 20 }, (_, i) => ({ : 'valid') as TransactionStatus, })); +const columns: ColumnDef[] = [ + { + id: 'select', + header: ({ table }) => ( + + ), + cell: ({ row }) => ( + + ), + }, + { + header: 'No', + accessorKey: 'id', + }, + { + header: 'Nama Lengkap', + accessorKey: 'name', + }, + { + header: 'Nomor Transaksi', + accessorKey: 'transactionNumber', + }, + { + header: 'Order Valid?', + accessorKey: 'status', + cell: ({ row }) => { + const status = row.original.status; + const statusColors: Record = { + valid: 'bg-success-500 text-white', + invalid: 'bg-danger-500 text-white', + unchecked: 'bg-yellow-400 text-black', + }; + const statusText: Record = { + valid: 'Valid', + invalid: 'Invalid', + unchecked: 'Unchecked', + }; + return ( +
+ {statusText[status]} +
+ ); + }, + }, + { + header: 'Action', + cell: ({ row }) => ( + + ), + }, +]; + export const Components: FC = (): ReactElement => { - const [searchQuery, setSearchQuery] = useState(''); - const [currentPage, setCurrentPage] = useState(1); - const itemsPerPage = 9; + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 9, + }); - // Filter data based on search query - const filteredData = mockTransactions.filter( - (item) => - item.name.toLowerCase().includes(searchQuery.toLowerCase()) || - item.transactionNumber.toLowerCase().includes(searchQuery.toLowerCase()) - ); + const [rowSelection, setRowSelection] = React.useState({}); - // Paginate data - const indexOfLastItem = currentPage * itemsPerPage; - const indexOfFirstItem = indexOfLastItem - itemsPerPage; - const currentItems = filteredData.slice(indexOfFirstItem, indexOfLastItem); - - const handleValidate = (id: number) => { - console.log(`Validate transaction with id: ${id}`); - // Implement validation functionality - }; - - const handlePageChange = (pageNumber: number) => { - setCurrentPage(pageNumber); - }; - - const handleSearch = (e: React.ChangeEvent) => { - setSearchQuery(e.target.value); - setCurrentPage(1); // Reset to first page when searching - }; + const table = useReactTable({ + data: mockTransactions, + columns, + state: { + pagination, + rowSelection, + }, + enableRowSelection: true, + onRowSelectionChange: setRowSelection, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + onPaginationChange: setPagination, + pageCount: Math.ceil(mockTransactions.length / pagination.pageSize), + manualPagination: false, + }); return (
@@ -77,8 +151,6 @@ export const Components: FC = (): ReactElement => {
@@ -97,64 +169,7 @@ export const Components: FC = (): ReactElement => {
{/* Table */} - index + 1 + indexOfFirstItem, - }, - { label: 'Nama Lengkap', key: 'name' }, - { label: 'Nomor Transaksi', key: 'transactionNumber' }, - { - label: 'Order Valid?', - render: (item: Transaction) => { - const statusColors: Record = { - valid: 'bg-success-500 text-white', - invalid: 'bg-danger-500 text-white', - unchecked: 'bg-yellow-400 text-black', - }; - const statusText: Record = { - valid: 'Valid', - invalid: 'Invalid', - unchecked: 'Unchecked', - }; - return ( -
- {statusText[item.status]} -
- ); - }, - }, - { - label: 'Action', - render: (item: Transaction) => ( - - ), - }, - ]} - /> - - {/* Pagination */} - +
);