'use client'; import BaseButton from '@/components/ui-kit/BaseButton'; import BaseIconButton from '@/components/ui-kit/BaseIconButton'; import { useAuthContext } from '@/context/auth-context'; import { box_requests } from '@/data/box/box.requests'; import { item_requests } from '@/data/item/item.requests'; import { party_requests } from '@/data/party/party.requests'; import { FormValues, RealCreateBoxBodyType, UpdateRealBoxBodyType } from '@/data/real-box/real-box.model'; import { real_box_requests } from '@/data/real-box/real-box.requests'; import { pageLinks } from '@/helpers/constants'; import { useMyNavigation } from '@/hooks/useMyNavigation'; import { useMyTranslation } from '@/hooks/useMyTranslation'; import { notifyUnknownError } from '@/services/notification'; import { AddCircleRounded, Close } from '@mui/icons-material'; import { Box, Button, Checkbox, Chip, CircularProgress, FormControl, FormHelperText, Grid, InputLabel, ListItemText, MenuItem, OutlinedInput, Select, Stack, styled, Typography, } from '@mui/material'; import { useQuery } from '@tanstack/react-query'; import get from 'lodash.get'; import { useSearchParams } from 'next/navigation'; import { useEffect, useMemo, useState } from 'react'; import { Controller, useFieldArray, useForm } from 'react-hook-form'; const StyledCreateBox = styled(Box)` .item-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; } & > * { flex: 1 1 1; } `; interface Props { partiesData?: { value: number; label: string }[]; initialValues?: { id?: number; boxId?: string; partyId?: number; partyName?: string; paketIds?: Array; }; } const DashboardCreateRealBoxPage = ({ initialValues, partiesData }: Props) => { const { user } = useAuthContext(); const editMode = !!initialValues?.id; const t = useMyTranslation(); const params = useSearchParams(); const { push } = useMyNavigation(); const [partyId, setPartyId] = useState(initialValues?.partyId || ''); const [loading, setLoading] = useState(false); const selectMenuProps = useMemo( () => ({ PaperProps: { style: { maxHeight: 280 } }, autoFocus: false, disableAutoFocus: true, disableEnforceFocus: true, disableRestoreFocus: true, disableScrollLock: true, }), [] ); // Barcha box/packetlarni barcha sahifadan yuklash uchun state const [allPackets, setAllPackets] = useState([]); // Barcha mahsulotlarni barcha sahifadan yuklash uchun map const [allItemsMap, setAllItemsMap] = useState<{ [packetId: number]: any[] }>({}); const { control, handleSubmit, setValue, reset, watch, formState: { errors }, } = useForm({ defaultValues: { partyName: initialValues?.partyName || '', packetItemDtos: initialValues?.paketIds ? initialValues.paketIds.map(paket => ({ packetId: paket.id, itemDtos: paket.items ? paket.items.map((item: any) => item.id) : [], })) : params.get('party_id') ? [{ packetId: +params.get('party_id')!, itemDtos: [] }] : [{ packetId: 0, itemDtos: [] }], id: initialValues?.id, boxId: initialValues?.boxId, partyId: initialValues?.partyId, }, }); // Paketlar va mahsulotlarni yuklash const [isLoadingPackets, setIsLoadingPackets] = useState(false); useEffect(() => { const fetchAllPackets = async () => { if (!partyId) { setAllPackets([]); return; } setIsLoadingPackets(true); let packets: any[] = []; let totalPages = 1; try { const firstRes = await box_requests.getAll({ partyId, page: 1 }); const firstData = firstRes?.data?.data; packets = firstData?.data || []; totalPages = firstData?.totalPages || 1; if (totalPages > 1) { const promises = []; for (let page = 2; page <= totalPages; page++) { promises.push(box_requests.getAll({ partyId, page })); } const results = await Promise.all(promises); results.forEach(res => { const data = res?.data?.data; packets = [...packets, ...(data?.data || [])]; }); } } catch (e) {} setAllPackets(packets); setIsLoadingPackets(false); }; fetchAllPackets(); }, [partyId]); const fetchAllItemsForPacket = async (packetId: number) => { let items: any[] = []; let totalPages = 1; try { const firstRes = await item_requests.getAll({ packetId, page: 1 }); const firstData = firstRes?.data?.data; items = firstData?.data || []; totalPages = firstData?.totalPages || 1; if (totalPages > 1) { const promises = []; for (let page = 2; page <= totalPages; page++) { promises.push(item_requests.getAll({ packetId, page })); } const results = await Promise.all(promises); results.forEach(res => { const data = res?.data?.data; items = [...items, ...(data?.data || [])]; }); } } catch (e) {} setAllItemsMap(prev => ({ ...prev, [packetId]: items })); return items; }; useEffect(() => { if (initialValues) { reset({ partyName: initialValues.partyName || '', packetItemDtos: initialValues.paketIds ? initialValues.paketIds.map(paket => ({ packetId: paket.id, itemDtos: paket.items ? paket.items.map((item: any) => item.id) : [], })) : [{ packetId: 0, itemDtos: [] }], id: initialValues.id, boxId: initialValues.boxId, partyId: initialValues.partyId, }); if (initialValues.partyId) { setPartyId(initialValues.partyId); } if (initialValues.paketIds) { initialValues.paketIds.forEach((paket: any) => { fetchAllItemsForPacket(paket.id); }); } } }, [initialValues, reset]); // useFieldArray keyName="key" orqali unique key const { fields, append, remove } = useFieldArray({ control, name: 'packetItemDtos', keyName: 'key', }); const requiredText = t('required'); const { data: parties = [], isLoading: isLoadingParties } = useQuery({ queryKey: ['parties-list', 'COLLECTING'], queryFn: () => party_requests.getAll({ status: 'COLLECTING' }), select: data => data.data.data.data.map((p: any) => ({ id: p.id, name: p.name, })), }); const onSubmit = handleSubmit(async values => { try { setLoading(true); if (editMode) { const updateBody: UpdateRealBoxBodyType = { boxId: initialValues!.boxId!, partyName: values.partyName, packetItemDtos: values.packetItemDtos.map(packet => ({ packetId: packet.packetId, itemDtos: packet.itemDtos, })), }; await real_box_requests.update(updateBody); } else { const createBody: RealCreateBoxBodyType = { partyName: values.partyName, packetItemDtos: values.packetItemDtos.map(packet => ({ packetId: packet.packetId, itemDtos: packet.itemDtos, })), }; await real_box_requests.create(createBody); } push(pageLinks.dashboard.real_boxes.index); } catch (error) { notifyUnknownError(error); } finally { setLoading(false); } }); const appendPacket = () => { append({ packetId: 0, itemDtos: [] }); setTimeout(() => { document.activeElement instanceof HTMLElement && document.activeElement.blur(); }, 0); }; const removePacket = (index: number) => { remove(index); }; const handlePartyChange = (event: any) => { const selectedParty = parties.find(p => p.id === event.target.value); if (selectedParty) { setValue('partyName', selectedParty.name); setPartyId(selectedParty.id); setValue('packetItemDtos', [{ packetId: 0, itemDtos: [] }]); } }; const PacketRow = ({ index, field }: { index: number; field: any }) => { const packetId = watch(`packetItemDtos.${index}.packetId`); const [keyword, setKeyword] = useState(''); const [selectedProductNames, setSelectedProductNames] = useState<{ [productId: number]: string }>({}); const packetsList = keyword ? allPackets.filter(p => (p.name || '').toLowerCase().includes(keyword.toLowerCase())) : allPackets; const itemsList = allItemsMap[packetId] || []; const loadingItems = !allItemsMap[packetId] && !!packetId; useEffect(() => { if (packetId && !allItemsMap[packetId]) { fetchAllItemsForPacket(packetId); } }, [packetId]); useEffect(() => { if (packetId && field?.itemDtos?.length && itemsList.length) { const names: { [productId: number]: string } = {}; field.itemDtos.forEach((id: number) => { const prod = itemsList.find(p => p.id === id); names[id] = prod?.name || prod?.nameRu || String(id); }); setSelectedProductNames(names); } }, [field?.itemDtos, itemsList, packetId]); const handleProductChange = (product: any, checked: boolean) => { setSelectedProductNames(prev => { if (checked) { return { ...prev, [product.id]: product.name || product.nameRu || String(product.id) }; } else { const newNames = { ...prev }; delete newNames[product.id]; return newNames; } }); }; useEffect(() => { const element = document.getElementById(`packet-select-${index}`); if (element) { element.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }, [fields.length]); const handleSelectAllProducts = async () => { if (!packetId) return; let allProducts = allItemsMap[packetId] || []; if (!allProducts.length) { allProducts = await fetchAllItemsForPacket(packetId); } if (allProducts.length > 0) { setValue( `packetItemDtos.${index}.itemDtos`, allProducts.map((p: any) => p.id) ); setSelectedProductNames( allProducts.reduce( (acc, p) => ({ ...acc, [p.id]: p.name || p.nameRu || String(p.id), }), {} ) ); } }; const handleClearAll = () => { setValue(`packetItemDtos.${index}.itemDtos`, []); setSelectedProductNames({}); }; return (
{t('packet')}
setKeyword(e.target.value)} autoFocus={false} />
{t('packet')} ( )} /> {!!get(errors, `packetItemDtos.${index}.packetId`) && ( {requiredText} )}
{fields.length > 1 && ( removePacket(index)} > )}
{packetId && ( {t('products')} {loadingItems ? ( ) : ( ( )} /> )} )}
); }; return ( {editMode ? t('update_box') : t('create_box')} {t('party_name')} {t('party_name')} ( )} /> {!!errors.partyId && {requiredText}}
{fields.map((field, index) => ( ))} } sx={{ mt: 2 }}> {t('add_more')}
{loading ? : editMode ? t('update_box') : t('create_box')}
); }; export default DashboardCreateRealBoxPage;