Merge branch 'dev' into 'main'

Dev

See merge request azizziy/cpost!39
This commit is contained in:
Azizbek Usmonov
2025-06-26 17:06:17 +05:00
10 changed files with 333 additions and 101 deletions

View File

@@ -3,7 +3,7 @@
import Loader from '@/components/common/Loader'; import Loader from '@/components/common/Loader';
import { Scrollbar } from '@/components/common/Scrollbar'; import { Scrollbar } from '@/components/common/Scrollbar';
import { box_requests } from '@/data/box/box.requests'; import { box_requests } from '@/data/box/box.requests';
import { Box, styled, SxProps, Table, TableBody, TableCell, TableHead, TableRow, Theme } from '@mui/material'; import { Box, styled, type SxProps, Table, TableBody, TableCell, TableHead, TableRow, type Theme } from '@mui/material';
import React from 'react'; import React from 'react';
export interface ColumnData<Data, DataKey = keyof Data> { export interface ColumnData<Data, DataKey = keyof Data> {
@@ -72,39 +72,65 @@ const MyTable = <Data extends { id: number | string }>(props: Props<Data>) => {
const [boxStatuses, setBoxStatuses] = React.useState<Record<string, boolean>>({}); const [boxStatuses, setBoxStatuses] = React.useState<Record<string, boolean>>({});
// Enhanced sorting: completed boxes (green) go to the bottom
const sortedData = React.useMemo(() => {
return [...data].sort((a: any, b: any) => {
const aPrint = a.print ? 1 : 0;
const bPrint = b.print ? 1 : 0;
if (aPrint !== bPrint) {
return aPrint - bPrint; // false (0) avval, true (1) keyin
}
const aStatus = boxStatuses[a.id] ? 1 : 0;
const bStatus = boxStatuses[b.id] ? 1 : 0;
if (aStatus !== bStatus) {
return aStatus - bStatus;
}
return Number(a.id) - Number(b.id); // fallback sort
});
}, [data, boxStatuses]);
React.useEffect(() => { React.useEffect(() => {
const fetchBoxStatuses = async () => { const fetchBoxStatuses = async () => {
if (!data.length || loading) return;
const statuses: Record<string, boolean> = {}; const statuses: Record<string, boolean> = {};
await Promise.all( try {
data.map(async row => { await Promise.all(
try { data.map(async row => {
const res = await box_requests.find({ packetId: row.id }); try {
const boxData = res.data.data; const res = await box_requests.find({ packetId: row.id });
const boxData = res.data.data;
const total = boxData.items.reduce( const total = boxData.items.reduce(
(acc: { totalAmount: number; totalAccepted: number }, item: any) => { (acc: { totalAmount: number; totalAccepted: number }, item: any) => {
acc.totalAmount += +item.amount || 0; acc.totalAmount += +item.amount || 0;
acc.totalAccepted += +item.acceptedNumber || 0; acc.totalAccepted += +item.acceptedNumber || 0;
return acc; return acc;
}, },
{ totalAmount: 0, totalAccepted: 0 } { totalAmount: 0, totalAccepted: 0 }
); );
statuses[row.id] = total.totalAmount === total.totalAccepted; // Box is complete (green) when all items are accepted
} catch (error) { statuses[row.id] = total.totalAmount === total.totalAccepted && total.totalAmount > 0;
console.error('Error fetching box status:', error); } catch (error) {
statuses[row.id] = false; console.error(`Error fetching box status for ${row.id}:`, error);
} statuses[row.id] = false;
}) }
); })
);
setBoxStatuses(statuses); setBoxStatuses(statuses);
} catch (error) {
console.error('Error fetching box statuses:', error);
}
}; };
if (!loading && data.length > 0) { fetchBoxStatuses();
fetchBoxStatuses();
}
}, [data, loading]); }, [data, loading]);
return ( return (
@@ -141,19 +167,37 @@ const MyTable = <Data extends { id: number | string }>(props: Props<Data>) => {
</StyledTableCell> </StyledTableCell>
</StyledTableRow> </StyledTableRow>
) : ( ) : (
data.map((row: any, rowIndex) => { sortedData.map((row: any, rowIndex) => {
const status = boxStatuses[row.id]; const isCompleted = boxStatuses[row.id];
console.log(row, 'rows');
return ( return (
<StyledTableRow <StyledTableRow
key={row.id} key={row.id}
sx={{ sx={{
background: !row.hasInvoice ? 'inherit' : status ? '#a3e635' : '#f87171', background: row.print
...(onClickRow ? '#dbeafe' // kok rang (bg-blue-100)
: !row.hasInvoice
? 'inherit'
: isCompleted
? '#dcfce7' // yashil (bg-green-100)
: '#fef2f2', // qizil (bg-red-100)
borderLeft: !row.hasInvoice
? 'inherit'
: row.print
? '4px solid #3b82f6' // kok chegara (border-blue-500)
: isCompleted
? '4px solid #22c55e' // yashil chegara
: '4px solid #ef4444', // qizil chegara
...(onClickRow && !row.hasInvoice
? { ? {
cursor: 'pointer', cursor: 'pointer',
'&:hover': { '&:hover': {
backgroundColor: '#f1f1f1', backgroundColor: row.print
? '#bfdbfe' // hover kok (bg-blue-200)
: isCompleted
? '#bbf7d0' // hover yashil (bg-green-200)
: '#fee2e2', // hover qizil (bg-red-200)
}, },
} }
: {}), : {}),

View File

@@ -1,13 +1,13 @@
import * as React from 'react'; import BaseButton from '@/components/ui-kit/BaseButton';
import { styled, alpha } from '@mui/material/styles'; import { BoxStatus } from '@/data/box/box.model';
import { PartyStatus, PrintStatus } from '@/data/party/party.model';
import { getBoxStatusStyles } from '@/theme/getStatusBoxStyles';
import { ArrowDropDown } from '@mui/icons-material';
import { PopoverOrigin, SvgIcon, Typography } from '@mui/material';
import Menu, { MenuProps } from '@mui/material/Menu'; import Menu, { MenuProps } from '@mui/material/Menu';
import MenuItem from '@mui/material/MenuItem'; import MenuItem from '@mui/material/MenuItem';
import { Box, CircularProgress, IconButton, PopoverOrigin, SvgIcon, Typography } from '@mui/material'; import { alpha, styled } from '@mui/material/styles';
import { ArrowDropDown, MoreVert } from '@mui/icons-material'; import * as React from 'react';
import { getBoxStatusStyles } from '@/theme/getStatusBoxStyles';
import { BoxStatus, IBox } from '@/data/box/box.model';
import { PartyStatus } from '@/data/party/party.model';
import BaseButton from '@/components/ui-kit/BaseButton';
type PlacementType = { type PlacementType = {
anchorOrigin?: PopoverOrigin; anchorOrigin?: PopoverOrigin;
@@ -53,7 +53,7 @@ type StatusChangePopupProps = {
placement?: PlacementType; placement?: PlacementType;
anchor: { anchor: {
text: React.ReactNode; text: React.ReactNode;
status: BoxStatus | PartyStatus; status: BoxStatus | PartyStatus | PrintStatus;
}; };
}; };

View File

@@ -1,4 +1,4 @@
import React, { ForwardedRef, forwardRef } from 'react'; import { ForwardedRef, forwardRef } from 'react';
import ReactSelect, { StylesConfig } from 'react-select'; import ReactSelect, { StylesConfig } from 'react-select';
export const selectDefaultStyles: StylesConfig = { export const selectDefaultStyles: StylesConfig = {

View File

@@ -1,4 +1,5 @@
export type BoxStatus = 'READY_TO_INVOICE' | 'READY'; export type BoxStatus = 'READY_TO_INVOICE' | 'READY';
export type PrintStatus = 'false' | 'true';
export const BoxStatusList: BoxStatus[] = ['READY_TO_INVOICE', 'READY']; export const BoxStatusList: BoxStatus[] = ['READY_TO_INVOICE', 'READY'];
export interface IBox { export interface IBox {
@@ -16,6 +17,7 @@ export interface IBox {
hasInvoice: boolean; hasInvoice: boolean;
totalItems: number; totalItems: number;
status: BoxStatus; status: BoxStatus;
print: PrintStatus;
totalBrutto: number; totalBrutto: number;
} }
@@ -77,18 +79,19 @@ export type CreateBoxBodyType = {
}; };
export type UpdateBoxBodyType = { export type UpdateBoxBodyType = {
passportId: number; passportId?: number;
status: BoxStatus; status?: BoxStatus;
packetId: string; packetId?: string;
print?: boolean;
// clientId: number; // clientId: number;
cargoId: string; cargoId?: string;
// type: string; // type: string;
// name: string; // name: string;
// volume: string; // volume: string;
// boxWeight: number; // boxWeight: number;
// brutto: number; // brutto: number;
items: { items?: {
cargoId: string; cargoId: string;
trekId: string; trekId: string;
name: string; name: string;

View File

@@ -6,10 +6,11 @@ export type Party = {
}; };
export type PartyStatus = 'COLLECTING' | 'ON_THE_WAY' | 'IN_CUSTOMS' | 'IN_WAREHOUSE' | 'ARRIVED' | 'DELIVERED'; export type PartyStatus = 'COLLECTING' | 'ON_THE_WAY' | 'IN_CUSTOMS' | 'IN_WAREHOUSE' | 'ARRIVED' | 'DELIVERED';
export type PrintStatus = 'false' | 'true';
export const PartyStatusList: PartyStatus[] = ['COLLECTING', 'ON_THE_WAY', 'IN_CUSTOMS', 'IN_WAREHOUSE', 'ARRIVED', 'DELIVERED']; export const PartyStatusList: PartyStatus[] = ['COLLECTING', 'ON_THE_WAY', 'IN_CUSTOMS', 'IN_WAREHOUSE', 'ARRIVED', 'DELIVERED'];
export const PartyStatusOptions: { export const PartyStatusOptions: {
label: string; label: string;
value: PartyStatus; value: PartyStatus | PrintStatus;
}[] = [ }[] = [
{ {
label: 'COLLECTING', label: 'COLLECTING',
@@ -19,6 +20,18 @@ export const PartyStatusOptions: {
label: 'ON_THE_WAY', label: 'ON_THE_WAY',
value: 'ON_THE_WAY', value: 'ON_THE_WAY',
}, },
{
label: 'Chop etilmagan',
value: 'false',
},
{
label: 'Chop etilgan',
value: 'true',
},
{
label: 'ON_THE_WAY',
value: 'ON_THE_WAY',
},
{ {
label: 'IN_CUSTOMS', label: 'IN_CUSTOMS',
value: 'IN_CUSTOMS', value: 'IN_CUSTOMS',

View File

@@ -277,7 +277,7 @@ const DashboardCreateBoxPage = ({ initialValues, partiesData }: Props) => {
const item_delete_promises = initialValues.products_list const item_delete_promises = initialValues.products_list
.filter(item => { .filter(item => {
if (!updateBody.items.find(i => String(i.id) === String(item.id))) { if (!updateBody.items?.find(i => String(i.id) === String(item.id))) {
return true; return true;
} else { } else {
return false; return false;

View File

@@ -54,7 +54,7 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
}} }}
key={key} key={key}
> >
<Box sx={{ border: '1px solid black' }}> <Box sx={{ border: '2px solid black', borderBottom: 'none' }}>
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}> <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
<Box <Box
sx={{ sx={{
@@ -65,7 +65,7 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
gap: '12px', gap: '12px',
}} }}
> >
<Image alt='logo' src={Logo} width={30} height={30} priority unoptimized /> <Image alt='logo' src={Logo} width={55} height={55} priority unoptimized />
<Box <Box
sx={{ sx={{
color: '#fff', color: '#fff',
@@ -75,42 +75,44 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
}} }}
> >
<Typography sx={{ color: 'black', fontSize: '10px' }}>CPOST EXPRESS CARGO</Typography> <Typography sx={{ color: 'black', fontSize: '10px' }}>CPOST EXPRESS CARGO</Typography>
<Typography sx={{ color: 'black', fontSize: '10px' }}>Reys: {boxData?.partyName}</Typography> <Typography sx={{ color: 'black', fontSize: '10px' }}>
<Typography sx={{ color: 'black', fontSize: '10px' }}>{boxData?.client_id}</Typography> Reys: {boxData?.partyName}-{boxData?.client_id}
</Typography>
<Typography sx={{ color: 'black', fontSize: '10px' }}>TEL: +(998) 90 113 44 77</Typography>
</Box> </Box>
</Box> </Box>
<Box sx={{ display: 'flex', gap: '4px', marginTop: '5px', marginRight: '5px' }}> <Box sx={{ display: 'flex', gap: '10px', marginTop: '5px', marginRight: '5px' }}>
<Image alt='telegram' src={TelegramChanel} width={15} height={15} priority unoptimized /> <Image alt='telegram' src={TelegramChanel} width={50} height={50} priority unoptimized />
<Image alt='instagram' src={InstagramChanel} width={15} height={15} priority unoptimized /> <Image alt='instagram' src={InstagramChanel} width={50} height={50} priority unoptimized />
<Typography sx={{ color: 'black', fontSize: '8px' }}>TEL: +(998) 90 113 44 77</Typography>
</Box> </Box>
</Box> </Box>
<Box </Box>
sx={{ <Box
borderTop: '1px solid black', sx={{
textAlign: 'start', border: '1px solid black',
width: 'auto', borderTop: '1px solid black',
display: 'grid', textAlign: 'start',
gridTemplateColumns: 'repeat(3, 1fr)', width: 'auto',
'@media print': { display: 'grid',
pageBreakInside: 'avoid', gridTemplateColumns: 'repeat(3, 1fr)',
}, '@media print': {
}} pageBreakInside: 'avoid',
> },
{boxData?.products_list.map((list, index) => ( }}
<Box >
sx={{ {boxData?.products_list.map((list, index) => (
borderRight: '1px solid black', <Box
textAlign: 'start', sx={{
width: 'auto', border: '1px solid black',
padding: '4px', textAlign: 'start',
}} width: 'auto',
key={index} padding: '4px',
> }}
<Typography sx={{ fontSize: '12px' }}>{list.trekId}</Typography> key={index}
</Box> >
))} <Typography sx={{ fontSize: '12px' }}>{list.trekId}</Typography>
</Box> </Box>
))}
</Box> </Box>
</Box> </Box>
); );

View File

@@ -10,7 +10,7 @@ import BaseInput from '@/components/ui-kit/BaseInput';
import BasePagination from '@/components/ui-kit/BasePagination'; import BasePagination from '@/components/ui-kit/BasePagination';
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect'; import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
import { useAuthContext } from '@/context/auth-context'; import { useAuthContext } from '@/context/auth-context';
import { type BoxStatus, BoxStatusList, type IBox } from '@/data/box/box.model'; import { type BoxStatus, BoxStatusList, type IBox, PrintStatus } from '@/data/box/box.model';
import { box_requests } from '@/data/box/box.requests'; import { box_requests } from '@/data/box/box.requests';
import type { Product, UpdateProductBodyType } from '@/data/item/item.mode'; import type { Product, UpdateProductBodyType } from '@/data/item/item.mode';
import { item_requests } from '@/data/item/item.requests'; import { item_requests } from '@/data/item/item.requests';
@@ -23,8 +23,20 @@ import useRequest from '@/hooks/useRequest';
import { file_service } from '@/services/file-service'; import { file_service } from '@/services/file-service';
import { notifyUnknownError } from '@/services/notification'; import { notifyUnknownError } from '@/services/notification';
import { getStatusColor } from '@/theme/getStatusBoxStyles'; import { getStatusColor } from '@/theme/getStatusBoxStyles';
import { Add, Circle, Delete, Download, Edit, FilterList, FilterListOff, Print, RemoveRedEye, Search } from '@mui/icons-material'; import {
import { Box, Button, Card, CardContent, Modal, Stack, TextField, Typography } from '@mui/material'; Add,
CheckCircle,
Circle,
Delete,
Download,
Edit,
FilterList,
FilterListOff,
Print,
RemoveRedEye,
Search,
} from '@mui/icons-material';
import { Box, Button, Card, CardContent, FormControl, MenuItem, Modal, Select, Stack, Typography } from '@mui/material';
import { useEffect, useMemo, useRef, useState } from 'react'; import { useEffect, useMemo, useRef, useState } from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import AsyncSelect from 'react-select/async'; import AsyncSelect from 'react-select/async';
@@ -61,11 +73,13 @@ const DashboardBoxesPage = (props: Props) => {
const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined); const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined);
const [trackId, setTrackId] = useState<string>(); const [trackId, setTrackId] = useState<string>();
const [partyFilter, setPartyFilter] = useState<{ label: string; value: number } | undefined>(undefined); const [partyFilter, setPartyFilter] = useState<{ label: string; value: number } | undefined>(undefined);
const [boxFilter, setBoxFilter] = useState<{ label: string; value: number } | undefined>(undefined);
const [deleteIds, setDeleteIds] = useState<number[]>([]); const [deleteIds, setDeleteIds] = useState<number[]>([]);
const [downloadIds, setDownloadIds] = useState<number[]>([]); const [downloadIds, setDownloadIds] = useState<number[]>([]);
const [changeStatusIds, setChangeStatusIds] = useState<number[]>([]); const [changeStatusIds, setChangeStatusIds] = useState<number[]>([]);
const [boxAmounts, setBoxAmounts] = useState<Record<number, { totalAmount: number; totalAccepted: number }>>({}); const [boxAmounts, setBoxAmounts] = useState<Record<number, { totalAmount: number; totalAccepted: number }>>({});
const [printStatuses, setPrintStatuses] = useState<Record<number, string>>({});
// Print uchun state // Print uchun state
const [selectedBoxForPrint, setSelectedBoxForPrint] = useState<IBox | null>(null); const [selectedBoxForPrint, setSelectedBoxForPrint] = useState<IBox | null>(null);
@@ -73,8 +87,6 @@ const DashboardBoxesPage = (props: Props) => {
const printRef = useRef<HTMLDivElement>(null); const printRef = useRef<HTMLDivElement>(null);
// Available status options (simulating admin/user permissions)
// Print functionality // Print functionality
const handlePrint = useReactToPrint({ const handlePrint = useReactToPrint({
contentRef: printRef, contentRef: printRef,
@@ -100,7 +112,6 @@ const DashboardBoxesPage = (props: Props) => {
const onPrintBox = async (boxData: IBox) => { const onPrintBox = async (boxData: IBox) => {
try { try {
// Fetch detailed box data
const response = await box_requests.find({ packetId: boxData.id }); const response = await box_requests.find({ packetId: boxData.id });
const boxOne = response.data.data; const boxOne = response.data.data;
@@ -158,6 +169,14 @@ const DashboardBoxesPage = (props: Props) => {
return p; return p;
}, [isAdmin]); }, [isAdmin]);
const printOptions = useMemo(() => {
const p = ['false'] as PrintStatus[];
if (isAdmin) {
p.push('false');
}
return p;
}, [isAdmin]);
const getBoxesQuery = useRequest( const getBoxesQuery = useRequest(
() => () =>
box_requests.getAll({ box_requests.getAll({
@@ -181,9 +200,11 @@ const DashboardBoxesPage = (props: Props) => {
item_requests.getAll({ item_requests.getAll({
page: page, page: page,
trekId: trackId, trekId: trackId,
packetId: boxFilter?.value,
partyId: partyFilter?.value,
}), }),
{ {
dependencies: [page, trackId], dependencies: [page, trackId, boxFilter?.value, partyFilter?.value],
selectData(data) { selectData(data) {
return data.data.data; return data.data.data;
}, },
@@ -232,8 +253,24 @@ const DashboardBoxesPage = (props: Props) => {
setPage(1); setPage(1);
setKeyword(''); setKeyword('');
setBoxStatusFilter(undefined); setBoxStatusFilter(undefined);
setPartyFilter(undefined);
}; };
const { data: defaultBoxOptions, refetch } = useRequest(
() =>
box_requests.getAll({
partyId: partyFilter?.value,
}),
{
enabled: !!partyFilter,
selectData(data) {
return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
},
placeholderData: [],
dependencies: [partyFilter],
}
);
const onDelete = async (id: number) => { const onDelete = async (id: number) => {
if (deleteIds.includes(id)) return; if (deleteIds.includes(id)) return;
@@ -277,13 +314,26 @@ const DashboardBoxesPage = (props: Props) => {
} }
}; };
const onChangePrint = async (id: number, newStatus: PrintStatus) => {
if (changeStatusIds.includes(id)) return;
try {
setChangeStatusIds(p => [...p, id]);
getBoxesQuery.refetch();
} catch (error) {
notifyUnknownError(error);
} finally {
setChangeStatusIds(prev => prev.filter(i => i !== id));
}
};
useEffect(() => { useEffect(() => {
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
setPage(1); setPage(1);
getBoxesQuery.refetch(); getBoxesQuery.refetch();
}, 350); }, 350);
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
}, [keyword, partyFilter?.value]); }, [keyword, partyFilter?.value, boxFilter?.value]);
useEffect(() => { useEffect(() => {
const fetchAmounts = async () => { const fetchAmounts = async () => {
@@ -319,6 +369,14 @@ const DashboardBoxesPage = (props: Props) => {
} }
}, [list, loading]); }, [list, loading]);
// Calculate completion statistics
const boxOptions = (inputValue: string) => {
return box_requests.getAll({ cargoId: inputValue }).then(res => {
return res.data.data.data.map(p => ({ label: p.name, value: p.id }));
});
};
const columns: ColumnData<IBox>[] = [ const columns: ColumnData<IBox>[] = [
{ {
label: t('No'), label: t('No'),
@@ -361,10 +419,16 @@ const DashboardBoxesPage = (props: Props) => {
renderCell: data => { renderCell: data => {
const total = boxAmounts[data.id]; const total = boxAmounts[data.id];
if (!total) return <Typography>...</Typography>; if (!total) return <Typography>...</Typography>;
const isCompleted = total.totalAmount === total.totalAccepted && total.totalAmount > 0;
return ( return (
<Typography> <Stack direction='row' alignItems='center' spacing={1}>
{total.totalAmount} | {total.totalAccepted} <Typography>
</Typography> {total.totalAmount} | {total.totalAccepted}
</Typography>
{isCompleted && <CheckCircle sx={{ color: '#22c55e', fontSize: 16 }} />}
</Stack>
); );
}, },
}, },
@@ -459,13 +523,72 @@ const DashboardBoxesPage = (props: Props) => {
}, },
renderCell(data) { renderCell(data) {
const total = boxAmounts[data.id]; const total = boxAmounts[data.id];
const isCompleted = total?.totalAccepted === total?.totalAmount && total?.totalAmount > 0;
return ( return (
<Button onClick={() => onPrintBox(data)} disabled={total?.totalAccepted !== total?.totalAmount}> <Button onClick={() => onPrintBox(data)}>
<Print className='h-3 w-3 mr-1' /> <Print className='h-3 w-3 mr-1' />
</Button> </Button>
); );
}, },
}, },
{
dataKey: 'status',
label: t('status'),
width: 240,
renderHeaderCell(rowIndex) {
return (
<Stack direction={'row'} alignItems={'center'}>
<span>{t('print_status')}</span>
</Stack>
);
},
renderCell(data) {
const currentValue = printStatuses[data.id] || (data.print ? 'true' : 'false');
return (
<FormControl sx={{ m: 1, border: 'none', minWidth: 120, background: data.print ? '#3489E4' : '#DF2F99' }} size='small'>
<Select
labelId={`print-status-${data.id}`}
id={`print-status-${data.id}`}
sx={{ color: 'white', border: 'none' }}
value={currentValue}
onChange={async e => {
const newValue = e.target.value as PrintStatus;
// Local state yangilanadi
setPrintStatuses(prev => ({
...prev,
[data.id]: newValue,
}));
// Callback chaqiriladi
onChangePrint(data.id, newValue);
// Serverga request yuboriladi
try {
const res = await box_requests.find({ packetId: data.id });
await box_requests.update({
cargoId: String(res.data.data.packet.cargoId),
items: res.data.data.items,
print: newValue === 'true' ? true : newValue === 'false' && false,
packetId: String(res.data.data.packet.id),
passportId: res.data.data.client.passportId,
status: res.data.data.packet.status,
});
refetch();
getBoxesQuery.refetch();
} catch (error) {
console.error('Print status update failed:', error);
}
}}
>
<MenuItem value='true'>Chop etildi</MenuItem>
<MenuItem value='false'>Chop etilmadi</MenuItem>
</Select>
</FormControl>
);
},
},
{ {
label: '', label: '',
width: 100, width: 100,
@@ -572,6 +695,7 @@ const DashboardBoxesPage = (props: Props) => {
{t('create_packet')} {t('create_packet')}
</BaseButton> </BaseButton>
<Button onClick={handleOpen}>{t('product_inspection')}</Button> <Button onClick={handleOpen}>{t('product_inspection')}</Button>
<Modal open={open} onClose={handleClose} aria-labelledby='modal-modal-title' aria-describedby='modal-modal-description'> <Modal open={open} onClose={handleClose} aria-labelledby='modal-modal-title' aria-describedby='modal-modal-description'>
<Box sx={style}> <Box sx={style}>
<Typography id='modal-modal-title' variant='h6' component='h2'> <Typography id='modal-modal-title' variant='h6' component='h2'>
@@ -580,12 +704,42 @@ const DashboardBoxesPage = (props: Props) => {
<Typography id='modal-modal-description' sx={{ mt: 2 }}> <Typography id='modal-modal-description' sx={{ mt: 2 }}>
{t('enter_product')} {t('enter_product')}
</Typography> </Typography>
<TextField <AsyncSelect
id='outlined-basic' isClearable
label={t('track_id')} value={partyFilter}
variant='outlined' onChange={(newValue: any) => {
setPartyFilter(newValue);
setPage(1);
}}
styles={selectDefaultStyles}
noOptionsMessage={() => t('not_found')}
loadingMessage={() => t('loading')}
defaultOptions={defaultPartyOptions!}
loadOptions={partyOptions}
placeholder={t('filter_party_name')}
/>
<AsyncSelect
isClearable
value={boxFilter}
onChange={(newValue: any) => {
setBoxFilter(newValue);
setPage(1);
}}
styles={selectDefaultStyles}
noOptionsMessage={() => t('enter_box_name_to_find')}
loadingMessage={() => t('loading')}
defaultOptions={defaultBoxOptions!}
loadOptions={boxOptions}
placeholder={t('filter_box_name')}
/>
<BaseInput
InputProps={{
startAdornment: <Search color='primary' />,
}}
value={trackId} value={trackId}
onChange={e => setTrackId(e.target.value)} onChange={e => setTrackId(e.target.value)}
placeholder={t('filter_item_name')}
/> />
{trackId && trackId.length > 0 && ( {trackId && trackId.length > 0 && (
<> <>

View File

@@ -86,6 +86,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
const [allPackets, setAllPackets] = useState<any[]>([]); const [allPackets, setAllPackets] = useState<any[]>([]);
// Barcha mahsulotlarni barcha sahifadan yuklash uchun map // Barcha mahsulotlarni barcha sahifadan yuklash uchun map
const [allItemsMap, setAllItemsMap] = useState<{ [packetId: number]: any[] }>({}); const [allItemsMap, setAllItemsMap] = useState<{ [packetId: number]: any[] }>({});
console.log(initialValues?.partyName);
const { const {
control, control,
@@ -529,8 +530,17 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
field.onChange(e); field.onChange(e);
handlePartyChange(e); handlePartyChange(e);
}} }}
value={field.value || ''} value={field.value || initialValues?.partyId || ''} // Bu yerda partyId ishlatish kerak
disabled={isLoadingParties} disabled={isLoadingParties}
renderValue={selected => {
// Agar edit mode bo'lsa va initialValues mavjud bo'lsa
if (editMode && initialValues?.partyName && selected === initialValues?.partyId) {
return initialValues.partyName;
}
// Aks holda parties ro'yxatidan topish
const selectedParty = parties.find(p => p.id === selected);
return selectedParty ? selectedParty.name : '';
}}
> >
{isLoadingParties ? ( {isLoadingParties ? (
<MenuItem disabled> <MenuItem disabled>

View File

@@ -1,7 +1,7 @@
import { BoxStatus } from '@/data/box/box.model'; import { BoxStatus } from '@/data/box/box.model';
import { PartyStatus } from '@/data/party/party.model'; import { PartyStatus, PrintStatus } from '@/data/party/party.model';
export function getStatusColor(status: BoxStatus | PartyStatus) { export function getStatusColor(status: BoxStatus | PartyStatus | PrintStatus) {
switch (status) { switch (status) {
case 'COLLECTING': { case 'COLLECTING': {
return '#FD9C2B'; return '#FD9C2B';
@@ -24,13 +24,19 @@ export function getStatusColor(status: BoxStatus | PartyStatus) {
case 'IN_CUSTOMS': { case 'IN_CUSTOMS': {
return '#C9A26E'; return '#C9A26E';
} }
case 'false': {
return '#C9A26E';
}
case 'true': {
return '#3489E4';
}
default: { default: {
return '#17D792'; return '#17D792';
} }
} }
} }
export function getBoxStatusStyles(status: BoxStatus | PartyStatus) { export function getBoxStatusStyles(status: BoxStatus | PartyStatus | PrintStatus) {
let color = getStatusColor(status); let color = getStatusColor(status);
return { return {