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] =
useState<ProjectFlock>();
const deleteModal = useModal();
const confirmModal = useModal();
const [isDeleteLoading, setIsDeleteLoading] = useState(false);
const [selectedIds, setSelectedIds] = useState<number[]>([]);
const [selectedFlocks, setSelectedFlocks] = useState<ProjectFlock[]>([]);
// Columns
const projectFlocksColumns: ColumnDef<ProjectFlock>[] = [
{
header: '#',
cell: (props) =>
tableFilterState.pageSize * (tableFilterState.page - 1) +
props.row.index +
1,
id: 'select',
header: () => {
const allSelected =
isResponseSuccess(projectFlocks) &&
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',
header: 'Flock',
@@ -226,11 +254,9 @@ const ProjectFlockTable = () => {
toast.success('Successfully delete Project Flock!');
setIsDeleteLoading(false);
};
const searchChangeHandler: ChangeEventHandler<HTMLInputElement> = (e) => {
updateFilter('search', e.target.value);
};
const updateSortingFilter = useCallback(
(
sortName: Exclude<keyof typeof tableFilterState, 'page' | 'pageSize'>,
@@ -244,6 +270,34 @@ const ProjectFlockTable = () => {
},
[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 (
<>
@@ -259,14 +313,28 @@ const ProjectFlockTable = () => {
<Icon icon='ic:round-plus' width={24} height={24} />
Tambah
</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'>
<DebouncedTextInput
name='search'
placeholder='Cari Area'
value={tableFilterState.search}
onChange={searchChangeHandler}
className={{
wrapper: 'w-full sm:max-w-3xs',
className={{
wrapper: 'w-full sm:max-w-3xs',
input: 'w-full',
inputWrapper: 'w-full',
}}
@@ -323,17 +391,30 @@ const ProjectFlockTable = () => {
</div>
<ConfirmationModal
ref={deleteModal.ref}
type='error'
text={`Apakah anda yakin ingin menghapus data Project Flock ini (${selectedProjectFlock?.flock?.name})?`}
ref={confirmModal.ref}
type='success'
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={{
text: 'Tidak',
}}
primaryButton={{
text: 'Ya',
color: 'error',
isLoading: isDeleteLoading,
onClick: confirmationModalDeleteClickHandler,
color: 'success',
onClick: async () => {
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 = {
name: string;
status: string;
flock: Flock;
flock_id: number;
area: Area;