travelmarine-frontend/src/app/components/YachtGrid.tsx

164 lines
6.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client";
import { Card, CardContent, CardHeader } from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import Image from "next/image";
import Icon from "@/components/ui/icon";
import Link from "next/link";
import FeaturedYacht from "./FeaturedYacht";
import useApiClient from "@/hooks/useApiClient";
import { useEffect, useState } from "react";
import {
formatMinCost,
formatSpeed,
formatWidth,
getImageUrl,
} from "@/lib/utils";
export default function YachtGrid() {
const client = useApiClient();
const [featuredYacht, setFeaturedYacht] =
useState<CatalogItemShortDto | null>(null);
const [yachtCatalog, setYachtCatalog] = useState<
CatalogItemShortDto[] | null
>(null);
useEffect(() => {
(async () => {
const response = await client.get<MainPageCatalogResponseDto>(
"/catalog/main-page/"
);
setFeaturedYacht(response.data.featuredYacht);
setYachtCatalog(response.data.restYachts);
})();
}, []);
return (
<section className="text-white">
<div className="container max-w-6xl mx-auto px-4 mt-6 md:mt-12">
{/* Header Section */}
<div className="mb-6">
<h1 className="text-3xl md:text-4xl font-bold mb-4 text-black">
Яхты и катера в аренду
</h1>
<h2 className="text-l text-black font-bold mb-2">
Онлайн бронирование яхт и катеров
</h2>
<p className="text-gray-700 max-w-3xl leading-relaxed">
Каталог лучших яхт Балаклавы разных ценовых сегментах.
</p>
<p className="text-gray-700 leading-relaxed">
Проверенные лодки с лицензией на перевозки, опытные капитаны.
Выбирайте удобную дату, время и бронируйте.
</p>
</div>
{/* Featured Yacht Block */}
{featuredYacht && <FeaturedYacht yacht={featuredYacht} />}
{/* Yacht Grid */}
{yachtCatalog && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-6">
{yachtCatalog.map((yacht) => (
<Link
key={yacht.id}
href={`/catalog/${yacht.id ?? 0}`}
className="block"
>
<Card className="overflow-hidden bg-white text-gray-900 cursor-pointer transition-all duration-200 hover:shadow-lg">
<CardHeader className="p-0 relative">
<div className="relative">
{/* Best Offer Badge - над карточкой */}
{yacht.topText && (
<div className="w-full flex justify-center">
<div
className="flex w-full items-center justify-center text-white px-4 py-2 text-sm font-medium bg-cover bg-center bg-no-repeat"
style={{
backgroundImage:
"url('/images/best-yacht-bg.jpg')",
}}
>
<span>{yacht.topText}</span>
</div>
</div>
)}
<Image
src={getImageUrl(yacht.mainImageUrl)}
alt={yacht.name}
width={400}
height={250}
className="w-full h-48 object-cover"
/>
{/* Badge Overlay */}
{!yacht.hasQuickRent && !yacht.topText && (
<>
<div className="absolute top-3 left-3">
<div className="flex items-center justify-center bg-black/40 text-white px-3 py-1 rounded-lg text-sm flex items-center gap-1">
<Icon size={16} name="restart" />
<span>По запросу</span>
</div>
</div>
</>
)}
</div>
</CardHeader>
<CardContent className="p-4">
<div className="flex justify-between gap-4">
{/* Левая колонка - название и длина */}
<div className="space-y-2">
<h3 className="font-bold text-l">{yacht.name}</h3>
<div className="flex items-center gap-1 text-sm">
<Icon size={16} name="width" />
<span>{formatWidth(yacht.length)}</span>
</div>
</div>
{/* Правая колонка - цена и футы */}
<div className="flex flex-col justify-between">
<div className="w-fit">
{yacht.isBestOffer ? (
<p
style={{
background:
"linear-gradient(90deg, #008299 0%, #7E8FFF 100%)",
}}
className="text-l font-bold text-white pl-2 pr-3 rounded-t-[5px] rounded-bl-[10px] rounded-br-[30px] whitespace-nowrap"
>
{formatMinCost(yacht.minCost)} / час
</p>
) : (
<p className="w-fit text-l whitespace-nowrap">
{formatMinCost(yacht.minCost)} / час
</p>
)}
</div>
<div className="flex items-center gap-1 text-sm">
<Icon size={16} name="anchor" />
<span>{formatSpeed(yacht.speed)}</span>
</div>
</div>
</div>
</CardContent>
</Card>
</Link>
))}
</div>
)}
{/* Call to Action Button */}
<div className="text-center">
<Link href="/catalog">
<Button
size="lg"
className="bg-white text-gray-900 hover:bg-gray-100 px-8 py-3 h-[56px] w-[336px] text-lg font-bold"
>
Каталог яхт
</Button>
</Link>
</div>
</div>
</section>
);
}