feat(FE-87): slicing ui multiple approval checkbox and approval modal confirmation

This commit is contained in:
randy-ar
2025-10-18 12:58:18 +07:00
parent a573551110
commit 9964e1797a
2 changed files with 97 additions and 15 deletions
@@ -114,17 +114,45 @@ const ProjectFlockTable = () => {
const [selectedProjectFlock, setSelectedProjectFlock] = const [selectedProjectFlock, setSelectedProjectFlock] =
useState<ProjectFlock>(); useState<ProjectFlock>();
const deleteModal = useModal(); const deleteModal = useModal();
const confirmModal = useModal();
const [isDeleteLoading, setIsDeleteLoading] = useState(false); const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [selectedFlocks, setSelectedFlocks] = useState<ProjectFlock[]>([]);
// Columns // Columns
const projectFlocksColumns: ColumnDef<ProjectFlock>[] = [ const projectFlocksColumns: ColumnDef<ProjectFlock>[] = [
{ {
header: '#', id: 'select',
cell: (props) => header: () => {
tableFilterState.pageSize * (tableFilterState.page - 1) + const allSelected =
props.row.index + isResponseSuccess(projectFlocks) &&
1, projectFlocks.data.length > 0 &&
selectedIds.length === projectFlocks.data.length;
return (
<input
type='checkbox'
className='checkbox checkbox-sm'
checked={allSelected}
onChange={(e) => handleSelectAll(e.target.checked)}
/>
);
},
cell: (props) => {
const id = props.row.original.id;
const isChecked = selectedIds.includes(id);
return (
<input
type='checkbox'
className='checkbox checkbox-sm'
checked={isChecked}
onChange={(e) => handleSelectRow(id, e.target.checked)}
/>
);
},
}, },
{ {
accessorKey: 'flock.name', accessorKey: 'flock.name',
header: 'Flock', header: 'Flock',
@@ -226,11 +254,9 @@ const ProjectFlockTable = () => {
toast.success('Successfully delete Project Flock!'); toast.success('Successfully delete Project Flock!');
setIsDeleteLoading(false); setIsDeleteLoading(false);
}; };
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => { const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
updateFilter('search', e.target.value); updateFilter('search', e.target.value);
}; };
const updateSortingFilter = useCallback( const updateSortingFilter = useCallback(
( (
sortName: Exclude<keyof typeof tableFilterState, 'page' | 'pageSize'>, sortName: Exclude<keyof typeof tableFilterState, 'page' | 'pageSize'>,
@@ -244,6 +270,34 @@ const ProjectFlockTable = () => {
}, },
[updateFilter] [updateFilter]
); );
const handleSelectAll = (checked: boolean) => {
if (checked && isResponseSuccess(projectFlocks)) {
const allIds = projectFlocks.data.map((item) => item.id);
setSelectedIds(allIds);
setSelectedFlocks(projectFlocks.data);
} else {
setSelectedIds([]);
setSelectedFlocks([]);
}
};
const handleSelectRow = (id: number, checked: boolean) => {
if (!isResponseSuccess(projectFlocks)) return;
const targetFlock = projectFlocks.data.find((item) => item.id === id);
if (!targetFlock) return;
if (checked) {
setSelectedIds((prev) => [...prev, id]);
setSelectedFlocks((prev) => [...(prev || []), targetFlock]);
} else {
setSelectedIds((prev) => prev.filter((val) => val !== id));
setSelectedFlocks((prev) =>
(prev || []).filter((flock) => flock.id !== id)
);
}
};
return ( return (
<> <>
@@ -259,6 +313,20 @@ const ProjectFlockTable = () => {
<Icon icon='ic:round-plus' width={24} height={24} /> <Icon icon='ic:round-plus' width={24} height={24} />
Tambah Tambah
</Button> </Button>
<Button
variant='outline'
color='success'
onClick={() => {
if (selectedIds.length > 0) {
confirmModal.openModal();
}
}}
disabled={!(selectedIds.length > 0)}
className='w-full sm:w-fit'
>
<Icon icon='material-symbols:check' width={24} height={24} />
Approve
</Button>
<div className='ms-auto w-full sm:w-auto'> <div className='ms-auto w-full sm:w-auto'>
<DebouncedTextInput <DebouncedTextInput
name='search' name='search'
@@ -323,17 +391,30 @@ const ProjectFlockTable = () => {
</div> </div>
<ConfirmationModal <ConfirmationModal
ref={deleteModal.ref} ref={confirmModal.ref}
type='error' type='success'
text={`Apakah anda yakin ingin menghapus data Project Flock ini (${selectedProjectFlock?.flock?.name})?`} text={
selectedFlocks.length > 0
? `Apakah anda yakin ingin approve Project Flock berikut? (${selectedFlocks
.map(
(flock, index) =>
`${flock.flock?.name ?? '(Tanpa nama)'} - ${
flock.area?.name ?? '-'
}`
)
.join(', ')})`
: 'Tidak ada Project Flock yang dipilih.'
}
secondaryButton={{ secondaryButton={{
text: 'Tidak', text: 'Tidak',
}} }}
primaryButton={{ primaryButton={{
text: 'Ya', text: 'Ya',
color: 'error', color: 'success',
isLoading: isDeleteLoading, onClick: async () => {
onClick: confirmationModalDeleteClickHandler, toast.success('Project Flock berhasil di-approve!');
confirmModal.closeModal();
},
}} }}
/> />
</> </>
+1
View File
@@ -7,6 +7,7 @@ import { ProductCategory } from "@/types/api/master-data/product-category";
export type BaseProjectFlock = { export type BaseProjectFlock = {
name: string; name: string;
status: string;
flock: Flock; flock: Flock;
flock_id: number; flock_id: number;
area: Area; area: Area;