mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-87): slicing ui multiple approval checkbox and approval modal confirmation
This commit is contained in:
@@ -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,14 +313,28 @@ 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'
|
||||||
placeholder='Cari Area'
|
placeholder='Cari Area'
|
||||||
value={tableFilterState.search}
|
value={tableFilterState.search}
|
||||||
onChange={searchChangeHandler}
|
onChange={searchChangeHandler}
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full sm:max-w-3xs',
|
wrapper: 'w-full sm:max-w-3xs',
|
||||||
input: 'w-full',
|
input: 'w-full',
|
||||||
inputWrapper: 'w-full',
|
inputWrapper: 'w-full',
|
||||||
}}
|
}}
|
||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user