"use client"; import { createTours, hotelBadge, hotelTarif, hotelTransport, } 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 IconSelect from "@/shared/ui/iocnSelect"; 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 * as LucideIcons from "lucide-react"; import { ChevronDownIcon, 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, isEditMode, }: { setStep: Dispatch>; data: GetOneTours | 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, time: "", }, amenities: [], hotel_meals: [], travelDateTime: { date: undefined, time: "", }, passenger_count: 1, min_person: 1, max_person: 1, languages: "", duration: 1, badges: [], images: [], hotel_info: "", hotel_info_ru: "", hotel_meals_info: "", hotel_meals_info_ru: "", ticket_itinerary: [], }, }); const { addAmenity, setId } = useTicketStore(); useEffect(() => { if (isEditMode && data?.data) { const tourData = data.data; form.setValue("title", tourData.title); form.setValue("title_ru", formatPrice(tourData.title)); form.setValue("price", tourData.price); setDisplayPrice(formatPrice(tourData.price)); form.setValue("passenger_count", tourData.passenger_count || 1); form.setValue("min_person", tourData.min_person || 1); form.setValue("max_person", tourData.max_person || 1); form.setValue("departure", tourData.departure || ""); form.setValue("departure_ru", tourData.departure || ""); form.setValue("destination", tourData.destination || ""); form.setValue("destination_ru", tourData.destination || ""); form.setValue("location_name", tourData.location_name || ""); form.setValue("location_name_ru", tourData.location_name || ""); form.setValue("hotel_info", tourData.hotel_info || ""); form.setValue("hotel_info_ru", tourData.hotel_info || ""); form.setValue("hotel_meals_info", tourData.hotel_meals || ""); form.setValue("hotel_meals_info_ru", tourData.hotel_meals || ""); form.setValue("languages", tourData.languages || ""); form.setValue("duration", tourData.duration_days || 1); form.setValue("visa_required", tourData.visa_required ? "yes" : "no"); form.setValue("badges", tourData.badge || []); // DateTime fields if (tourData.departure_time) { const departureDate = new Date(tourData.departure_time); form.setValue("departureDateTime", { date: departureDate, time: departureDate.toTimeString().slice(0, 8), // HH:MM:SS }); } if (tourData.travel_time) { const travelDate = new Date(tourData.travel_time); form.setValue("travelDateTime", { date: travelDate, time: travelDate.toTimeString().slice(0, 8), }); } // Amenities if (tourData.ticket_amenities && tourData.ticket_amenities.length > 0) { const amenities = tourData.ticket_amenities.map((item) => ({ name: item.name, name_ru: item.name_ru, icon_name: item.icon_name, })); form.setValue("amenities", amenities); } if ( tourData.ticket_included_services && tourData.ticket_included_services.length > 0 ) { const services = tourData.ticket_included_services.map((item) => ({ image: item.image, title: item.title, title_ru: item.title_ru, description: item.desc_uz || item.desc, desc_ru: item.desc || item.desc, })); form.setValue("hotel_services", services); } if ( tourData.ticket_hotel_meals && tourData.ticket_hotel_meals.length > 0 ) { const meals = tourData.ticket_hotel_meals.map((item) => ({ image: item.image, title: item.name, title_ru: item.name_ru, description: item.desc, desc_ru: item.desc_ru, })); form.setValue("hotel_meals", meals); } // Transport if (tourData.transports && tourData.transports.length > 0) { const transports = tourData.transports.map((item, index) => ({ transport: index + 1, // Agar transport ID bo'lsa, uni ishlatish kerak price: item.price, })); // const tariff = tourData.tar => ({ // transport: index + 1, // price: item.price, // })); form.setValue("transport", transports); // form.setValue("tarif", ); } // Ticket itinerary if (tourData.ticket_itinerary && tourData.ticket_itinerary.length > 0) { const itinerary = tourData.ticket_itinerary.map((item) => ({ ticket_itinerary_image: [], // Image fayllarni alohida handle qilish kerak title: item.title, title_ru: item.title_ru, duration: item.duration, ticket_itinerary_destinations: [], // Agar destinations bo'lsa qo'shish kerak })); form.setValue("ticket_itinerary", itinerary); } form.setValue("banner", tourData.image_banner); if (tourData.ticket_images && tourData.ticket_images.length > 0) { const images = tourData.ticket_images.map((img) => img.image); // faqat linklarni olamiz form.setValue("images", images); } } }, [isEditMode, data, form]); const { watch, setValue } = form; const selectedDate = watch("departureDateTime.date"); const selectedDateTravel = watch("travelDateTime.date"); const [selectedIcon, setSelectedIcon] = useState(""); const { mutate: create } = 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", }); }, }); function onSubmit(value: z.infer) { const formData = new FormData(); 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)); formData.append("languages", value.languages); formData.append("hotel_info", value.hotel_info); formData.append("hotel_info_ru", value.hotel_info_ru); formData.append("hotel_meals", value.hotel_meals_info); formData.append("hotel_meals_ru", value.hotel_meals_info_ru); formData.append("duration_days", String(value.duration)); formData.append("rating", String("0.0")); formData.append("image_banner", value.banner); 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, i) => { formData.append(`badge[${i}]`, String(e)); }); value.images.forEach((e) => formData.append("ticket_images", e)); value.amenities.forEach((e, i) => { formData.append(`ticket_amenities[${i}]name`, e.name); formData.append(`ticket_amenities[${i}]name_ru`, e.name_ru); formData.append(`ticket_amenities[${i}]icon_name`, e.icon_name); addAmenity({ icon_name: e.icon_name, name: e.name, name_ru: e.name_ru, }); }); value.hotel_services.forEach((e, i) => { 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); }); value.ticket_itinerary.forEach((e, i) => { formData.append(`ticket_itinerary[${i}]title`, e.title); formData.append(`ticket_itinerary[${i}]title_ru`, e.title_ru); formData.append(`ticket_itinerary[${i}]duration`, String(e.duration)); e.ticket_itinerary_image.forEach((e, f) => { formData.append( `ticket_itinerary[${i}]ticket_itinerary_image[${f}]image`, e.image, ); }); e.ticket_itinerary_destinations.forEach((e, f) => { formData.append( `ticket_itinerary[${i}]ticket_itinerary_destinations[${f}]name`, String(e.name), ); formData.append( `ticket_itinerary[${i}]ticket_itinerary_destinations[${f}]name_ru`, String(e.name_ru), ); }); }); value.hotel_meals.forEach((e, i) => { 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); }); create(formData); } const { data: badge } = useQuery({ queryKey: ["all_badge"], queryFn: () => hotelBadge({ 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 }), }); 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", Number(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", Number(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", Number(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); }} />
)} /> (
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); }} />
setValue("travelDateTime.time", e.target.value) } className="bg-background !h-12 appearance-none [&::-webkit-calendar-picker-indicator]:hidden [&::-webkit-calendar-picker-indicator]:appearance-none" />
)} />
( )} /> ( field.onChange(Number(e.target.value))} value={field.value} onBlur={field.onBlur} 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("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 updatedTransport = form .getValues("tarif") .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) : ""; setTarifDisplayPrice(updatedPrices); }} className="h-12 !text-md" />
); })}
{tariff?.data?.data?.results?.map((item: any) => { const selected = form .getValues("tarif") .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 updatedTransport = form .getValues("transport") .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 selected = form .getValues("transport") .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} ); })}
)} />
(
)} /> img.image)} /> (
{form.watch("amenities").map((item, idx) => { const Icon = (LucideIcons as any)[item.icon_name] || XIcon; return ( {item.name} ); })}
)} /> (