print added
This commit is contained in:
@@ -217,5 +217,6 @@
|
|||||||
"enter_product": "请输入产品的追溯ID",
|
"enter_product": "请输入产品的追溯ID",
|
||||||
"confirmation": "确认",
|
"confirmation": "确认",
|
||||||
"view_packet": "查看包裹数据",
|
"view_packet": "查看包裹数据",
|
||||||
"accepted_number": "已接收"
|
"accepted_number": "已接收",
|
||||||
|
"print": "打印"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,5 +217,6 @@
|
|||||||
"enter_product": "Enter your product tracking ID",
|
"enter_product": "Enter your product tracking ID",
|
||||||
"confirmation": "Confirm",
|
"confirmation": "Confirm",
|
||||||
"view_packet": "View package data",
|
"view_packet": "View package data",
|
||||||
"accepted_number": "Accepted"
|
"accepted_number": "Accepted",
|
||||||
|
"print": "Print"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,5 +230,6 @@
|
|||||||
"view_packet": "Просмотреть данные посылки",
|
"view_packet": "Просмотреть данные посылки",
|
||||||
"accepted_number": "Принято",
|
"accepted_number": "Принято",
|
||||||
"qr_code": "QR код",
|
"qr_code": "QR код",
|
||||||
"created_at": "Дата добавления"
|
"created_at": "Дата добавления",
|
||||||
|
"print": "Печать"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -228,7 +228,7 @@
|
|||||||
"product_inspection": "Mahsulotlarni tekshirish",
|
"product_inspection": "Mahsulotlarni tekshirish",
|
||||||
"enter_product": "Mahsulotning Trassirovka IDni kiriting",
|
"enter_product": "Mahsulotning Trassirovka IDni kiriting",
|
||||||
"confirmation": "Tasdiqlash",
|
"confirmation": "Tasdiqlash",
|
||||||
|
"print": "Chop etish",
|
||||||
"qr_code": "QR kod",
|
"qr_code": "QR kod",
|
||||||
"created_at": "Qo‘shilgan sana"
|
"created_at": "Qo‘shilgan sana"
|
||||||
}
|
}
|
||||||
|
|||||||
17158
package-lock.json
generated
17158
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@
|
|||||||
"react-hot-toast": "^2.4.1",
|
"react-hot-toast": "^2.4.1",
|
||||||
"react-i18next": "^14.0.0",
|
"react-i18next": "^14.0.0",
|
||||||
"react-select": "^5.8.0",
|
"react-select": "^5.8.0",
|
||||||
|
"react-to-print": "^3.1.0",
|
||||||
"simplebar-react": "^3.2.4",
|
"simplebar-react": "^3.2.4",
|
||||||
"swiper": "^11.0.5",
|
"swiper": "^11.0.5",
|
||||||
"use-dehydrated-state": "^0.1.0",
|
"use-dehydrated-state": "^0.1.0",
|
||||||
|
|||||||
BIN
public/instagram.png
Normal file
BIN
public/instagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 287 KiB |
BIN
public/telegram.jpg
Normal file
BIN
public/telegram.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 89 KiB |
@@ -1,33 +1,33 @@
|
|||||||
:root {
|
:root {
|
||||||
--app-height: 100%;
|
--app-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #555351;
|
color: #555351;
|
||||||
font-family: "Inter", "Arial", sans-serif !important;
|
font-family: 'Inter', 'Arial', sans-serif !important;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dashboard-layout {
|
.dashboard-layout {
|
||||||
font-family: 'SF Pro Display', sans-serif !important;
|
font-family: 'SF Pro Display', sans-serif !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
*,
|
*,
|
||||||
*::after,
|
*::after,
|
||||||
*::before {
|
*::before {
|
||||||
box-sizing: inherit;
|
box-sizing: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *:focus-visible {
|
/* *:focus-visible {
|
||||||
@@ -36,47 +36,55 @@ body {
|
|||||||
} */
|
} */
|
||||||
|
|
||||||
.visually-hidden {
|
.visually-hidden {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 1px;
|
width: 1px;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: -1px;
|
margin: -1px;
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
clip: rect(0 0 0 0);
|
clip: rect(0 0 0 0);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-select {
|
.no-select {
|
||||||
-webkit-touch-callout: none;
|
-webkit-touch-callout: none;
|
||||||
-webkit-user-select: none;
|
-webkit-user-select: none;
|
||||||
-khtml-user-select: none;
|
-khtml-user-select: none;
|
||||||
-moz-user-select: none;
|
-moz-user-select: none;
|
||||||
-ms-user-select: none;
|
-ms-user-select: none;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes spin {
|
@keyframes spin {
|
||||||
0% {
|
0% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
100% {
|
100% {
|
||||||
transform: rotate(360deg);
|
transform: rotate(360deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------- Number input ni chiziqchalarini ko'rsatmaslik ------------------ */
|
/* -------------------------- Number input ni chiziqchalarini ko'rsatmaslik ------------------ */
|
||||||
/* Chrome, Safari, Edge, Opera */
|
/* Chrome, Safari, Edge, Opera */
|
||||||
input::-webkit-outer-spin-button,
|
input::-webkit-outer-spin-button,
|
||||||
input::-webkit-inner-spin-button {
|
input::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Firefox */
|
/* Firefox */
|
||||||
input[type='number'] {
|
input[type='number'] {
|
||||||
-moz-appearance: textfield;
|
-moz-appearance: textfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brd {
|
.printContent {
|
||||||
border: 1px solid red !important;
|
display: none;
|
||||||
}
|
|
||||||
|
@media print {
|
||||||
|
@page {
|
||||||
|
size: 10mm 10mm;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
118
src/routes/private/boxes-print/BoxesPrint.tsx
Normal file
118
src/routes/private/boxes-print/BoxesPrint.tsx
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
import InstagramChanel from '@/../public/instagram.png';
|
||||||
|
import Logo from '@/../public/logo.jpeg';
|
||||||
|
import TelegramChanel from '@/../public/telegram.jpg';
|
||||||
|
import { Box, Typography } from '@mui/material';
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
|
interface BoxesPrintProps {
|
||||||
|
boxData?: {
|
||||||
|
id: number;
|
||||||
|
box_name: string;
|
||||||
|
net_weight: number;
|
||||||
|
box_weight: number;
|
||||||
|
box_type: string;
|
||||||
|
box_size: string;
|
||||||
|
passportName: string;
|
||||||
|
status: string;
|
||||||
|
packetId: number;
|
||||||
|
partyId: number;
|
||||||
|
partyName: string;
|
||||||
|
passportId: string;
|
||||||
|
client_id: string;
|
||||||
|
clientName: string;
|
||||||
|
products_list: Array<{
|
||||||
|
id: number;
|
||||||
|
price: number;
|
||||||
|
cargoId: string;
|
||||||
|
trekId: string;
|
||||||
|
name: string;
|
||||||
|
nameRu: string;
|
||||||
|
amount: number;
|
||||||
|
acceptedNumber: number;
|
||||||
|
weight: number;
|
||||||
|
}>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const BoxesPrint = forwardRef<HTMLDivElement, BoxesPrintProps>(({ boxData }, ref) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
ref={ref}
|
||||||
|
sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
width: '100mm',
|
||||||
|
height: '100mm',
|
||||||
|
margin: '0 auto',
|
||||||
|
fontSize: '9px',
|
||||||
|
'@media print': {
|
||||||
|
width: '100mm',
|
||||||
|
height: '100mm',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{ border: '1px solid black' }}>
|
||||||
|
<Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
color: '#fff',
|
||||||
|
padding: '4px',
|
||||||
|
display: 'flex',
|
||||||
|
// flexDirection: 'column',
|
||||||
|
gap: '12px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Image alt='logo' src={Logo} width={30} height={30} priority unoptimized />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
color: '#fff',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: '4px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</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>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
borderTop: '1px solid black',
|
||||||
|
textAlign: 'start',
|
||||||
|
width: 'auto',
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||||
|
'@media print': {
|
||||||
|
pageBreakInside: 'avoid',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{boxData?.products_list.map((list, index) => (
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
borderRight: '1px solid black',
|
||||||
|
textAlign: 'start',
|
||||||
|
width: 'auto',
|
||||||
|
padding: '4px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Typography sx={{ fontSize: '12px' }}>{list.trekId}</Typography>
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
BoxesPrint.displayName = 'BoxesPrint';
|
||||||
|
|
||||||
|
export default BoxesPrint;
|
||||||
32
src/routes/private/boxes-print/BoxesPrintList.tsx
Normal file
32
src/routes/private/boxes-print/BoxesPrintList.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import { forwardRef } from 'react';
|
||||||
|
import BoxesPrint from './BoxesPrint';
|
||||||
|
|
||||||
|
interface BoxesPrintListProps {
|
||||||
|
boxData: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunkArray = (arr: any[], chunkSize: number): any[][] => {
|
||||||
|
const result = [];
|
||||||
|
for (let i = 0; i < arr.length; i += chunkSize) {
|
||||||
|
result.push(arr.slice(i, i + chunkSize));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
const BoxesPrintList = forwardRef<HTMLDivElement, BoxesPrintListProps>(({ boxData }, ref) => {
|
||||||
|
const productsChunks = chunkArray(boxData.products_list || [], 36);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div ref={ref}>
|
||||||
|
{productsChunks.map((chunk, index) => (
|
||||||
|
<div key={index} style={{ pageBreakAfter: 'always' }}>
|
||||||
|
<BoxesPrint boxData={{ ...boxData, products_list: chunk }} />
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
BoxesPrintList.displayName = 'BoxesPrintList';
|
||||||
|
|
||||||
|
export default BoxesPrintList;
|
||||||
@@ -1,16 +1,20 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import type React from 'react';
|
||||||
|
|
||||||
import ActionPopMenu from '@/components/common/ActionPopMenu';
|
import ActionPopMenu from '@/components/common/ActionPopMenu';
|
||||||
import { ColumnData, MyTable } from '@/components/common/MyTable';
|
import { type ColumnData, MyTable } from '@/components/common/MyTable';
|
||||||
import StatusChangePopup from '@/components/common/StatusChangePopup';
|
import StatusChangePopup from '@/components/common/StatusChangePopup';
|
||||||
import BaseButton from '@/components/ui-kit/BaseButton';
|
import BaseButton from '@/components/ui-kit/BaseButton';
|
||||||
import BaseInput from '@/components/ui-kit/BaseInput';
|
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 { useAuthContext } from '@/context/auth-context';
|
import { useAuthContext } from '@/context/auth-context';
|
||||||
import { BoxStatus, BoxStatusList, IBox } from '@/data/box/box.model';
|
import { type BoxStatus, BoxStatusList, type IBox } from '@/data/box/box.model';
|
||||||
import { box_requests } from '@/data/box/box.requests';
|
import { box_requests } from '@/data/box/box.requests';
|
||||||
import { 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';
|
||||||
|
import { party_requests } from '@/data/party/party.requests';
|
||||||
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
|
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
|
||||||
import useInput from '@/hooks/useInput';
|
import useInput from '@/hooks/useInput';
|
||||||
import { useMyNavigation } from '@/hooks/useMyNavigation';
|
import { useMyNavigation } from '@/hooks/useMyNavigation';
|
||||||
@@ -19,10 +23,13 @@ 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, RemoveRedEye, Search } from '@mui/icons-material';
|
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 { Box, Button, Card, CardContent, Modal, Stack, TextField, Typography } from '@mui/material';
|
||||||
import { useEffect, useMemo, 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 { useReactToPrint } from 'react-to-print';
|
||||||
|
import BoxesPrintList from '../boxes-print/BoxesPrintList';
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
@@ -43,7 +50,7 @@ const style = {
|
|||||||
|
|
||||||
const DashboardBoxesPage = (props: Props) => {
|
const DashboardBoxesPage = (props: Props) => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const handleOpen = () => setOpen(true);
|
const [openModal, setOpenModal] = useState(false);
|
||||||
const handleClose = () => setOpen(false);
|
const handleClose = () => setOpen(false);
|
||||||
const t = useMyTranslation();
|
const t = useMyTranslation();
|
||||||
const navigation = useMyNavigation();
|
const navigation = useMyNavigation();
|
||||||
@@ -53,12 +60,96 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
|
const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
|
||||||
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 [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 }>>({});
|
||||||
|
|
||||||
|
// Print uchun state
|
||||||
|
const [selectedBoxForPrint, setSelectedBoxForPrint] = useState<IBox | null>(null);
|
||||||
|
const [selectedBoxDetails, setSelectedBoxDetails] = useState<any>(null);
|
||||||
|
|
||||||
|
const printRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
// Available status options (simulating admin/user permissions)
|
||||||
|
|
||||||
|
// Print functionality
|
||||||
|
const handlePrint = useReactToPrint({
|
||||||
|
contentRef: printRef,
|
||||||
|
onAfterPrint: () => {
|
||||||
|
setSelectedBoxForPrint(null);
|
||||||
|
setSelectedBoxDetails(null);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: defaultPartyOptions } = useRequest(() => party_requests.getAll({}), {
|
||||||
|
enabled: true,
|
||||||
|
selectData(data) {
|
||||||
|
return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
|
||||||
|
},
|
||||||
|
placeholderData: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const partyOptions = (inputValue: string) => {
|
||||||
|
return party_requests.getAll({ partyName: inputValue }).then(res => {
|
||||||
|
return res.data.data.data.map(p => ({ label: p.name, value: p.id }));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onPrintBox = async (boxData: IBox) => {
|
||||||
|
try {
|
||||||
|
// Fetch detailed box data
|
||||||
|
const response = await box_requests.find({ packetId: boxData.id });
|
||||||
|
const boxOne = response.data.data;
|
||||||
|
|
||||||
|
const detailedBoxData = {
|
||||||
|
id: +boxData.id,
|
||||||
|
box_name: boxOne.packet.name,
|
||||||
|
net_weight: +boxOne.packet.brutto,
|
||||||
|
box_weight: +boxOne.packet.boxWeight,
|
||||||
|
box_type: boxOne.packet.boxType,
|
||||||
|
box_size: boxOne.packet.volume,
|
||||||
|
passportName: boxOne.packet.passportName,
|
||||||
|
status: boxOne.packet.status,
|
||||||
|
packetId: boxData.id,
|
||||||
|
partyId: +boxOne.packet.partyId,
|
||||||
|
partyName: boxOne.packet.partyName,
|
||||||
|
passportId: boxOne.client?.passportId,
|
||||||
|
client_id: boxOne.packet?.cargoId,
|
||||||
|
clientName: boxOne.client?.passportName,
|
||||||
|
products_list: boxOne.items.map((item: any) => ({
|
||||||
|
id: item.id,
|
||||||
|
price: item.price,
|
||||||
|
cargoId: item.cargoId,
|
||||||
|
trekId: item.trekId,
|
||||||
|
name: item.name,
|
||||||
|
nameRu: item.nameRu,
|
||||||
|
amount: +item.amount,
|
||||||
|
acceptedNumber: item.acceptedNumber,
|
||||||
|
weight: +item.weight,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
setSelectedBoxDetails(detailedBoxData);
|
||||||
|
setTimeout(() => {
|
||||||
|
handlePrint();
|
||||||
|
}, 100);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch box details:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpen = (data: any) => {
|
||||||
|
setOpen(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenModal = (data: any) => {
|
||||||
|
setOpenModal(true);
|
||||||
|
setSelectedBoxForPrint(data);
|
||||||
|
};
|
||||||
|
|
||||||
const boxStatusOptions = useMemo(() => {
|
const boxStatusOptions = useMemo(() => {
|
||||||
const p = ['READY_TO_INVOICE'] as BoxStatus[];
|
const p = ['READY_TO_INVOICE'] as BoxStatus[];
|
||||||
if (isAdmin) {
|
if (isAdmin) {
|
||||||
@@ -72,6 +163,7 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
box_requests.getAll({
|
box_requests.getAll({
|
||||||
page: page,
|
page: page,
|
||||||
cargoId: keyword,
|
cargoId: keyword,
|
||||||
|
partyId: partyFilter?.value,
|
||||||
status: boxStatusFilter,
|
status: boxStatusFilter,
|
||||||
direction: 'desc',
|
direction: 'desc',
|
||||||
sort: 'id',
|
sort: 'id',
|
||||||
@@ -191,7 +283,7 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
getBoxesQuery.refetch();
|
getBoxesQuery.refetch();
|
||||||
}, 350);
|
}, 350);
|
||||||
return () => clearTimeout(timeoutId);
|
return () => clearTimeout(timeoutId);
|
||||||
}, [keyword]);
|
}, [keyword, partyFilter?.value]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchAmounts = async () => {
|
const fetchAmounts = async () => {
|
||||||
@@ -227,7 +319,6 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
}
|
}
|
||||||
}, [list, loading]);
|
}, [list, loading]);
|
||||||
|
|
||||||
// No, PartyName, PacketName, PartyTozaOg'irlik, CountOfItems, WeightOfItems, CargoID, PassportNameFamily - PacketStatusForInvoice
|
|
||||||
const columns: ColumnData<IBox>[] = [
|
const columns: ColumnData<IBox>[] = [
|
||||||
{
|
{
|
||||||
label: t('No'),
|
label: t('No'),
|
||||||
@@ -355,6 +446,26 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
dataKey: 'id',
|
||||||
|
label: t('print'),
|
||||||
|
width: 120,
|
||||||
|
renderHeaderCell(rowIndex) {
|
||||||
|
return (
|
||||||
|
<Stack direction={'row'} alignItems={'center'}>
|
||||||
|
<span>{t('print')}</span>
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
renderCell(data) {
|
||||||
|
const total = boxAmounts[data.id];
|
||||||
|
return (
|
||||||
|
<Button onClick={() => onPrintBox(data)} disabled={total?.totalAccepted !== total?.totalAmount}>
|
||||||
|
<Print className='h-3 w-3 mr-1' />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: '',
|
label: '',
|
||||||
width: 100,
|
width: 100,
|
||||||
@@ -405,6 +516,7 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const [items, setItems] = useState<Product>();
|
const [items, setItems] = useState<Product>();
|
||||||
const [loaer, setLoading] = useState(false);
|
const [loaer, setLoading] = useState(false);
|
||||||
const {
|
const {
|
||||||
@@ -431,7 +543,7 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
|
|
||||||
const updateBody: UpdateProductBodyType = {
|
const updateBody: UpdateProductBodyType = {
|
||||||
itemId: item.id,
|
itemId: item.id,
|
||||||
acceptedNumber,
|
acceptedNumber: item.amount,
|
||||||
amount: item.amount,
|
amount: item.amount,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
nameRu: item.nameRu,
|
nameRu: item.nameRu,
|
||||||
@@ -441,11 +553,11 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
|
|
||||||
await item_requests.update(updateBody);
|
await item_requests.update(updateBody);
|
||||||
|
|
||||||
// Ma'lumotni yangilab olamiz
|
|
||||||
getListQuery.refetch();
|
getListQuery.refetch();
|
||||||
getBoxesQuery.refetch();
|
getBoxesQuery.refetch();
|
||||||
|
|
||||||
setValues(prev => ({ ...prev, [item.trekId]: '' }));
|
setValues(prev => ({ ...prev, [item.trekId]: '' }));
|
||||||
|
setTrackId('');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
notifyUnknownError(error);
|
notifyUnknownError(error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -472,12 +584,13 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
id='outlined-basic'
|
id='outlined-basic'
|
||||||
label={t('track_id')}
|
label={t('track_id')}
|
||||||
variant='outlined'
|
variant='outlined'
|
||||||
|
value={trackId}
|
||||||
onChange={e => setTrackId(e.target.value)}
|
onChange={e => setTrackId(e.target.value)}
|
||||||
/>
|
/>
|
||||||
{trackId && trackId.length > 0 && (
|
{trackId && trackId.length > 0 && (
|
||||||
<>
|
<>
|
||||||
{getListQuery.loading ? (
|
{getListQuery.loading ? (
|
||||||
<Typography sx={{ mt: 2 }}>{t('loading')}...</Typography> // yoki <CircularProgress />
|
<Typography sx={{ mt: 2 }}>{t('loading')}...</Typography>
|
||||||
) : getListQuery.data?.data && getListQuery.data?.data.length > 0 ? (
|
) : getListQuery.data?.data && getListQuery.data?.data.length > 0 ? (
|
||||||
getListQuery.data?.data.map(e => (
|
getListQuery.data?.data.map(e => (
|
||||||
<Box key={e.id} sx={{ width: '100%', display: 'flex', flexDirection: 'column' }}>
|
<Box key={e.id} sx={{ width: '100%', display: 'flex', flexDirection: 'column' }}>
|
||||||
@@ -491,15 +604,6 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
<Typography sx={{ fontSize: 14 }}>Paket nomi: {e?.packetName}</Typography>
|
<Typography sx={{ fontSize: 14 }}>Paket nomi: {e?.packetName}</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</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
|
<Button
|
||||||
sx={{ mt: '10px' }}
|
sx={{ mt: '10px' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
@@ -552,7 +656,20 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
setKeyword(e.target.value);
|
setKeyword(e.target.value);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
<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')}
|
||||||
|
/>
|
||||||
<BaseButton colorVariant='gray' startIcon={<FilterListOff />} size='small' onClick={resetFilter}>
|
<BaseButton colorVariant='gray' startIcon={<FilterListOff />} size='small' onClick={resetFilter}>
|
||||||
{t('reset_filter')}
|
{t('reset_filter')}
|
||||||
</BaseButton>
|
</BaseButton>
|
||||||
@@ -565,6 +682,13 @@ const DashboardBoxesPage = (props: Props) => {
|
|||||||
<BasePagination page={page} pageSize={pageSize} totalCount={totalElements} onChange={handleChange} />
|
<BasePagination page={page} pageSize={pageSize} totalCount={totalElements} onChange={handleChange} />
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* Print komponenti - sahifaning oxirida yashirin */}
|
||||||
|
{selectedBoxDetails && (
|
||||||
|
<div style={{ display: 'none' }}>
|
||||||
|
<BoxesPrintList ref={printRef} boxData={selectedBoxDetails} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const DashboardClientsPage = (props: Props) => {
|
|||||||
customer_requests.getAll({
|
customer_requests.getAll({
|
||||||
page: page,
|
page: page,
|
||||||
clientName: name,
|
clientName: name,
|
||||||
autoCargoId: keyword,
|
sort: keyword,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
selectData(data) {
|
selectData(data) {
|
||||||
|
|||||||
@@ -1,34 +1,30 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import AsyncSelect from 'react-select/async';
|
|
||||||
import ActionPopMenu from '@/components/common/ActionPopMenu';
|
import ActionPopMenu from '@/components/common/ActionPopMenu';
|
||||||
import { MyTable, ColumnData } from '@/components/common/MyTable';
|
import { ColumnData, MyTable } from '@/components/common/MyTable';
|
||||||
import StatusChangePopup from '@/components/common/StatusChangePopup';
|
|
||||||
import BaseButton from '@/components/ui-kit/BaseButton';
|
import BaseButton from '@/components/ui-kit/BaseButton';
|
||||||
import BaseIconButton from '@/components/ui-kit/BaseIconButton';
|
|
||||||
import BaseInput from '@/components/ui-kit/BaseInput';
|
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 { useAuthContext } from '@/context/auth-context';
|
||||||
import { BoxStatus, BoxStatusList } from '@/data/box/box.model';
|
import { BoxStatus, BoxStatusList } from '@/data/box/box.model';
|
||||||
|
import { box_requests } from '@/data/box/box.requests';
|
||||||
import { Product } from '@/data/item/item.mode';
|
import { Product } from '@/data/item/item.mode';
|
||||||
import { item_requests } from '@/data/item/item.requests';
|
import { item_requests } from '@/data/item/item.requests';
|
||||||
import { Party, PartyStatus, PartyStatusList } from '@/data/party/party.model';
|
|
||||||
import { party_requests } from '@/data/party/party.requests';
|
import { party_requests } from '@/data/party/party.requests';
|
||||||
import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
|
import { UserRoleEnum } from '@/data/user/user.model';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '@/helpers/constants';
|
||||||
import useInput from '@/hooks/useInput';
|
import useInput from '@/hooks/useInput';
|
||||||
import { useMyTranslation } from '@/hooks/useMyTranslation';
|
import { useMyTranslation } from '@/hooks/useMyTranslation';
|
||||||
import useRequest from '@/hooks/useRequest';
|
import useRequest from '@/hooks/useRequest';
|
||||||
|
import AddPhotosModal from '@/routes/private/items/components/AddPhotosModal';
|
||||||
import EditItemModal from '@/routes/private/items/components/EditItemModal';
|
import EditItemModal from '@/routes/private/items/components/EditItemModal';
|
||||||
import { notifyUnknownError } from '@/services/notification';
|
import { notifyUnknownError } from '@/services/notification';
|
||||||
import { getBoxStatusStyles, getStatusColor } from '@/theme/getStatusBoxStyles';
|
import { getBoxStatusStyles, getStatusColor } from '@/theme/getStatusBoxStyles';
|
||||||
import { Add, AddCircleOutline, Check, Circle, Delete, Edit, FilterList, FilterListOff, Search } from '@mui/icons-material';
|
import { Add, Check, Circle, Delete, Edit, FilterList, FilterListOff, Search } from '@mui/icons-material';
|
||||||
import { Box, Stack, SvgIcon, Tooltip, Typography } from '@mui/material';
|
import { Box, Stack, Typography } from '@mui/material';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useEffect, useMemo, useState } from 'react';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import AsyncSelect from 'react-select/async';
|
||||||
import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect';
|
|
||||||
import { box_requests } from '@/data/box/box.requests';
|
|
||||||
import { useAuthContext } from '@/context/auth-context';
|
|
||||||
import { UserRoleEnum } from '@/data/user/user.model';
|
|
||||||
import AddPhotosModal from '@/routes/private/items/components/AddPhotosModal';
|
|
||||||
|
|
||||||
type Props = {};
|
type Props = {};
|
||||||
|
|
||||||
|
|||||||
@@ -3405,6 +3405,11 @@ react-select@*, react-select@^5.8.0:
|
|||||||
react-transition-group "^4.3.0"
|
react-transition-group "^4.3.0"
|
||||||
use-isomorphic-layout-effect "^1.2.0"
|
use-isomorphic-layout-effect "^1.2.0"
|
||||||
|
|
||||||
|
react-to-print@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.npmjs.org/react-to-print/-/react-to-print-3.1.0.tgz"
|
||||||
|
integrity sha512-hiJZVmJtaRm9EHoUTG2bordyeRxVSGy9oFVV7fSvzOWwctPp6jbz2R6NFkaokaTYBxC7wTM/fMV5eCXsNpEwsA==
|
||||||
|
|
||||||
react-transition-group@^4.3.0, react-transition-group@^4.4.5:
|
react-transition-group@^4.3.0, react-transition-group@^4.4.5:
|
||||||
version "4.4.5"
|
version "4.4.5"
|
||||||
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"
|
resolved "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz"
|
||||||
@@ -3415,7 +3420,7 @@ react-transition-group@^4.3.0, react-transition-group@^4.4.5:
|
|||||||
loose-envify "^1.4.0"
|
loose-envify "^1.4.0"
|
||||||
prop-types "^15.6.2"
|
prop-types "^15.6.2"
|
||||||
|
|
||||||
"react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "react@^17.0.0 || ^18.0.0 || ^19.0.0", react@^18, "react@^18 || ^19", react@^18.2.0, "react@>= 16.0.0", "react@>= 16.8.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>= 17.0.2", react@>=16, react@>=16.6.0, react@>=16.8, react@>=16.8.0:
|
"react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "react@^16.8.0 || ^17.0.0 || ^18.0.0 || ~19", "react@^17.0.0 || ^18.0.0 || ^19.0.0", react@^18, "react@^18 || ^19", react@^18.2.0, "react@>= 16.0.0", "react@>= 16.8.0", "react@>= 16.8.0 || 17.x.x || ^18.0.0-0", "react@>= 17.0.2", react@>=16, react@>=16.6.0, react@>=16.8, react@>=16.8.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
resolved "https://registry.npmjs.org/react/-/react-18.2.0.tgz"
|
||||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||||
|
|||||||
Reference in New Issue
Block a user