mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-62): implement bulk removal functionality for selected products and ekspedisi in MovementForm
This commit is contained in:
@@ -38,6 +38,8 @@ interface MovementFormProps {
|
||||
|
||||
const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
const [, setMovementFormErrorMessage] = useState('');
|
||||
const [selectedProducts, setSelectedProducts] = useState<number[]>([]);
|
||||
const [selectedEkspedisi, setSelectedEkspedisi] = useState<number[]>([]);
|
||||
|
||||
const {
|
||||
deleteModal,
|
||||
@@ -120,6 +122,15 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
[formik]
|
||||
);
|
||||
|
||||
const bulkRemoveProduct = useCallback(() => {
|
||||
const updatedProducts =
|
||||
formik.values.product?.filter(
|
||||
(_, idx) => !selectedProducts.includes(idx)
|
||||
) ?? [];
|
||||
formik.setFieldValue('product', updatedProducts);
|
||||
setSelectedProducts([]);
|
||||
}, [formik, selectedProducts]);
|
||||
|
||||
const addEkspedisi = () => {
|
||||
const newEkspedisi = [
|
||||
...(formik.values.ekspedisi || []),
|
||||
@@ -157,6 +168,15 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
[formik]
|
||||
);
|
||||
|
||||
const bulkRemoveEkspedisi = useCallback(() => {
|
||||
const updatedEkspedisi =
|
||||
formik.values.ekspedisi?.filter(
|
||||
(_, idx) => !selectedEkspedisi.includes(idx)
|
||||
) ?? [];
|
||||
formik.setFieldValue('ekspedisi', updatedEkspedisi);
|
||||
setSelectedEkspedisi([]);
|
||||
}, [formik, selectedEkspedisi]);
|
||||
|
||||
const isRepeaterInputError = <T extends 'product' | 'ekspedisi'>(
|
||||
arrayName: T,
|
||||
column: T extends 'product' ? keyof ProductSchema : keyof EkspedisiSchema,
|
||||
@@ -333,6 +353,29 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
<table className='table'>
|
||||
<thead>
|
||||
<tr>
|
||||
{type !== 'detail' && (
|
||||
<th>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='checkbox'
|
||||
checked={
|
||||
formik.values.product?.length ===
|
||||
selectedProducts.length &&
|
||||
formik.values.product?.length > 0
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedProducts(
|
||||
formik.values.product?.map((_, idx) => idx) ??
|
||||
[]
|
||||
);
|
||||
} else {
|
||||
setSelectedProducts([]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</th>
|
||||
)}
|
||||
<th>Produk</th>
|
||||
<th>Qty</th>
|
||||
{type !== 'detail' && <th>Aksi</th>}
|
||||
@@ -341,6 +384,27 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
<tbody>
|
||||
{formik.values.product?.map((product, idx) => (
|
||||
<tr key={`product-row-${idx}-${product.product_id}`}>
|
||||
{type !== 'detail' && (
|
||||
<td>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='checkbox'
|
||||
checked={selectedProducts.includes(idx)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedProducts([
|
||||
...selectedProducts,
|
||||
idx,
|
||||
]);
|
||||
} else {
|
||||
setSelectedProducts(
|
||||
selectedProducts.filter((i) => i !== idx)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<SelectInput
|
||||
required
|
||||
@@ -407,15 +471,32 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
</table>
|
||||
</div>
|
||||
{type !== 'detail' && (
|
||||
<Button
|
||||
type='button'
|
||||
color='success'
|
||||
onClick={addProduct}
|
||||
className='w-fit mx-auto mt-4'
|
||||
>
|
||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||
Tambah Produk
|
||||
</Button>
|
||||
<div className='flex justify-center items-center mt-4 gap-4'>
|
||||
{selectedProducts.length > 0 && (
|
||||
<Button
|
||||
type='button'
|
||||
color='error'
|
||||
onClick={bulkRemoveProduct}
|
||||
className='w-fit'
|
||||
>
|
||||
<Icon
|
||||
icon='material-symbols:delete-outline-rounded'
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
Hapus Produk Terpilih ({selectedProducts.length})
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type='button'
|
||||
color='success'
|
||||
onClick={addProduct}
|
||||
className='w-fit'
|
||||
>
|
||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||
Tambah Produk
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
@@ -428,6 +509,30 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
<table className='table'>
|
||||
<thead>
|
||||
<tr>
|
||||
{type !== 'detail' && (
|
||||
<th>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='checkbox'
|
||||
checked={
|
||||
formik.values.ekspedisi?.length ===
|
||||
selectedEkspedisi.length &&
|
||||
formik.values.ekspedisi?.length > 0
|
||||
}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedEkspedisi(
|
||||
formik.values.ekspedisi?.map(
|
||||
(_, idx) => idx
|
||||
) ?? []
|
||||
);
|
||||
} else {
|
||||
setSelectedEkspedisi([]);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</th>
|
||||
)}
|
||||
<th>Produk</th>
|
||||
<th>Qty</th>
|
||||
<th>Supplier</th>
|
||||
@@ -444,6 +549,27 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
<tr
|
||||
key={`ekspedisi-row-${idx}-${ekspedisi.product_id}-${ekspedisi.supplier_id}`}
|
||||
>
|
||||
{type !== 'detail' && (
|
||||
<td>
|
||||
<input
|
||||
type='checkbox'
|
||||
className='checkbox'
|
||||
checked={selectedEkspedisi.includes(idx)}
|
||||
onChange={(e) => {
|
||||
if (e.target.checked) {
|
||||
setSelectedEkspedisi([
|
||||
...selectedEkspedisi,
|
||||
idx,
|
||||
]);
|
||||
} else {
|
||||
setSelectedEkspedisi(
|
||||
selectedEkspedisi.filter((i) => i !== idx)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</td>
|
||||
)}
|
||||
<td>
|
||||
<SelectInput
|
||||
required
|
||||
@@ -634,15 +760,33 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||
</table>
|
||||
</div>
|
||||
{type !== 'detail' && (
|
||||
<Button
|
||||
type='button'
|
||||
color='success'
|
||||
onClick={addEkspedisi}
|
||||
className='w-fit mx-auto mt-4'
|
||||
>
|
||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||
Tambah Ekspedisi
|
||||
</Button>
|
||||
<div className='flex justify-center items-center mt-4 gap-4'>
|
||||
{selectedEkspedisi.length > 0 && (
|
||||
<Button
|
||||
type='button'
|
||||
color='error'
|
||||
onClick={bulkRemoveEkspedisi}
|
||||
disabled={selectedEkspedisi.length === 0}
|
||||
className='w-fit'
|
||||
>
|
||||
<Icon
|
||||
icon='material-symbols:delete-outline-rounded'
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
Hapus Ekspedisi Terpilih ({selectedEkspedisi.length})
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
type='button'
|
||||
color='success'
|
||||
onClick={addEkspedisi}
|
||||
className='w-fit'
|
||||
>
|
||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||
Tambah Ekspedisi
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user