add boxes
This commit is contained in:
@@ -15,6 +15,7 @@ import { notifyUnknownError } from '@/services/notification';
|
|||||||
import { AddCircleRounded, Close } from '@mui/icons-material';
|
import { AddCircleRounded, Close } from '@mui/icons-material';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
Chip,
|
Chip,
|
||||||
CircularProgress,
|
CircularProgress,
|
||||||
@@ -192,20 +193,20 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
const [paketName, setPaketName] = useState<string>('');
|
const [paketName, setPaketName] = useState<string>('');
|
||||||
const PacketRow = ({ index, field }: { index: number; field: any }) => {
|
const PacketRow = ({ index, field }: { index: number; field: any }) => {
|
||||||
const packetId = watch(`packetItemDtos.${index}.packetId`);
|
const packetId = watch(`packetItemDtos.${index}.packetId`);
|
||||||
// Tanlangan paketning name'ini olish
|
|
||||||
const [itemsPage, setItemsPage] = useState(1);
|
const [itemsPage, setItemsPage] = useState(1);
|
||||||
const [itemsList, setItemsList] = useState<any[]>([]);
|
const [itemsList, setItemsList] = useState<any[]>([]);
|
||||||
const [itemsHasMore, setItemsHasMore] = useState(true);
|
const [itemsHasMore, setItemsHasMore] = useState(true);
|
||||||
const itemScrollRef = useRef<HTMLDivElement>(null);
|
const itemScrollRef = useRef<HTMLDivElement>(null);
|
||||||
// Packetlar uchun scroll state
|
|
||||||
const [packetsPage, setPacketsPage] = useState(1);
|
const [packetsPage, setPacketsPage] = useState(1);
|
||||||
const [packetsList, setPacketsList] = useState<any[]>([]);
|
const [packetsList, setPacketsList] = useState<any[]>([]);
|
||||||
const selectedPacket = packetsList.find(p => p.id === packetId);
|
|
||||||
const [packetsHasMore, setPacketsHasMore] = useState(true);
|
const [packetsHasMore, setPacketsHasMore] = useState(true);
|
||||||
|
const [selectedProductNames, setSelectedProductNames] = useState<{ [packetIndex: number]: { [productId: number]: string } }>({});
|
||||||
|
const [paketName, setPaketName] = useState<string>('');
|
||||||
|
const [lastPacketId, setLastPacketId] = useState<number | null>(null);
|
||||||
|
|
||||||
const { isLoading: isLoadingProducts } = useQuery({
|
const { isLoading: isLoadingProducts } = useQuery({
|
||||||
queryKey: ['product-list', packetId, itemsPage],
|
queryKey: ['product-list', packetId, itemsPage],
|
||||||
queryFn: () => item_requests.list({ packetId, page: itemsPage }),
|
queryFn: () => item_requests.getAll({ packetId, page: itemsPage }),
|
||||||
enabled: !!packetId,
|
enabled: !!packetId,
|
||||||
onSuccess: data => {
|
onSuccess: data => {
|
||||||
const newItems = data?.data?.data?.data || [];
|
const newItems = data?.data?.data?.data || [];
|
||||||
@@ -215,7 +216,6 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
|
|
||||||
const packetScrollRef = useRef<HTMLDivElement>(null);
|
const packetScrollRef = useRef<HTMLDivElement>(null);
|
||||||
const [keyword, setKeyword] = useState<string>('');
|
const [keyword, setKeyword] = useState<string>('');
|
||||||
|
|
||||||
const { isFetching: isLoadingPackets } = useQuery({
|
const { isFetching: isLoadingPackets } = useQuery({
|
||||||
queryKey: ['packets-list', partyId, keyword, packetsPage],
|
queryKey: ['packets-list', partyId, keyword, packetsPage],
|
||||||
queryFn: () => box_requests.getAll({ partyId, cargoId: keyword, page: packetsPage }),
|
queryFn: () => box_requests.getAll({ partyId, cargoId: keyword, page: packetsPage }),
|
||||||
@@ -246,46 +246,11 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setItemsPage(1);
|
|
||||||
setItemsList([]);
|
|
||||||
setItemsHasMore(true);
|
|
||||||
}, [packetId]);
|
|
||||||
|
|
||||||
const [selectedProductNames, setSelectedProductNames] = useState<{ [packetIndex: number]: { [productId: number]: string } }>({});
|
|
||||||
|
|
||||||
const handleSelectAll = (checked: boolean, packetIndex: number, packetId: number, itemsList: any[]) => {
|
|
||||||
setSelectedProductNames(prev => {
|
|
||||||
const prevNames = prev[packetIndex] || {};
|
|
||||||
if (checked) {
|
|
||||||
// add all products of current page
|
|
||||||
const newNames = { ...prevNames };
|
|
||||||
itemsList.forEach(p => {
|
|
||||||
newNames[p.id] = p.nameRu || p.name || String(p.id);
|
|
||||||
});
|
|
||||||
return { ...prev, [packetIndex]: newNames };
|
|
||||||
} else {
|
|
||||||
// remove all products of current page
|
|
||||||
const newNames = { ...prevNames };
|
|
||||||
itemsList.forEach(p => {
|
|
||||||
delete newNames[p.id];
|
|
||||||
});
|
|
||||||
return { ...prev, [packetIndex]: newNames };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
setValue(
|
|
||||||
`packetItemDtos.${packetIndex}.itemDtos`,
|
|
||||||
checked
|
|
||||||
? Array.from(new Set([...(watch(`packetItemDtos.${packetIndex}.itemDtos`) || []), ...itemsList.map(p => p.id)]))
|
|
||||||
: (watch(`packetItemDtos.${packetIndex}.itemDtos`) || []).filter(id => !itemsList.some(p => p.id === id))
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleProductChange = (packetIndex: number, product: any, checked: boolean) => {
|
const handleProductChange = (packetIndex: number, product: any, checked: boolean) => {
|
||||||
setSelectedProductNames(prev => {
|
setSelectedProductNames(prev => {
|
||||||
const prevNames = prev[packetIndex] || {};
|
const prevNames = prev[packetIndex] || {};
|
||||||
if (checked) {
|
if (checked) {
|
||||||
return { ...prev, [packetIndex]: { ...prevNames, [product.id]: product.nameRu || product.name || String(product.id) } };
|
return { ...prev, [packetIndex]: { ...prevNames, [product.id]: product.name || product.nameRu || String(product.id) } };
|
||||||
} else {
|
} else {
|
||||||
const newNames = { ...prevNames };
|
const newNames = { ...prevNames };
|
||||||
delete newNames[product.id];
|
delete newNames[product.id];
|
||||||
@@ -294,6 +259,46 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSelectAllProducts = async () => {
|
||||||
|
if (!packetId) return;
|
||||||
|
let allProducts: any[] = [];
|
||||||
|
let page = 1;
|
||||||
|
let totalPages = 1;
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
const res = await item_requests.list({ packetId, page });
|
||||||
|
const data = res?.data?.data;
|
||||||
|
const products = data?.data || [];
|
||||||
|
totalPages = data?.totalPages || 1;
|
||||||
|
allProducts = [...allProducts, ...products];
|
||||||
|
page++;
|
||||||
|
} while (page <= totalPages);
|
||||||
|
} catch (e) {
|
||||||
|
// error silent
|
||||||
|
}
|
||||||
|
if (allProducts.length > 0) {
|
||||||
|
setValue(
|
||||||
|
`packetItemDtos.${index}.itemDtos`,
|
||||||
|
allProducts.map((p: any) => p.id)
|
||||||
|
);
|
||||||
|
setSelectedProductNames((prev: any) => ({
|
||||||
|
...prev,
|
||||||
|
[index]: allProducts.reduce(
|
||||||
|
(acc, p) => ({
|
||||||
|
...acc,
|
||||||
|
[p.id]: p.name || p.nameRu || String(p.id),
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClearAll = () => {
|
||||||
|
setValue(`packetItemDtos.${index}.itemDtos`, []);
|
||||||
|
setSelectedProductNames((prev: any) => ({ ...prev, [index]: {} }));
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box className='item-row' mb={2} display={'flex'} flexDirection={'column'}>
|
<Box className='item-row' mb={2} display={'flex'} flexDirection={'column'}>
|
||||||
<div style={{ width: '100%' }}>
|
<div style={{ width: '100%' }}>
|
||||||
@@ -339,6 +344,11 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
autoFocus: false,
|
autoFocus: false,
|
||||||
}}
|
}}
|
||||||
onClick={e => e.stopPropagation()}
|
onClick={e => e.stopPropagation()}
|
||||||
|
onChange={e => {
|
||||||
|
field.onChange(e);
|
||||||
|
const selected = packetsList.find(p => p.id === e.target.value);
|
||||||
|
setPaketName(selected?.name || '');
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{isLoadingPackets && packetsList.length === 0 ? (
|
{isLoadingPackets && packetsList.length === 0 ? (
|
||||||
<MenuItem disabled>
|
<MenuItem disabled>
|
||||||
@@ -381,22 +391,23 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
|
|
||||||
{packetId && (
|
{packetId && (
|
||||||
<Box mt={2} sx={{ width: '100%' }}>
|
<Box mt={2} sx={{ width: '100%' }}>
|
||||||
<Typography fontSize='18px' sx={{ textAlign: 'start' }} fontWeight={500} color='#5D5850' mb={2}>
|
<Box display='flex' justifyContent='space-between' alignItems='center' mb={2}>
|
||||||
|
<Typography fontSize='18px' sx={{ textAlign: 'start' }} fontWeight={500} color='#5D5850'>
|
||||||
{t('products')}
|
{t('products')}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Box>
|
||||||
|
<Button size='small' color='primary' variant='outlined' sx={{ mr: 1 }} onClick={handleSelectAllProducts}>
|
||||||
|
{t('select_all') || 'Barcha mahsulotni tanlash'}
|
||||||
|
</Button>
|
||||||
|
<Button size='small' color='error' variant='outlined' onClick={handleClearAll}>
|
||||||
|
{t('cancel') || 'Hammasini bekor qilish'}
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
{isLoadingProducts && itemsList.length === 0 ? (
|
{isLoadingProducts && itemsList.length === 0 ? (
|
||||||
<CircularProgress />
|
<CircularProgress />
|
||||||
) : (
|
) : (
|
||||||
<FormControl fullWidth>
|
<FormControl fullWidth>
|
||||||
{/* <Box display='flex' alignItems='center' mb={1}>
|
|
||||||
<Checkbox
|
|
||||||
indeterminate={selectedProducts.length > 0 && selectedProducts.length < itemsList.length}
|
|
||||||
checked={itemsList.length > 0 && selectedProducts.length === itemsList.length}
|
|
||||||
onChange={e => handleSelectAll(e.target.checked)}
|
|
||||||
disabled={itemsList.length === 0}
|
|
||||||
/>
|
|
||||||
<Typography variant='body2'>{t('select_all')}</Typography>
|
|
||||||
</Box> */}
|
|
||||||
<Controller
|
<Controller
|
||||||
name={`packetItemDtos.${index}.itemDtos`}
|
name={`packetItemDtos.${index}.itemDtos`}
|
||||||
control={control}
|
control={control}
|
||||||
@@ -415,13 +426,14 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
}}
|
}}
|
||||||
renderValue={selected => (
|
renderValue={selected => (
|
||||||
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 0.5 }}>
|
||||||
{(selected as any[]).map(id => (
|
{(selected as any[]).map(id => {
|
||||||
|
return (
|
||||||
<Chip
|
<Chip
|
||||||
key={id}
|
key={id}
|
||||||
label={
|
label={
|
||||||
selectedProductNames[index]?.[id] ||
|
selectedProductNames[index]?.[id] ||
|
||||||
itemsList.find(p => p.id === id)?.nameRu ||
|
|
||||||
itemsList.find(p => p.id === id)?.name ||
|
itemsList.find(p => p.id === id)?.name ||
|
||||||
|
itemsList.find(p => p.id === id)?.nameRu ||
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
onDelete={e => {
|
onDelete={e => {
|
||||||
@@ -430,20 +442,11 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
handleProductChange(index, { id }, false);
|
handleProductChange(index, { id }, false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<MenuItem>
|
|
||||||
<Checkbox
|
|
||||||
indeterminate={field.value.length > 0 && field.value.length < itemsList.length}
|
|
||||||
checked={
|
|
||||||
itemsList.length > 0 && itemsList.every((p: any) => field.value.includes(p.id))
|
|
||||||
}
|
|
||||||
onChange={e => handleSelectAll(e.target.checked, index, packetId, itemsList)}
|
|
||||||
/>
|
|
||||||
<Typography variant='body2'>{t('select_all')}</Typography>
|
|
||||||
</MenuItem>
|
|
||||||
{itemsList.map(product => (
|
{itemsList.map(product => (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={product.id}
|
key={product.id}
|
||||||
@@ -462,7 +465,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Checkbox checked={field.value.includes(product.id)} />
|
<Checkbox checked={field.value.includes(product.id)} />
|
||||||
<ListItemText primary={product.nameRu || product.name || product.id} />
|
<ListItemText primary={product.name || product.nameRu || product.id} />
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
|
|||||||
Reference in New Issue
Block a user