diff --git a/src/app/master-data/area/page.tsx b/src/app/master-data/area/page.tsx
index f8789af2..2c3cef14 100644
--- a/src/app/master-data/area/page.tsx
+++ b/src/app/master-data/area/page.tsx
@@ -1,11 +1,7 @@
import AreasTable from '@/components/pages/master-data/area/AreasTable';
const Nonstock = () => {
- return (
-
- );
+ return ;
};
export default Nonstock;
diff --git a/src/app/master-data/bank/page.tsx b/src/app/master-data/bank/page.tsx
index 3f913c55..371cc3bf 100644
--- a/src/app/master-data/bank/page.tsx
+++ b/src/app/master-data/bank/page.tsx
@@ -1,11 +1,7 @@
import BanksTable from '@/components/pages/master-data/bank/BanksTable';
const Bank = () => {
- return (
-
- );
+ return ;
};
export default Bank;
diff --git a/src/app/master-data/customer/page.tsx b/src/app/master-data/customer/page.tsx
index 8aec1088..05c0e1e8 100644
--- a/src/app/master-data/customer/page.tsx
+++ b/src/app/master-data/customer/page.tsx
@@ -1,11 +1,7 @@
import CustomersTable from '@/components/pages/master-data/customer/CustomersTable';
const Customer = () => {
- return (
-
- );
+ return ;
};
export default Customer;
diff --git a/src/app/master-data/flock/page.tsx b/src/app/master-data/flock/page.tsx
index 76cc32c1..418018ab 100644
--- a/src/app/master-data/flock/page.tsx
+++ b/src/app/master-data/flock/page.tsx
@@ -1,11 +1,7 @@
import FlockTable from '@/components/pages/master-data/flock/FlocksTable';
const Flock = () => {
- return (
-
- );
+ return ;
};
export default Flock;
diff --git a/src/app/master-data/kandang/page.tsx b/src/app/master-data/kandang/page.tsx
index 293eb0da..e281e82c 100644
--- a/src/app/master-data/kandang/page.tsx
+++ b/src/app/master-data/kandang/page.tsx
@@ -1,11 +1,7 @@
import KandangsTable from '@/components/pages/master-data/kandang/KandangsTable';
const Nonstock = () => {
- return (
-
- );
+ return ;
};
export default Nonstock;
diff --git a/src/app/master-data/location/page.tsx b/src/app/master-data/location/page.tsx
index 338fdbff..af65761f 100644
--- a/src/app/master-data/location/page.tsx
+++ b/src/app/master-data/location/page.tsx
@@ -1,11 +1,7 @@
import LocationsTable from '@/components/pages/master-data/location/LocationsTable';
const Nonstock = () => {
- return (
-
- );
+ return ;
};
export default Nonstock;
diff --git a/src/app/master-data/nonstock/page.tsx b/src/app/master-data/nonstock/page.tsx
index 0812a5e2..02ed2e1e 100644
--- a/src/app/master-data/nonstock/page.tsx
+++ b/src/app/master-data/nonstock/page.tsx
@@ -1,11 +1,7 @@
import NonstocksTable from '@/components/pages/master-data/nonstock/NonstocksTable';
const Nonstock = () => {
- return (
-
- );
+ return ;
};
export default Nonstock;
diff --git a/src/app/master-data/product-category/page.tsx b/src/app/master-data/product-category/page.tsx
index 78a4fda3..7c0a6656 100644
--- a/src/app/master-data/product-category/page.tsx
+++ b/src/app/master-data/product-category/page.tsx
@@ -1,11 +1,7 @@
import ProductCategoryTable from '@/components/pages/master-data/product-category/ProductCategoryTable';
const ProductCategory = () => {
- return (
-
- );
+ return ;
};
export default ProductCategory;
diff --git a/src/app/master-data/production-standard/page.tsx b/src/app/master-data/production-standard/page.tsx
index ed1107cd..17944ebe 100644
--- a/src/app/master-data/production-standard/page.tsx
+++ b/src/app/master-data/production-standard/page.tsx
@@ -1,11 +1,7 @@
import ProductionStandardTable from '@/components/pages/master-data/production-standard/ProductionStandardTable';
const ProductionStandardPage = () => {
- return (
-
- );
+ return ;
};
export default ProductionStandardPage;
diff --git a/src/app/master-data/supplier/page.tsx b/src/app/master-data/supplier/page.tsx
index 8000be0a..169fd071 100644
--- a/src/app/master-data/supplier/page.tsx
+++ b/src/app/master-data/supplier/page.tsx
@@ -1,11 +1,7 @@
import SuppliersTable from '@/components/pages/master-data/supplier/SupplierTable';
const Supplier = () => {
- return (
-
- );
+ return ;
};
export default Supplier;
diff --git a/src/app/master-data/uom/page.tsx b/src/app/master-data/uom/page.tsx
index 689b9d0d..b5ba52b8 100644
--- a/src/app/master-data/uom/page.tsx
+++ b/src/app/master-data/uom/page.tsx
@@ -1,11 +1,7 @@
import UomsTable from '@/components/pages/master-data/uom/UomsTable';
const Nonstock = () => {
- return (
-
- );
+ return ;
};
export default Nonstock;
diff --git a/src/app/master-data/warehouse/page.tsx b/src/app/master-data/warehouse/page.tsx
index eb5ae416..7119283e 100644
--- a/src/app/master-data/warehouse/page.tsx
+++ b/src/app/master-data/warehouse/page.tsx
@@ -1,11 +1,7 @@
import WarehousesTable from '@/components/pages/master-data/warehouse/WarehousesTable';
const Warehouse = () => {
- return (
-
- );
+ return ;
};
export default Warehouse;
diff --git a/src/components/pages/master-data/area/AreasTable.tsx b/src/components/pages/master-data/area/AreasTable.tsx
index d92c7840..cc8084d8 100644
--- a/src/components/pages/master-data/area/AreasTable.tsx
+++ b/src/components/pages/master-data/area/AreasTable.tsx
@@ -1,6 +1,6 @@
'use client';
-import { ChangeEventHandler, useEffect, useState } from 'react';
+import { ChangeEventHandler, useMemo, useState } from 'react';
import useSWR from 'swr';
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
import toast from 'react-hot-toast';
@@ -11,71 +11,92 @@ import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import Button from '@/components/Button';
import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
-import SelectInput, { OptionType } from '@/components/input/SelectInput';
-import RowDropdownOptions from '@/components/table/RowDropdownOptions';
-import RowCollapseOptions from '@/components/table/RowCollapseOptions';
-import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
import RequirePermission from '@/components/helper/RequirePermission';
+import PopoverButton from '@/components/popover/PopoverButton';
+import PopoverContent from '@/components/popover/PopoverContent';
import { Area } from '@/types/api/master-data/area';
import { AreaApi } from '@/services/api/master-data';
import { cn } from '@/lib/helper';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
-import { ROWS_OPTIONS } from '@/config/constant';
const RowOptionsMenu = ({
- type = 'dropdown',
+ popoverPosition = 'bottom',
props,
deleteClickHandler,
}: {
- type: 'dropdown' | 'collapse';
+ popoverPosition: 'bottom' | 'top';
props: CellContext;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `area#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-area#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -87,10 +108,17 @@ const AreasTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '' },
- paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' },
+ initial: {
+ search: '',
+ },
+ paramMap: {
+ page: 'page',
+ pageSize: 'limit',
+ },
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: areas,
isLoading,
@@ -101,65 +129,12 @@ const AreasTable = () => {
);
const deleteModal = useModal();
-
const [selectedArea, setSelectedArea] = useState(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const areasColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedArea(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -179,95 +154,114 @@ const AreasTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const areasColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedArea(props.row.original);
+ deleteModal.openModal();
+ };
- // track sorting
- useEffect(() => {
- const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
-
- if (!isNameSorted) {
- updateFilter('nameSort', '');
- } else {
- updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
- }
- }, [sorting, updateFilter]);
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(areas) ? areas?.data : []}
- columns={areasColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(areas) ? areas?.meta?.page : 0}
- totalItems={isResponseSuccess(areas) ? areas?.meta?.total_results : 0}
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20': isResponseSuccess(areas) && areas?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(areas) ? areas?.data : []}
+ columns={areasColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(areas) ? areas?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(areas) ? areas?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full': isResponseSuccess(areas) && areas?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `bank#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-bank#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -87,10 +108,17 @@ const BanksTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '' },
- paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' },
+ initial: {
+ search: '',
+ },
+ paramMap: {
+ page: 'page',
+ pageSize: 'limit',
+ },
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: banks,
isLoading,
@@ -101,78 +129,12 @@ const BanksTable = () => {
);
const deleteModal = useModal();
-
const [selectedBank, setSelectedBank] = useState(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const banksColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'alias',
- header: 'Alias',
- },
- {
- accessorKey: 'account_number',
- header: 'No. Rekening',
- },
- {
- accessorKey: 'owner',
- header: 'Pemilik',
- cell: (props) => (props.getValue() ? props.getValue() : '-'),
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedBank(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -192,93 +154,127 @@ const BanksTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const banksColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorKey: 'alias',
+ header: 'Alias',
+ },
+ {
+ accessorKey: 'account_number',
+ header: 'No. Rekening',
+ },
+ {
+ accessorKey: 'owner',
+ header: 'Pemilik',
+ cell: (props) => props.getValue() || '-',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedBank(props.row.original);
+ deleteModal.openModal();
+ };
- // track sorting
- useEffect(() => {
- const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
-
- if (!isNameSorted) {
- updateFilter('nameSort', '');
- } else {
- updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
- }
- }, [sorting]);
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(banks) ? banks?.data : []}
- columns={banksColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(banks) ? banks?.meta?.page : 0}
- totalItems={isResponseSuccess(banks) ? banks?.meta?.total_results : 0}
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20': isResponseSuccess(banks) && banks?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(banks) ? banks?.data : []}
+ columns={banksColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(banks) ? banks?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(banks) ? banks?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full': isResponseSuccess(banks) && banks?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `customer#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-customer#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -83,16 +108,17 @@ const CustomersTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '', picSort: '' },
+ initial: {
+ search: '',
+ },
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
- picSort: 'sort_pic',
},
});
- // Fetch Data
+ const [sorting, setSorting] = useState([]);
+
const {
data: customers,
isLoading,
@@ -102,87 +128,16 @@ const CustomersTable = () => {
CustomerApi.getAllFetcher
);
- // State
const deleteModal = useModal();
const [selectedCustomer, setSelectedCustomer] = useState<
Customer | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- // Columns Definition
- const customersColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'pic',
- header: 'PIC',
- cell: (props) => props.row.original.pic.name,
- },
- {
- accessorKey: 'type',
- header: 'Type',
- cell: (props) => props.row.original.type,
- },
- {
- accessorKey: 'phone',
- header: 'Phone',
- },
- {
- accessorKey: 'email',
- header: 'Email',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedCustomer(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
-
- // Handler
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -202,81 +157,132 @@ const CustomersTable = () => {
toast.success('Successfully delete Customer!');
setIsDeleteLoading(false);
};
- const searchChangeHandler = (e: React.ChangeEvent) => {
- updateFilter('search', e.target.value);
- };
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
- setPageSize(newVal.value as number);
- };
+
+ const customersColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorFn: (row) => row.pic?.name ?? '-',
+ header: 'PIC',
+ },
+ {
+ accessorKey: 'type',
+ header: 'Type',
+ },
+ {
+ accessorKey: 'phone',
+ header: 'Phone',
+ },
+ {
+ accessorKey: 'email',
+ header: 'Email',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
+
+ const deleteClickHandler = () => {
+ setSelectedCustomer(props.row.original);
+ deleteModal.openModal();
+ };
+
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
-
-
+
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(customers) ? customers?.data : []}
- columns={customersColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(customers) ? customers?.meta?.page : 0}
- totalItems={
- isResponseSuccess(customers) ? customers?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(customers) && customers?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(customers) ? customers?.data : []}
+ columns={customersColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(customers) ? customers?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(customers) ? customers?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(customers) && customers?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `flock#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-flock#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -93,15 +108,17 @@ const FlockTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '' },
+ initial: {
+ search: '',
+ },
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
},
});
- // Fetch Data
+ const [sorting, setSorting] = useState([]);
+
const {
data: flocks,
isLoading,
@@ -111,74 +128,16 @@ const FlockTable = () => {
FlockApi.getAllFetcher
);
- // State
const deleteModal = useModal();
const [selectedFlock, setSelectedFlock] = useState(
undefined
);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- // Columns Definition
- const flocksColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'created_at',
- header: 'Dibuat pada',
- cell: (props) =>
- new Date(props.row.original.created_at).toLocaleDateString(),
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedFlock(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
-
- // Handler
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -196,85 +155,128 @@ const FlockTable = () => {
toast.success('Successfully delete Flock!');
setIsDeleteLoading(false);
};
- const searchChangeHandler = (e: React.ChangeEvent) => {
- updateFilter('search', e.target.value);
- };
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
- setPageSize(newVal.value as number);
- };
+
+ const flocksColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorKey: 'created_at',
+ header: 'Dibuat pada',
+ cell: (props) =>
+ new Date(props.row.original.created_at).toLocaleDateString('id-ID'),
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
+
+ const deleteClickHandler = () => {
+ setSelectedFlock(props.row.original);
+ deleteModal.openModal();
+ };
+
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(flocks) ? flocks?.data : []}
- columns={flocksColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(flocks) ? flocks?.meta?.page : 0}
- totalItems={
- isResponseSuccess(flocks) ? flocks?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- className={{
- containerClassName: cn({
- 'mb-20': isResponseSuccess(flocks) && flocks?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(flocks) ? flocks?.data : []}
+ columns={flocksColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(flocks) ? flocks?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(flocks) ? flocks?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(flocks) && flocks?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `kandang#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-kandang#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -94,21 +110,15 @@ const KandangsTable = () => {
} = useTableFilter({
initial: {
search: '',
- nameSort: '',
- locationSort: '',
- capacitySort: '',
- picSort: '',
},
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
- locationSort: 'sort_location',
- capacitySort: 'sort_capacity',
- picSort: ' sort_pic',
},
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: kandangs,
isLoading,
@@ -119,82 +129,14 @@ const KandangsTable = () => {
);
const deleteModal = useModal();
-
const [selectedKandang, setSelectedKandang] = useState(
undefined
);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const kandangsColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'location',
- header: 'Lokasi',
- cell: (props) => props.row.original.location.name,
- },
- {
- accessorKey: 'capacity',
- header: 'Kapasitas',
- cell: (props) => formatNumber(props.row.original.capacity ?? 0),
- },
- {
- accessorKey: 'pic',
- header: 'PIC',
- cell: (props) => props.row.original.pic.name,
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedKandang(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -216,114 +158,128 @@ const KandangsTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const kandangsColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorFn: (row) => row.location?.name ?? '-',
+ header: 'Lokasi',
+ },
+ {
+ accessorKey: 'capacity',
+ header: 'Kapasitas',
+ cell: (props) => formatNumber(props.row.original.capacity ?? 0),
+ },
+ {
+ accessorFn: (row) => row.pic?.name ?? '-',
+ header: 'PIC',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedKandang(props.row.original);
+ deleteModal.openModal();
+ };
- const updateSortingFilter = useCallback(
- (
- sortName: Exclude,
- sortFilter: ColumnSort | undefined
- ) => {
- if (!sortFilter) {
- updateFilter(sortName, '');
- } else {
- updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc');
- }
- },
- [updateFilter]
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
);
- // track sorting
- useEffect(() => {
- const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name');
- const locationSortFilter = sorting.find(
- (sortItem) => sortItem.id === 'location'
- );
- const picSortFilter = sorting.find((sortItem) => sortItem.id === 'pic');
-
- updateSortingFilter('nameSort', nameSortFilter);
- updateSortingFilter('locationSort', locationSortFilter);
- updateSortingFilter('picSort', picSortFilter);
- }, [sorting, updateSortingFilter]);
-
return (
<>
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(kandangs) ? kandangs?.data : []}
- columns={kandangsColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(kandangs) ? kandangs?.meta?.page : 0}
- totalItems={
- isResponseSuccess(kandangs) ? kandangs?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(kandangs) && kandangs?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(kandangs) ? kandangs?.data : []}
+ columns={kandangsColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(kandangs) ? kandangs?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(kandangs) ? kandangs?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(kandangs) && kandangs?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `location#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-location#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -92,16 +108,17 @@ const LocationsTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '', addressSort: '', areaSort: '' },
+ initial: {
+ search: '',
+ },
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
- addressSort: 'sort_address',
- areaSort: ' sort_area',
},
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: locations,
isLoading,
@@ -112,76 +129,14 @@ const LocationsTable = () => {
);
const deleteModal = useModal();
-
const [selectedLocation, setSelectedLocation] = useState<
Location | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const locationsColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'address',
- header: 'Alamat',
- },
- {
- accessorKey: 'area',
- header: 'Area',
- cell: (props) => props.row.original.area.name,
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedLocation(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -203,114 +158,123 @@ const LocationsTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const locationsColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorKey: 'address',
+ header: 'Alamat',
+ },
+ {
+ accessorFn: (row) => row.area?.name ?? '-',
+ header: 'Area',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedLocation(props.row.original);
+ deleteModal.openModal();
+ };
- const updateSortingFilter = useCallback(
- (
- sortName: Exclude,
- sortFilter: ColumnSort | undefined
- ) => {
- if (!sortFilter) {
- updateFilter(sortName, '');
- } else {
- updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc');
- }
- },
- [updateFilter]
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
);
- // track sorting
- useEffect(() => {
- const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name');
- const addressSortFilter = sorting.find(
- (sortItem) => sortItem.id === 'address'
- );
- const areaSortFilter = sorting.find((sortItem) => sortItem.id === 'area');
-
- updateSortingFilter('nameSort', nameSortFilter);
- updateSortingFilter('addressSort', addressSortFilter);
- updateSortingFilter('areaSort', areaSortFilter);
- }, [sorting, updateSortingFilter]);
-
return (
<>
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(locations) ? locations?.data : []}
- columns={locationsColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(locations) ? locations?.meta?.page : 0}
- totalItems={
- isResponseSuccess(locations) ? locations?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(locations) && locations?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(locations) ? locations?.data : []}
+ columns={locationsColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(locations) ? locations?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(locations) ? locations?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(locations) && locations?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
{
className='px-3 py-2.5 w-fit text-sm text-base-100 rounded-lg shadow-sm'
>
- Tambah Nonstock
+ Add Nonstock
diff --git a/src/components/pages/master-data/product-category/ProductCategoryTable.tsx b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx
index 11199c73..3a872b7f 100644
--- a/src/components/pages/master-data/product-category/ProductCategoryTable.tsx
+++ b/src/components/pages/master-data/product-category/ProductCategoryTable.tsx
@@ -1,6 +1,12 @@
'use client';
-import { ChangeEventHandler, useEffect, useRef, useState } from 'react';
+import {
+ ChangeEventHandler,
+ useEffect,
+ useMemo,
+ useRef,
+ useState,
+} from 'react';
import useSWR from 'swr';
import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
import toast from 'react-hot-toast';
@@ -11,11 +17,9 @@ import DebouncedTextInput from '@/components/input/DebouncedTextInput';
import Button from '@/components/Button';
import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
-import SelectInput, { OptionType } from '@/components/input/SelectInput';
-import RowDropdownOptions from '@/components/table/RowDropdownOptions';
-import RowCollapseOptions from '@/components/table/RowCollapseOptions';
-import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
import RequirePermission from '@/components/helper/RequirePermission';
+import PopoverButton from '@/components/popover/PopoverButton';
+import PopoverContent from '@/components/popover/PopoverContent';
import { ProductCategory } from '@/types/api/master-data/product-category';
import { ProductCategoryApi } from '@/services/api/master-data';
@@ -23,60 +27,83 @@ import { cn } from '@/lib/helper';
import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
import { useTableFilter } from '@/services/hooks/useTableFilter';
import { useUiStore } from '@/stores/ui/ui.store';
-import { ROWS_OPTIONS } from '@/config/constant';
const RowOptionsMenu = ({
- type = 'dropdown',
+ popoverPosition = 'bottom',
props,
deleteClickHandler,
}: {
- type: 'dropdown' | 'collapse';
+ popoverPosition: 'bottom' | 'top';
props: CellContext;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `product-category#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-product-category#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -91,10 +118,17 @@ const ProductCategoryTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: searchValue, nameSort: '' },
- paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' },
+ initial: {
+ search: searchValue,
+ },
+ paramMap: {
+ page: 'page',
+ pageSize: 'limit',
+ },
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: productCategories,
isLoading,
@@ -105,71 +139,15 @@ const ProductCategoryTable = () => {
);
const deleteModal = useModal();
-
const [selectedProductCategory, setSelectedProductCategory] = useState<
ProductCategory | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const productCategoryColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'code',
- header: 'Code',
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedProductCategory(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ setSearchValue(e.target.value);
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -191,15 +169,51 @@ const ProductCategoryTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- setSearchValue(e.target.value);
- updateFilter('search', e.target.value);
- };
+ const productCategoryColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'code',
+ header: 'Code',
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
- setPageSize(newVal.value as number);
- };
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
+
+ const deleteClickHandler = () => {
+ setSelectedProductCategory(props.row.original);
+ deleteModal.openModal();
+ };
+
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
useEffect(() => {
// Store current path on mount
@@ -223,91 +237,86 @@ const ProductCategoryTable = () => {
};
}, [resetSearchValue]);
- useEffect(() => {
- const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
- if (!isNameSorted) {
- updateFilter('nameSort', '');
- } else {
- updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
- }
- }, [sorting, updateFilter]);
-
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+
+ {/* Search */}
+
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={
- isResponseSuccess(productCategories) ? productCategories?.data : []
- }
- columns={productCategoryColumns}
- pageSize={tableFilterState.pageSize}
- page={
- isResponseSuccess(productCategories)
- ? productCategories?.meta?.page
- : 0
- }
- totalItems={
- isResponseSuccess(productCategories)
- ? productCategories?.meta?.total_results
- : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(productCategories) &&
- productCategories?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+
+ {/* Table Section */}
+
+
+ data={
+ isResponseSuccess(productCategories)
+ ? productCategories?.data
+ : []
+ }
+ columns={productCategoryColumns}
+ pageSize={tableFilterState.pageSize}
+ page={
+ isResponseSuccess(productCategories)
+ ? productCategories?.meta?.page
+ : 0
+ }
+ totalItems={
+ isResponseSuccess(productCategories)
+ ? productCategories?.meta?.total_results
+ : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(productCategories) &&
+ productCategories?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
+
{
className='px-3 py-2.5 w-fit text-sm text-base-100 rounded-lg shadow-sm'
>
- Tambah Produk
+ Add Product
diff --git a/src/components/pages/master-data/production-standard/ProductionStandardTable.tsx b/src/components/pages/master-data/production-standard/ProductionStandardTable.tsx
index a8df6ae8..09e83fd1 100644
--- a/src/components/pages/master-data/production-standard/ProductionStandardTable.tsx
+++ b/src/components/pages/master-data/production-standard/ProductionStandardTable.tsx
@@ -1,92 +1,121 @@
'use client';
-import Button from '@/components/Button';
-import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
-import { ProductionStandard } from '@/types/api/master-data/production-standard';
-import { Icon } from '@iconify/react';
+import { useMemo, useState } from 'react';
import useSWR from 'swr';
-import { ProductionStandardApi } from '@/services/api/master-data';
-import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
-import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
-import { CellContext } from '@tanstack/react-table';
-import { useModal } from '@/components/Modal';
-import { useState } from 'react';
-import RowDropdownOptions from '@/components/table/RowDropdownOptions';
-import RowCollapseOptions from '@/components/table/RowCollapseOptions';
-import ConfirmationModal from '@/components/modal/ConfirmationModal';
+import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
import toast from 'react-hot-toast';
-import { cn } from '@/lib/helper';
+
+import { Icon } from '@iconify/react';
+import Table from '@/components/Table';
+import Button from '@/components/Button';
+import { useModal } from '@/components/Modal';
+import ConfirmationModal from '@/components/modal/ConfirmationModal';
import RequirePermission from '@/components/helper/RequirePermission';
+import PopoverButton from '@/components/popover/PopoverButton';
+import PopoverContent from '@/components/popover/PopoverContent';
+
+import { ProductionStandard } from '@/types/api/master-data/production-standard';
+import { ProductionStandardApi } from '@/services/api/master-data';
+import { cn } from '@/lib/helper';
+import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
const RowOptionsMenu = ({
- type = 'dropdown',
+ popoverPosition = 'bottom',
props,
deleteClickHandler,
}: {
- type: 'dropdown' | 'collapse';
+ popoverPosition: 'bottom' | 'top';
props: CellContext;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `production-standard#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-production-standard#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
const ProductionStandardTable = () => {
- const deleteModal = useModal();
+ const [sorting, setSorting] = useState([]);
+ const {
+ data: productionStandards,
+ isLoading,
+ mutate: refreshProductionStandards,
+ } = useSWR(
+ `${ProductionStandardApi.basePath}`,
+ ProductionStandardApi.getAllFetcher
+ );
+
+ const deleteModal = useModal();
const [selectedProductionStandard, setSelectedProductionStandard] = useState<
ProductionStandard | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const { data: productionStandards, mutate: refreshProductionStandards } =
- useSWR(
- `${ProductionStandardApi.basePath}`,
- ProductionStandardApi.getAllFetcher
- );
-
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -107,112 +136,107 @@ const ProductionStandardTable = () => {
setIsDeleteLoading(false);
};
+ const productionStandardColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) => props.row.index + 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorFn: (row) => row.project_category ?? '-',
+ header: 'Kategori',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
+
+ const deleteClickHandler = () => {
+ setSelectedProductionStandard(props.row.original);
+ deleteModal.openModal();
+ };
+
+ return (
+
+ );
+ },
+ },
+ ],
+ [deleteModal]
+ );
+
return (
<>
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
-
+
+ {/* Table Section */}
+
data={
isResponseSuccess(productionStandards)
? productionStandards.data
: []
}
- columns={[
- {
- header: 'No',
- accessorFn: (row, index) => index + 1,
- },
- {
- header: 'Nama',
- accessorKey: 'name',
- },
- {
- header: 'Kategori',
- accessorFn: (row) => row.project_category,
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize =
- props.table.getPaginationRowModel().rows.length;
- const currentPageRows =
- props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows =
- currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedProductionStandard(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ]}
+ columns={productionStandardColumns}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
className={{
- headerColumnClassName: cn(
- TABLE_DEFAULT_STYLING.headerColumnClassName,
- 'last:flex last:flex-row last:justify-end'
- ),
- bodyColumnClassName: cn(
- TABLE_DEFAULT_STYLING.bodyColumnClassName,
- 'last:flex last:flex-row last:justify-end'
- ),
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(productionStandards) &&
+ productionStandards?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
}}
/>
-
+
-
-
-
+
+
>
);
};
diff --git a/src/components/pages/master-data/supplier/SupplierTable.tsx b/src/components/pages/master-data/supplier/SupplierTable.tsx
index 2620c9e6..e5b225ec 100644
--- a/src/components/pages/master-data/supplier/SupplierTable.tsx
+++ b/src/components/pages/master-data/supplier/SupplierTable.tsx
@@ -1,87 +1,102 @@
'use client';
-import Button from '@/components/Button';
+import { ChangeEventHandler, useMemo, useState } from 'react';
+import useSWR from 'swr';
+import { CellContext, ColumnDef, SortingState } from '@tanstack/react-table';
+import toast from 'react-hot-toast';
+
+import { Icon } from '@iconify/react';
+import Table from '@/components/Table';
import DebouncedTextInput from '@/components/input/DebouncedTextInput';
-import SelectInput, { OptionType } from '@/components/input/SelectInput';
+import Button from '@/components/Button';
import { useModal } from '@/components/Modal';
import ConfirmationModal from '@/components/modal/ConfirmationModal';
-import Table from '@/components/Table';
-import RowCollapseOptions from '@/components/table/RowCollapseOptions';
-import RowDropdownOptions from '@/components/table/RowDropdownOptions';
-import RowOptionsMenuWrapper from '@/components/table/RowOptionsMenuWrapper';
import RequirePermission from '@/components/helper/RequirePermission';
-import { ROWS_OPTIONS } from '@/config/constant';
-import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
-import { cn } from '@/lib/helper';
-import { SupplierApi } from '@/services/api/master-data';
-import { useTableFilter } from '@/services/hooks/useTableFilter';
-import { Supplier } from '@/types/api/master-data/supplier';
-import { Icon } from '@iconify/react';
-import { CellContext, ColumnDef } from '@tanstack/react-table';
-import { useState } from 'react';
-import toast from 'react-hot-toast';
-import useSWR from 'swr';
+import PopoverButton from '@/components/popover/PopoverButton';
+import PopoverContent from '@/components/popover/PopoverContent';
-const RowOptions = ({
- type = 'dropdown',
+import { Supplier } from '@/types/api/master-data/supplier';
+import { SupplierApi } from '@/services/api/master-data';
+import { cn } from '@/lib/helper';
+import { isResponseError, isResponseSuccess } from '@/lib/api-helper';
+import { useTableFilter } from '@/services/hooks/useTableFilter';
+
+const RowOptionsMenu = ({
+ popoverPosition = 'bottom',
props,
deleteClickHandler,
}: {
- type: 'dropdown' | 'collapse';
+ popoverPosition: 'bottom' | 'top';
props: CellContext;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `supplier#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-supplier#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -93,15 +108,17 @@ const SuppliersTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '' },
+ initial: {
+ search: '',
+ },
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
},
});
- // Fetch Data
+ const [sorting, setSorting] = useState([]);
+
const {
data: suppliers,
isLoading,
@@ -111,97 +128,16 @@ const SuppliersTable = () => {
SupplierApi.getAllFetcher
);
- // State
const deleteModal = useModal();
const [selectedSupplier, setSelectedSupplier] = useState<
Supplier | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- // Columns Definition
- const suppliersColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'alias',
- header: 'Alias',
- },
- {
- accessorKey: 'pic',
- header: 'Nama PIC',
- },
- {
- accessorKey: 'category',
- header: 'Kategori',
- },
- {
- accessorKey: 'type',
- header: 'Tipe',
- },
- {
- accessorKey: 'phone',
- header: 'No. Telp',
- },
- {
- accessorKey: 'email',
- header: 'Email',
- },
- {
- accessorKey: 'address',
- header: 'Alamat',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedSupplier(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
-
- // Handler
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -221,82 +157,146 @@ const SuppliersTable = () => {
toast.success('Successfully delete Supplier!');
setIsDeleteLoading(false);
};
- const searchChangeHandler = (e: React.ChangeEvent) => {
- updateFilter('search', e.target.value);
- };
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
- setPageSize(newVal.value as number);
- };
+
+ const suppliersColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorKey: 'alias',
+ header: 'Alias',
+ },
+ {
+ accessorKey: 'pic',
+ header: 'Nama PIC',
+ },
+ {
+ accessorKey: 'category',
+ header: 'Kategori',
+ },
+ {
+ accessorKey: 'type',
+ header: 'Tipe',
+ },
+ {
+ accessorKey: 'phone',
+ header: 'No. Telp',
+ },
+ {
+ accessorKey: 'email',
+ header: 'Email',
+ },
+ {
+ accessorKey: 'address',
+ header: 'Alamat',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
+
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
+
+ const deleteClickHandler = () => {
+ setSelectedSupplier(props.row.original);
+ deleteModal.openModal();
+ };
+
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(suppliers) ? suppliers?.data : []}
- columns={suppliersColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(suppliers) ? suppliers?.meta?.page : 0}
- totalItems={
- isResponseSuccess(suppliers) ? suppliers?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(suppliers) && suppliers?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(suppliers) ? suppliers?.data : []}
+ columns={suppliersColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(suppliers) ? suppliers?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(suppliers) ? suppliers?.meta?.total_results : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(suppliers) && suppliers?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `uom#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-uom#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -87,10 +108,17 @@ const UomsTable = () => {
setPageSize,
toQueryString: getTableFilterQueryString,
} = useTableFilter({
- initial: { search: '', nameSort: '' },
- paramMap: { page: 'page', pageSize: 'limit', nameSort: 'sort_name' },
+ initial: {
+ search: '',
+ },
+ paramMap: {
+ page: 'page',
+ pageSize: 'limit',
+ },
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: uoms,
isLoading,
@@ -101,65 +129,12 @@ const UomsTable = () => {
);
const deleteModal = useModal();
-
const [selectedUom, setSelectedUom] = useState(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const uomsColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedUom(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -179,93 +154,112 @@ const UomsTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const uomsColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedUom(props.row.original);
+ deleteModal.openModal();
+ };
- // track sorting
- useEffect(() => {
- const isNameSorted = sorting.find((sortItem) => sortItem.id === 'name');
-
- if (!isNameSorted) {
- updateFilter('nameSort', '');
- } else {
- updateFilter('nameSort', isNameSorted.desc ? 'desc' : 'asc');
- }
- }, [sorting, updateFilter]);
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
+ );
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(uoms) ? uoms?.data : []}
- columns={uomsColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(uoms) ? uoms?.meta?.page : 0}
- totalItems={isResponseSuccess(uoms) ? uoms?.meta?.total_results : 0}
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20': isResponseSuccess(uoms) && uoms?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(uoms) ? uoms?.data : []}
+ columns={uomsColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(uoms) ? uoms?.meta?.page : 0}
+ totalItems={isResponseSuccess(uoms) ? uoms?.meta?.total_results : 0}
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full': isResponseSuccess(uoms) && uoms?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+
;
deleteClickHandler: () => void;
}) => {
+ const popoverId = `warehouse#${props.row.original.id}`;
+ const popoverAnchorName = `--anchor-warehouse#${props.row.original.id}`;
+
+ const closePopover = () => {
+ document.getElementById(popoverId)?.hidePopover();
+ };
+
return (
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
@@ -94,23 +110,15 @@ const WarehousesTable = () => {
} = useTableFilter({
initial: {
search: '',
- nameSort: '',
- typeSort: '',
- areaSort: '',
- locationSort: '',
- kandangSort: '',
},
paramMap: {
page: 'page',
pageSize: 'limit',
- nameSort: 'sort_name',
- typeSort: 'sort_type',
- areaSort: ' sort_area',
- locationSort: ' sort_location',
- kandangSort: ' sort_kandang',
},
});
+ const [sorting, setSorting] = useState([]);
+
const {
data: warehouses,
isLoading,
@@ -121,101 +129,14 @@ const WarehousesTable = () => {
);
const deleteModal = useModal();
-
const [selectedWarehouse, setSelectedWarehouse] = useState<
Warehouse | undefined
>(undefined);
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
- const [sorting, setSorting] = useState([]);
-
- const warehousesColumns: ColumnDef[] = [
- {
- header: '#',
- cell: (props) =>
- tableFilterState.pageSize * (tableFilterState.page - 1) +
- props.row.index +
- 1,
- },
- {
- accessorKey: 'name',
- header: 'Nama',
- },
- {
- accessorKey: 'type',
- header: 'Tipe',
- },
- {
- accessorKey: 'area',
- header: 'Area',
- cell: (props) => props.row.original.area.name,
- },
- {
- accessorKey: 'location',
- header: 'Lokasi',
- cell: (props) => {
- if (
- props.row.original.type === 'LOKASI' ||
- props.row.original.type === 'KANDANG'
- ) {
- return props.row.original.location.name;
- } else {
- return '-';
- }
- },
- },
- {
- accessorKey: 'kandang',
- header: 'Kandang',
- cell: (props) => {
- if (props.row.original.type === 'KANDANG') {
- return props.row.original.kandang.name;
- } else {
- return '-';
- }
- },
- },
- {
- header: 'Aksi',
- cell: (props) => {
- const currentPageSize = props.table.getPaginationRowModel().rows.length;
- const currentPageRows = props.table.getPaginationRowModel().flatRows;
- const currentRowRelativeIndex =
- currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
-
- const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
-
- const deleteClickHandler = () => {
- setSelectedWarehouse(props.row.original);
- deleteModal.openModal();
- };
-
- return (
- <>
- {currentPageSize > 2 && (
-
-
-
- )}
-
- {currentPageSize <= 2 && (
-
-
-
- )}
- >
- );
- },
- },
- ];
+ const searchChangeHandler: ChangeEventHandler = (e) => {
+ updateFilter('search', e.target.value);
+ };
const confirmationModalDeleteClickHandler = async () => {
setIsDeleteLoading(true);
@@ -237,118 +158,149 @@ const WarehousesTable = () => {
setIsDeleteLoading(false);
};
- const searchChangeHandler: ChangeEventHandler = (e) => {
- updateFilter('search', e.target.value);
- };
+ const warehousesColumns: ColumnDef[] = useMemo(
+ () => [
+ {
+ header: 'No',
+ cell: (props) =>
+ tableFilterState.pageSize * (tableFilterState.page - 1) +
+ props.row.index +
+ 1,
+ },
+ {
+ accessorKey: 'name',
+ header: 'Nama',
+ },
+ {
+ accessorKey: 'type',
+ header: 'Tipe',
+ },
+ {
+ accessorFn: (row) => row.area?.name ?? '-',
+ header: 'Area',
+ },
+ {
+ accessorKey: 'location',
+ header: 'Lokasi',
+ cell: (props) => {
+ if (
+ props.row.original.type === 'LOKASI' ||
+ props.row.original.type === 'KANDANG'
+ ) {
+ return props.row.original.location?.name ?? '-';
+ }
+ return '-';
+ },
+ },
+ {
+ accessorKey: 'kandang',
+ header: 'Kandang',
+ cell: (props) => {
+ if (props.row.original.type === 'KANDANG') {
+ return props.row.original.kandang?.name ?? '-';
+ }
+ return '-';
+ },
+ },
+ {
+ header: 'Aksi',
+ cell: (props: CellContext) => {
+ const currentPageSize =
+ props.table.getPaginationRowModel().rows.length;
+ const currentPageRows = props.table.getPaginationRowModel().flatRows;
+ const currentRowRelativeIndex =
+ currentPageRows.findIndex((r) => r.id === props.row.id) + 1;
- const pageSizeChangeHandler = (val: OptionType | OptionType[] | null) => {
- const newVal = val as OptionType;
+ const isLast2Rows = currentRowRelativeIndex > currentPageSize - 2;
- setPageSize(newVal.value as number);
- };
+ const deleteClickHandler = () => {
+ setSelectedWarehouse(props.row.original);
+ deleteModal.openModal();
+ };
- const updateSortingFilter = useCallback(
- (
- sortName: Exclude,
- sortFilter: ColumnSort | undefined
- ) => {
- if (!sortFilter) {
- updateFilter(sortName, '');
- } else {
- updateFilter(sortName, sortFilter.desc ? 'desc' : 'asc');
- }
- },
- [updateFilter]
+ return (
+
+ );
+ },
+ },
+ ],
+ [tableFilterState.pageSize, tableFilterState.page, deleteModal]
);
- // track sorting
- useEffect(() => {
- const nameSortFilter = sorting.find((sortItem) => sortItem.id === 'name');
- const typeSortFilter = sorting.find((sortItem) => sortItem.id === 'type');
- const areaSortFilter = sorting.find((sortItem) => sortItem.id === 'area');
- const locationSortFilter = sorting.find(
- (sortItem) => sortItem.id === 'location'
- );
- const kandangSortFilter = sorting.find(
- (sortItem) => sortItem.id === 'kandang'
- );
-
- updateSortingFilter('nameSort', nameSortFilter);
- updateSortingFilter('typeSort', typeSortFilter);
- updateSortingFilter('areaSort', areaSortFilter);
- updateSortingFilter('locationSort', locationSortFilter);
- updateSortingFilter('kandangSort', kandangSortFilter);
- }, [sorting, updateSortingFilter]);
-
return (
<>
-
-
-
-
-
-
-
-
+
+ {/* Header Section */}
+
+ {/* Action Buttons */}
+
+
+
+
+
+ {/* Search */}
+
-
-
-
-
+ }
+ className={{
+ wrapper: 'w-full min-w-24 max-w-3xs',
+ inputWrapper: 'rounded-xl! shadow-button-soft',
+ input:
+ 'placeholder:font-semibold placeholder:text-base-content/50',
}}
- onChange={pageSizeChangeHandler}
- className={{ wrapper: 'max-w-28' }}
/>
-
- data={isResponseSuccess(warehouses) ? warehouses?.data : []}
- columns={warehousesColumns}
- pageSize={tableFilterState.pageSize}
- page={isResponseSuccess(warehouses) ? warehouses?.meta?.page : 0}
- totalItems={
- isResponseSuccess(warehouses) ? warehouses?.meta?.total_results : 0
- }
- onPageChange={setPage}
- isLoading={isLoading}
- sorting={sorting}
- setSorting={setSorting}
- className={{
- containerClassName: cn({
- 'mb-20':
- isResponseSuccess(warehouses) && warehouses?.data?.length === 0,
- }),
- tableWrapperClassName: 'overflow-x-auto min-h-full!',
- tableClassName: 'font-inter w-full table-auto min-h-full!',
- headerRowClassName: 'border-b border-b-gray-200',
- headerColumnClassName:
- 'px-6 py-3 text-xs font-semibold text-gray-500 last:flex last:flex-row last:justify-end',
- bodyRowClassName: 'border-b border-b-gray-200',
- bodyColumnClassName:
- 'px-6 py-3 last:flex last:flex-row last:justify-end',
- }}
- />
+ {/* Table Section */}
+
+
+ data={isResponseSuccess(warehouses) ? warehouses?.data : []}
+ columns={warehousesColumns}
+ pageSize={tableFilterState.pageSize}
+ page={isResponseSuccess(warehouses) ? warehouses?.meta?.page : 0}
+ totalItems={
+ isResponseSuccess(warehouses)
+ ? warehouses?.meta?.total_results
+ : 0
+ }
+ onPageChange={setPage}
+ onPageSizeChange={setPageSize}
+ isLoading={isLoading}
+ sorting={sorting}
+ setSorting={setSorting}
+ className={{
+ containerClassName: cn('p-3 mb-0', {
+ 'w-full':
+ isResponseSuccess(warehouses) &&
+ warehouses?.data?.length === 0,
+ }),
+ headerColumnClassName: 'text-nowrap',
+ }}
+ />
+