@@ -3,7 +3,7 @@
|
||||
import Loader from '@/components/common/Loader';
|
||||
import { Scrollbar } from '@/components/common/Scrollbar';
|
||||
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';
|
||||
|
||||
export interface ColumnData<Data, DataKey = keyof Data> {
|
||||
@@ -72,10 +72,34 @@ const MyTable = <Data extends { id: number | string }>(props: Props<Data>) => {
|
||||
|
||||
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(() => {
|
||||
const fetchBoxStatuses = async () => {
|
||||
if (!data.length || loading) return;
|
||||
|
||||
const statuses: Record<string, boolean> = {};
|
||||
|
||||
try {
|
||||
await Promise.all(
|
||||
data.map(async row => {
|
||||
try {
|
||||
@@ -91,20 +115,22 @@ const MyTable = <Data extends { id: number | string }>(props: Props<Data>) => {
|
||||
{ totalAmount: 0, totalAccepted: 0 }
|
||||
);
|
||||
|
||||
statuses[row.id] = total.totalAmount === total.totalAccepted;
|
||||
// Box is complete (green) when all items are accepted
|
||||
statuses[row.id] = total.totalAmount === total.totalAccepted && total.totalAmount > 0;
|
||||
} catch (error) {
|
||||
console.error('Error fetching box status:', error);
|
||||
console.error(`Error fetching box status for ${row.id}:`, error);
|
||||
statuses[row.id] = false;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
setBoxStatuses(statuses);
|
||||
} catch (error) {
|
||||
console.error('Error fetching box statuses:', error);
|
||||
}
|
||||
};
|
||||
|
||||
if (!loading && data.length > 0) {
|
||||
fetchBoxStatuses();
|
||||
}
|
||||
}, [data, loading]);
|
||||
|
||||
return (
|
||||
@@ -141,19 +167,37 @@ const MyTable = <Data extends { id: number | string }>(props: Props<Data>) => {
|
||||
</StyledTableCell>
|
||||
</StyledTableRow>
|
||||
) : (
|
||||
data.map((row: any, rowIndex) => {
|
||||
const status = boxStatuses[row.id];
|
||||
sortedData.map((row: any, rowIndex) => {
|
||||
const isCompleted = boxStatuses[row.id];
|
||||
console.log(row, 'rows');
|
||||
|
||||
return (
|
||||
<StyledTableRow
|
||||
key={row.id}
|
||||
sx={{
|
||||
background: !row.hasInvoice ? 'inherit' : status ? '#a3e635' : '#f87171',
|
||||
...(onClickRow
|
||||
background: row.print
|
||||
? '#dbeafe' // ko‘k 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' // ko‘k chegara (border-blue-500)
|
||||
: isCompleted
|
||||
? '4px solid #22c55e' // yashil chegara
|
||||
: '4px solid #ef4444', // qizil chegara
|
||||
...(onClickRow && !row.hasInvoice
|
||||
? {
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f1f1f1',
|
||||
backgroundColor: row.print
|
||||
? '#bfdbfe' // hover ko‘k (bg-blue-200)
|
||||
: isCompleted
|
||||
? '#bbf7d0' // hover yashil (bg-green-200)
|
||||
: '#fee2e2', // hover qizil (bg-red-200)
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import * as React from 'react';
|
||||
import { styled, alpha } from '@mui/material/styles';
|
||||
import BaseButton from '@/components/ui-kit/BaseButton';
|
||||
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 MenuItem from '@mui/material/MenuItem';
|
||||
import { Box, CircularProgress, IconButton, PopoverOrigin, SvgIcon, Typography } from '@mui/material';
|
||||
import { ArrowDropDown, MoreVert } from '@mui/icons-material';
|
||||
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';
|
||||
import { alpha, styled } from '@mui/material/styles';
|
||||
import * as React from 'react';
|
||||
|
||||
type PlacementType = {
|
||||
anchorOrigin?: PopoverOrigin;
|
||||
@@ -53,7 +53,7 @@ type StatusChangePopupProps = {
|
||||
placement?: PlacementType;
|
||||
anchor: {
|
||||
text: React.ReactNode;
|
||||
status: BoxStatus | PartyStatus;
|
||||
status: BoxStatus | PartyStatus | PrintStatus;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { ForwardedRef, forwardRef } from 'react';
|
||||
import { ForwardedRef, forwardRef } from 'react';
|
||||
import ReactSelect, { StylesConfig } from 'react-select';
|
||||
|
||||
export const selectDefaultStyles: StylesConfig = {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
export type BoxStatus = 'READY_TO_INVOICE' | 'READY';
|
||||
export type PrintStatus = 'false' | 'true';
|
||||
export const BoxStatusList: BoxStatus[] = ['READY_TO_INVOICE', 'READY'];
|
||||
|
||||
export interface IBox {
|
||||
@@ -16,6 +17,7 @@ export interface IBox {
|
||||
hasInvoice: boolean;
|
||||
totalItems: number;
|
||||
status: BoxStatus;
|
||||
print: PrintStatus;
|
||||
totalBrutto: number;
|
||||
}
|
||||
|
||||
@@ -77,18 +79,19 @@ export type CreateBoxBodyType = {
|
||||
};
|
||||
|
||||
export type UpdateBoxBodyType = {
|
||||
passportId: number;
|
||||
status: BoxStatus;
|
||||
packetId: string;
|
||||
passportId?: number;
|
||||
status?: BoxStatus;
|
||||
packetId?: string;
|
||||
print?: boolean;
|
||||
// clientId: number;
|
||||
cargoId: string;
|
||||
cargoId?: string;
|
||||
|
||||
// type: string;
|
||||
// name: string;
|
||||
// volume: string;
|
||||
// boxWeight: number;
|
||||
// brutto: number;
|
||||
items: {
|
||||
items?: {
|
||||
cargoId: string;
|
||||
trekId: string;
|
||||
name: string;
|
||||
|
||||
@@ -6,10 +6,11 @@ export type Party = {
|
||||
};
|
||||
|
||||
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 PartyStatusOptions: {
|
||||
label: string;
|
||||
value: PartyStatus;
|
||||
value: PartyStatus | PrintStatus;
|
||||
}[] = [
|
||||
{
|
||||
label: 'COLLECTING',
|
||||
@@ -19,6 +20,18 @@ export const PartyStatusOptions: {
|
||||
label: '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',
|
||||
value: 'IN_CUSTOMS',
|
||||
|
||||
@@ -277,7 +277,7 @@ const DashboardCreateBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
|
||||
const item_delete_promises = initialValues.products_list
|
||||
.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;
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -54,7 +54,7 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, 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={{
|
||||
@@ -65,7 +65,7 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
|
||||
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
|
||||
sx={{
|
||||
color: '#fff',
|
||||
@@ -75,18 +75,21 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
|
||||
}}
|
||||
>
|
||||
<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' }}>{boxData?.client_id}</Typography>
|
||||
<Typography sx={{ color: 'black', fontSize: '10px' }}>
|
||||
Reys: {boxData?.partyName}-{boxData?.client_id}
|
||||
</Typography>
|
||||
<Typography sx={{ color: 'black', fontSize: '10px' }}>TEL: +(998) 90 113 44 77</Typography>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box sx={{ display: 'flex', gap: '4px', marginTop: '5px', marginRight: '5px' }}>
|
||||
<Image alt='telegram' src={TelegramChanel} width={15} height={15} priority unoptimized />
|
||||
<Image alt='instagram' src={InstagramChanel} width={15} height={15} priority unoptimized />
|
||||
<Typography sx={{ color: 'black', fontSize: '8px' }}>TEL: +(998) 90 113 44 77</Typography>
|
||||
<Box sx={{ display: 'flex', gap: '10px', marginTop: '5px', marginRight: '5px' }}>
|
||||
<Image alt='telegram' src={TelegramChanel} width={50} height={50} priority unoptimized />
|
||||
<Image alt='instagram' src={InstagramChanel} width={50} height={50} priority unoptimized />
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
border: '1px solid black',
|
||||
borderTop: '1px solid black',
|
||||
textAlign: 'start',
|
||||
width: 'auto',
|
||||
@@ -100,7 +103,7 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
|
||||
{boxData?.products_list.map((list, index) => (
|
||||
<Box
|
||||
sx={{
|
||||
borderRight: '1px solid black',
|
||||
border: '1px solid black',
|
||||
textAlign: 'start',
|
||||
width: 'auto',
|
||||
padding: '4px',
|
||||
@@ -112,7 +115,6 @@ const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData, key }
|
||||
))}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import BaseInput from '@/components/ui-kit/BaseInput';
|
||||
import BasePagination from '@/components/ui-kit/BasePagination';
|
||||
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
|
||||
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 type { Product, UpdateProductBodyType } from '@/data/item/item.mode';
|
||||
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 { notifyUnknownError } from '@/services/notification';
|
||||
import { getStatusColor } from '@/theme/getStatusBoxStyles';
|
||||
import { Add, Circle, Delete, Download, Edit, FilterList, FilterListOff, Print, RemoveRedEye, Search } from '@mui/icons-material';
|
||||
import { Box, Button, Card, CardContent, Modal, Stack, TextField, Typography } from '@mui/material';
|
||||
import {
|
||||
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 { useForm } from 'react-hook-form';
|
||||
import AsyncSelect from 'react-select/async';
|
||||
@@ -61,11 +73,13 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
const [boxStatusFilter, setBoxStatusFilter] = useState<BoxStatus | undefined>(undefined);
|
||||
const [trackId, setTrackId] = useState<string>();
|
||||
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 [downloadIds, setDownloadIds] = useState<number[]>([]);
|
||||
const [changeStatusIds, setChangeStatusIds] = useState<number[]>([]);
|
||||
const [boxAmounts, setBoxAmounts] = useState<Record<number, { totalAmount: number; totalAccepted: number }>>({});
|
||||
const [printStatuses, setPrintStatuses] = useState<Record<number, string>>({});
|
||||
|
||||
// Print uchun state
|
||||
const [selectedBoxForPrint, setSelectedBoxForPrint] = useState<IBox | null>(null);
|
||||
@@ -73,8 +87,6 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
|
||||
const printRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// Available status options (simulating admin/user permissions)
|
||||
|
||||
// Print functionality
|
||||
const handlePrint = useReactToPrint({
|
||||
contentRef: printRef,
|
||||
@@ -100,7 +112,6 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
|
||||
const onPrintBox = async (boxData: IBox) => {
|
||||
try {
|
||||
// Fetch detailed box data
|
||||
const response = await box_requests.find({ packetId: boxData.id });
|
||||
const boxOne = response.data.data;
|
||||
|
||||
@@ -158,6 +169,14 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
return p;
|
||||
}, [isAdmin]);
|
||||
|
||||
const printOptions = useMemo(() => {
|
||||
const p = ['false'] as PrintStatus[];
|
||||
if (isAdmin) {
|
||||
p.push('false');
|
||||
}
|
||||
return p;
|
||||
}, [isAdmin]);
|
||||
|
||||
const getBoxesQuery = useRequest(
|
||||
() =>
|
||||
box_requests.getAll({
|
||||
@@ -181,9 +200,11 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
item_requests.getAll({
|
||||
page: page,
|
||||
trekId: trackId,
|
||||
packetId: boxFilter?.value,
|
||||
partyId: partyFilter?.value,
|
||||
}),
|
||||
{
|
||||
dependencies: [page, trackId],
|
||||
dependencies: [page, trackId, boxFilter?.value, partyFilter?.value],
|
||||
selectData(data) {
|
||||
return data.data.data;
|
||||
},
|
||||
@@ -232,8 +253,24 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
setPage(1);
|
||||
setKeyword('');
|
||||
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) => {
|
||||
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(() => {
|
||||
const timeoutId = setTimeout(() => {
|
||||
setPage(1);
|
||||
getBoxesQuery.refetch();
|
||||
}, 350);
|
||||
return () => clearTimeout(timeoutId);
|
||||
}, [keyword, partyFilter?.value]);
|
||||
}, [keyword, partyFilter?.value, boxFilter?.value]);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchAmounts = async () => {
|
||||
@@ -319,6 +369,14 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
}
|
||||
}, [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>[] = [
|
||||
{
|
||||
label: t('No'),
|
||||
@@ -361,10 +419,16 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
renderCell: data => {
|
||||
const total = boxAmounts[data.id];
|
||||
if (!total) return <Typography>...</Typography>;
|
||||
|
||||
const isCompleted = total.totalAmount === total.totalAccepted && total.totalAmount > 0;
|
||||
|
||||
return (
|
||||
<Stack direction='row' alignItems='center' spacing={1}>
|
||||
<Typography>
|
||||
{total.totalAmount} | {total.totalAccepted}
|
||||
</Typography>
|
||||
{isCompleted && <CheckCircle sx={{ color: '#22c55e', fontSize: 16 }} />}
|
||||
</Stack>
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -459,13 +523,72 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
},
|
||||
renderCell(data) {
|
||||
const total = boxAmounts[data.id];
|
||||
const isCompleted = total?.totalAccepted === total?.totalAmount && total?.totalAmount > 0;
|
||||
|
||||
return (
|
||||
<Button onClick={() => onPrintBox(data)} disabled={total?.totalAccepted !== total?.totalAmount}>
|
||||
<Button onClick={() => onPrintBox(data)}>
|
||||
<Print className='h-3 w-3 mr-1' />
|
||||
</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: '',
|
||||
width: 100,
|
||||
@@ -572,6 +695,7 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
{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'>
|
||||
@@ -580,12 +704,42 @@ const DashboardBoxesPage = (props: Props) => {
|
||||
<Typography id='modal-modal-description' sx={{ mt: 2 }}>
|
||||
{t('enter_product')}
|
||||
</Typography>
|
||||
<TextField
|
||||
id='outlined-basic'
|
||||
label={t('track_id')}
|
||||
variant='outlined'
|
||||
<AsyncSelect
|
||||
isClearable
|
||||
value={partyFilter}
|
||||
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}
|
||||
onChange={e => setTrackId(e.target.value)}
|
||||
placeholder={t('filter_item_name')}
|
||||
/>
|
||||
{trackId && trackId.length > 0 && (
|
||||
<>
|
||||
|
||||
@@ -86,6 +86,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
const [allPackets, setAllPackets] = useState<any[]>([]);
|
||||
// Barcha mahsulotlarni barcha sahifadan yuklash uchun map
|
||||
const [allItemsMap, setAllItemsMap] = useState<{ [packetId: number]: any[] }>({});
|
||||
console.log(initialValues?.partyName);
|
||||
|
||||
const {
|
||||
control,
|
||||
@@ -529,8 +530,17 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => {
|
||||
field.onChange(e);
|
||||
handlePartyChange(e);
|
||||
}}
|
||||
value={field.value || ''}
|
||||
value={field.value || initialValues?.partyId || ''} // Bu yerda partyId ishlatish kerak
|
||||
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 ? (
|
||||
<MenuItem disabled>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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) {
|
||||
case 'COLLECTING': {
|
||||
return '#FD9C2B';
|
||||
@@ -24,13 +24,19 @@ export function getStatusColor(status: BoxStatus | PartyStatus) {
|
||||
case 'IN_CUSTOMS': {
|
||||
return '#C9A26E';
|
||||
}
|
||||
case 'false': {
|
||||
return '#C9A26E';
|
||||
}
|
||||
case 'true': {
|
||||
return '#3489E4';
|
||||
}
|
||||
default: {
|
||||
return '#17D792';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getBoxStatusStyles(status: BoxStatus | PartyStatus) {
|
||||
export function getBoxStatusStyles(status: BoxStatus | PartyStatus | PrintStatus) {
|
||||
let color = getStatusColor(status);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user