add boxes

This commit is contained in:
Samandar Turg'unboev
2025-06-20 18:28:43 +05:00
parent 75dea29b7b
commit 70b730fb3f

View File

@@ -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}>
{t('products')} <Typography fontSize='18px' sx={{ textAlign: 'start' }} fontWeight={500} color='#5D5850'>
</Typography> {t('products')}
</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,35 +426,27 @@ 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 => {
<Chip return (
key={id} <Chip
label={ key={id}
selectedProductNames[index]?.[id] || label={
itemsList.find(p => p.id === id)?.nameRu || selectedProductNames[index]?.[id] ||
itemsList.find(p => p.id === id)?.name || itemsList.find(p => p.id === id)?.name ||
id itemsList.find(p => p.id === id)?.nameRu ||
} id
onDelete={e => { }
e.stopPropagation(); onDelete={e => {
field.onChange(field.value.filter((x: any) => x !== id)); e.stopPropagation();
handleProductChange(index, { id }, false); field.onChange(field.value.filter((x: any) => x !== id));
}} 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>