'use client'; import { cart_api, OrderCreateBody } from '@/features/cart/lib/api'; import { orderForm } from '@/features/cart/lib/form'; import { BASE_URL } from '@/shared/config/api/URLs'; import formatDate from '@/shared/lib/formatDate'; import formatPrice from '@/shared/lib/formatPrice'; import { cn } from '@/shared/lib/utils'; import { Button } from '@/shared/ui/button'; import { Calendar } from '@/shared/ui/calendar'; import { Form, FormControl, FormField, FormItem, FormMessage, } from '@/shared/ui/form'; import { Input } from '@/shared/ui/input'; import { Label } from '@/shared/ui/label'; import { Popover, PopoverContent, PopoverTrigger } from '@/shared/ui/popover'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/shared/ui/select'; import { Textarea } from '@/shared/ui/textarea'; import { userStore } from '@/widgets/welcome/lib/hook'; import { zodResolver } from '@hookform/resolvers/zod'; import { Map, Placemark, Polygon, YMaps, ZoomControl, } from '@pbe/react-yandex-maps'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { Calendar as CalIcon, CheckCircle2, Clock, Loader2, LocateFixed, MapPin, Minus, Package, Plus, ShoppingBag, Trash2, User, } from 'lucide-react'; import { useTranslations } from 'next-intl'; import Image from 'next/image'; import { useRouter, useSearchParams } from 'next/navigation'; import { useEffect, useState } from 'react'; import { useForm } from 'react-hook-form'; import { toast } from 'sonner'; import z from 'zod'; import OrderItem, { order_api } from '../lib/api'; const deliveryTimeSlots = [ { id: 1, label: '10:00 - 12:00', start: '10:00', end: '12:00' }, { id: 2, label: '12:00 - 14:00', start: '12:00', end: '14:00' }, { id: 3, label: '14:00 - 16:00', start: '14:00', end: '16:00' }, { id: 4, label: '16:00 - 18:00', start: '16:00', end: '18:00' }, ]; interface CoordsData { lat: number; lon: number; polygon: [number, number][][]; } const RefreshOrder = () => { const [deliveryDate, setDeliveryDate] = useState(); const [selectedTimeSlot, setSelectedTimeSlot] = useState(''); const [orderItems, setOrderItems] = useState([]); const { user } = userStore(); const [quantityInputs, setQuantityInputs] = useState>( {}, ); const t = useTranslations(); const queryClient = useQueryClient(); const searchParams = useSearchParams(); const router = useRouter(); const id = searchParams.get('id'); const { data, isLoading } = useQuery({ queryKey: ['order_list'], queryFn: () => order_api.list(), select: (res) => res.data, }); const initialValues = data?.find((e) => e.id === Number(id)); useEffect(() => { if (initialValues?.items) { const items = initialValues.items.map((item: OrderItem) => ({ ...item })); setOrderItems(items); const inputs: Record = {}; items.forEach((item: OrderItem) => { inputs[item.id] = String(item.quantity); }); setQuantityInputs(inputs); } }, [initialValues]); const form = useForm>({ resolver: zodResolver(orderForm), defaultValues: { comment: initialValues?.comment || '', lat: '41.311081', long: '69.240562', }, }); useEffect(() => { if (initialValues?.comment) { form.setValue('comment', initialValues.comment); } }, [initialValues, form]); const [orderSuccess, setOrderSuccess] = useState(false); const { mutate, isPending } = useMutation({ mutationFn: (body: OrderCreateBody) => cart_api.createOrder(body), onSuccess: () => { setOrderSuccess(true); queryClient.refetchQueries({ queryKey: ['cart_items'] }); queryClient.refetchQueries({ queryKey: ['order_list'] }); }, onError: () => { toast.error(t('Xatolik yuz berdi'), { richColors: true, position: 'top-center', }); }, }); const [coords, setCoords] = useState({ latitude: 41.311081, longitude: 69.240562, zoom: 12, }); const [polygonCoords, setPolygonCoords] = useState< [number, number][][] | null >(null); // Input o'zgarishi — foydalanuvchi "0.5", "1.75" yoza oladi const handleQuantityInput = (itemId: number, value: string) => { // Faqat raqam va nuqtaga ruxsat if (!/^(\d+\.?\d*)?$/.test(value)) return; setQuantityInputs((prev) => ({ ...prev, [itemId]: value })); const parsed = parseFloat(value); if (!isNaN(parsed) && parsed > 0) { setOrderItems((prev) => prev.map((item) => item.id === itemId ? { ...item, quantity: parsed } : item, ), ); } }; // Blur — bo'sh yoki 0 qiymatni 1 ga qaytarish const handleQuantityBlur = (itemId: number) => { const val = parseFloat(quantityInputs[itemId]); if (!val || val <= 0) { setQuantityInputs((prev) => ({ ...prev, [itemId]: '1' })); setOrderItems((prev) => prev.map((item) => item.id === itemId ? { ...item, quantity: 1 } : item, ), ); } }; // ± tugmalar — 0.5 qadamda o'zgartirish const updateQuantity = (itemId: number, delta: number) => { setOrderItems((prev) => prev.map((item) => { if (item.id !== itemId) return item; const newQty = Math.max( 0.5, Math.round((item.quantity + delta) * 100) / 100, ); setQuantityInputs((inputs) => ({ ...inputs, [itemId]: String(newQty), })); return { ...item, quantity: newQty }; }), ); }; // Item o'chirish — agar 0 ta qolsa profile sahifaga yo'naltiradi const deleteItem = (itemId: number) => { const updated = orderItems.filter((item) => item.id !== itemId); setOrderItems(updated); if (updated.length === 0) { toast.info(t('Buyurtmada mahsulot qolmadi'), { richColors: true, position: 'top-center', }); router.push('/profile'); } }; const getCoords = async (name: string): Promise => { const res = await fetch( `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent( name, )}&format=json&polygon_geojson=1&limit=1`, ); const data = await res.json(); if (data.length > 0 && data[0].geojson) { const lat = parseFloat(data[0].lat); const lon = parseFloat(data[0].lon); let polygon: [number, number][][] = []; if (data[0].geojson.type === 'Polygon') { polygon = data[0].geojson.coordinates.map((ring: [number, number][]) => ring.map((coord: [number, number]) => [coord[1], coord[0]]), ); } else if (data[0].geojson.type === 'MultiPolygon') { polygon = data[0].geojson.coordinates.map( (poly: [number, number][][]) => poly[0].map((coord: [number, number]) => [coord[1], coord[0]]), ); } return { lat, lon, polygon }; } return null; }; const handleMapClick = ( e: ymaps.IEvent, ) => { const [lat, lon] = e.get('coords'); setCoords({ latitude: lat, longitude: lon, zoom: 18 }); form.setValue('lat', lat.toString(), { shouldDirty: true }); form.setValue('long', lon.toString(), { shouldDirty: true }); }; const handleShowMyLocation = () => { if (!navigator.geolocation) { alert("Sizning brauzeringiz geolokatsiyani qo'llab-quvvatlamaydi"); return; } navigator.geolocation.getCurrentPosition( (position) => { const lat = position.coords.latitude; const lon = position.coords.longitude; setCoords({ latitude: lat, longitude: lon, zoom: 14 }); form.setValue('lat', lat.toString()); form.setValue('long', lon.toString()); }, (error) => { alert('Joylashuv aniqlanmadi: ' + error.message); }, ); }; const cityValue = form.watch('city'); useEffect(() => { if (!cityValue || cityValue.length < 3) return; const timeout = setTimeout(async () => { const result = await getCoords(cityValue); if (!result) return; setCoords({ latitude: result.lat, longitude: result.lon, zoom: 12 }); setPolygonCoords(result.polygon); form.setValue('lat', result.lat.toString(), { shouldDirty: true }); form.setValue('long', result.lon.toString(), { shouldDirty: true }); }, 700); return () => clearTimeout(timeout); }, [cityValue]); const onSubmit = (value: z.infer) => { if (!deliveryDate) { toast.error(t('Yetkazib berish sanasini tanlang'), { richColors: true, position: 'top-center', }); return; } if (!selectedTimeSlot) { toast.error(t('Yetkazib berish vaqtini tanlang'), { richColors: true, position: 'top-center', }); return; } if (!initialValues) { toast.error(t('Buyurtma topilmadi'), { richColors: true, position: 'top-center', }); return; } const order_products = orderItems .filter( (item) => item.product.prices && item.product.prices.length > 0 && item.product.prices[0].price_type?.code && item.product.prices[0].price, ) .map((item) => ({ inventory_kind: 'G', product_code: item.product.code, on_balance: 'Y', order_quant: item.quantity, price_type_code: item.product.prices![0].price_type.code, product_price: item.price, warehouse_code: process.env.NEXT_PUBLIC_WARHOUSES_CODE!, })); if (user) { const dealTime = formatDate.format(deliveryDate, 'DD.MM.YYYY'); mutate({ order: [ { filial_code: process.env.NEXT_PUBLIC_FILIAL_CODE!, delivery_date: `${dealTime}`, room_code: process.env.NEXT_PUBLIC_ROOM_CODE!, deal_time: formatDate.format(new Date(), 'DD.MM.YYYY'), robot_code: process.env.NEXT_PUBLIC_ROBOT_CODE!, status: 'D', sales_manager_code: process.env.NEXT_PUBLIC_SALES_MANAGER_CODE!, person_code: user?.username, currency_code: '860', owner_person_code: user?.username, note: value.comment, order_products: order_products, }, ], }); } else { toast.error(t('Xatolik yuz berdi'), { richColors: true, position: 'top-center', }); } }; const totalPrice = orderItems.reduce( (sum, item) => sum + Number(item.price) * item.quantity, 0, ); const totalItems = orderItems.reduce((sum, item) => sum + item.quantity, 0); if (isLoading) { return (
); } if (!initialValues) { return (

{t('Buyurtma topilmadi')}

{t("Ushbu buyurtma mavjud emas yoki o'chirilgan")}

); } if (orderSuccess) { return (

{t('Buyurtma qabul qilindi!')}

{t('Buyurtmangiz muvaffaqiyatli qayta qabul qilindi')}

); } return (
<> {/* Header */}

{t('Buyurtmani qayta rasmiylashtirish')}

{t('Buyurtma')} #{initialValues.id}{' '} {t("uchun ma'lumotlarni yangilang")}

{/* Left Column - Forms */}
{/* Contact Information */}

{t("Shaxsiy ma'lumotlar")}

(