mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-26 00:05:45 +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 MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
||||||
const [, setMovementFormErrorMessage] = useState('');
|
const [, setMovementFormErrorMessage] = useState('');
|
||||||
|
const [selectedProducts, setSelectedProducts] = useState<number[]>([]);
|
||||||
|
const [selectedEkspedisi, setSelectedEkspedisi] = useState<number[]>([]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
deleteModal,
|
deleteModal,
|
||||||
@@ -120,6 +122,15 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
[formik]
|
[formik]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const bulkRemoveProduct = useCallback(() => {
|
||||||
|
const updatedProducts =
|
||||||
|
formik.values.product?.filter(
|
||||||
|
(_, idx) => !selectedProducts.includes(idx)
|
||||||
|
) ?? [];
|
||||||
|
formik.setFieldValue('product', updatedProducts);
|
||||||
|
setSelectedProducts([]);
|
||||||
|
}, [formik, selectedProducts]);
|
||||||
|
|
||||||
const addEkspedisi = () => {
|
const addEkspedisi = () => {
|
||||||
const newEkspedisi = [
|
const newEkspedisi = [
|
||||||
...(formik.values.ekspedisi || []),
|
...(formik.values.ekspedisi || []),
|
||||||
@@ -157,6 +168,15 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
[formik]
|
[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'>(
|
const isRepeaterInputError = <T extends 'product' | 'ekspedisi'>(
|
||||||
arrayName: T,
|
arrayName: T,
|
||||||
column: T extends 'product' ? keyof ProductSchema : keyof EkspedisiSchema,
|
column: T extends 'product' ? keyof ProductSchema : keyof EkspedisiSchema,
|
||||||
@@ -333,6 +353,29 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<table className='table'>
|
<table className='table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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>Produk</th>
|
||||||
<th>Qty</th>
|
<th>Qty</th>
|
||||||
{type !== 'detail' && <th>Aksi</th>}
|
{type !== 'detail' && <th>Aksi</th>}
|
||||||
@@ -341,6 +384,27 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<tbody>
|
<tbody>
|
||||||
{formik.values.product?.map((product, idx) => (
|
{formik.values.product?.map((product, idx) => (
|
||||||
<tr key={`product-row-${idx}-${product.product_id}`}>
|
<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>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
@@ -407,15 +471,32 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
|
<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
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='success'
|
color='success'
|
||||||
onClick={addProduct}
|
onClick={addProduct}
|
||||||
className='w-fit mx-auto mt-4'
|
className='w-fit'
|
||||||
>
|
>
|
||||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
Tambah Produk
|
Tambah Produk
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -428,6 +509,30 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<table className='table'>
|
<table className='table'>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<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>Produk</th>
|
||||||
<th>Qty</th>
|
<th>Qty</th>
|
||||||
<th>Supplier</th>
|
<th>Supplier</th>
|
||||||
@@ -444,6 +549,27 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
<tr
|
<tr
|
||||||
key={`ekspedisi-row-${idx}-${ekspedisi.product_id}-${ekspedisi.supplier_id}`}
|
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>
|
<td>
|
||||||
<SelectInput
|
<SelectInput
|
||||||
required
|
required
|
||||||
@@ -634,15 +760,33 @@ const MovementForm = ({ type = 'add', initialValues }: MovementFormProps) => {
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{type !== 'detail' && (
|
{type !== 'detail' && (
|
||||||
|
<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
|
<Button
|
||||||
type='button'
|
type='button'
|
||||||
color='success'
|
color='success'
|
||||||
onClick={addEkspedisi}
|
onClick={addEkspedisi}
|
||||||
className='w-fit mx-auto mt-4'
|
className='w-fit'
|
||||||
>
|
>
|
||||||
<Icon icon='ic:round-plus' width={24} height={24} />
|
<Icon icon='ic:round-plus' width={24} height={24} />
|
||||||
Tambah Ekspedisi
|
Tambah Ekspedisi
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user