"use client"; import { createTours, getAllAmenities, hotelBadge, hotelTransport, updateTours, } from "@/pages/tours/lib/api"; import { TourformSchema } from "@/pages/tours/lib/form"; import { useTicketStore } from "@/pages/tours/lib/store"; import type { GetOneTours } from "@/pages/tours/lib/type"; import TicketsImagesModel from "@/pages/tours/ui/TicketsImagesModel"; import formatPrice from "@/shared/lib/formatPrice"; import { Badge } from "@/shared/ui/badge"; import { Button } from "@/shared/ui/button"; import { Calendar } from "@/shared/ui/calendar"; import { Command, CommandGroup, CommandItem, CommandList, } from "@/shared/ui/command"; 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 { RadioGroup, RadioGroupItem } from "@/shared/ui/radio-group"; import { Textarea } from "@/shared/ui/textarea"; import { zodResolver } from "@hookform/resolvers/zod"; import { useMutation, useQuery } from "@tanstack/react-query"; import { ChevronDownIcon, Loader2, SquareCheckBig, XIcon } from "lucide-react"; import { useEffect, useState, type Dispatch, type SetStateAction } from "react"; import { useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import { toast } from "sonner"; import z from "zod"; const StepOne = ({ setStep, data, id, isEditMode, }: { setStep: Dispatch>; data: GetOneTours | undefined; id: string | undefined; isEditMode: boolean; }) => { const [displayPrice, setDisplayPrice] = useState(""); // const [tarifdisplayPrice, setTarifDisplayPrice] = useState([]); const [transportPrices, setTransportPrices] = useState([]); const { t } = useTranslation(); const [openDate, setOpenDate] = useState(false); const [openDateTravel, setOpenDateTravel] = useState(false); const form = useForm>({ resolver: zodResolver(TourformSchema), defaultValues: { title: "", title_ru: "", hotel_services: [], price: 0, departure: "", // tarif: [], transport: [], departure_ru: "", destination: "", destination_ru: "", location_name: "", location_name_ru: "", departureDateTime: { date: undefined, }, amenities: [], hotel_meals: [], travelDateTime: { date: undefined, }, passenger_count: "1", min_person: "1", max_person: "1", extra_service: [], paid_extra_service: [], languages: "", duration: "1", badges: [], images: [], hotel_info: "", hotel_info_ru: "", hotel_meals_info: "", hotel_meals_info_ru: "", ticket_itinerary: [], }, }); const { addAmenity, setId, removeAmenity } = useTicketStore(); useEffect(() => { if (!isEditMode || !data?.data) return; const tour = data.data; // 🔹 Jo'nash vaqti let departureDateTime = undefined; if (tour.departure_time) { const d = new Date(tour.departure_time); departureDateTime = { date: d, }; } // 🔹 Qaytish vaqti let travelDateTime = undefined; if (tour.travel_time) { const d = new Date(tour.travel_time); travelDateTime = { date: d, }; } // 🔹 Transport const transports = tour.transports?.map((t, i) => ({ transport: i + 1, price: t.price ?? 0, })) ?? []; setTransportPrices(transports.map((t) => formatPrice(t.price ?? 0))); // 🔹 Tarif // const tariffs = // tour.tariff?.map((t) => ({ // tariff: t.tariff ?? 0, // price: t.price ?? 0, // })) ?? []; // setTarifDisplayPrice(tariffs.map((t) => formatPrice(t.price ?? 0))); form.reset({ title: tour.title_uz ?? "", title_ru: tour.title_ru ?? "", price: tour.price ?? 0, passenger_count: String(tour.passenger_count) ?? "1", min_person: String(tour.min_person) ?? "1", max_person: String(tour.max_person) ?? "1", departure: tour.departure_uz ?? "", departure_ru: tour.departure_ru ?? "", destination: tour.destination_uz ?? "", destination_ru: tour.destination_ru ?? "", location_name: tour.location_name_uz ?? "", location_name_ru: tour.location_name_ru ?? "", hotel_info: tour.hotel_info_uz ?? "", hotel_info_ru: tour.hotel_info_ru ?? "", hotel_meals_info: tour.hotel_meals_uz ?? "", hotel_meals_info_ru: tour.hotel_meals_ru ?? "", languages: tour.languages ?? "", duration: String(tour.duration_days) ?? "1", visa_required: tour.visa_required ? "yes" : "no", badges: tour.badge ?? [], departureDateTime, travelDateTime, amenities: tour.ticket_amenities.map((e) => e.id), hotel_services: tour.ticket_included_services?.map((service) => ({ id: service.id, image: service.image ?? null, title: service.title_uz ?? service.title ?? "", title_ru: service.title_ru ?? "", description: service.desc_uz ?? service.desc ?? "", desc_ru: service.desc_ru ?? "", })) ?? [], hotel_meals: tour.ticket_hotel_meals?.map((meal) => ({ id: meal.id, image: meal.image ?? null, title: meal.name_uz ?? meal.name ?? "", title_ru: meal.name_ru ?? "", description: meal.desc_uz ?? meal.desc ?? "", desc_ru: meal.desc_ru ?? "", })) ?? [], transport: transports, // tarif: tariffs, ticket_itinerary: tour.ticket_itinerary?.map((item) => ({ id: item.id, title: item.title_uz ?? item.title ?? "", title_ru: item.title_ru ?? "", duration: item.duration ?? 1, ticket_itinerary_image: item.ticket_itinerary_image?.map((img) => ({ image: img.image, })) ?? [], ticket_itinerary_destinations: item.ticket_itinerary_destinations?.map((dest) => ({ name: dest.name_uz ?? dest.name ?? "", name_ru: dest.name_ru ?? "", })) ?? [], })) ?? [], banner: tour.image_banner ?? null, images: tour.ticket_images.map((img) => ({ id: img.id, image: img.image, })), extra_service: tour.extra_service?.map((s) => ({ name: s.name_uz ?? s.name ?? "", name_ru: s.name_ru ?? "", })) ?? [], paid_extra_service: tour.paid_extra_service?.map((s) => ({ name: s.name_uz ?? s.name ?? "", name_ru: s.name_ru ?? "", price: s.price ?? 0, })) ?? [], }); // Display price setDisplayPrice(formatPrice(tour.price ?? 0)); // TicketStore uchun id setId(tour.id); }, [isEditMode, data, form, setId]); const { watch, setValue } = form; const selectedDate = watch("departureDateTime.date"); const selectedDateTravel = watch("travelDateTime.date"); const { mutate: create, isPending } = useMutation({ mutationFn: (body: FormData) => { return createTours({ body }); }, onSuccess: (res) => { setId(res.data.data.id); setStep(2); }, onError: () => { toast.error(t("Xatolik yuz berdi"), { richColors: true, position: "top-center", }); }, }); const { mutate: update, isPending: updatePending } = useMutation({ mutationFn: ({ body, id }: { id: number; body: FormData }) => { return updateTours({ body, id }); }, onSuccess: (res) => { setId(res.data.data.id); setStep(2); }, onError: () => { toast.error(t("Xatolik yuz berdi"), { richColors: true, position: "top-center", }); }, }); function onSubmit(value: z.infer) { const formData = new FormData(); // Asosiy ma'lumotlar formData.append("title", value.title); formData.append("location_name", value.location_name); formData.append("location_name_ru", value.location_name_ru); formData.append( "visa_required", value.visa_required === "yes" ? "true" : "false", ); formData.append("title_ru", value.title_ru); formData.append("price", String(value.price)); formData.append("min_person", String(value.min_person)); formData.append("max_person", String(value.max_person)); formData.append("departure", String(value.departure)); formData.append("departure_ru", String(value.departure_ru)); formData.append("destination", String(value.destination)); formData.append("destination_ru", String(value.destination_ru)); formData.append( "departure_time", value.departureDateTime.date?.toISOString(), ); formData.append( "travel_time", String(value.travelDateTime.date.toISOString()), ); formData.append("passenger_count", String(value.passenger_count)); if (value.languages) { formData.append("languages", value.languages); } if (value.hotel_info) { formData.append("hotel_info", value.hotel_info); } if (value.hotel_info_ru) { formData.append("hotel_info_ru", value.hotel_info_ru); } if (value.hotel_meals_info) { formData.append("hotel_meals", value.hotel_meals_info); } if (value.hotel_meals_info_ru) { formData.append("hotel_meals_ru", value.hotel_meals_info_ru); } formData.append("duration_days", String(value.duration)); formData.append("rating", String("0.0")); if (value.banner instanceof File) { formData.append("image_banner", value.banner); } console.log(value.banner, "value.banner"); // Tarif va transport // value.tarif?.forEach((e, i) => { // formData.append(`tariff[${i}]tariff`, String(e.tariff)); // formData.append(`tariff[${i}]price`, String(e.price)); // }); value.transport?.forEach((e, i) => { formData.append(`transports[${i}]transport`, String(e.transport)); formData.append(`transports[${i}]price`, String(e.price)); }); value.badges?.forEach((e) => { formData.append(`badge`, String(e)); }); value.amenities?.forEach((e) => { formData.append(`ticket_amenities`, String(e)); }); value.images.forEach((e) => { if (e.id) { formData.append(`ticket_images_ids`, String(e.id)); } else if (e.id === undefined) { formData.append(`ticket_images`, e.image!); } }); // 🔹 Hotel Services - edit rejimida ID yuborish, yangi bo'lsa to'liq ma'lumot yuborish value.hotel_services && value.hotel_services.forEach((e, i) => { if (e.id && typeof e.image === "string") { formData.append(`ticket_included_services_ids`, String(e.id)); } else { // Yangi xizmat yoki o'zgartirilgan xizmat if (e.image instanceof File) { formData.append(`ticket_included_services[${i}]image`, e.image); } formData.append(`ticket_included_services[${i}]title`, e.title); formData.append(`ticket_included_services[${i}]title_ru`, e.title_ru); formData.append(`ticket_included_services[${i}]desc_ru`, e.desc_ru); formData.append(`ticket_included_services[${i}]desc`, e.description); } }); // 🔹 Ticket Itinerary - edit rejimida ID yuborish value.ticket_itinerary?.forEach((itinerary, i) => { if (itinerary.id) { // Mavjud itinerary (o'zgartirilmagan) const hasNewImages = itinerary.ticket_itinerary_image?.some( (img) => img instanceof File || (typeof img === "object" && "image" in img && img.image instanceof File), ); if (!hasNewImages) { formData.append(`ticket_itinerary_ids`, String(itinerary.id)); return; // Faqat ID yuborish, boshqa ma'lumot kerak emas } } // Yangi itinerary yoki o'zgartirilgan itinerary formData.append(`ticket_itinerary[${i}]title`, itinerary.title); formData.append(`ticket_itinerary[${i}]title_ru`, itinerary.title_ru); formData.append( `ticket_itinerary[${i}]duration`, String(itinerary.duration), ); // Rasmlar if (Array.isArray(itinerary.ticket_itinerary_image)) { itinerary.ticket_itinerary_image.forEach((img, j) => { let file: File | null = null; if (img instanceof File) { file = img; } else if ( typeof img === "object" && "image" in img && img.image instanceof File ) { file = img.image; } if (file) { formData.append( `ticket_itinerary[${i}]ticket_itinerary_image[${j}]image`, file, ); } }); } // Destinations if (Array.isArray(itinerary.ticket_itinerary_destinations)) { itinerary.ticket_itinerary_destinations.forEach((dest, k) => { formData.append( `ticket_itinerary[${i}]ticket_itinerary_destinations[${k}]name`, dest.name, ); formData.append( `ticket_itinerary[${i}]ticket_itinerary_destinations[${k}]name_ru`, dest.name_ru, ); }); } }); if (value.hotel_meals) { value.hotel_meals.forEach((e, i) => { if (e.id && typeof e.image === "string") { // Mavjud meal (o'zgartirilmagan) formData.append(`ticket_hotel_meals_ids`, String(e.id)); } else { // Yangi meal yoki o'zgartirilgan meal if (e.image instanceof File) { formData.append(`ticket_hotel_meals[${i}]image`, e.image); } formData.append(`ticket_hotel_meals[${i}]name`, e.title); formData.append(`ticket_hotel_meals[${i}]name_ru`, e.title_ru); formData.append(`ticket_hotel_meals[${i}]desc`, e.description); formData.append(`ticket_hotel_meals[${i}]desc_ru`, e.desc_ru); } }); } // Extra services value.extra_service && value.extra_service.forEach((e, i) => { formData.append(`extra_service[${i}]name`, e.name); formData.append(`extra_service[${i}]name_ru`, e.name_ru); }); value.paid_extra_service && value.paid_extra_service.forEach((e, i) => { formData.append(`paid_extra_service[${i}]name`, e.name); formData.append(`paid_extra_service[${i}]name_ru`, e.name_ru); formData.append(`paid_extra_service[${i}]price`, String(e.price)); }); if (isEditMode && id) { update({ body: formData, id: Number(id), }); } else { create(formData); } } const { data: badge } = useQuery({ queryKey: ["all_badge"], queryFn: () => hotelBadge({ page: 1, page_size: 10 }), }); const { data: amenitiesData } = useQuery({ queryKey: ["all_amenities"], queryFn: () => getAllAmenities({ page: 1, page_size: 10 }), }); // const { data: tariff } = useQuery({ // queryKey: ["all_tarif"], // queryFn: () => hotelTarif({ page: 1, page_size: 10 }), // }); const { data: transport } = useQuery({ queryKey: ["all_transport"], queryFn: () => hotelTransport({ page: 1, page_size: 10 }), }); console.log(form.formState.errors); return (
( )} /> ( )} /> ( { const raw = e.target.value.replace(/\D/g, ""); const num = Number(raw); if (!isNaN(num)) { form.setValue("price", num); setDisplayPrice(raw ? formatPrice(num) : ""); } }} className="h-12 !text-md" /> )} />
( form.setValue("min_person", e.target.value) } className="h-12 !text-md [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [appearance:textfield]" /> )} /> ( form.setValue("max_person", e.target.value) } className="h-12 !text-md [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [appearance:textfield]" /> )} />
( )} /> ( )} /> ( )} /> ( )} /> ( )} /> ( )} /> ( form.setValue("passenger_count", e.target.value) } className="h-12 !text-md [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [appearance:textfield]" /> )} />
(
{ setValue("departureDateTime.date", date!); setOpenDate(false); }} toYear={new Date().getFullYear() + 100} />
)} /> {/* (
setValue("departureDateTime.time", e.target.value) } className="bg-background !h-12 appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none" />
)} /> */} (
{ setValue("travelDateTime.date", date!); setOpenDateTravel(false); }} toYear={new Date().getFullYear() + 100} />
{/*
setValue("travelDateTime.time", e.target.value) } className="bg-background !h-12 appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none" />
*/}
)} />
( form.setValue("duration", e.target.value)} className="h-12 !text-md [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none [appearance:textfield]" /> )} /> ( )} />
(
{(form.watch("badges") ?? []).length > 0 && (form.watch("badges") ?? []).map((badgeId: number) => { const badgeItem = badge?.data?.data?.results?.find( (b: any) => b.id === badgeId, ); return ( {badgeItem?.name || `Badge #${badgeId}`} ); })}
{badge?.data?.data?.results?.map((item: any) => { const currentBadges = form.getValues("badges") ?? []; const selected = currentBadges.includes(item.id); return ( { if (selected) { form.setValue( "badges", currentBadges.filter( (b: number) => b !== item.id, ), ); } else { form.setValue("badges", [ ...currentBadges, item.id, ]); } }} className="flex items-center gap-2" > {item.name} ); })}
)} /> (
{(form.watch("amenities") ?? []).length > 0 && (form.watch("amenities") ?? []).map((badgeId: number) => { const badgeItem = amenitiesData?.data?.data?.results?.find( (b: any) => b.id === badgeId, ); return ( {badgeItem?.name || `Qulaylilar #${badgeId}`} ); })}
{amenitiesData?.data?.data?.results?.map( (item: any) => { const currentBadges = form.getValues("amenities") ?? []; const selected = currentBadges.includes(item.id); return ( { const selected = currentBadges.includes( item.id, ); if (selected) { removeAmenity(item.id); form.setValue( "amenities", currentBadges.filter( (b: number) => b !== item.id, ), ); } else { addAmenity(item.id); form.setValue("amenities", [ ...currentBadges, item.id, ]); } }} className="flex items-center gap-2" > {item.name} ); }, )}
)} /> {/* (
{form.watch("tarif")?.map((tr, idx) => { const transportItem = tariff?.data?.data?.results?.find( (item: any) => item.id === tr.tariff, ); return (
{transportItem?.name || `Tarif #${tr.tariff}`} { const raw = e.target.value.replace(/\D/g, ""); const num = Number(raw); const currentTarifs = form.getValues("tarif") || []; const updatedTransport = currentTarifs.map( (t, i) => i === idx ? { ...t, price: num } : t, ); form.setValue("tarif", updatedTransport); // Local holatda ham yangilaymiz: const updatedPrices = [...tarifdisplayPrice]; updatedPrices[idx] = raw ? formatPrice(num) : "0"; setTarifDisplayPrice(updatedPrices); }} className="h-12 !text-md" />
); })}
{tariff?.data?.data?.results?.map((item: any) => { const currentTarifs = form.getValues("tarif") || []; const selected = currentTarifs.some( (t) => t.tariff === item.id, ); return ( { const current = form.getValues("tarif") || []; if (selected) { form.setValue( "tarif", current.filter( (t) => t.tariff !== item.id, ), ); } else { form.setValue("tarif", [ ...current, { tariff: item.id, price: 0 }, ]); } }} className="flex items-center gap-2" > {item.name} ); })}
)} /> */}
(
{form.watch("transport")?.map((tr, idx) => { const transportItem = transport?.data?.data?.results?.find( (item: any) => item.id === tr.transport, ); return (
{transportItem?.name || `Transport #${tr.transport}`} {/* { const raw = e.target.value.replace(/\D/g, ""); const num = Number(raw); const currentTransports = form.getValues("transport") || []; const updatedTransport = currentTransports.map( (t, i) => i === idx ? { ...t, price: num } : t, ); form.setValue("transport", updatedTransport); // Local holatda ham yangilaymiz: const updatedPrices = [...transportPrices]; updatedPrices[idx] = raw ? formatPrice(num) : ""; setTransportPrices(updatedPrices); }} className="h-12 !text-md" /> */}
); })}
{transport?.data?.data?.results?.map((item: any) => { const currentTransports = form.getValues("transport") || []; const selected = currentTransports.some( (t) => t.transport === item.id, ); return ( { const current = form.getValues("transport") || []; if (selected) { form.setValue( "transport", current.filter( (t) => t.transport !== item.id, ), ); } else { form.setValue("transport", [ ...current, { transport: item.id, price: 0 }, ]); } }} className="flex items-center gap-2" > {item.name} ); })}
)} />
(
)} /> ({ id: img.id, image: img.image, })) : undefined } /> (
{/* Ko'rsatilayotgan xizmatlar */}
{(form.watch("extra_service") ?? []).map((item, idx) => ( {item.name} ))}
{/* Yangi xizmat qo'shish */}
)} /> (
{/* Ro'yxat */}
{(form.watch("paid_extra_service") || []).map((item, idx) => ( {item.name} —{" "} {formatPrice(item.price, true)} ))}
{/* Qo'shish formasi */}
{ const input = e.target as HTMLInputElement; const raw = input.value.replace(/\D/g, ""); input.value = raw ? Number(raw).toLocaleString("ru-RU") : ""; }} /> {/* Qo'shish tugmasi */}
)} /> (