"use client"; import { Button } from "@/components/ui/button"; import Image from "next/image"; import Link from "next/link"; import { useMutation } from "@tanstack/react-query"; import { User, ArrowUpRight, Map, ArrowLeft, Heart } from "lucide-react"; import { useEffect, useState, Suspense } from "react"; import { useRouter, useSearchParams } from "next/navigation"; import useApiClient from "@/hooks/useApiClient"; import { getImageUrl, formatPrice, calculateTotalPrice } from "@/lib/utils"; import { parseISO } from "date-fns"; import { CatalogItemLongDto } from "@/api/types"; function ConfirmPageContent() { const [yacht, setYacht] = useState(null); const client = useApiClient(); const [promocode, setPromocode] = useState(""); const [isPromocodeApplied, setIsPromocodeApplied] = useState(false); const router = useRouter(); const searchParams = useSearchParams(); // Извлекаем параметры из URL const yachtId = searchParams.get("yachtId"); const guestCount = searchParams.get("guests"); const departureDate = searchParams.get("departureDate"); const departureTime = searchParams.get("departureTime"); const arrivalDate = searchParams.get("arrivalDate"); const arrivalTime = searchParams.get("arrivalTime"); useEffect(() => { (async () => { const response = await client.get( `/catalog/${yachtId}/` ); setYacht(response.data); })(); }, [yachtId]); // Расчет стоимости через функцию const { totalHours, totalPrice } = calculateTotalPrice( departureDate, departureTime, arrivalDate, arrivalTime, yacht?.minCost || 0 ); // Обработчик применения промокода const handlePromocodeApply = () => { if (promocode.trim().toUpperCase() === "DISCOUNT50") { setIsPromocodeApplied(true); } else { setIsPromocodeApplied(false); } }; // Финальная цена с учетом скидки const finalPrice = isPromocodeApplied ? totalPrice * 0.5 : totalPrice; // Функция для форматирования даты (краткий формат) const formatDate = (dateString: string | null) => { if (!dateString) return null; try { const date = parseISO(dateString); const months = [ "янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек", ]; const day = date.getDate(); const month = months[date.getMonth()]; return `${day} ${month}`; } catch { return null; } }; // Функция для форматирования даты (полный формат для десктопа) const formatDateFull = (dateString: string | null) => { if (!dateString) return null; try { const date = parseISO(dateString); const months = [ "января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря", ]; const day = date.getDate(); const month = months[date.getMonth()]; return `${day} ${month}`; } catch { return null; } }; // Функция для форматирования времени const formatTime = (timeString: string | null) => { if (!timeString) return null; // Декодируем URL-encoded строку (например, 00%3A00 -> 00:00) const decoded = decodeURIComponent(timeString); return decoded.split(":").slice(0, 2).join(":"); }; // Форматируем данные для отображения const departureDateFormatted = formatDate(departureDate); const departureTimeFormatted = formatTime(departureTime); const arrivalDateFormatted = formatDate(arrivalDate); const arrivalTimeFormatted = formatTime(arrivalTime); // Полный формат для десктопной версии const departureDateFormattedFull = formatDateFull(departureDate); const arrivalDateFormattedFull = formatDateFull(arrivalDate); // Формируем строки для отображения const departureDisplay = departureDateFormatted && departureTimeFormatted ? `${departureDateFormatted} ${departureTimeFormatted}` : "Не выбрано"; const arrivalDisplay = arrivalDateFormatted && arrivalTimeFormatted ? `${arrivalDateFormatted} ${arrivalTimeFormatted}` : "Не выбрано"; const datesDisplay = departureDateFormattedFull && departureTimeFormatted && arrivalDateFormattedFull && arrivalTimeFormatted ? `${departureDateFormattedFull} в ${departureTimeFormatted} — ${arrivalDateFormattedFull} в ${arrivalTimeFormatted}` : "Не выбрано"; const guestsDisplay = guestCount ? guestCount === "1" ? "1 гость" : `${guestCount} гостей` : "Не выбрано"; const { mutate } = useMutation({ mutationKey: ["create-reservation", yachtId], mutationFn: async () => { if ( !departureDate || !departureTime || !yachtId || !arrivalDate || !arrivalTime ) { throw new Error("Ошибка получения данных бронирования"); } const departureDateTime = new Date( `${departureDate}T${departureTime}` ); const arrivalDateTime = new Date(`${arrivalDate}T${arrivalTime}`); const startUtc = Math.floor(departureDateTime.getTime() / 1000); const endUtc = Math.floor(arrivalDateTime.getTime() / 1000); const body = { startUtc, endUtc, yachtId: Number(yachtId), reservatorId: Number("userId"), // TODO }; await client.post("/reservations", body); router.push("/profile/reservations"); }, }); if (!yacht) { return
; } return (
{/* Мобильная версия */}
{/* Верхний блок с навигацией */}
{/* Кнопка назад */} {/* Центральный блок с информацией */}

Яхта {yacht.name}

{departureDateFormatted || "Не выбрано"} Гостей: {guestCount || "Не выбрано"}
{/* Кнопка избранного */}
{/* Заголовок с иконкой */}

Ваше бронирование 🛥️

{/* Поля Выход и Заход */}
{departureDisplay}
{arrivalDisplay}
{/* По местному времени яхты */}
По местному времени яхты
{/* Гости */}
{guestsDisplay}
{/* Правила отмены */}

Правила отмены

При отмене до 10 мая вы получите частичный возврат.{" "} Подробнее

{/* Детализация цены */}

Детализация цены

{totalHours > 0 && yacht.minCost ? ( <>
{formatPrice(yacht.minCost)}₽ ×{" "} {totalHours}ч {formatPrice(totalPrice)} ₽
Услуги 0 Р
{isPromocodeApplied && (
Скидка (DISCOUNT50): - {formatPrice( totalPrice * 0.5 )}{" "} Р
)}
Итого: {formatPrice(finalPrice)} Р
) : (
Укажите даты для расчета стоимости
)}
{/* Промокод */}
{ setPromocode(e.target.value); setIsPromocodeApplied(false); }} onKeyDown={(e) => { if (e.key === "Enter") { handlePromocodeApply(); } }} className="flex-1 min-w-0 px-4 py-3 h-[64px] border border-[#DFDFDF] rounded-full text-sm text-[#757575] focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent" />
{/* Кнопка отправки заявки */}
{/* Десктопная версия */}
{/* Breadcrumbs - скрыты на мобильных */}
Аренда яхты > Ваше бронирование
{/* Левая колонка - Информация о яхте и ценах - скрыта на мобильных */}
{/* Изображение яхты */}
Яхта {/* Плашка владельца */}
Владелец {yacht.owner.firstName}
{/* Название яхты */}

Яхта {yacht.name}

{/* Детализация цены */}

Детализация цены

{totalHours > 0 && yacht.minCost ? ( <>
{formatPrice( yacht.minCost )} ₽ × {totalHours}ч {formatPrice( totalPrice )}{" "} ₽
Услуги 0 Р
{isPromocodeApplied && (
Скидка (DISCOUNT50): - {formatPrice( totalPrice * 0.5 )}{" "} Р
)}
Итого: {formatPrice( finalPrice )}{" "} Р
) : (
Укажите даты для расчета стоимости
)}
{/* Промокод */}
{ setPromocode(e.target.value); setIsPromocodeApplied(false); }} onKeyDown={(e) => { if (e.key === "Enter") { handlePromocodeApply(); } }} className="flex-1 min-w-0 px-4 sm:px-8 py-5 h-[64px] border border-[#DFDFDF] rounded-full text-base text-[#757575] focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent" />
{/* Правая колонка - Подтверждение бронирования */}
{/* Заголовок */}

Проверьте данные

Ваше бронирование

{/* Сведения о бронирования */}
{/* Даты */}
Даты
{datesDisplay}
{/* Гости */}
Гости
{guestsDisplay}
{/* Дополнительные услуги */}
Нет дополнительных услуг
{/* Правила отмены */}

Правила отмены

При отмене до 10 мая вы получите частичный возврат.

Подробнее {/* Указание времени и кнопка отправки */}
По местному времени яхты
); } export default function ConfirmPage() { return ( Загрузка...
} > ); }