From e7c4cda9a2159545500bfb73fd570365c176783c Mon Sep 17 00:00:00 2001 From: Samandar Turg'unboev Date: Thu, 22 May 2025 10:12:44 +0500 Subject: [PATCH 1/4] real-boxing --- messages/cn.json | 19 +- messages/en.json | 19 +- messages/ru.json | 5 +- messages/uz.json | 7 +- .../DashboardCreateRealBox.tsx | 455 +++++------------- .../DashboardEditRealBox.tsx | 3 +- .../real-boxes/DashboardRealBoxesPage.tsx | 220 ++++----- yarn.lock | 23 +- 8 files changed, 258 insertions(+), 493 deletions(-) diff --git a/messages/cn.json b/messages/cn.json index 3d87c19..2669bb9 100644 --- a/messages/cn.json +++ b/messages/cn.json @@ -15,7 +15,6 @@ "safe_warehouse": "安全仓库", "we_proud_to_serve_global": "我们以为全球提供最佳的货运和运输解决方案感到自豪。", "our_services": "我们的服务", - "air_transport": "空运", "air_transport__subtitle": "CPost提供各类大型和重型货物的空运服务。", "car_transport": "汽车运输", @@ -28,13 +27,11 @@ "warehouse_yivu_and_guanchjou__subtitle": "CPost在中国提供仓储物流服务,与从中国运输的车辆同时进行。", "customs_office_service": "海关清关服务", "customs_office_service__subtitle": "CPost重视客户的时间,并提供货物的海关申报服务。按照HS和TN编码对货物进行分类。", - "pricing": { "title": "价格", "limit": "交货时间:", "min_weight": "最小重量", "more": "更多详情", - "pricing1": { "title": "空运", "price": "每千克从$10起", @@ -60,7 +57,6 @@ "min_weight": "1立方米" } }, - "our_partners": "我们的合作伙伴", "news_subtitle": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "contacts_subtitle": "Creative mouse is here for you to make sure you can build a more resilient portfolio. We curate bespoke offerings across alternative.", @@ -70,7 +66,6 @@ "telegram": "Telegram", "instagram": "Instagram", "real_address": "塔什干市,奥尔马佐尔区,_______街", - "faq": { "title": "常见问题", "subtitle": "Creative mouse is here for you to make sure you can build a more resilient portfolio. We curate bespoke offerings across alternative.", @@ -79,7 +74,6 @@ "answer": "大多数物流公司通过其网站或移动应用提供在线追踪服务。您可以输入跟踪号以获取货物的实时位置和状态更新。" } }, - "footer_site_info_text": "可靠且快速的物流服务提供商", "privacy_policy": "隐私政策", "terms_of_use": "使用条款", @@ -89,7 +83,6 @@ "info": "信息", "join_tg": "加入我们的Telegram", "all_rights_reserved": "版权所有", - "calc_obj": { "title": "计算器", "subtitle": "选择您的订单的运输类型和重量,以了解运费。", @@ -107,7 +100,6 @@ "delivery_type_car": "汽车" }, "price": "价格", - "__dash": "------------------------------------DASHBOARD------------------------------------------------------", "dashboard": "仪表板", "parties": "派对", @@ -179,13 +171,10 @@ "count_of_boxes": "箱子数量", "count_of_items": "物品数量", "download_excel": "下载Excel", - "enter_party_name_to_find": "输入要查找的派对名称...", "enter_box_name_to_find": "输入要查找的箱子名称...", "enter_client_name_to_find": "输入要查找的客户名称...", - "filter_packet_name": "封包名稱過濾器", - "filter_party_name": "派对名称过滤器", "filter_box_name": "箱子名称过滤器", "filter_track_id": "跟踪ID过滤器", @@ -193,7 +182,6 @@ "filter_item_name": "产品名称过滤器", "filter_by_box_status": "箱子状态过滤器", "filter_by_party_status": "派对状态过滤器", - "COLLECTING": "收集中", "ON_THE_WAY": "在路上", "ARRIVED": "已到达", @@ -202,7 +190,6 @@ "IN_CUSTOMS": "在海關", "IN_WAREHOUSE": "接觸客戶", "DELIVERED": "發表", - "add_photo_to_item": "將照片加入項目", "photo": "照片", "summa": "總結", @@ -221,5 +208,7 @@ "passport": "護照", "weight_of_items": "產品重量", "update_packet": "編輯套件", - "party_weight": "大量重量" -} + "party_weight": "大量重量", + "qr_code": "二维码", + "created_at": "添加日期" +} \ No newline at end of file diff --git a/messages/en.json b/messages/en.json index 751b513..c2e3f11 100644 --- a/messages/en.json +++ b/messages/en.json @@ -15,7 +15,6 @@ "safe_warehouse": "Secure Warehouse", "we_proud_to_serve_global": "We take pride in providing the best freight and transportation solutions worldwide.", "our_services": "Our Services", - "air_transport": "Air Transport", "air_transport__subtitle": "CPost offers air transportation for a wide range of large-sized and heavy goods.", "car_transport": "Car Transport", @@ -28,13 +27,11 @@ "warehouse_yivu_and_guanchjou__subtitle": "CPost offers the use of warehouse logistics services in China simultaneously with transporting vehicles from China.", "customs_office_service": "Customs Clearance Services", "customs_office_service__subtitle": "CPost values its customers' time and offers customs declaration services for goods. Classification of goods by HS and TN codes.", - "pricing": { "title": "Pricing", "limit": "Delivery time:", "min_weight": "Minimum Weight", "more": "More Details", - "pricing1": { "title": "Air Transport", "price": "From $10/KG", @@ -60,7 +57,6 @@ "min_weight": "1m3" } }, - "our_partners": "Our Partners", "news_subtitle": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.", "contacts_subtitle": "Creative mouse is here for you to make sure you can build a more resilient portfolio. We curate bespoke offerings across alternative.", @@ -70,7 +66,6 @@ "telegram": "Telegram", "instagram": "Instagram", "real_address": "Tashkent city, Olmazor district, _______ street", - "faq": { "title": "Frequently Asked Questions", "subtitle": "Creative mouse is here for you to make sure you can build a more resilient portfolio. We curate bespoke offerings across alternative.", @@ -79,7 +74,6 @@ "answer": "Most logistics companies provide online tracking services through their websites or mobile apps. You can enter your tracking number to get real-time updates on the delivery location and status." } }, - "footer_site_info_text": "Reliable and Fast Logistics Service Provider", "privacy_policy": "Privacy Policy", "terms_of_use": "Terms of Use", @@ -89,7 +83,6 @@ "info": "Information", "join_tg": "Join our telegram", "all_rights_reserved": "All Rights Reserved", - "calc_obj": { "title": "Calculator", "subtitle": "Select the delivery type and weight of your order to find out the delivery cost", @@ -107,7 +100,6 @@ "delivery_type_car": "Auto" }, "price": "Price", - "__dash": "------------------------------------DASHBOARD------------------------------------------------------", "dashboard": "Dashboard", "parties": "Parties", @@ -179,12 +171,10 @@ "count_of_boxes": "Count of boxes", "count_of_items": "Count of items", "download_excel": "Download excel", - "enter_party_name_to_find": "Enter party name to find...", "enter_box_name_to_find": "Enter box name to find...", "enter_client_name_to_find": "Enter client name to find...", "filter_packet_name": "Packet name filter", - "filter_party_name": "Party name filter", "filter_box_name": "Box name filter", "filter_track_id": "Track id filter", @@ -192,7 +182,6 @@ "filter_item_name": "Product name filter", "filter_by_box_status": "Box Status filter", "filter_by_party_status": "Party Status filter", - "COLLECTING": "Collecting", "ON_THE_WAY": "On the way", "ARRIVED": "Arrived", @@ -201,7 +190,6 @@ "IN_CUSTOMS": "At customs", "IN_WAREHOUSE": "Reaching out to customers", "DELIVERED": "Delivered", - "add_photo_to_item": "Add photo to item", "photo": "photo", "summa": "summa", @@ -220,5 +208,8 @@ "passport": "Passport", "weight_of_items": "Products weight", "update_packet": "Edit Paket", - "party_weight": "Batch weight" -} + "party_weight": "Batch weight", + + "qr_code": "QR Code", + "created_at": "Date of joining" +} \ No newline at end of file diff --git a/messages/ru.json b/messages/ru.json index 095e24e..e4aa6d6 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -221,5 +221,8 @@ "passport": "Паспорт", "weight_of_items": "Вес продукта", "update_packet": "Редактировать пакет", - "party_weight": "Вес партии" + "party_weight": "Вес партии", + + "qr_code": "QR код", + "created_at": "Дата добавления" } diff --git a/messages/uz.json b/messages/uz.json index a89a517..389d01a 100644 --- a/messages/uz.json +++ b/messages/uz.json @@ -113,7 +113,7 @@ "parties": "Partiyalar", "create_party": "Partiya yaratish", "update_party": "Partiyani yangilash", - "create_box": "Qutni yaratish", + "create_box": "Qutini yaratish", "create_packet": "Paket yaratish", "update_box": "Qutni yangilash", "update_package": "Paketni yangilash", @@ -220,5 +220,8 @@ "are_you_sure_delete_party": "{name} yuk partiyasini o'chirishga ishonchingiz komilmi?", "passport": "Pasport", "update_packet": "Paketni Tahrirlash", - "party_weight": "Partiya og'irligi" + "party_weight": "Partiya og'irligi", + + "qr_code": "QR kod", + "created_at": "Qo‘shilgan sana" } diff --git a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx index 7a776d7..7c42e85 100644 --- a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx @@ -6,7 +6,7 @@ import { party_requests } from '@/data/party/party.requests'; import { pageLinks } from '@/helpers/constants'; import { notifyError, notifyUnknownError } from '@/services/notification'; import { Box, Divider, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material'; -import { useParams, useRouter, useSearchParams } from 'next/navigation'; +import { useParams, useSearchParams, useRouter } from 'next/navigation'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { useLocale } from 'use-intl'; import { Controller, useFieldArray, useForm } from 'react-hook-form'; @@ -21,7 +21,6 @@ import { customer_requests } from '@/data/customers/customer.requests'; import { useAuthContext } from '@/context/auth-context'; import { useMyNavigation } from '@/hooks/useMyNavigation'; import AsyncSelect from 'react-select/async'; -import { Party } from '@/data/party/party.model'; import cloneDeep from 'lodash.clonedeep'; import { item_requests } from '@/data/item/item.requests'; import get from 'lodash.get'; @@ -57,20 +56,16 @@ type Props = { box_size: string; status: BoxStatus; packetId: string; - passportName: string; passportId: number; partyId: number; partyName: string; - clientId: number; client_id: string; clientName: string; - products_list: { id: number; price: number | string; - cargoId: string; trekId: string; name: string; @@ -93,16 +88,14 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { finished: boolean; partyFinished: boolean; clientFinished: boolean; - settedDefaultParty: Party | null; + settedDefaultParty: any; settedDefaultClient: Customer | null; - // settedDefaultPartyValue: { value: number; label: string }[] | null; }>({ settedDefaultParty: null, settedDefaultClient: null, partyFinished: false, clientFinished: false, finished: false, - // settedDefaultPartyValue: partiesData?.[0] || null, }); const { register, @@ -114,28 +107,30 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { } = useForm({ defaultValues: { partyId: params.get('party_id') ? +params.get('party_id')! : '', + paketIds: editMode + ? [{ id: initialValues?.partyId }] + : params.get('party_id') + ? [{ id: +params.get('party_id')! }] + : [{ id: '' }], box_weight: 0.9, box_type: 'KG', box_size: '50x40x40', status: 'READY_TO_INVOICE', cargoId: initialValues?.client_id, - // passportId: {value: initialValues?.passportId}, - ...(editMode - ? {} - : { - products_list: [ - { - id: '', - cargoId: '', - trekId: '', - name: '', - nameRu: '', - amount: '', - weight: '', - price: '', - }, - ], - }), + products_list: editMode + ? initialValues?.products_list + : [ + { + id: '', + cargoId: '', + trekId: '', + name: '', + nameRu: '', + amount: '', + weight: '', + price: '', + }, + ], ...initialValues, }, }); @@ -146,12 +141,17 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { name: 'products_list', keyName: 'key', }); + const pakets = useFieldArray({ + control, + name: 'paketIds', + keyName: 'key', + }); const controlledProductFields = watch('products_list'); const partyIdValue = watch('partyId'); const clientIdValue = watch('client_id'); const cargoId = watch('cargoId'); const requiredText = t('required'); - const [selectedPassport, setSelectedPassport] = useState(null); // Tanlangan passportni saqlash uchun state (tipi Passport yoki null) + const [selectedPassport, setSelectedPassport] = useState(null); const passportOptionsInitial = initialValues?.passportId && initialValues?.passportName && [ @@ -160,20 +160,16 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { label: initialValues?.passportName, }, ]; - const n = "123ds" - n.toUpperCase() + const { data: passportOptions } = useRequest(() => passport_requests.getAll({ cargoId: cargoId?.toUpperCase() }), { enabled: !!cargoId, selectData: data => { - // Ma'lumotlarni BaseReactSelect uchun mos formatga o'tkazish const passportOptions = data.data.data.map((passport: Passport) => ({ - // data.data endi Passport[] - value: passport.id, // passport id sini value sifatida - label: passport.fullName, // fullName ni label sifatida + value: passport.id, + label: passport.fullName, })); const passportId = watch('passportId'); - if (!passportId && initialValues?.passportId && cargoId === initialValues?.client_id) { const currentOption = passportOptions?.find((item: { value: number }) => item.value === initialValues?.passportId); setValue('passportId', currentOption); @@ -182,14 +178,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { return passportOptions; }, dependencies: [cargoId], - placeholderData: [], // Kerak emas, chunki server PageAble qaytarmayapti - onSuccess(data) { - // if (data?.data.data?.[0]?.id) { - // setValue("passportId", initialValues?.passportId) - // setValue('passport_id', data.data.data[0].id); - // setSelectedPassport(data.data.data[0]); // Birinchi elementni tanlash - // } - }, + placeholderData: [], }); useEffect(() => { @@ -205,6 +194,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { if (!editMode && data?.data?.data?.data?.[0]) { helperRef.current.settedDefaultParty = data.data.data.data[0]; setValue('partyId', data.data.data.data[0].id); + setValue('paketIds[0].id', data.data.data.data[0].id); } helperRef.current.partyFinished = true; if (helperRef.current.clientFinished) { @@ -223,7 +213,6 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { enabled: !!partyIdValue, selectData(data) { return data.data.data.data.map(p => ({ value: p.aviaCargoId, label: p.fullName })); - // return data.data.data.map(p => ({ value: p.id, label: p.fullName })); }, dependencies: [partyIdValue], onSuccess(data) { @@ -241,7 +230,6 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { ); const onPassportChange = (newValue: Passport | null) => { - // Tipi Passport | null setSelectedPassport(newValue); if (newValue) { setValue('passport_id', newValue.id || null); @@ -251,17 +239,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { }; const onSubmit = handleSubmit(async values => { - try { setLoading(true); if (editMode) { const updateBody: UpdateBoxBodyType = { cargoId: values.client_id, - passportId: values.passportId.value, + passportId: values.passportId?.value, status: values.status, - packetId: initialValues?.packetId, - + packetId: values.paketIds.map((p: any) => p.id), // Bir nechta paketId items: values.products_list.map((item: any) => { const _price = +item.price ? +item.price : 0; const _amount = +item.amount ? +item.amount : 0; @@ -269,9 +255,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { return { id: item.id, - // cargoId: item.cargoId, trekId: item.trekId, - // name: item.name + (item.nameRu ? ` / ${item.nameRu}` : ''), name: item.name, nameRu: item?.nameRu, weight: +item.weight, @@ -300,7 +284,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { const createBody: CreateBoxBodyType = { status: values.status, cargoId: values.cargoId, - passportId: values.passportId.value, + passportId: values.passportId?.value, partyId: values.partyId, items: values.products_list.map((item: any) => { return { @@ -328,11 +312,13 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { }); }; - // const clientOptions = (inputValue: string) => { - // return customer_requests.getAll({ clientName: inputValue, page: 1 }).then(res => { - // return res.data.data.data.map(p => ({ label: p.fullName, value: p.id })); - // }); - // }; + const appendPaket = () => { + pakets.append({ id: '' }); + }; + + const removePaket = (index: number) => { + pakets.remove(index); + }; const appendProduct = () => { products.append({ @@ -355,7 +341,6 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { if (!text) return; try { - // const responseText = await box_requests.translateWithGoogleApi({ text }); const responseText = await box_requests.translateWithMemoryApi({ text }); setValue(`products_list.${index}.nameRu`, responseText || ''); } catch (error) { @@ -380,11 +365,11 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { label: string; value: BoxStatus; }[] = [ - { - label: t('READY_TO_INVOICE'), - value: 'READY_TO_INVOICE', - }, - ]; + { + label: t('READY_TO_INVOICE'), + value: 'READY_TO_INVOICE', + }, + ]; if (isAdmin) { p.push({ @@ -408,11 +393,11 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { > - {editMode ? t('update_packet') : t('create_packet')} + {editMode ? t('update_box') : t('create_box')} - + {t('party_name')} @@ -429,15 +414,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { defaultValue={ editMode ? { - value: initialValues.partyId, - label: initialValues.partyName, - } + value: initialValues.partyId, + label: initialValues.partyName, + } : partiesData?.length - ? { + ? { value: partiesData[0].value, label: partiesData[0].label, } - : null + : null } styles={selectDefaultStyles} noOptionsMessage={() => t('not_found')} @@ -451,88 +436,9 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { ); }} /> - {/* @ts-expect-error */} - {!!errors.partyId?.message && {errors.partyId?.message}} - - - - - {t('status')} - - { - return ( - p.value === field.value)} - onChange={(newValue: any) => { - field.onChange(newValue.value); - }} - onBlur={field.onBlur} - name={field.name} - options={boxStatuses} - /> - ); - }} - /> - {/* @ts-expect-error */} - {!!errors.box_type?.message && {errors.box_type?.message}} - - - - - {t('cargo_id')} - - - {!!errors.net_weight?.message && ( - // @ts-expect-error - {errors.net_weight?.message} - )} - - - - {t('passport')} - - - { - return ( - { - onPassportChange(newValue); - field.onChange(newValue); - }} - // options={passportOptions || passportOptionsInitial || []} - options={passportOptions || passportOptionsInitial || []} - // isLoading={passportLoading} - placeholder={t('passport')} - isDisabled={!clientIdValue || !!initialValues} - noOptionsMessage={() => t('not_found')} - loadingMessage={() => t('loading')} - /> - ); - }} - /> + {/* {!!errors.partyId?.message && ( + {errors.partyId?.message} + )} */} @@ -544,196 +450,69 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { padding: '24px', }} > - {controlledProductFields.map((product: any, index: number) => { - // - - // - let totalPrice = 0; - - try { - const p = +product.price * +product.amount; - if (!Number.isNaN(p)) { - totalPrice = p; - } - } catch (error) {} - - return ( - - - - - {t('track_id')} - - - ID - - ), + + {t('packet')} + + {pakets.fields.map((field, index) => ( + + + ( + { + paketField.onChange(newValue?.value); }} - fullWidth - placeholder={t('id')} - sx={{ - '.MuiInputBase-root': { - paddingLeft: 0, - }, - }} - {...register(`products_list.${index}.trekId`, { required: requiredText })} + defaultValue={ + editMode && index === 0 + ? { + value: initialValues.partyId, + label: initialValues.partyName, + } + : partiesData?.length && index === 0 + ? { + value: partiesData[0].value, + label: partiesData[0].label, + } + : null + } + styles={selectDefaultStyles} + noOptionsMessage={() => t('not_found')} + loadingMessage={() => t('loading')} + onBlur={paketField.onBlur} + name={paketField.name} + defaultOptions={defaultParties!} + loadOptions={partyOptions} + placeholder={t('enter_party_name_to_find')} /> - {!!get(errors, `products_list.${index}.trekId`) && ( - {requiredText} - )} - - - - {t('name')} - - { - translateAndUpdateRussianName(event.target.value, index); - }} - /> - {!!get(errors, `products_list.${index}.name`) && ( - {requiredText} - )} - - - - {'NAME_RU'} - - - {!!get(errors, `products_list.${index}.name`) && ( - {requiredText} - )} - - - - {t('quantity')} - - - {!!get(errors, `products_list.${index}.amount`) && ( - {requiredText} - )} - - - - {t('weight')} - - - {!!get(errors, `products_list.${index}.amount`) && ( - {requiredText} - )} - - {isAdmin && ( - - - - {t('weight')} - - - - - - - - {t('price')} - - - {!!get(errors, `products_list.${index}.price`) && ( - {requiredText} - )} - - - - {t('total_price')} - - - - )} - - - removeProduct(index)} - > - - - - - + /> + {!!get(errors, `paketIds.${index}.id`) && ( + {requiredText} + )} - ); - })} - - - } onClick={appendProduct}> + {pakets.fields.length > 1 && ( + + removePaket(index)} + > + + + + )} + + ))} + + } + onClick={appendPaket} + > {t('add_more')} @@ -749,4 +528,4 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { ); }; -export default DashboardCreateRealBoxPage; +export default DashboardCreateRealBoxPage; \ No newline at end of file diff --git a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx index ef70a4d..4a20ef3 100644 --- a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx @@ -6,6 +6,7 @@ import useRequest from '@/hooks/useRequest'; import DashboardCreateBoxPage from '@/routes/private/boxes-create/DashboardCreateBox'; import { useParams } from 'next/navigation'; import React from 'react'; +import DashboardCreateRealBoxPage from './DashboardCreateRealBox'; type Props = {}; @@ -78,7 +79,7 @@ const DashboardEditRealBoxPage = (props: Props) => { return ( <> - + ); }; diff --git a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx index 680cf06..86ed532 100644 --- a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx +++ b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx @@ -19,7 +19,7 @@ import useRequest from '@/hooks/useRequest'; import { file_service } from '@/services/file-service'; import { notifyUnknownError } from '@/services/notification'; import { getBoxStatusStyles, getStatusColor } from '@/theme/getStatusBoxStyles'; -import { Add, AddCircleOutline, Circle, Delete, Download, Edit, FilterList, FilterListOff, Search, PlusOne } from '@mui/icons-material'; +import { Add, QrCode, AddCircleOutline, Circle, Delete, Download, Edit, FilterList, FilterListOff, Search, PlusOne } from '@mui/icons-material'; import { Box, Button, Stack, Tooltip, Typography } from '@mui/material'; import { useRouter } from 'next/navigation'; import React, { useEffect, useMemo, useState } from 'react'; @@ -84,7 +84,6 @@ const DashboardRealBoxesPage = (props: Props) => { } }, [getBoxesQuery]); const loading = getBoxesQuery.loading; - const handleChange = (newPage: number) => { setTimeout(() => { setPage(newPage); @@ -158,39 +157,23 @@ const DashboardRealBoxesPage = (props: Props) => { }, }, { - dataKey: 'id', - label: "Qo'shish", + label: t("qr_code"), width: 120, renderCell: data => { - return ; }, }, { - dataKey: 'partyName', - label: t('party_name'), - width: 120, - }, - { - dataKey: 'name', - label: t('name'), - width: 120, - }, - { - dataKey: 'packetNetWeight', - label: t("weight"), - width: 120, - }, - { - dataKey: 'totalItems', - label: t('count_of_items'), - width: 120, - }, - { - dataKey: 'totalNetWeight', - label: t("party_weight"), + dataKey: 'id', + label: t("add_more"), width: 120, + renderCell: data => { + return ; + }, }, { dataKey: 'cargoId', @@ -198,73 +181,98 @@ const DashboardRealBoxesPage = (props: Props) => { width: 120, }, { - dataKey: 'passportName', - label: t('client'), + dataKey: 'partyName', + label: t('party_name'), width: 120, }, + // { + // dataKey: 'name', + // label: t('name'), + // width: 120, + // }, + // { + // dataKey: 'packetNetWeight', + // label: t("weight"), + // width: 120, + // }, { - dataKey: 'status', - label: t('status'), - width: 240, - renderHeaderCell(rowIndex) { - return ( - - {t('box_status')} - { - return { - icon: , - label: t(stat), - onClick() { - setBoxStatusFilter(stat); - setPage(1); - }, - }; - })} - mainIcon={} - placement={{ - anchorOrigin: { - vertical: 'bottom', - horizontal: 'center', - }, - transformOrigin: { - horizontal: 'center', - vertical: 'top', - }, - }} - /> - - ); - }, - renderCell(data) { - return ( - { - return { - icon: ( - - ), - label: t(stat), - onClick: () => { - onChangeStatus(data.id, stat); - }, - }; - })} - /> - ); - }, + dataKey: 'totalItems', + label: t('count_of_items'), + width: 120, }, + // { + // dataKey: 'totalNetWeight', + // label: t("party_weight"), + // width: 120, + // }, + // { + // dataKey: 'passportName', + // label: t('client'), + // width: 120, + // }, + // { + // dataKey: 'status', + // label: t('status'), + // width: 240, + // renderHeaderCell(rowIndex) { + // return ( + // + // {t('box_status')} + // { + // return { + // icon: , + // label: t(stat), + // onClick() { + // setBoxStatusFilter(stat); + // setPage(1); + // }, + // }; + // })} + // mainIcon={} + // placement={{ + // anchorOrigin: { + // vertical: 'bottom', + // horizontal: 'center', + // }, + // transformOrigin: { + // horizontal: 'center', + // vertical: 'top', + // }, + // }} + // /> + // + // ); + // }, + // renderCell(data) { + // return ( + // { + // return { + // icon: ( + // + // ), + // label: t(stat), + // onClick: () => { + // onChangeStatus(data.id, stat); + // }, + // }; + // })} + // /> + // ); + // }, + // }, { label: '', width: 100, @@ -277,7 +285,7 @@ const DashboardRealBoxesPage = (props: Props) => { icon: , label: t('edit'), onClick: () => { - navigation.push(pageLinks.dashboard.boxes.edit(data.id)); + navigation.push(pageLinks.dashboard.real_boxes.edit(data.id)); }, }, { @@ -289,19 +297,15 @@ const DashboardRealBoxesPage = (props: Props) => { dontCloseOnClick: true, loading: deleteIds.includes(data.id), }, - ...(data.status === 'READY' - ? [ - { - icon: , - label: t('download_excel'), - onClick: () => { - onDownloadExcel(data.id); - }, - loading: downloadIds.includes(data.id), - dontCloseOnClick: true, - }, - ] - : []), + { + icon: , + label: t('download_excel'), + onClick: () => { + onDownloadExcel(data.id); + }, + loading: downloadIds.includes(data.id), + dontCloseOnClick: true, + }, ]} /> ); @@ -312,8 +316,8 @@ const DashboardRealBoxesPage = (props: Props) => { return ( - } href={pageLinks.dashboard.boxes.create}> - {t('create_packet')} + } href={pageLinks.dashboard.real_boxes.create}> + {t('create_box')} { color: '#000', }} > - {t('packet')} + {t('boxes')} Date: Sat, 24 May 2025 09:29:47 +0500 Subject: [PATCH 2/4] real boxing create and edit components --- .../layout/dashboard-layout/routes.tsx | 16 +- src/data/real-box/real-box.model.ts | 74 ++++ src/data/real-box/real-box.requests.ts | 63 +++ .../boxes-create/DashboardCreateBox.tsx | 2 +- .../DashboardCreateRealBox.tsx | 395 +++++------------- .../real-boxes/DashboardRealBoxesPage.tsx | 3 +- 6 files changed, 262 insertions(+), 291 deletions(-) create mode 100644 src/data/real-box/real-box.model.ts create mode 100644 src/data/real-box/real-box.requests.ts diff --git a/src/components/layout/dashboard-layout/routes.tsx b/src/components/layout/dashboard-layout/routes.tsx index 8f04871..70f91b2 100644 --- a/src/components/layout/dashboard-layout/routes.tsx +++ b/src/components/layout/dashboard-layout/routes.tsx @@ -34,13 +34,13 @@ export const routes = [ roles: [UserRoleEnum.ADMIN, UserRoleEnum.CHINA_WORKER], }, { - title: 'boxes', - path: pageLinks.dashboard.real_boxes.index, + title: 'packet', + path: pageLinks.dashboard.boxes.index, icon: ( - + @@ -49,13 +49,13 @@ export const routes = [ roles: [UserRoleEnum.ADMIN, UserRoleEnum.CHINA_WORKER], }, { - title: 'packet', - path: pageLinks.dashboard.boxes.index, + title: 'boxes', + path: pageLinks.dashboard.real_boxes.index, icon: ( - + diff --git a/src/data/real-box/real-box.model.ts b/src/data/real-box/real-box.model.ts new file mode 100644 index 0000000..9737437 --- /dev/null +++ b/src/data/real-box/real-box.model.ts @@ -0,0 +1,74 @@ +export type BoxStatus = 'READY_TO_INVOICE' | 'READY'; +export const BoxStatusList: BoxStatus[] = ['READY_TO_INVOICE', 'READY']; + +export interface IBox { + packetNetWeight: string; + totalNetWeight: string; + cargoId: string; + passportName: string; + id: number; + partyName: string; + boxType: string; + name: string; + volume: string; + boxWeight: number; + brutto: number; + hasInvoice: boolean; + totalItems: number; + status: BoxStatus; + totalBrutto: number; +} + +export interface IBoxDetail { + packet: { + id: number; + cargoId: string; + packetNetWeight: number; + passportName: string; + totalItems: number; + totalNetWeight: number; + partyName: string; + partyId: string; + boxType: string; + name: string; + volume: string; + boxWeight: number; + brutto: number; + hasInvoice: boolean; + status: BoxStatus; + }; + client: { + passportId: number; + passportName: string; + }; + items: [ + { + id: number; + partyName: string; + boxName: string; + cargoId: string; + trekId: string; + name: string; + nameRu: string; + amount: number; + weight: number; + price: number; + totalPrice: number; + hasImage: boolean; + imageUrl: string | null; + packetName: string; + status: BoxStatus; + }, + ]; +} + +export type RealCreateBoxBodyType = { + partyName: string, + packetDtos: number[] +}; + +export type UpdateRealBoxBodyType = { + boxId: string, + partyName: string, + packetDtos: number[] +}; diff --git a/src/data/real-box/real-box.requests.ts b/src/data/real-box/real-box.requests.ts new file mode 100644 index 0000000..fe8f147 --- /dev/null +++ b/src/data/real-box/real-box.requests.ts @@ -0,0 +1,63 @@ +import { IBox, UpdateBoxBodyType, IBoxDetail, BoxStatus } from '@/data/box/box.model'; +import { CommonResponseType, PageAble } from '@/helpers/types'; +import { request } from '@/services/request'; +import axios from 'axios'; +import { RealCreateBoxBodyType, UpdateRealBoxBodyType } from './real-box.model'; + +export const real_box_requests = { + async getAll(params?: { + page?: number; + sort?: string; + direction?: string; + cargoId?: string; + partyId?: string | number; + status?: BoxStatus; + }) { + return request.get>>('/boxes/list', { params }); + }, + async create({ ...body }: RealCreateBoxBodyType) { + return request.post('/boxes/create', body); + }, + async update({ boxId, ...body }: UpdateRealBoxBodyType) { + return request.put('/packets/update', body, { + params: { boxId }, + }); + }, + async find(params: { packetId?: number | string }) { + return request.get>('/packets/find', { params }); + }, + async delete(params: { packetId: number | string }) { + return request.delete('/packets/delete', { params }); + }, + async downloadExcel(params: { packetId: number | string }) { + return request.get('/packets/download', { params, responseType: 'blob' }); + }, + async translateWithGoogleApi(params: { text: string }): Promise { + const response = await axios.post('https://translation.googleapis.com/language/translate/v2', undefined, { + params: { + q: params.text, + target: 'ru', + source: 'zh', + key: 'AIzaSyA5uAPZyjF_yo1hYOWWJ2uP7XgcmohZc8o', + }, + }); + + return response.data.data.translations?.[0]?.translatedText ?? ''; + }, + async translateWithMemoryApi(params: { text: string }): Promise { + const response = await axios.get<{ + responseData: { + translatedText: string; + match: number; + }; + }>('https://api.mymemory.translated.net/get', { + params: { + q: params.text, + langpair: 'zh|ru', + // key: '7a4ac2e07cde1ff1e9de', + }, + }); + + return response.data.responseData.translatedText; + }, +}; \ No newline at end of file diff --git a/src/routes/private/boxes-create/DashboardCreateBox.tsx b/src/routes/private/boxes-create/DashboardCreateBox.tsx index 7bf5327..8f4ade8 100644 --- a/src/routes/private/boxes-create/DashboardCreateBox.tsx +++ b/src/routes/private/boxes-create/DashboardCreateBox.tsx @@ -193,7 +193,7 @@ const DashboardCreateBoxPage = ({ initialValues, partiesData }: Props) => { }); useEffect(() => { - setValue('passportId', ''); + setValue('passportId', 'AA1234567'); }, [cargoId]); const { data: defaultParties, status: defaultPartiesStatus } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), { diff --git a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx index 7c42e85..9e595ca 100644 --- a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx @@ -1,33 +1,25 @@ 'use client'; import BaseButton from '@/components/ui-kit/BaseButton'; -import BaseInput from '@/components/ui-kit/BaseInput'; import { party_requests } from '@/data/party/party.requests'; import { pageLinks } from '@/helpers/constants'; -import { notifyError, notifyUnknownError } from '@/services/notification'; -import { Box, Divider, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material'; -import { useParams, useSearchParams, useRouter } from 'next/navigation'; +import { notifyUnknownError } from '@/services/notification'; +import { Box, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material'; +import { useSearchParams } from 'next/navigation'; import React, { useEffect, useMemo, useRef, useState } from 'react'; -import { useLocale } from 'use-intl'; import { Controller, useFieldArray, useForm } from 'react-hook-form'; import BaseIconButton from '@/components/ui-kit/BaseIconButton'; import { AddCircleRounded, Close } from '@mui/icons-material'; -import { box_requests } from '@/data/box/box.requests'; import useRequest from '@/hooks/useRequest'; import { useMyTranslation } from '@/hooks/useMyTranslation'; -import { BoxStatus, CreateBoxBodyType, UpdateBoxBodyType } from '@/data/box/box.model'; -import BaseReactSelect, { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect'; -import { customer_requests } from '@/data/customers/customer.requests'; +import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect'; import { useAuthContext } from '@/context/auth-context'; import { useMyNavigation } from '@/hooks/useMyNavigation'; import AsyncSelect from 'react-select/async'; -import cloneDeep from 'lodash.clonedeep'; -import { item_requests } from '@/data/item/item.requests'; +import { box_requests } from '@/data/box/box.requests'; +import { real_box_requests } from '@/data/real-box/real-box.requests'; + import get from 'lodash.get'; -import Loader from '@/components/common/Loader'; -import { Customer } from '@/data/customers/customer.model'; -import { Passport } from '@/data/passport/passport.model'; -import { passport_requests } from '@/data/passport/passport.request'; const StyledCreateBox = styled(Box)` .item-row { @@ -37,9 +29,6 @@ const StyledCreateBox = styled(Box)` gap: 16px; } - .item-row-field { - } - & > * { flex: 1 1 1; } @@ -49,20 +38,11 @@ type Props = { partiesData?: { value: number; label: string }[]; initialValues?: { id: number; + boxId: string; box_name: string; - net_weight: number; - box_weight: number; - box_type: string; - box_size: string; - status: BoxStatus; - packetId: string; - passportName: string; - passportId: number; partyId: number; partyName: string; - clientId: number; - client_id: string; - clientName: string; + packetId: string; products_list: { id: number; price: number | string; @@ -77,31 +57,30 @@ type Props = { }; const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { - const [cargoIdValue, setCargoIdValue] = useState(''); const { user, isAdmin: isAdminUser } = useAuthContext(); const editMode = !!initialValues && !!initialValues.id; const isAdmin = isAdminUser && editMode; const t = useMyTranslation(); const params = useSearchParams(); const navigation = useMyNavigation(); + const [partyId, setPartyId] = useState(""); + const [loading, setLoading] = useState(false); const helperRef = useRef<{ finished: boolean; partyFinished: boolean; clientFinished: boolean; settedDefaultParty: any; - settedDefaultClient: Customer | null; }>({ settedDefaultParty: null, - settedDefaultClient: null, partyFinished: false, clientFinished: false, finished: false, }); + const { register, control, handleSubmit, - watch, setValue, formState: { errors }, } = useForm({ @@ -112,80 +91,46 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { : params.get('party_id') ? [{ id: +params.get('party_id')! }] : [{ id: '' }], - box_weight: 0.9, - box_type: 'KG', - box_size: '50x40x40', - status: 'READY_TO_INVOICE', - cargoId: initialValues?.client_id, - products_list: editMode - ? initialValues?.products_list - : [ - { - id: '', - cargoId: '', - trekId: '', - name: '', - nameRu: '', - amount: '', - weight: '', - price: '', - }, - ], ...initialValues, }, }); - const [loading, setLoading] = useState(false); - const products = useFieldArray({ - control, - name: 'products_list', - keyName: 'key', - }); const pakets = useFieldArray({ control, name: 'paketIds', keyName: 'key', }); - const controlledProductFields = watch('products_list'); - const partyIdValue = watch('partyId'); - const clientIdValue = watch('client_id'); - const cargoId = watch('cargoId'); + const requiredText = t('required'); - const [selectedPassport, setSelectedPassport] = useState(null); - const passportOptionsInitial = initialValues?.passportId && - initialValues?.passportName && [ - { - value: initialValues?.passportId, - label: initialValues?.passportName, + const getBoxesQuery = useRequest( + () => + box_requests.getAll({ + partyId: partyId, + }), + { + selectData(data) { + return data?.data?.data; }, - ]; + } + ); - const { data: passportOptions } = useRequest(() => passport_requests.getAll({ cargoId: cargoId?.toUpperCase() }), { - enabled: !!cargoId, - selectData: data => { - const passportOptions = data.data.data.map((passport: Passport) => ({ - value: passport.id, - label: passport.fullName, - })); - - const passportId = watch('passportId'); - if (!passportId && initialValues?.passportId && cargoId === initialValues?.client_id) { - const currentOption = passportOptions?.find((item: { value: number }) => item.value === initialValues?.passportId); - setValue('passportId', currentOption); - } - - return passportOptions; - }, - dependencies: [cargoId], - placeholderData: [], - }); + const { data: list } = useMemo(() => { + if (getBoxesQuery.data?.data) { + return { + data: getBoxesQuery.data.data.filter((box: any) => box.status === 'READY_TO_INVOICE'), + }; + } + return { data: [] }; + }, [getBoxesQuery, partyId]); useEffect(() => { - setValue('passportId', ''); - }, [cargoId]); + if (partyId) { + getBoxesQuery.refetch(); + } + }, [partyId]); - const { data: defaultParties, status: defaultPartiesStatus } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), { + const { data: defaultParties } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), { enabled: true, selectData(data) { return data.data.data.data.map(p => ({ value: p.id, label: p.name })); @@ -204,98 +149,24 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { placeholderData: [], }); - const { data: defaultClients } = useRequest( - () => - customer_requests.getAll({ - page: 1, - }), - { - enabled: !!partyIdValue, - selectData(data) { - return data.data.data.data.map(p => ({ value: p.aviaCargoId, label: p.fullName })); - }, - dependencies: [partyIdValue], - onSuccess(data) { - if (!editMode && !clientIdValue && data?.data?.data?.data?.[0]) { - helperRef.current.settedDefaultClient = data.data.data?.data?.[0]; - setValue('client_id', data.data.data.data[0].aviaCargoId); - } - helperRef.current.clientFinished = true; - if (helperRef.current.partyFinished) { - helperRef.current.finished = true; - } - }, - placeholderData: [], - } - ); - - const onPassportChange = (newValue: Passport | null) => { - setSelectedPassport(newValue); - if (newValue) { - setValue('passport_id', newValue.id || null); - } else { - setValue('passport_id', null); - } - }; - const onSubmit = handleSubmit(async values => { try { setLoading(true); + const packetDtos = values.paketIds.map((paket: any) => paket.id).filter((id: any) => id); if (editMode) { - const updateBody: UpdateBoxBodyType = { - cargoId: values.client_id, - passportId: values.passportId?.value, - status: values.status, - packetId: values.paketIds.map((p: any) => p.id), // Bir nechta paketId - items: values.products_list.map((item: any) => { - const _price = +item.price ? +item.price : 0; - const _amount = +item.amount ? +item.amount : 0; - const _total_price = _price ? _price * _amount : 0; - - return { - id: item.id, - trekId: item.trekId, - name: item.name, - nameRu: item?.nameRu, - weight: +item.weight, - amount: +item.amount, - price: _price, - totalPrice: _total_price, - }; - }), + const updateBody: UpdateRealBoxBodyType = { + boxId: initialValues?.boxId, + partyName: values.partyName, + packetDtos, }; - - const item_delete_promises = initialValues.products_list - .filter(item => { - if (!updateBody.items.find(i => String(i.id) === String(item.id))) { - return true; - } else { - return false; - } - }) - .map(item => { - return item_requests.delete({ itemId: item.id }); - }); - - await box_requests.update(updateBody); - await Promise.all(item_delete_promises); + await real_box_requests.update(updateBody); } else { - const createBody: CreateBoxBodyType = { - status: values.status, - cargoId: values.cargoId, - passportId: values.passportId?.value, - partyId: values.partyId, - items: values.products_list.map((item: any) => { - return { - trekId: item.trekId, - name: item.name, - weight: +item.weight, - amount: +item.amount, - }; - }), + const createBody: RealCreateBoxBodyType = { + partyName: values.partyName, + packetDtos, }; - await box_requests.create(createBody); + await real_box_requests.create(createBody); } navigation.push(pageLinks.dashboard.boxes.index); @@ -320,67 +191,6 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { pakets.remove(index); }; - const appendProduct = () => { - products.append({ - id: '', - cargoId: '', - trekId: '', - name: '', - amount: '', - weight: '', - price: '', - totalPrice: '', - }); - }; - - const removeProduct = (index: number) => { - products.remove(index); - }; - - const translateAndUpdateRussianName = async (text: string, index: number) => { - if (!text) return; - - try { - const responseText = await box_requests.translateWithMemoryApi({ text }); - setValue(`products_list.${index}.nameRu`, responseText || ''); - } catch (error) { - console.error(error); - notifyError('Translation api error'); - } - }; - - const boxTypes = [ - { - label: 'KG', - value: 'KG', - }, - { - label: 'GABARIT', - value: 'GABARIT', - }, - ]; - - const boxStatuses = useMemo(() => { - const p: { - label: string; - value: BoxStatus; - }[] = [ - { - label: t('READY_TO_INVOICE'), - value: 'READY_TO_INVOICE', - }, - ]; - - if (isAdmin) { - p.push({ - label: t('READY'), - value: 'READY', - }); - } - - return p; - }, [isAdmin]); - return ( { name='partyId' control={control} rules={{ required: requiredText }} - render={({ field, fieldState, formState }) => { - return ( - { - field.onChange(newValue.value); - }} - defaultValue={ - editMode + render={({ field }) => ( + { + field.onChange(newValue.value); + setPartyId(newValue.value); + }} + defaultValue={ + editMode + ? { + value: initialValues.partyId, + label: initialValues.partyName, + } + : partiesData?.length ? { - value: initialValues.partyId, - label: initialValues.partyName, + value: partiesData[0].value, + label: partiesData[0].label, } - : partiesData?.length - ? { - value: partiesData[0].value, - label: partiesData[0].label, - } - : null - } - styles={selectDefaultStyles} - noOptionsMessage={() => t('not_found')} - loadingMessage={() => t('loading')} - onBlur={field.onBlur} - name={field.name} - defaultOptions={defaultParties!} - loadOptions={partyOptions} - placeholder={t('enter_party_name_to_find')} - /> - ); - }} + : null + } + styles={selectDefaultStyles} + noOptionsMessage={() => t('not_found')} + loadingMessage={() => t('loading')} + onBlur={field.onBlur} + name={field.name} + defaultOptions={defaultParties!} + loadOptions={partyOptions} + placeholder={t('enter_party_name_to_find')} + /> + )} /> - {/* {!!errors.partyId?.message && ( - {errors.partyId?.message} - )} */} @@ -460,32 +266,48 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { name={`paketIds.${index}.id`} control={control} rules={{ required: requiredText }} - render={({ field: paketField, fieldState }) => ( + render={({ field: paketField }) => ( { paketField.onChange(newValue?.value); }} defaultValue={ - editMode && index === 0 + editMode && index === 0 && initialValues.packetId ? { - value: initialValues.partyId, - label: initialValues.partyName, + value: initialValues.packetId, + label: initialValues.box_name || `Box ${initialValues.packetId}`, } - : partiesData?.length && index === 0 - ? { - value: partiesData[0].value, - label: partiesData[0].label, - } - : null + : null } styles={selectDefaultStyles} noOptionsMessage={() => t('not_found')} loadingMessage={() => t('loading')} onBlur={paketField.onBlur} name={paketField.name} - defaultOptions={defaultParties!} - loadOptions={partyOptions} - placeholder={t('enter_party_name_to_find')} + defaultOptions={ + list.length > 0 + ? list.map((box: any) => ({ + value: box.id, + label: box.box_name || box.name || `Box ${box.id}`, + })) + : [] + } + loadOptions={async (inputValue: string) => { + if (!partyId || partyId === '') return []; + try { + const res = await box_requests.getAll({ + partyId: partyId, + }); + return res.data.data.data.map((box: any) => ({ + label: box.box_name || box.name || `Box ${box.id}`, + value: box.id, + })); + } catch (error) { + notifyUnknownError(error); + return []; + } + }} + placeholder={t('enter_box_name_to_find')} /> )} /> @@ -528,4 +350,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { ); }; -export default DashboardCreateRealBoxPage; \ No newline at end of file +export default DashboardCreateRealBoxPage; + +export type RealCreateBoxBodyType = { + partyName: string; + packetDtos: number[]; +}; + +export type UpdateRealBoxBodyType = { + boxId: string; + partyName: string; + packetDtos: number[]; +}; \ No newline at end of file diff --git a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx index 86ed532..173897f 100644 --- a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx +++ b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx @@ -10,6 +10,7 @@ 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 { real_box_requests } from '@/data/real-box/real-box.requests'; import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants'; import useDebouncedInput from '@/hooks/useDebouncedInput'; import useInput from '@/hooks/useInput'; @@ -49,7 +50,7 @@ const DashboardRealBoxesPage = (props: Props) => { const getBoxesQuery = useRequest( () => - box_requests.getAll({ + real_box_requests.getAll({ page: page, cargoId: keyword, status: boxStatusFilter, From 417ab7dd74b286e04aa70803e119ab2b8c780110 Mon Sep 17 00:00:00 2001 From: Samandar Turg'unboev Date: Sat, 24 May 2025 09:31:30 +0500 Subject: [PATCH 3/4] real boxing create and edit components --- src/routes/private/real-boxes-create/DashboardEditRealBox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx index 4a20ef3..846af9b 100644 --- a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx @@ -79,7 +79,7 @@ const DashboardEditRealBoxPage = (props: Props) => { return ( <> - + ); }; From ce2b8f3a62b8bb722a5473c5397a98ca519d3905 Mon Sep 17 00:00:00 2001 From: Samandar Turg'unboev Date: Sat, 24 May 2025 23:02:52 +0500 Subject: [PATCH 4/4] realbox edit components --- package.json | 6 +- src/data/real-box/real-box.model.ts | 92 +++---- src/data/real-box/real-box.requests.ts | 22 +- .../private/boxes-create/DashboardEditBox.tsx | 1 + .../DashboardCreateRealBox.tsx | 254 +++++++++--------- .../DashboardEditRealBox.tsx | 68 ++--- .../real-boxes/DashboardRealBoxesPage.tsx | 41 ++- 7 files changed, 227 insertions(+), 257 deletions(-) diff --git a/package.json b/package.json index 5e2f34f..ea5b16c 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,9 @@ "version": "0.1.0", "private": true, "scripts": { - "dev": "cross-env NEXT_PUBLIC_API_URL=https://cpcargo.uz next dev --port=3080", + "dev": "cross-env NEXT_PUBLIC_API_URL=https://cpost.felixits.uz next dev --port=3080", "build": "next build", - "build:dev": "cross-env NEXT_PUBLIC_API_URL=https://cpcargo.uz next build", + "build:dev": "cross-env NEXT_PUBLIC_API_URL=https://cpost.felixits.uz next build", "build:prod": "cross-env NEXT_PUBLIC_API_URL=https://api.cpost-express.uz next build", "start": "next start", "lint": "next lint", @@ -72,4 +72,4 @@ "vitest": "^1.1.3" }, "packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e" -} +} \ No newline at end of file diff --git a/src/data/real-box/real-box.model.ts b/src/data/real-box/real-box.model.ts index 9737437..86d8f30 100644 --- a/src/data/real-box/real-box.model.ts +++ b/src/data/real-box/real-box.model.ts @@ -1,74 +1,44 @@ export type BoxStatus = 'READY_TO_INVOICE' | 'READY'; + export const BoxStatusList: BoxStatus[] = ['READY_TO_INVOICE', 'READY']; -export interface IBox { - packetNetWeight: string; - totalNetWeight: string; - cargoId: string; - passportName: string; +export interface IRealBox { + boxName: string; id: number; + packetsCount: number; partyName: string; - boxType: string; - name: string; - volume: string; - boxWeight: number; - brutto: number; - hasInvoice: boolean; - totalItems: number; - status: BoxStatus; - totalBrutto: number; } -export interface IBoxDetail { - packet: { - id: number; - cargoId: string; - packetNetWeight: number; - passportName: string; - totalItems: number; - totalNetWeight: number; - partyName: string; - partyId: string; - boxType: string; - name: string; - volume: string; - boxWeight: number; - brutto: number; - hasInvoice: boolean; - status: BoxStatus; - }; - client: { - passportId: number; - passportName: string; - }; - items: [ - { +export interface IRealBoxDetail { + message: string; + data: { + boxName: string; + party: { id: number; - partyName: string; - boxName: string; - cargoId: string; - trekId: string; name: string; - nameRu: string; - amount: number; - weight: number; - price: number; - totalPrice: number; - hasImage: boolean; - imageUrl: string | null; + }; + packets: Array<{ + id: number; packetName: string; - status: BoxStatus; - }, - ]; + }>; + }; } -export type RealCreateBoxBodyType = { - partyName: string, - packetDtos: number[] -}; +export interface RealCreateBoxBodyType { + partyName: string; + packetDtos: number[]; +} -export type UpdateRealBoxBodyType = { - boxId: string, - partyName: string, - packetDtos: number[] -}; +export interface UpdateRealBoxBodyType { + boxId: string; + partyName: string; + packetDtos: number[]; +} + +export interface FormValues { + partyName: string; + paketIds: Array<{ id: string | number }>; + id?: number; + boxId?: string; + partyId?: number; +} \ No newline at end of file diff --git a/src/data/real-box/real-box.requests.ts b/src/data/real-box/real-box.requests.ts index fe8f147..4b7aa8c 100644 --- a/src/data/real-box/real-box.requests.ts +++ b/src/data/real-box/real-box.requests.ts @@ -2,7 +2,7 @@ import { IBox, UpdateBoxBodyType, IBoxDetail, BoxStatus } from '@/data/box/box.m import { CommonResponseType, PageAble } from '@/helpers/types'; import { request } from '@/services/request'; import axios from 'axios'; -import { RealCreateBoxBodyType, UpdateRealBoxBodyType } from './real-box.model'; +import { IRealBox, IRealBoxDetail, RealCreateBoxBodyType, UpdateRealBoxBodyType } from './real-box.model'; export const real_box_requests = { async getAll(params?: { @@ -10,27 +10,31 @@ export const real_box_requests = { sort?: string; direction?: string; cargoId?: string; + boxName?: string, partyId?: string | number; status?: BoxStatus; }) { - return request.get>>('/boxes/list', { params }); + return request.get>>('/boxes/list', { params }); }, async create({ ...body }: RealCreateBoxBodyType) { return request.post('/boxes/create', body); }, async update({ boxId, ...body }: UpdateRealBoxBodyType) { - return request.put('/packets/update', body, { + return request.put('/boxes/change', body, { params: { boxId }, }); }, - async find(params: { packetId?: number | string }) { - return request.get>('/packets/find', { params }); + async find(params: { boxId?: number | string }) { + return request.get(`/boxes/find/${params.boxId}`,); }, - async delete(params: { packetId: number | string }) { - return request.delete('/packets/delete', { params }); + async delete(params: { boxId: number | string }) { + return request.delete('/boxes/delete', { params }); }, - async downloadExcel(params: { packetId: number | string }) { - return request.get('/packets/download', { params, responseType: 'blob' }); + async downloadExcel(params: { boxId: number | string }) { + return request.get(`/boxes/download/`, { params }); + }, + async downloadQrCode(params: { boxId: number | string }) { + return request.get(`/qr/${params.boxId}`, { responseType: 'blob' }); }, async translateWithGoogleApi(params: { text: string }): Promise { const response = await axios.post('https://translation.googleapis.com/language/translate/v2', undefined, { diff --git a/src/routes/private/boxes-create/DashboardEditBox.tsx b/src/routes/private/boxes-create/DashboardEditBox.tsx index bc2ee89..de89b8b 100644 --- a/src/routes/private/boxes-create/DashboardEditBox.tsx +++ b/src/routes/private/boxes-create/DashboardEditBox.tsx @@ -71,6 +71,7 @@ const DashboardEditBoxPage = (props: Props) => { } ); + console.log(getOneBox, "pkets"); if (getOneBox.loading || !getOneBox.data) { return ; diff --git a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx index 9e595ca..f52b985 100644 --- a/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardCreateRealBox.tsx @@ -1,69 +1,57 @@ 'use client'; import BaseButton from '@/components/ui-kit/BaseButton'; +import BaseIconButton from '@/components/ui-kit/BaseIconButton'; import { party_requests } from '@/data/party/party.requests'; +import { box_requests } from '@/data/box/box.requests'; +import { real_box_requests } from '@/data/real-box/real-box.requests'; import { pageLinks } from '@/helpers/constants'; import { notifyUnknownError } from '@/services/notification'; import { Box, FormHelperText, Grid, Stack, Typography, styled } from '@mui/material'; +import { AddCircleRounded, Close } from '@mui/icons-material'; import { useSearchParams } from 'next/navigation'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { Controller, useFieldArray, useForm } from 'react-hook-form'; -import BaseIconButton from '@/components/ui-kit/BaseIconButton'; -import { AddCircleRounded, Close } from '@mui/icons-material'; -import useRequest from '@/hooks/useRequest'; -import { useMyTranslation } from '@/hooks/useMyTranslation'; +import AsyncSelect from 'react-select/async'; import { selectDefaultStyles } from '@/components/ui-kit/BaseReactSelect'; import { useAuthContext } from '@/context/auth-context'; import { useMyNavigation } from '@/hooks/useMyNavigation'; -import AsyncSelect from 'react-select/async'; -import { box_requests } from '@/data/box/box.requests'; -import { real_box_requests } from '@/data/real-box/real-box.requests'; - +import { useMyTranslation } from '@/hooks/useMyTranslation'; +import { FormValues, RealCreateBoxBodyType, UpdateRealBoxBodyType } from '@/data/real-box/real-box.model'; import get from 'lodash.get'; +import useRequest from '@/hooks/useRequest'; const StyledCreateBox = styled(Box)` - .item-row { - display: flex; - align-items: center; - justify-content: space-between; - gap: 16px; - } + .item-row { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + } - & > * { - flex: 1 1 1; - } + & > * { + flex: 1 1 1; + } `; -type Props = { +interface Props { partiesData?: { value: number; label: string }[]; initialValues?: { - id: number; - boxId: string; - box_name: string; - partyId: number; - partyName: string; - packetId: string; - products_list: { - id: number; - price: number | string; - cargoId: string; - trekId: string; - name: string; - nameRu: string; - amount: number; - weight: number; - }[]; + id?: number; + boxId?: string; + partyId?: number; + partyName?: string; + paketIds?: Array<{ id: number; packetName: string }>; }; -}; +} const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { const { user, isAdmin: isAdminUser } = useAuthContext(); - const editMode = !!initialValues && !!initialValues.id; - const isAdmin = isAdminUser && editMode; + const editMode = !!initialValues?.id; const t = useMyTranslation(); const params = useSearchParams(); - const navigation = useMyNavigation(); - const [partyId, setPartyId] = useState(""); + const { push } = useMyNavigation(); + const [partyId, setPartyId] = useState(''); const [loading, setLoading] = useState(false); const helperRef = useRef<{ finished: boolean; @@ -82,20 +70,41 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { control, handleSubmit, setValue, + reset, formState: { errors }, - } = useForm({ + } = useForm({ defaultValues: { - partyId: params.get('party_id') ? +params.get('party_id')! : '', - paketIds: editMode - ? [{ id: initialValues?.partyId }] + partyName: initialValues?.partyName || '', + paketIds: initialValues?.paketIds + ? initialValues.paketIds.map((paket) => ({ id: paket.id })) : params.get('party_id') ? [{ id: +params.get('party_id')! }] : [{ id: '' }], - ...initialValues, + id: initialValues?.id, + boxId: initialValues?.boxId, + partyId: initialValues?.partyId, }, }); - const pakets = useFieldArray({ + // Reset form when initialValues change (for edit mode) + useEffect(() => { + if (initialValues) { + reset({ + partyName: initialValues.partyName || '', + paketIds: initialValues.paketIds + ? initialValues.paketIds.map((paket) => ({ id: paket.id })) + : [{ id: '' }], + id: initialValues.id, + boxId: initialValues.boxId, + partyId: initialValues.partyId, + }); + if (initialValues.partyId) { + setPartyId(initialValues.partyId); + } + } + }, [initialValues, reset]); + + const { fields, append, remove } = useFieldArray({ control, name: 'paketIds', keyName: 'key', @@ -109,54 +118,52 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { partyId: partyId, }), { - selectData(data) { - return data?.data?.data; - }, - } + selectData: (data) => data?.data?.data ?? [], + enabled: !!partyId, + }, ); - const { data: list } = useMemo(() => { - if (getBoxesQuery.data?.data) { - return { - data: getBoxesQuery.data.data.filter((box: any) => box.status === 'READY_TO_INVOICE'), - }; - } - return { data: [] }; - }, [getBoxesQuery, partyId]); + const list = useMemo(() => { + return getBoxesQuery.data?.data.filter((box: any) => box.status === 'READY_TO_INVOICE') ?? []; + }, [getBoxesQuery.data]); useEffect(() => { if (partyId) { getBoxesQuery.refetch(); } - }, [partyId]); + }, [partyId, getBoxesQuery.refetch]); - const { data: defaultParties } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), { - enabled: true, - selectData(data) { - return data.data.data.data.map(p => ({ value: p.id, label: p.name })); + const { data: defaultParties } = useRequest( + () => party_requests.getAll({ status: 'COLLECTING' }), + { + enabled: true, + selectData: (data) => + data.data.data.data.map((p: any) => ({ value: p.id, label: p.name })), + onSuccess: (data) => { + if (!editMode && data?.data?.data?.data?.[0]) { + const defaultParty = data.data.data.data[0]; + helperRef.current.settedDefaultParty = defaultParty; + setValue('partyName', defaultParty.name); + setValue('paketIds.0.id', defaultParty.id); // Use dot notation + setPartyId(defaultParty.id); + } + helperRef.current.partyFinished = true; + if (helperRef.current.clientFinished) { + helperRef.current.finished = true; + } + }, + placeholderData: [], }, - onSuccess(data) { - if (!editMode && data?.data?.data?.data?.[0]) { - helperRef.current.settedDefaultParty = data.data.data.data[0]; - setValue('partyId', data.data.data.data[0].id); - setValue('paketIds[0].id', data.data.data.data[0].id); - } - helperRef.current.partyFinished = true; - if (helperRef.current.clientFinished) { - helperRef.current.finished = true; - } - }, - placeholderData: [], - }); + ); - const onSubmit = handleSubmit(async values => { + const onSubmit = handleSubmit(async (values) => { try { setLoading(true); - const packetDtos = values.paketIds.map((paket: any) => paket.id).filter((id: any) => id); + const packetDtos = values.paketIds.map((paket) => Number(paket.id)).filter((id) => id); if (editMode) { const updateBody: UpdateRealBoxBodyType = { - boxId: initialValues?.boxId, + boxId: initialValues!.boxId!, partyName: values.partyName, packetDtos, }; @@ -169,7 +176,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { await real_box_requests.create(createBody); } - navigation.push(pageLinks.dashboard.boxes.index); + push(pageLinks.dashboard.real_boxes.index); } catch (error) { notifyUnknownError(error); } finally { @@ -177,18 +184,25 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { } }); - const partyOptions = (inputValue: string) => { - return party_requests.getAll({ status: 'COLLECTING', partyName: inputValue }).then(res => { - return res.data.data.data.map(p => ({ label: p.name, value: p.id })); - }); + const partyOptions = async (inputValue: string) => { + try { + const res = await party_requests.getAll({ + status: 'COLLECTING', + partyName: inputValue, + }); + return res.data.data.data.map((p: any) => ({ label: p.name, value: p.id })); + } catch (error) { + notifyUnknownError(error); + return []; + } }; const appendPaket = () => { - pakets.append({ id: '' }); + append({ id: '' }); }; const removePaket = (index: number) => { - pakets.remove(index); + remove(index); }; return ( @@ -201,31 +215,31 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { backgroundColor: '#fff', }} > - - + + {editMode ? t('update_box') : t('create_box')} - + {t('party_name')} ( { - field.onChange(newValue.value); - setPartyId(newValue.value); + field.onChange(newValue?.label ?? ''); + setPartyId(newValue?.value ?? ''); }} defaultValue={ editMode ? { - value: initialValues.partyId, - label: initialValues.partyName, + value: initialValues?.partyId, + label: initialValues?.partyName, } : partiesData?.length ? { @@ -239,12 +253,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { loadingMessage={() => t('loading')} onBlur={field.onBlur} name={field.name} - defaultOptions={defaultParties!} + defaultOptions={defaultParties ?? []} loadOptions={partyOptions} placeholder={t('enter_party_name_to_find')} /> )} /> + {!!errors.partyName && ( + {requiredText} + )} @@ -256,10 +273,10 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { padding: '24px', }} > - + {t('packet')} - {pakets.fields.map((field, index) => ( + {fields.map((field, index) => ( { render={({ field: paketField }) => ( { - paketField.onChange(newValue?.value); + paketField.onChange(newValue?.value ?? ''); }} defaultValue={ - editMode && index === 0 && initialValues.packetId + editMode && initialValues?.paketIds?.[index] ? { - value: initialValues.packetId, - label: initialValues.box_name || `Box ${initialValues.packetId}`, + value: initialValues.paketIds[index].id, + label: + initialValues.paketIds[index].packetName || + `Box ${initialValues.paketIds[index].id}`, } : null } @@ -284,19 +303,15 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { loadingMessage={() => t('loading')} onBlur={paketField.onBlur} name={paketField.name} - defaultOptions={ - list.length > 0 - ? list.map((box: any) => ({ - value: box.id, - label: box.box_name || box.name || `Box ${box.id}`, - })) - : [] - } + defaultOptions={list.map((box: any) => ({ + value: box.id, + label: box.box_name || box.name || `Box ${box.id}`, + }))} loadOptions={async (inputValue: string) => { - if (!partyId || partyId === '') return []; + if (!partyId) return []; try { const res = await box_requests.getAll({ - partyId: partyId, + partyId, }); return res.data.data.data.map((box: any) => ({ label: box.box_name || box.name || `Box ${box.id}`, @@ -315,7 +330,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { {requiredText} )} - {pakets.fields.length > 1 && ( + {fields.length > 1 && ( { )} ))} - + } @@ -342,7 +357,7 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { - + {editMode ? t('update') : t('create')} @@ -350,15 +365,4 @@ const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { ); }; -export default DashboardCreateRealBoxPage; - -export type RealCreateBoxBodyType = { - partyName: string; - packetDtos: number[]; -}; - -export type UpdateRealBoxBodyType = { - boxId: string; - partyName: string; - packetDtos: number[]; -}; \ No newline at end of file +export default DashboardCreateRealBoxPage; \ No newline at end of file diff --git a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx index 846af9b..76a37a1 100644 --- a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx +++ b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx @@ -1,12 +1,11 @@ 'use client'; import Loader from '@/components/common/Loader'; -import { box_requests } from '@/data/box/box.requests'; import useRequest from '@/hooks/useRequest'; -import DashboardCreateBoxPage from '@/routes/private/boxes-create/DashboardCreateBox'; import { useParams } from 'next/navigation'; -import React from 'react'; +import React, { useEffect } from 'react'; import DashboardCreateRealBoxPage from './DashboardCreateRealBox'; +import { real_box_requests } from '@/data/real-box/real-box.requests'; type Props = {}; @@ -16,70 +15,39 @@ const DashboardEditRealBoxPage = (props: Props) => { const getOneBox = useRequest( () => { - return box_requests.find({ packetId: box_id }); + return real_box_requests.find({ boxId: box_id }); }, { selectData(data) { - const boxData = data.data.data; + const boxData = data.data; // ⬅️ Faqat data.data, data.data.data emas + if (!boxData) return null; + console.log(boxData.data, 'boxdata'); return { - id: +box_id, - box_name: boxData.packet.name, - net_weight: +boxData.packet.brutto, - box_weight: +boxData.packet.boxWeight, - box_type: boxData.packet.boxType, - box_size: boxData.packet.volume, - passportName: boxData.packet.passportName, - status: boxData.packet.status, - packetId: box_id, - - partyId: +boxData.packet.partyId, - partyName: boxData.packet.partyName, - - // client_id: boxData.client?.passportId, - passportId: boxData.client?.passportId, - client_id: boxData.packet?.cargoId, - clientId: boxData.client?.passportId, - clientName: boxData.client?.passportName, - - products_list: [ - ...boxData.items.map(item => { - let name = item.name; - let nameRu = item.nameRu; - - // try { - // name = item.name.split(' / ')[0]; - // nameRu = item.name.split(' / ')[1]; - // } catch (error) { - // console.error('prepare edit values error', error); - // } - - return { - id: item.id, - price: item.price, - - cargoId: item.cargoId, - trekId: item.trekId, - name: name, - nameRu: nameRu, - amount: +item.amount, - weight: +item.weight, - }; - }), - ], + id: box_id, + boxId: box_id!, + partyId: boxData.data.party.id, // ⬅️ To‘g‘ri yo‘l + partyName: boxData.data.party.name!, + paketIds: boxData.data.packets! }; }, } ); + useEffect(() => { + getOneBox.refetch() + }, [box_id]) + + console.log(getOneBox); + if (getOneBox.loading || !getOneBox.data) { return ; } return ( <> - + ); }; diff --git a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx index 173897f..152edaf 100644 --- a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx +++ b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx @@ -10,6 +10,7 @@ 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 { IRealBox } from '@/data/real-box/real-box.model'; import { real_box_requests } from '@/data/real-box/real-box.requests'; import { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants'; import useDebouncedInput from '@/hooks/useDebouncedInput'; @@ -23,6 +24,7 @@ import { getBoxStatusStyles, getStatusColor } from '@/theme/getStatusBoxStyles'; import { Add, QrCode, AddCircleOutline, Circle, Delete, Download, Edit, FilterList, FilterListOff, Search, PlusOne } from '@mui/icons-material'; import { Box, Button, Stack, Tooltip, Typography } from '@mui/material'; import { useRouter } from 'next/navigation'; +import { log } from 'node:console'; import React, { useEffect, useMemo, useState } from 'react'; type Props = {}; @@ -84,6 +86,7 @@ const DashboardRealBoxesPage = (props: Props) => { }; } }, [getBoxesQuery]); + const loading = getBoxesQuery.loading; const handleChange = (newPage: number) => { setTimeout(() => { @@ -102,7 +105,7 @@ const DashboardRealBoxesPage = (props: Props) => { try { setDeleteIds(p => [...p, id]); - await box_requests.delete({ packetId: id }); + await real_box_requests.delete({ boxId: id }); getBoxesQuery.refetch(); } catch (error) { notifyUnknownError(error); @@ -116,7 +119,7 @@ const DashboardRealBoxesPage = (props: Props) => { try { setDownloadIds(p => [...p, id]); - const response = await box_requests.downloadExcel({ packetId: id }); + const response = await real_box_requests.downloadExcel({ boxId: id }); const file = new File([response.data], 'Box-excel.xlsx', { type: response.data.type }); file_service.download(file); } catch (error) { @@ -126,6 +129,23 @@ const DashboardRealBoxesPage = (props: Props) => { } }; + const onDownloadQrCode = async (id: number) => { + if (downloadIds.includes(id)) return; + + try { + setDownloadIds(p => [...p, id]); + const response = await real_box_requests.downloadQrCode({ boxId: id }); + console.log(response, "rres"); + const file = new File([response.data], 'qr.png', { type: response.data.type }); + file_service.download(file); + } catch (error) { + notifyUnknownError(error); + console.log(error); + } finally { + setDownloadIds(prev => prev.filter(i => i !== id)); + } + }; + const onChangeStatus = async (id: number, newStatus: BoxStatus) => { if (changeStatusIds.includes(id)) return; @@ -149,7 +169,7 @@ const DashboardRealBoxesPage = (props: Props) => { }, [keyword]); // No, PartyName, PacketName, PartyTozaOg'irlik, CountOfItems, WeightOfItems, CargoID, PassportNameFamily - PacketStatusForInvoice - const columns: ColumnData[] = [ + const columns: ColumnData[] = [ { label: t('No'), width: 100, @@ -161,9 +181,12 @@ const DashboardRealBoxesPage = (props: Props) => { label: t("qr_code"), width: 120, renderCell: data => { - return ; + ; }, }, { @@ -177,12 +200,12 @@ const DashboardRealBoxesPage = (props: Props) => { }, }, { - dataKey: 'cargoId', + dataKey: 'boxName', label: t('cargo_id'), width: 120, }, { - dataKey: 'partyName', + dataKey: "boxName", label: t('party_name'), width: 120, }, @@ -197,7 +220,7 @@ const DashboardRealBoxesPage = (props: Props) => { // width: 120, // }, { - dataKey: 'totalItems', + dataKey: 'packetsCount', label: t('count_of_items'), width: 120, }, @@ -360,7 +383,7 @@ const DashboardRealBoxesPage = (props: Props) => { - +