'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, useRouter, 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 { 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'; 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 { display: flex; align-items: center; justify-content: space-between; gap: 16px; } .item-row-field { } & > * { 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 DashboardCreateBoxPage = ({ 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 DashboardCreateBoxPage;