api ulandi
This commit is contained in:
@@ -5,6 +5,7 @@ import {
|
||||
hotelBadge,
|
||||
hotelTarif,
|
||||
hotelTransport,
|
||||
updateTours,
|
||||
} from "@/pages/tours/lib/api";
|
||||
import { TourformSchema } from "@/pages/tours/lib/form";
|
||||
import { useTicketStore } from "@/pages/tours/lib/store";
|
||||
@@ -46,10 +47,12 @@ import z from "zod";
|
||||
const StepOne = ({
|
||||
setStep,
|
||||
data,
|
||||
id,
|
||||
isEditMode,
|
||||
}: {
|
||||
setStep: Dispatch<SetStateAction<number>>;
|
||||
data: GetOneTours | undefined;
|
||||
id: string | undefined;
|
||||
isEditMode: boolean;
|
||||
}) => {
|
||||
const [displayPrice, setDisplayPrice] = useState("");
|
||||
@@ -88,6 +91,8 @@ const StepOne = ({
|
||||
passenger_count: 1,
|
||||
min_person: 1,
|
||||
max_person: 1,
|
||||
extra_service: [],
|
||||
paid_extra_service: [],
|
||||
languages: "",
|
||||
duration: 1,
|
||||
badges: [],
|
||||
@@ -103,119 +108,152 @@ const StepOne = ({
|
||||
const { addAmenity, setId } = useTicketStore();
|
||||
|
||||
useEffect(() => {
|
||||
if (isEditMode && data?.data) {
|
||||
const tourData = data.data;
|
||||
if (!isEditMode || !data?.data) return;
|
||||
|
||||
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 || []);
|
||||
const tour = data.data;
|
||||
|
||||
// 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
|
||||
});
|
||||
}
|
||||
// 🔹 Oddiy text maydonlar
|
||||
form.setValue("title", tour.title_uz ?? "");
|
||||
form.setValue("title_ru", tour.title_ru ?? "");
|
||||
form.setValue("price", tour.price ?? 0);
|
||||
setDisplayPrice(formatPrice(tour.price ?? 0));
|
||||
|
||||
if (tourData.travel_time) {
|
||||
const travelDate = new Date(tourData.travel_time);
|
||||
form.setValue("travelDateTime", {
|
||||
date: travelDate,
|
||||
time: travelDate.toTimeString().slice(0, 8),
|
||||
});
|
||||
}
|
||||
form.setValue("passenger_count", tour.passenger_count ?? 1);
|
||||
form.setValue("min_person", tour.min_person ?? 1);
|
||||
form.setValue("max_person", tour.max_person ?? 1);
|
||||
|
||||
// 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);
|
||||
}
|
||||
form.setValue("departure", tour.departure_uz ?? "");
|
||||
form.setValue("departure_ru", tour.departure_ru ?? "");
|
||||
form.setValue("destination", tour.destination_uz ?? "");
|
||||
form.setValue("destination_ru", tour.destination_ru ?? "");
|
||||
form.setValue("location_name", tour.location_name_uz ?? "");
|
||||
form.setValue("location_name_ru", tour.location_name_ru ?? "");
|
||||
|
||||
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);
|
||||
}
|
||||
form.setValue("hotel_info", tour.hotel_info_uz ?? "");
|
||||
form.setValue("hotel_info_ru", tour.hotel_info_ru ?? "");
|
||||
form.setValue("hotel_meals_info", tour.hotel_meals_uz ?? "");
|
||||
form.setValue("hotel_meals_info_ru", tour.hotel_meals_ru ?? "");
|
||||
|
||||
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);
|
||||
}
|
||||
form.setValue("languages", tour.languages ?? "");
|
||||
form.setValue("duration", tour.duration_days ?? 1);
|
||||
form.setValue("visa_required", tour.visa_required ? "yes" : "no");
|
||||
form.setValue("badges", tour.badge ?? []);
|
||||
|
||||
// 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);
|
||||
}
|
||||
// 🔹 Jo‘nash vaqti
|
||||
if (tour.departure_time) {
|
||||
const d = new Date(tour.departure_time);
|
||||
form.setValue("departureDateTime", {
|
||||
date: d,
|
||||
time: d.toTimeString().slice(0, 8),
|
||||
});
|
||||
}
|
||||
}, [isEditMode, data, form]);
|
||||
|
||||
// 🔹 Qaytish vaqti
|
||||
if (tour.travel_time) {
|
||||
const d = new Date(tour.travel_time);
|
||||
form.setValue("travelDateTime", {
|
||||
date: d,
|
||||
time: d.toTimeString().slice(0, 8),
|
||||
});
|
||||
}
|
||||
|
||||
// 🔹 Qulayliklar (amenities)
|
||||
form.setValue(
|
||||
"amenities",
|
||||
tour.ticket_amenities?.map((a) => ({
|
||||
name: a.name ?? "",
|
||||
name_ru: a.name_ru ?? "",
|
||||
icon_name: a.icon_name ?? "",
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 Xizmatlar (hotel_services)
|
||||
form.setValue(
|
||||
"hotel_services",
|
||||
tour.ticket_included_services?.map((s) => ({
|
||||
image: s.image ?? null,
|
||||
title: s.title_uz ?? "",
|
||||
title_ru: s.title_ru ?? "",
|
||||
description: s.desc_uz ?? "",
|
||||
desc_ru: s.desc_ru ?? "",
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 Taomlar (hotel_meals)
|
||||
form.setValue(
|
||||
"hotel_meals",
|
||||
tour.ticket_hotel_meals?.map((m) => ({
|
||||
image: m.image ?? null,
|
||||
title: m.name ?? "",
|
||||
title_ru: m.name_ru ?? "",
|
||||
description: m.desc ?? "",
|
||||
desc_ru: m.desc_ru ?? "",
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 Transport
|
||||
const transports =
|
||||
tour.transports?.map((t, i) => ({
|
||||
transport: i + 1,
|
||||
price: t.price ?? 0,
|
||||
})) ?? [];
|
||||
form.setValue("transport", transports);
|
||||
setTransportPrices(transports.map((t) => formatPrice(t.price ?? 0))); // 👈 YANGI QO‘SHILGAN
|
||||
|
||||
// 🔹 Tarif
|
||||
const tariffs =
|
||||
tour.tariff?.map((t) => ({
|
||||
tariff: t.tariff ?? 0,
|
||||
price: t.price ?? 0,
|
||||
})) ?? [];
|
||||
form.setValue("tarif", tariffs);
|
||||
setTarifDisplayPrice(tariffs.map((t) => formatPrice(t.price ?? 0)));
|
||||
|
||||
// 🔹 Yo‘nalishlar (ticket_itinerary)
|
||||
form.setValue(
|
||||
"ticket_itinerary",
|
||||
tour.ticket_itinerary?.map((item) => ({
|
||||
ticket_itinerary_image:
|
||||
item.ticket_itinerary_image?.map((img) => ({
|
||||
image: img.image,
|
||||
})) ?? [],
|
||||
title: item.title ?? "",
|
||||
title_ru: item.title_ru ?? "",
|
||||
duration: item.duration ?? 1,
|
||||
ticket_itinerary_destinations:
|
||||
item.ticket_itinerary_destinations?.map((d) => ({
|
||||
name: d.name ?? "",
|
||||
name_ru: d.name_ru ?? "",
|
||||
})) ?? [],
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 Banner va rasmlar
|
||||
form.setValue("banner", tour.image_banner ?? null);
|
||||
form.setValue("images", tour.ticket_images?.map((img) => img.image) ?? []);
|
||||
|
||||
// 🔹 Bepul xizmatlar (extra_service)
|
||||
form.setValue(
|
||||
"extra_service",
|
||||
tour.extra_service?.map((s) => ({
|
||||
name: s.name_uz ?? s.name ?? "",
|
||||
name_ru: s.name_ru ?? "",
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 Pullik xizmatlar (paid_extra_service)
|
||||
form.setValue(
|
||||
"paid_extra_service",
|
||||
tour.paid_extra_service?.map((s) => ({
|
||||
name: s.name_uz ?? s.name ?? "",
|
||||
name_ru: s.name_ru ?? "",
|
||||
price: s.price ?? 0,
|
||||
})) ?? [],
|
||||
);
|
||||
|
||||
// 🔹 TicketStore uchun id
|
||||
setId(tour.id);
|
||||
}, [isEditMode, data, form, setId]);
|
||||
|
||||
const { watch, setValue } = form;
|
||||
const selectedDate = watch("departureDateTime.date");
|
||||
@@ -238,6 +276,22 @@ const StepOne = ({
|
||||
},
|
||||
});
|
||||
|
||||
const { mutate: update } = 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<typeof TourformSchema>) {
|
||||
const formData = new FormData();
|
||||
|
||||
@@ -273,7 +327,9 @@ const StepOne = ({
|
||||
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);
|
||||
if (value.banner instanceof File) {
|
||||
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));
|
||||
@@ -285,7 +341,11 @@ const StepOne = ({
|
||||
value.badges?.forEach((e, i) => {
|
||||
formData.append(`badge[${i}]`, String(e));
|
||||
});
|
||||
value.images.forEach((e) => formData.append("ticket_images", e));
|
||||
value.images.forEach((e) => {
|
||||
if (e instanceof File) {
|
||||
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);
|
||||
@@ -297,43 +357,67 @@ const StepOne = ({
|
||||
});
|
||||
});
|
||||
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);
|
||||
if (e 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);
|
||||
}
|
||||
});
|
||||
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),
|
||||
);
|
||||
e.ticket_itinerary_image.forEach((l, f) => {
|
||||
if (e instanceof File) {
|
||||
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));
|
||||
formData.append(
|
||||
`ticket_itinerary[${i}]ticket_itinerary_image[${f}]image`,
|
||||
l.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);
|
||||
if (e 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);
|
||||
}
|
||||
});
|
||||
create(formData);
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(form.formState.errors);
|
||||
|
||||
const { data: badge } = useQuery({
|
||||
queryKey: ["all_badge"],
|
||||
queryFn: () => hotelBadge({ page: 1, page_size: 10 }),
|
||||
@@ -392,7 +476,9 @@ const StepOne = ({
|
||||
name="price"
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<Label className="text-md">{t("Narx")} (1 kishi uchun)</Label>
|
||||
<Label className="text-md">
|
||||
{t("Narx")} {t("(1 kishi uchun)")}
|
||||
</Label>
|
||||
<FormControl>
|
||||
<Input
|
||||
type="text"
|
||||
@@ -1157,11 +1243,11 @@ const StepOne = ({
|
||||
name="visa_required"
|
||||
render={({ field }) => (
|
||||
<FormItem className="space-y-3">
|
||||
<Label>{t("Visa talab qilinadimi?")}</Label>
|
||||
<Label>{t("Visa talab qilinadimi")}?</Label>
|
||||
<FormControl>
|
||||
<RadioGroup
|
||||
onValueChange={field.onChange}
|
||||
defaultValue={field.value}
|
||||
value={field.value}
|
||||
className="flex gap-6"
|
||||
>
|
||||
<div className="flex items-center space-x-2">
|
||||
@@ -1170,7 +1256,7 @@ const StepOne = ({
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<RadioGroupItem value="no" id="visa_no" />
|
||||
<label htmlFor="visa_no">{t("Yo‘q")}</label>
|
||||
<label htmlFor="visa_no">{t("Yo'q")}</label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
@@ -1287,6 +1373,206 @@ const StepOne = ({
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="extra_service"
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<Label className="text-md">{t("Bepul xizmatlar")}</Label>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Ko'rsatilayotgan xizmatlar */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{form.watch("extra_service").map((item, idx) => (
|
||||
<Badge
|
||||
key={idx}
|
||||
variant="secondary"
|
||||
className="px-3 py-1 text-sm flex items-center gap-2"
|
||||
>
|
||||
<span>{item.name}</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const current = form.getValues("extra_service");
|
||||
form.setValue(
|
||||
"extra_service",
|
||||
current.filter((_, i) => i !== idx),
|
||||
);
|
||||
}}
|
||||
className="ml-1 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<XIcon className="size-4" />
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Yangi xizmat qo'shish */}
|
||||
<div className="flex gap-3 items-end flex-wrap">
|
||||
<Input
|
||||
id="extra_service_name"
|
||||
placeholder={t("Xizmat nomi (UZ)")}
|
||||
className="h-12 !text-md flex-1 min-w-[200px]"
|
||||
/>
|
||||
|
||||
<Input
|
||||
id="extra_service_name_ru"
|
||||
placeholder={t("Xizmat nomi (RU)")}
|
||||
className="h-12 !text-md flex-1 min-w-[200px]"
|
||||
/>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const nameInput = document.getElementById(
|
||||
"extra_service_name",
|
||||
) as HTMLInputElement;
|
||||
const nameRuInput = document.getElementById(
|
||||
"extra_service_name_ru",
|
||||
) as HTMLInputElement;
|
||||
|
||||
if (nameInput.value && nameRuInput.value) {
|
||||
const current = form.getValues("extra_service");
|
||||
form.setValue("extra_service", [
|
||||
...current,
|
||||
{
|
||||
name: nameInput.value,
|
||||
name_ru: nameRuInput.value,
|
||||
},
|
||||
]);
|
||||
nameInput.value = "";
|
||||
nameRuInput.value = "";
|
||||
}
|
||||
}}
|
||||
className="h-12"
|
||||
>
|
||||
{t("Qo'shish")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="paid_extra_service"
|
||||
render={() => (
|
||||
<FormItem>
|
||||
<Label className="text-md">{t("Pullik xizmatlar")}</Label>
|
||||
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Ro'yxat */}
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{(form.watch("paid_extra_service") || []).map((item, idx) => (
|
||||
<Badge
|
||||
key={idx}
|
||||
variant="secondary"
|
||||
className="px-3 py-1 text-sm flex items-center gap-2"
|
||||
>
|
||||
<span>
|
||||
{item.name} —{" "}
|
||||
<strong>{formatPrice(item.price)} so‘m</strong>
|
||||
</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const current = form.getValues("paid_extra_service");
|
||||
form.setValue(
|
||||
"paid_extra_service",
|
||||
current.filter((_, i) => i !== idx),
|
||||
);
|
||||
}}
|
||||
className="ml-1 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<XIcon className="size-4" />
|
||||
</button>
|
||||
</Badge>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Qo'shish formasi */}
|
||||
<div className="flex gap-3 items-end flex-wrap">
|
||||
<Input
|
||||
id="paid_service_name"
|
||||
placeholder={t("Xizmat nomi (UZ)")}
|
||||
className="h-12 !text-md flex-1 min-w-[200px]"
|
||||
/>
|
||||
|
||||
<Input
|
||||
id="paid_service_name_ru"
|
||||
placeholder={t("Xizmat nomi (RU)")}
|
||||
className="h-12 !text-md flex-1 min-w-[200px]"
|
||||
/>
|
||||
|
||||
{/* Narx maydoni */}
|
||||
<Input
|
||||
id="paid_service_price"
|
||||
type="text"
|
||||
inputMode="numeric"
|
||||
placeholder="1 500 000"
|
||||
className="h-12 !text-md w-[150px]"
|
||||
onInput={(e) => {
|
||||
const input = e.target as HTMLInputElement;
|
||||
const raw = input.value.replace(/\D/g, "");
|
||||
input.value = raw
|
||||
? Number(raw).toLocaleString("ru-RU")
|
||||
: "";
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Qo'shish tugmasi */}
|
||||
<Button
|
||||
type="button"
|
||||
onClick={() => {
|
||||
const nameInput = document.getElementById(
|
||||
"paid_service_name",
|
||||
) as HTMLInputElement;
|
||||
const nameRuInput = document.getElementById(
|
||||
"paid_service_name_ru",
|
||||
) as HTMLInputElement;
|
||||
const priceInput = document.getElementById(
|
||||
"paid_service_price",
|
||||
) as HTMLInputElement;
|
||||
|
||||
const raw = priceInput.value.replace(/\D/g, "");
|
||||
const num = Number(raw);
|
||||
|
||||
if (
|
||||
nameInput.value.trim() &&
|
||||
nameRuInput.value.trim() &&
|
||||
!isNaN(num)
|
||||
) {
|
||||
const current = form.getValues("paid_extra_service");
|
||||
form.setValue("paid_extra_service", [
|
||||
...current,
|
||||
{
|
||||
name: nameInput.value.trim(),
|
||||
name_ru: nameRuInput.value.trim(),
|
||||
price: num, // 🟢 0 ham bo‘lishi mumkin
|
||||
},
|
||||
]);
|
||||
|
||||
// inputlarni tozalaymiz
|
||||
nameInput.value = "";
|
||||
nameRuInput.value = "";
|
||||
priceInput.value = "";
|
||||
}
|
||||
}}
|
||||
className="h-12"
|
||||
>
|
||||
{t("Qo'shish")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<FormMessage />
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="hotel_info"
|
||||
@@ -1313,7 +1599,7 @@ const StepOne = ({
|
||||
<Label className="text-md">{t("Mehmonxona haqida")} (ru)</Label>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder={t("Mehmonxona haqida (ru)")}
|
||||
placeholder={t("Mehmonxona haqida") + " (ru)"}
|
||||
{...field}
|
||||
className="min-h-48 max-h-60 !text-md"
|
||||
/>
|
||||
@@ -1389,7 +1675,7 @@ const StepOne = ({
|
||||
|
||||
<Input
|
||||
id="hotel_service_title_ru"
|
||||
placeholder={t("Xizmat nomi (ru)")}
|
||||
placeholder={t("Xizmat nomi") + " (ru)"}
|
||||
className="h-12 !text-md"
|
||||
/>
|
||||
|
||||
@@ -1401,7 +1687,7 @@ const StepOne = ({
|
||||
|
||||
<Textarea
|
||||
id="hotel_service_desc_ru"
|
||||
placeholder={t("Xizmat tavsifi (ru)")}
|
||||
placeholder={t("Xizmat tavsifi") + " (ru)"}
|
||||
className="min-h-24 !text-md"
|
||||
/>
|
||||
|
||||
@@ -1487,7 +1773,7 @@ const StepOne = ({
|
||||
</Label>
|
||||
<FormControl>
|
||||
<Textarea
|
||||
placeholder={t("Mehmonxona taomlari haqida (ru)")}
|
||||
placeholder={t("Mehmonxona taomlari haqida") + " (ru)"}
|
||||
{...field}
|
||||
className="min-h-48 max-h-60"
|
||||
/>
|
||||
@@ -1563,7 +1849,7 @@ const StepOne = ({
|
||||
|
||||
<Input
|
||||
id="hotel_meals_title_ru"
|
||||
placeholder={t("Taom nomi (ru)")}
|
||||
placeholder={t("Taom nomi") + " (ru)"}
|
||||
className="h-12 !text-md"
|
||||
/>
|
||||
|
||||
@@ -1575,7 +1861,7 @@ const StepOne = ({
|
||||
|
||||
<Textarea
|
||||
id="hotel_meals_desc_ru"
|
||||
placeholder={t("Taom tavsifi (ru)")}
|
||||
placeholder={t("Taom tavsifi") + " (ru)"}
|
||||
className="min-h-24 !text-md"
|
||||
/>
|
||||
|
||||
@@ -1662,7 +1948,7 @@ const StepOne = ({
|
||||
{item.ticket_itinerary_destinations[0]?.name}
|
||||
</p>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{item.duration} kun
|
||||
{item.duration} {t("kun")}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@@ -1704,7 +1990,7 @@ const StepOne = ({
|
||||
|
||||
<Input
|
||||
id="ticket_itinerary_title_ru"
|
||||
placeholder={t("Sarlavha (RU)")}
|
||||
placeholder={t("Sarlavha") + " (ru)"}
|
||||
className="h-12 !text-md"
|
||||
/>
|
||||
|
||||
@@ -1724,7 +2010,7 @@ const StepOne = ({
|
||||
|
||||
<Input
|
||||
id="ticket_itinerary_destination_ru"
|
||||
placeholder={t("Manzil (RU)")}
|
||||
placeholder={t("Manzil") + " (ru)"}
|
||||
className="h-12 !text-md"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user