diff --git a/src/app/[locale]/dashboard/boxes/create/loading.tsx b/src/app/[locale]/dashboard/boxes/create/loading.tsx
new file mode 100644
index 0000000..3fbec00
--- /dev/null
+++ b/src/app/[locale]/dashboard/boxes/create/loading.tsx
@@ -0,0 +1,9 @@
+import { CircularProgress, Stack } from '@mui/material';
+
+export default function DashboardLoading() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/[locale]/dashboard/boxes/create/page.tsx b/src/app/[locale]/dashboard/boxes/create/page.tsx
new file mode 100644
index 0000000..f9ffc19
--- /dev/null
+++ b/src/app/[locale]/dashboard/boxes/create/page.tsx
@@ -0,0 +1,22 @@
+'use client';
+
+import useRequest from '@/hooks/useRequest';
+import { party_requests } from '@/data/party/party.requests';
+import Loader from '@/components/common/Loader';
+import React from 'react';
+import DashboardCreateRealBoxPage from '@/routes/private/real-boxes-create/DashboardCreateRealBox';
+
+export default function Home() {
+ const partiesData = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), {
+ selectData(data) {
+ return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
+ },
+ placeholderData: [],
+ });
+
+ if (partiesData.loading || !partiesData.data) {
+ return ;
+ }
+
+ return ;
+}
diff --git a/src/app/[locale]/dashboard/boxes/edit/[box_id]/loading.tsx b/src/app/[locale]/dashboard/boxes/edit/[box_id]/loading.tsx
new file mode 100644
index 0000000..3fbec00
--- /dev/null
+++ b/src/app/[locale]/dashboard/boxes/edit/[box_id]/loading.tsx
@@ -0,0 +1,9 @@
+import { CircularProgress, Stack } from '@mui/material';
+
+export default function DashboardLoading() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/[locale]/dashboard/boxes/edit/[box_id]/page.tsx b/src/app/[locale]/dashboard/boxes/edit/[box_id]/page.tsx
new file mode 100644
index 0000000..d06c55b
--- /dev/null
+++ b/src/app/[locale]/dashboard/boxes/edit/[box_id]/page.tsx
@@ -0,0 +1,5 @@
+import DashboardEditRealBoxPage from '@/routes/private/real-boxes-create/DashboardEditRealBox';
+
+export default function Home() {
+ return ;
+}
diff --git a/src/app/[locale]/dashboard/boxes/page.tsx b/src/app/[locale]/dashboard/boxes/page.tsx
new file mode 100644
index 0000000..80d8121
--- /dev/null
+++ b/src/app/[locale]/dashboard/boxes/page.tsx
@@ -0,0 +1,5 @@
+import DashboardRealBoxesPage from "@/routes/private/real-boxes/DashboardRealBoxesPage";
+
+export default function Home() {
+ return ;
+}
diff --git a/src/components/layout/dashboard-layout/routes.tsx b/src/components/layout/dashboard-layout/routes.tsx
index 238668d..8f04871 100644
--- a/src/components/layout/dashboard-layout/routes.tsx
+++ b/src/components/layout/dashboard-layout/routes.tsx
@@ -33,6 +33,21 @@ export const routes = [
),
roles: [UserRoleEnum.ADMIN, UserRoleEnum.CHINA_WORKER],
},
+ {
+ title: 'boxes',
+ path: pageLinks.dashboard.real_boxes.index,
+ icon: (
+
+
+
+ ),
+ roles: [UserRoleEnum.ADMIN, UserRoleEnum.CHINA_WORKER],
+ },
{
title: 'packet',
path: pageLinks.dashboard.boxes.index,
diff --git a/src/helpers/constants.ts b/src/helpers/constants.ts
index 6e4db66..3853f3e 100644
--- a/src/helpers/constants.ts
+++ b/src/helpers/constants.ts
@@ -18,6 +18,11 @@ export const pageLinks = {
create: '/dashboard/packets/create',
edit: (slug: string | number) => '/dashboard/packets/edit/' + slug,
},
+ real_boxes: {
+ index: '/dashboard/boxes',
+ create: '/dashboard/boxes/create',
+ edit: (slug: string | number) => '/dashboard/boxes/edit/' + slug,
+ },
items: {
index: '/dashboard/items',
create: '/dashboard/items/create',
diff --git a/src/routes/private/boxes/DashboardBoxesPage.tsx b/src/routes/private/boxes/DashboardBoxesPage.tsx
index 71588e0..ad35b65 100644
--- a/src/routes/private/boxes/DashboardBoxesPage.tsx
+++ b/src/routes/private/boxes/DashboardBoxesPage.tsx
@@ -335,7 +335,7 @@ const DashboardBoxesPage = (props: Props) => {
color: '#000',
}}
>
- {t('packets')}
+ {t('packet')}
* {
+ flex: 1 1 1;
+ }
+`;
+
+type Props = {
+ partiesData?: { value: number; label: string }[];
+ initialValues?: {
+ id: number;
+ 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;
+
+ products_list: {
+ id: number;
+ price: number | string;
+
+ cargoId: string;
+ trekId: string;
+ name: string;
+ nameRu: string;
+ amount: number;
+ weight: number;
+ }[];
+ };
+};
+
+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 helperRef = useRef<{
+ finished: boolean;
+ partyFinished: boolean;
+ clientFinished: boolean;
+ settedDefaultParty: Party | null;
+ 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,
+ control,
+ handleSubmit,
+ watch,
+ setValue,
+ formState: { errors },
+ } = useForm({
+ defaultValues: {
+ partyId: params.get('party_id') ? +params.get('party_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: '',
+ },
+ ],
+ }),
+ ...initialValues,
+ },
+ });
+
+ const [loading, setLoading] = useState(false);
+ const products = useFieldArray({
+ control,
+ name: 'products_list',
+ 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 passportOptionsInitial = initialValues?.passportId &&
+ initialValues?.passportName && [
+ {
+ value: initialValues?.passportId,
+ 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
+ }));
+
+ 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: [], // 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
+ // }
+ },
+ });
+
+ useEffect(() => {
+ setValue('passportId', '');
+ }, [cargoId]);
+
+ const { data: defaultParties, status: defaultPartiesStatus } = useRequest(() => party_requests.getAll({ status: 'COLLECTING' }), {
+ enabled: true,
+ selectData(data) {
+ return data.data.data.data.map(p => ({ value: p.id, label: p.name }));
+ },
+ 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);
+ }
+ helperRef.current.partyFinished = true;
+ if (helperRef.current.clientFinished) {
+ helperRef.current.finished = true;
+ }
+ },
+ 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 }));
+ // return data.data.data.map(p => ({ value: p.id, 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) => {
+ // Tipi 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);
+
+ if (editMode) {
+ const updateBody: UpdateBoxBodyType = {
+ cargoId: values.client_id,
+ passportId: values.passportId.value,
+ status: values.status,
+ packetId: initialValues?.packetId,
+
+ 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,
+ // cargoId: item.cargoId,
+ trekId: item.trekId,
+ // name: item.name + (item.nameRu ? ` / ${item.nameRu}` : ''),
+ name: item.name,
+ nameRu: item?.nameRu,
+ weight: +item.weight,
+ amount: +item.amount,
+ price: _price,
+ totalPrice: _total_price,
+ };
+ }),
+ };
+
+ 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);
+ } 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,
+ };
+ }),
+ };
+ await box_requests.create(createBody);
+ }
+
+ navigation.push(pageLinks.dashboard.boxes.index);
+ } catch (error) {
+ notifyUnknownError(error);
+ } finally {
+ setLoading(false);
+ }
+ });
+
+ 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 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 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.translateWithGoogleApi({ text });
+ 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 (
+
+
+
+ {editMode ? t('update_packet') : t('create_packet')}
+
+
+
+
+
+ {t('party_name')}
+
+ {
+ return (
+ {
+ field.onChange(newValue.value);
+ }}
+ defaultValue={
+ editMode
+ ? {
+ value: initialValues.partyId,
+ label: initialValues.partyName,
+ }
+ : 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')}
+ />
+ );
+ }}
+ />
+ {/* @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')}
+ />
+ );
+ }}
+ />
+
+
+
+
+ {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
+
+ ),
+ }}
+ fullWidth
+ placeholder={t('id')}
+ sx={{
+ '.MuiInputBase-root': {
+ paddingLeft: 0,
+ },
+ }}
+ {...register(`products_list.${index}.trekId`, { required: requiredText })}
+ />
+ {!!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)}
+ >
+
+
+
+
+
+
+ );
+ })}
+
+
+ } onClick={appendProduct}>
+ {t('add_more')}
+
+
+
+
+
+
+
+ {editMode ? t('update') : t('create')}
+
+
+
+ );
+};
+
+export default DashboardCreateRealBoxPage;
diff --git a/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx
new file mode 100644
index 0000000..ef70a4d
--- /dev/null
+++ b/src/routes/private/real-boxes-create/DashboardEditRealBox.tsx
@@ -0,0 +1,86 @@
+'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';
+
+type Props = {};
+
+const DashboardEditRealBoxPage = (props: Props) => {
+ const params = useParams();
+ const box_id = params.box_id as string;
+
+ const getOneBox = useRequest(
+ () => {
+ return box_requests.find({ packetId: box_id });
+ },
+ {
+ selectData(data) {
+ const boxData = data.data.data;
+
+ 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,
+ };
+ }),
+ ],
+ };
+ },
+ }
+ );
+
+
+ if (getOneBox.loading || !getOneBox.data) {
+ return ;
+ }
+
+ return (
+ <>
+
+ >
+ );
+};
+
+export default DashboardEditRealBoxPage;
diff --git a/src/routes/private/real-boxes-create/index.ts b/src/routes/private/real-boxes-create/index.ts
new file mode 100644
index 0000000..83b3a88
--- /dev/null
+++ b/src/routes/private/real-boxes-create/index.ts
@@ -0,0 +1 @@
+export { default } from './DashboardCreateRealBox';
diff --git a/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx
new file mode 100644
index 0000000..680cf06
--- /dev/null
+++ b/src/routes/private/real-boxes/DashboardRealBoxesPage.tsx
@@ -0,0 +1,368 @@
+'use client';
+
+import ActionPopMenu from '@/components/common/ActionPopMenu';
+import { MyTable, ColumnData } from '@/components/common/MyTable';
+import StatusChangePopup from '@/components/common/StatusChangePopup';
+import BaseButton from '@/components/ui-kit/BaseButton';
+import BaseIconButton from '@/components/ui-kit/BaseIconButton';
+import BaseInput from '@/components/ui-kit/BaseInput';
+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 { DEFAULT_PAGE_SIZE, pageLinks } from '@/helpers/constants';
+import useDebouncedInput from '@/hooks/useDebouncedInput';
+import useInput from '@/hooks/useInput';
+import { useMyNavigation } from '@/hooks/useMyNavigation';
+import { useMyTranslation } from '@/hooks/useMyTranslation';
+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 { Box, Button, Stack, Tooltip, Typography } from '@mui/material';
+import { useRouter } from 'next/navigation';
+import React, { useEffect, useMemo, useState } from 'react';
+
+type Props = {};
+
+const DashboardRealBoxesPage = (props: Props) => {
+ const t = useMyTranslation();
+ const navigation = useMyNavigation();
+ const { isAdmin } = useAuthContext();
+ const [page, setPage] = useState(1);
+ const [pageSize] = useState(DEFAULT_PAGE_SIZE);
+ const { value: keyword, onChange: handleKeyword, setValue: setKeyword } = useInput('');
+ const [boxStatusFilter, setBoxStatusFilter] = useState(undefined);
+
+ const [deleteIds, setDeleteIds] = useState([]);
+ const [downloadIds, setDownloadIds] = useState([]);
+ const [changeStatusIds, setChangeStatusIds] = useState([]);
+
+ const boxStatusOptions = useMemo(() => {
+ const p = ['READY_TO_INVOICE'] as BoxStatus[];
+ if (isAdmin) {
+ p.push('READY');
+ }
+ return p;
+ }, [isAdmin]);
+
+ const getBoxesQuery = useRequest(
+ () =>
+ box_requests.getAll({
+ page: page,
+ cargoId: keyword,
+ status: boxStatusFilter,
+ direction: 'desc',
+ sort: 'id',
+ }),
+ {
+ dependencies: [page, boxStatusFilter],
+ selectData(data) {
+ return data.data.data;
+ },
+ }
+ );
+
+ const {
+ data: list,
+ totalElements,
+ totalPages,
+ } = useMemo(() => {
+ if (getBoxesQuery.data?.data) {
+ return {
+ data: getBoxesQuery.data.data,
+ totalElements: getBoxesQuery.data.totalElements,
+ totalPages: getBoxesQuery.data.totalPages,
+ };
+ } else {
+ return {
+ data: [],
+ totalElements: 0,
+ totalPages: 0,
+ };
+ }
+ }, [getBoxesQuery]);
+ const loading = getBoxesQuery.loading;
+
+ const handleChange = (newPage: number) => {
+ setTimeout(() => {
+ setPage(newPage);
+ }, 100);
+ };
+
+ const resetFilter = () => {
+ setPage(1);
+ setKeyword('');
+ setBoxStatusFilter(undefined);
+ };
+
+ const onDelete = async (id: number) => {
+ if (deleteIds.includes(id)) return;
+
+ try {
+ setDeleteIds(p => [...p, id]);
+ await box_requests.delete({ packetId: id });
+ getBoxesQuery.refetch();
+ } catch (error) {
+ notifyUnknownError(error);
+ } finally {
+ setDeleteIds(prev => prev.filter(i => i !== id));
+ }
+ };
+
+ const onDownloadExcel = async (id: number) => {
+ if (downloadIds.includes(id)) return;
+
+ try {
+ setDownloadIds(p => [...p, id]);
+ const response = await box_requests.downloadExcel({ packetId: id });
+ const file = new File([response.data], 'Box-excel.xlsx', { type: response.data.type });
+ file_service.download(file);
+ } catch (error) {
+ notifyUnknownError(error);
+ } finally {
+ setDownloadIds(prev => prev.filter(i => i !== id));
+ }
+ };
+
+ const onChangeStatus = async (id: number, newStatus: BoxStatus) => {
+ if (changeStatusIds.includes(id)) return;
+
+ try {
+ setChangeStatusIds(p => [...p, id]);
+ await box_requests.changeStatus({ packetId: id, status: newStatus });
+ getBoxesQuery.refetch();
+ } catch (error) {
+ notifyUnknownError(error);
+ } finally {
+ setChangeStatusIds(prev => prev.filter(i => i !== id));
+ }
+ };
+
+ useEffect(() => {
+ const timeoutId = setTimeout(() => {
+ setPage(1);
+ getBoxesQuery.refetch();
+ }, 350);
+ return () => clearTimeout(timeoutId);
+ }, [keyword]);
+
+ // No, PartyName, PacketName, PartyTozaOg'irlik, CountOfItems, WeightOfItems, CargoID, PassportNameFamily - PacketStatusForInvoice
+ const columns: ColumnData[] = [
+ {
+ label: t('No'),
+ width: 100,
+ renderCell(data, rowIndex) {
+ return (page - 1) * pageSize + rowIndex + 1;
+ },
+ },
+ {
+ dataKey: 'id',
+ label: "Qo'shish",
+ 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"),
+ width: 120,
+ },
+ {
+ dataKey: 'cargoId',
+ label: t('cargo_id'),
+ 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,
+ numeric: true,
+ renderCell(data, rowIndex) {
+ return (
+ ,
+ label: t('edit'),
+ onClick: () => {
+ navigation.push(pageLinks.dashboard.boxes.edit(data.id));
+ },
+ },
+ {
+ icon: ,
+ label: t('delete'),
+ onClick: () => {
+ onDelete(data.id);
+ },
+ 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,
+ },
+ ]
+ : []),
+ ]}
+ />
+ );
+ },
+ },
+ ];
+
+ return (
+
+
+ } href={pageLinks.dashboard.boxes.create}>
+ {t('create_packet')}
+
+
+
+
+
+ {t('packet')}
+
+
+ ,
+ }}
+ placeholder={t('filter_packet_name')}
+ value={keyword}
+ onChange={e => {
+ setKeyword(e.target.value);
+ }}
+ />
+
+ } size='small' onClick={resetFilter}>
+ {t('reset_filter')}
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default DashboardRealBoxesPage;
diff --git a/src/routes/private/real-boxes/index.ts b/src/routes/private/real-boxes/index.ts
new file mode 100644
index 0000000..9283102
--- /dev/null
+++ b/src/routes/private/real-boxes/index.ts
@@ -0,0 +1 @@
+export { default } from './DashboardRealBoxesPage';