accepted items added

This commit is contained in:
Samandar Turg'unboev
2025-06-24 09:34:41 +05:00
parent 70b730fb3f
commit 11faf4a2c9
19 changed files with 957 additions and 325 deletions

View File

@@ -9,6 +9,8 @@ import BasePagination from '@/components/ui-kit/BasePagination';
import { useAuthContext } from '@/context/auth-context';
import { BoxStatus, BoxStatusList, IBox } from '@/data/box/box.model';
import { box_requests } from '@/data/box/box.requests';
import { Product, UpdateProductBodyType } from '@/data/item/item.mode';
import { item_requests } from '@/data/item/item.requests';
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
import useInput from '@/hooks/useInput';
import { useMyNavigation } from '@/hooks/useMyNavigation';
@@ -17,13 +19,32 @@ import useRequest from '@/hooks/useRequest';
import { file_service } from '@/services/file-service';
import { notifyUnknownError } from '@/services/notification';
import { getStatusColor } from '@/theme/getStatusBoxStyles';
import { Add, Circle, Delete, Download, Edit, FilterList, FilterListOff, Search } from '@mui/icons-material';
import { Box, Button, Stack, Typography } from '@mui/material';
import { Add, Circle, Delete, Download, Edit, FilterList, FilterListOff, RemoveRedEye, Search } from '@mui/icons-material';
import { Box, Button, Card, CardContent, Modal, Stack, TextField, Typography } from '@mui/material';
import { useEffect, useMemo, useState } from 'react';
import { useForm } from 'react-hook-form';
type Props = {};
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
border: '2px solid #000',
boxShadow: 24,
display: 'flex',
flexDirection: 'column',
gap: '10px',
p: 4,
};
const DashboardBoxesPage = (props: Props) => {
const [open, setOpen] = useState(false);
const handleOpen = () => setOpen(true);
const handleClose = () => setOpen(false);
const t = useMyTranslation();
const navigation = useMyNavigation();
const { isAdmin } = useAuthContext();
@@ -31,6 +52,7 @@ const DashboardBoxesPage = (props: Props) => {
const [pageSize] = useState(DEFAULT_PAGE_SIZE);
const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined);
const [trackId, setTrackId] = useState<string>();
const [deleteIds, setDeleteIds] = useState<number[]>([]);
const [downloadIds, setDownloadIds] = useState<number[]>([]);
@@ -61,6 +83,31 @@ const DashboardBoxesPage = (props: Props) => {
}
);
const getListQuery = useRequest(
() =>
item_requests.getAll({
page: page,
trekId: trackId,
}),
{
dependencies: [page, trackId],
selectData(data) {
return data.data.data;
},
}
);
const [values, setValues] = useState<{ [trackId: string]: number | '' }>({});
const handleAmountChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, max: number, trackId: string) => {
const val = Number(event.target.value);
if (val >= 1 && val <= max) {
setValues(prev => ({ ...prev, [trackId]: val }));
} else if (event.target.value === '') {
setValues(prev => ({ ...prev, [trackId]: '' }));
}
};
const {
data: list,
totalElements,
@@ -185,6 +232,62 @@ const DashboardBoxesPage = (props: Props) => {
dataKey: 'totalItems',
label: t('count_of_items'),
width: 120,
renderCell: data => {
const getOneBox = useRequest(
() => {
return box_requests.find({ packetId: data.id });
},
{
selectData(data) {
const boxData = data.data.data;
return {
products_list: [
...boxData.items.map(item => {
let name = item.name;
let nameRu = item.nameRu;
return {
id: item.id,
price: item.price,
cargoId: item.cargoId,
trekId: item.trekId,
name: name,
acceptedNumber: item.acceptedNumber,
nameRu: nameRu,
amount: +item.amount,
weight: +item.weight,
};
}),
],
};
},
}
);
return (
<div>
{(() => {
const total = getOneBox.data?.products_list.reduce(
(acc, product) => {
console.log(product, 'totalAccepted');
acc.totalAmount += +product.amount || 0;
acc.totalAccepted += +product.acceptedNumber || 0;
return acc;
},
{ totalAmount: 0, totalAccepted: 0 }
);
return (
<Typography>
{total?.totalAmount} | {total?.totalAccepted}
</Typography>
);
})()}
</div>
);
},
},
{
dataKey: 'totalNetWeight',
@@ -272,6 +375,13 @@ const DashboardBoxesPage = (props: Props) => {
return (
<ActionPopMenu
buttons={[
{
icon: <RemoveRedEye sx={{ path: { color: '#3489E4' } }} />,
label: t('view_packet'),
onClick: () => {
navigation.push(pageLinks.dashboard.boxes.detail(data.id));
},
},
{
icon: <Edit sx={{ path: { color: '#3489E4' } }} />,
label: t('edit'),
@@ -307,6 +417,53 @@ const DashboardBoxesPage = (props: Props) => {
},
},
];
const [items, setItems] = useState<Product>();
const [loaer, setLoading] = useState(false);
const {
register,
control,
handleSubmit,
watch,
setValue,
formState: { errors },
} = useForm<Product>({
defaultValues: {
trekId: items?.trekId,
name: items?.name,
nameRu: items?.nameRu,
amount: items?.amount,
weight: items?.weight,
acceptedNumber: Number(values),
},
});
const updateItems = async (item: Product, acceptedNumber: number) => {
try {
setLoading(true);
const updateBody: UpdateProductBodyType = {
itemId: item.id,
acceptedNumber,
amount: item.amount,
name: item.name,
nameRu: item.nameRu,
trekId: item.trekId,
weight: item.weight,
};
await item_requests.update(updateBody);
// Ma'lumotni yangilab olamiz
getListQuery.refetch();
getBoxesQuery.refetch();
setValues(prev => ({ ...prev, [item.trekId]: '' }));
} catch (error) {
notifyUnknownError(error);
} finally {
setLoading(false);
}
};
return (
<Box>
@@ -314,6 +471,66 @@ const DashboardBoxesPage = (props: Props) => {
<BaseButton colorVariant='blue' startIcon={<Add />} href={pageLinks.dashboard.boxes.create}>
{t('create_packet')}
</BaseButton>
<Button onClick={handleOpen}>{t('product_inspection')}</Button>
<Modal open={open} onClose={handleClose} aria-labelledby='modal-modal-title' aria-describedby='modal-modal-description'>
<Box sx={style}>
<Typography id='modal-modal-title' variant='h6' component='h2'>
{t('product_inspection')}
</Typography>
<Typography id='modal-modal-description' sx={{ mt: 2 }}>
{t('enter_product')}
</Typography>
<TextField
id='outlined-basic'
label={t('track_id')}
variant='outlined'
onChange={e => setTrackId(e.target.value)}
/>
{trackId && trackId.length > 0 && (
<>
{getListQuery.loading ? (
<Typography sx={{ mt: 2 }}>{t('loading')}...</Typography> // yoki <CircularProgress />
) : getListQuery.data?.data && getListQuery.data?.data.length > 0 ? (
getListQuery.data?.data.map(e => (
<Box key={e.id} sx={{ width: '100%', display: 'flex', flexDirection: 'column' }}>
<Card sx={{ minWidth: 275, mb: 2 }}>
<CardContent>
<Typography sx={{ fontSize: 14 }}>
{t('track_id')}: {e.trekId}
</Typography>
<Typography sx={{ fontSize: 14 }}>Nomi: {e.name || e.nameRu}</Typography>
<Typography sx={{ fontSize: 14 }}>Mahsulot soni: {e.amount}</Typography>
<Typography sx={{ fontSize: 14 }}>Paket nomi: {e?.packetName}</Typography>
</CardContent>
</Card>
<TextField
id={`amount-${e.trekId}`}
label='Mahsulot soni'
type='number'
sx={{ width: '100%' }}
value={values[e.trekId] ?? ''}
onChange={change => handleAmountChange(change, e.amount, e.trekId)}
inputProps={{ min: 1, max: e.amount }}
/>
<Button
sx={{ mt: '10px' }}
onClick={() => {
if (values[e.trekId] !== '') {
updateItems(e, Number(values[e.trekId]));
}
}}
>
{t('confirmation')}
</Button>
</Box>
))
) : (
<Typography sx={{ mt: 2 }}>{t('no_products_found') || 'Mahsulot topilmadi'}</Typography>
)}
</>
)}
</Box>
</Modal>
</Stack>
<Box
width={1}