From d9c154997dee2bcc85696fbbc3003e28646a07e7 Mon Sep 17 00:00:00 2001 From: ValdiANS Date: Mon, 19 Jan 2026 14:41:20 +0700 Subject: [PATCH] feat: create Closing Sapronak Summary component --- .../ClosingIncomingSapronaksSummaryTable.tsx | 174 ++++++++++++++++++ .../ClosingOutgoingSapronaksSummaryTable.tsx | 174 ++++++++++++++++++ 2 files changed, 348 insertions(+) create mode 100644 src/components/pages/closing/ClosingIncomingSapronaksSummaryTable.tsx create mode 100644 src/components/pages/closing/ClosingOutgoingSapronaksSummaryTable.tsx diff --git a/src/components/pages/closing/ClosingIncomingSapronaksSummaryTable.tsx b/src/components/pages/closing/ClosingIncomingSapronaksSummaryTable.tsx new file mode 100644 index 00000000..49e4f108 --- /dev/null +++ b/src/components/pages/closing/ClosingIncomingSapronaksSummaryTable.tsx @@ -0,0 +1,174 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import { useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; +import { ColumnDef, SortingState } from '@tanstack/react-table'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import Card from '@/components/Card'; +import Collapse from '@/components/Collapse'; + +import { cn, formatNumber } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ClosingApi } from '@/services/api/closing'; +import { ClosingIncomingSapronakSummary } from '@/types/api/closing'; + +interface ClosingIncomingSapronaksSummaryTableProps { + projectFlockId: number; +} + +const ClosingIncomingSapronaksSummaryTable = ({ + projectFlockId, +}: ClosingIncomingSapronaksSummaryTableProps) => { + const searchParams = useSearchParams(); + const kandangId = searchParams.get('kandangId'); + + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { + search: '', + nameSort: '', + }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + }, + }); + + const { + data: incomingSapronakSummaries, + isLoading: isLoadingIncomingSapronakSummaries, + } = useSWR( + `${ClosingApi.basePath}/${projectFlockId}/sapronak/summary${getTableFilterQueryString()}&type=incoming&kandang_id=${kandangId ? `${kandangId}` : ''}`, + ClosingApi.getAllIncomingSapronakSummaryFetcher, + { + keepPreviousData: true, + } + ); + + const [open, setOpen] = useState(true); + + const [sorting, setSorting] = useState([]); + const [rowSelection, setRowSelection] = useState>({}); + + const incomingSapronaksColumns: ColumnDef[] = + [ + { + header: '#', + cell: (props) => props.row.index + 1, + }, + { + accessorKey: 'category', + header: 'Kategori', + }, + { + accessorKey: 'total_qty', + header: 'Total Kuantitas', + cell: (props) => + `${formatNumber(props.row.original.total_qty)} ${props.row.original.uom.name}`, + }, + ]; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting, updateFilter]); + + useEffect(() => { + if (!open) { + setOpen( + isResponseSuccess(incomingSapronakSummaries) + ? incomingSapronakSummaries.data.length > 0 + : false + ); + } + }, [incomingSapronakSummaries, isResponseSuccess]); + + return ( + + +
Ringkasan Sapronak Masuk
+ + + + } + className='w-full!' + titleClassName='w-full p-0!' + > +
+ + data={ + isResponseSuccess(incomingSapronakSummaries) + ? incomingSapronakSummaries?.data + : [] + } + columns={incomingSapronaksColumns} + pageSize={tableFilterState.pageSize} + onPageSizeChange={setPageSize} + rowOptions={[10, 20, 50, 100]} + page={ + isResponseSuccess(incomingSapronakSummaries) + ? incomingSapronakSummaries?.meta?.page + : 0 + } + totalItems={ + isResponseSuccess(incomingSapronakSummaries) + ? incomingSapronakSummaries?.meta?.total_results + : 0 + } + onPageChange={setPage} + isLoading={isLoadingIncomingSapronakSummaries} + sorting={sorting} + setSorting={setSorting} + rowSelection={rowSelection} + setRowSelection={setRowSelection} + className={{ + containerClassName: cn({ + 'w-full mb-20': + isResponseSuccess(incomingSapronakSummaries) && + incomingSapronakSummaries?.data?.length === 0, + }), + }} + /> +
+
+
+ ); +}; + +export default ClosingIncomingSapronaksSummaryTable; diff --git a/src/components/pages/closing/ClosingOutgoingSapronaksSummaryTable.tsx b/src/components/pages/closing/ClosingOutgoingSapronaksSummaryTable.tsx new file mode 100644 index 00000000..42fcb588 --- /dev/null +++ b/src/components/pages/closing/ClosingOutgoingSapronaksSummaryTable.tsx @@ -0,0 +1,174 @@ +'use client'; + +import { ChangeEventHandler, useEffect, useState } from 'react'; +import { useSearchParams } from 'next/navigation'; +import useSWR from 'swr'; +import { ColumnDef, SortingState } from '@tanstack/react-table'; + +import { Icon } from '@iconify/react'; +import Table from '@/components/Table'; +import Card from '@/components/Card'; +import Collapse from '@/components/Collapse'; + +import { cn, formatNumber } from '@/lib/helper'; +import { isResponseSuccess } from '@/lib/api-helper'; +import { useTableFilter } from '@/services/hooks/useTableFilter'; +import { ClosingApi } from '@/services/api/closing'; +import { ClosingOutgoingSapronakSummary } from '@/types/api/closing'; + +interface ClosingOutgoingSapronaksSummaryTableProps { + projectFlockId: number; +} + +const ClosingOutgoingSapronaksSummaryTable = ({ + projectFlockId, +}: ClosingOutgoingSapronaksSummaryTableProps) => { + const searchParams = useSearchParams(); + const kandangId = searchParams.get('kandangId'); + + const { + state: tableFilterState, + updateFilter, + setPage, + setPageSize, + toQueryString: getTableFilterQueryString, + } = useTableFilter({ + initial: { + search: '', + nameSort: '', + }, + paramMap: { + page: 'page', + pageSize: 'limit', + nameSort: 'sort_name', + }, + }); + + const { + data: outgoingSapronakSummaries, + isLoading: isLoadingOutgoingSapronakSummaries, + } = useSWR( + `${ClosingApi.basePath}/${projectFlockId}/sapronak/summary${getTableFilterQueryString()}&type=outgoing&kandang_id=${kandangId ? `${kandangId}` : ''}`, + ClosingApi.getAllIncomingSapronakSummaryFetcher, + { + keepPreviousData: true, + } + ); + + const [open, setOpen] = useState(true); + + const [sorting, setSorting] = useState([]); + const [rowSelection, setRowSelection] = useState>({}); + + const outgoingSapronaksColumns: ColumnDef[] = + [ + { + header: '#', + cell: (props) => props.row.index + 1, + }, + { + accessorKey: 'category', + header: 'Kategori', + }, + { + accessorKey: 'total_qty', + header: 'Total Kuantitas', + cell: (props) => + `${formatNumber(props.row.original.total_qty)} ${props.row.original.uom.name}`, + }, + ]; + + const searchChangeHandler: ChangeEventHandler = (e) => { + updateFilter('search', e.target.value); + }; + + // track sorting + useEffect(() => { + const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name'); + + if (!isNameSorted) { + updateFilter('nameSort', ''); + } else { + updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc'); + } + }, [sorting, updateFilter]); + + useEffect(() => { + if (!open) { + setOpen( + isResponseSuccess(outgoingSapronakSummaries) + ? outgoingSapronakSummaries.data.length > 0 + : false + ); + } + }, [outgoingSapronakSummaries, isResponseSuccess]); + + return ( + + +
Ringkasan Sapronak Keluar
+ + + + } + className='w-full!' + titleClassName='w-full p-0!' + > +
+ + data={ + isResponseSuccess(outgoingSapronakSummaries) + ? outgoingSapronakSummaries?.data + : [] + } + columns={outgoingSapronaksColumns} + pageSize={tableFilterState.pageSize} + onPageSizeChange={setPageSize} + rowOptions={[10, 20, 50, 100]} + page={ + isResponseSuccess(outgoingSapronakSummaries) + ? outgoingSapronakSummaries?.meta?.page + : 0 + } + totalItems={ + isResponseSuccess(outgoingSapronakSummaries) + ? outgoingSapronakSummaries?.meta?.total_results + : 0 + } + onPageChange={setPage} + isLoading={isLoadingOutgoingSapronakSummaries} + sorting={sorting} + setSorting={setSorting} + rowSelection={rowSelection} + setRowSelection={setRowSelection} + className={{ + containerClassName: cn({ + 'w-full mb-20': + isResponseSuccess(outgoingSapronakSummaries) && + outgoingSapronakSummaries?.data?.length === 0, + }), + }} + /> +
+
+
+ ); +}; + +export default ClosingOutgoingSapronaksSummaryTable;