Доработки по главной странице, итерация 7
This commit is contained in:
parent
9083c29a26
commit
7b282e4435
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.5 0C4.7025 0 0 4.7025 0 10.5C0 16.2975 4.7025 21 10.5 21C16.2975 21 21 16.2975 21 10.5C21 4.7025 16.2975 0 10.5 0Z" fill="#0072A8"/>
|
||||
<path d="M14.9408 10.8861C17.5638 10.1129 16.4426 7.5531 14.4975 5.99692C11.2871 3.42913 6.34431 4.29467 4.15568 7.60179C2.55446 10.0205 3.91316 14.0958 7.93359 15.8C11.1489 17.1644 15.0183 16.6755 17.518 13.0723C14.7609 12.8199 11.7443 12.0994 10.479 10.8592C9.31615 9.71843 10.1342 8.08276 11.2275 8.11555" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M15.6835 14.8467C8.77668 15.0415 6.60893 11.3965 6.53935 9.88602C6.43797 7.6879 9.78154 5.44506 14.8784 10.8181" stroke="white" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 808 B |
|
|
@ -3,13 +3,6 @@
|
|||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { DatePicker } from "@/components/ui/date-picker";
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
|
|
@ -20,6 +13,7 @@ import {
|
|||
import Image from "next/image";
|
||||
import Icon from "@/components/ui/icon";
|
||||
import { useState } from "react";
|
||||
import { GuestPicker } from "@/components/form/guest-picker";
|
||||
|
||||
const yacht = {
|
||||
name: "Яхта",
|
||||
|
|
@ -58,6 +52,22 @@ export default function FeaturedYacht() {
|
|||
<div className="flex flex-col lg:flex-row gap-11 px-6 py-10">
|
||||
{/* Left side - Yacht details and images */}
|
||||
<div className="flex-1">
|
||||
{/* Promoted banner - Mobile only */}
|
||||
<div
|
||||
className="text-white flex items-center justify-center py-2 rounded-full text-center mb-6 relative lg:hidden"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(/images/badge-bg.jpg)",
|
||||
backgroundSize: "cover",
|
||||
backgroundPosition: "center",
|
||||
backgroundRepeat: "no-repeat",
|
||||
}}
|
||||
>
|
||||
<span className="text-xs font-medium relative z-10">
|
||||
Заметнее других — бронируют быстрее
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Header with yacht name and length */}
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h2 className="text-3xl font-bold">
|
||||
|
|
@ -101,18 +111,21 @@ export default function FeaturedYacht() {
|
|||
<div className="relative">
|
||||
<Image
|
||||
src={thumb}
|
||||
alt={`${yacht.name} view ${
|
||||
idx + 1
|
||||
}`}
|
||||
alt={`${
|
||||
yacht.name
|
||||
} view ${idx + 1}`}
|
||||
width={80}
|
||||
height={60}
|
||||
className={`w-20 h-16 object-cover rounded-[8px] cursor-pointer border-2 transition-all ${
|
||||
selectedImage === thumb
|
||||
selectedImage ===
|
||||
thumb
|
||||
? "border-[#008299]"
|
||||
: "border-gray-200 hover:border-gray-400"
|
||||
}`}
|
||||
onClick={() =>
|
||||
handleThumbnailClick(thumb)
|
||||
handleThumbnailClick(
|
||||
thumb
|
||||
)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -126,7 +139,8 @@ export default function FeaturedYacht() {
|
|||
|
||||
{/* Promoted badge */}
|
||||
{yacht.isPromoted && (
|
||||
<div className="flex items-center gap-2 text-sm text-gray-600">
|
||||
<div className="flex items-center gap-2 text-sm text-gray-400">
|
||||
<Icon size={21} name="ad" />
|
||||
<span>
|
||||
Это объявление продвигается.{" "}
|
||||
<span className="underline cursor-pointer">
|
||||
|
|
@ -140,9 +154,9 @@ export default function FeaturedYacht() {
|
|||
{/* Right side - Booking form */}
|
||||
<div className="min-w-[296px] flex flex-col justify-between">
|
||||
<div>
|
||||
{/* Promoted banner */}
|
||||
{/* Promoted banner - Desktop only */}
|
||||
<div
|
||||
className="text-white flex items-center justify-center py-2 rounded-full text-center mb-6 relative"
|
||||
className="text-white flex items-center justify-center py-2 rounded-full text-center mb-6 relative hidden lg:flex"
|
||||
style={{
|
||||
backgroundImage:
|
||||
"url(/images/badge-bg.jpg)",
|
||||
|
|
@ -170,34 +184,13 @@ export default function FeaturedYacht() {
|
|||
{/* Booking form */}
|
||||
<div className="space-y-5 mb-8">
|
||||
<div>
|
||||
<DatePicker />
|
||||
<DatePicker showIcon={false} />
|
||||
</div>
|
||||
<div>
|
||||
<DatePicker />
|
||||
<DatePicker showIcon={false} />
|
||||
</div>
|
||||
<div>
|
||||
<Select>
|
||||
<SelectTrigger className="w-full h-[64px]">
|
||||
<SelectValue placeholder="1 гость" />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="1">
|
||||
1 гость
|
||||
</SelectItem>
|
||||
<SelectItem value="2">
|
||||
2 гостя
|
||||
</SelectItem>
|
||||
<SelectItem value="3">
|
||||
3 гостя
|
||||
</SelectItem>
|
||||
<SelectItem value="4">
|
||||
4 гостя
|
||||
</SelectItem>
|
||||
<SelectItem value="5+">
|
||||
5+ гостей
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
<GuestPicker showIcon={false} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ const yachts = [
|
|||
feet: "7 Футов",
|
||||
img: "/images/yachts/yacht1.jpg",
|
||||
bestOfferText: "🔥 Лучшее предложение",
|
||||
colorPrice: true,
|
||||
},
|
||||
{
|
||||
name: "Яхта",
|
||||
|
|
@ -92,7 +93,8 @@ export default function YachtGrid() {
|
|||
<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')",
|
||||
backgroundImage:
|
||||
"url('/images/best-yacht-bg.jpg')",
|
||||
}}
|
||||
>
|
||||
<span>
|
||||
|
|
@ -127,24 +129,41 @@ export default function YachtGrid() {
|
|||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="p-4">
|
||||
<div className="flex justify-between items-start mb-1">
|
||||
<h3 className="font-bold text-l">
|
||||
{yacht.name}
|
||||
</h3>
|
||||
<div className="text-right">
|
||||
<p className="text-l">
|
||||
{yacht.price}
|
||||
</p>
|
||||
<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>{yacht.length}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between text-gray-600">
|
||||
<div className="flex items-center gap-1">
|
||||
<Icon size={16} name="width" />
|
||||
<span>{yacht.length}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<Icon size={16} name="anchor" />
|
||||
<span>{yacht.feet}</span>
|
||||
|
||||
{/* Правая колонка - цена и футы */}
|
||||
<div className="space-y-2">
|
||||
<div className="w-fit">
|
||||
{yacht.colorPrice ? (
|
||||
<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]"
|
||||
>
|
||||
{yacht.price}
|
||||
</p>
|
||||
) : (
|
||||
<p className="w-fit text-l">
|
||||
{yacht.price}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 text-sm">
|
||||
<Icon size={16} name="anchor" />
|
||||
<span>{yacht.feet}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
|
|
|||
|
|
@ -14,9 +14,10 @@ import { ChevronUp, ChevronDown } from "lucide-react";
|
|||
interface GuestPickerProps {
|
||||
onApply?: (adults: number, children: number) => void;
|
||||
className?: string;
|
||||
showIcon?: boolean;
|
||||
}
|
||||
|
||||
export const GuestPicker: React.FC<GuestPickerProps> = ({ onApply }) => {
|
||||
export const GuestPicker: React.FC<GuestPickerProps> = ({ onApply, showIcon = true }) => {
|
||||
const [adults, setAdults] = useState<number>(0);
|
||||
const [children, setChildren] = useState<number>(0);
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
|
|
@ -48,11 +49,13 @@ export const GuestPicker: React.FC<GuestPickerProps> = ({ onApply }) => {
|
|||
className="h-[64px] px-4 w-full justify-between"
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<Icon
|
||||
name="people"
|
||||
className="mr-3"
|
||||
/>
|
||||
<span>{getDisplayText()}</span>
|
||||
{showIcon && (
|
||||
<Icon
|
||||
name="people"
|
||||
className="mr-3"
|
||||
/>
|
||||
)}
|
||||
<span className="font-normal">{getDisplayText()}</span>
|
||||
</div>
|
||||
{isOpen ? (
|
||||
<ChevronUp className="h-4 w-4" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import * as React from "react";
|
||||
import { format } from "date-fns";
|
||||
import { ru } from "date-fns/locale";
|
||||
import { ChevronDownIcon } from "lucide-react";
|
||||
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Calendar } from "@/components/ui/calendar";
|
||||
|
|
@ -14,7 +14,11 @@ import {
|
|||
} from "@/components/ui/popover";
|
||||
import Icon from "./icon";
|
||||
|
||||
export function DatePicker() {
|
||||
interface DatePickerProps {
|
||||
showIcon?: boolean;
|
||||
}
|
||||
|
||||
export function DatePicker({ showIcon = true }: DatePickerProps) {
|
||||
const [date, setDate] = React.useState<Date>();
|
||||
const [departureTime, setDepartureTime] = React.useState("12:00");
|
||||
const [arrivalTime, setArrivalTime] = React.useState("13:00");
|
||||
|
|
@ -31,13 +35,29 @@ export function DatePicker() {
|
|||
<Button
|
||||
variant="outline"
|
||||
data-empty={!date}
|
||||
className="w-full h-[64px] justify-start text-left font-normal"
|
||||
className="w-full h-[64px] justify-between text-left font-normal"
|
||||
>
|
||||
<Icon name="calendar" className="w-4 h-4 text-brand mr-2" />
|
||||
{date ? (
|
||||
format(date, `d MMMM, ${departureTime} - ${arrivalTime}`, { locale: ru })
|
||||
<div className="flex items-center">
|
||||
{showIcon && (
|
||||
<Icon
|
||||
name="calendar"
|
||||
className="w-4 h-4 text-brand mr-2"
|
||||
/>
|
||||
)}
|
||||
{date ? (
|
||||
format(
|
||||
date,
|
||||
`d MMMM, ${departureTime} - ${arrivalTime}`,
|
||||
{ locale: ru }
|
||||
)
|
||||
) : (
|
||||
<span>Выберите дату и время</span>
|
||||
)}
|
||||
</div>
|
||||
{open ? (
|
||||
<ChevronUpIcon className="w-4 h-4" />
|
||||
) : (
|
||||
<span>Выберите дату и время</span>
|
||||
<ChevronDownIcon className="w-4 h-4" />
|
||||
)}
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
|
@ -79,37 +99,32 @@ export function DatePicker() {
|
|||
|
||||
{/* Поля времени */}
|
||||
<div className="flex gap-3 mb-4">
|
||||
<div className="flex-1">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="time"
|
||||
value={departureTime}
|
||||
onChange={(e) =>
|
||||
setDepartureTime(e.target.value)
|
||||
}
|
||||
className="w-full h-12 px-3 border border-gray-300 rounded-full text-gray-700 font-medium text-center focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent"
|
||||
/>
|
||||
<label className="absolute left-[24px] top-0 transform -translate-y-1/2 text-xs text-gray-500 pointer-events-none transition-all duration-200 bg-white px-1">
|
||||
Выход
|
||||
</label>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none" />
|
||||
</div>
|
||||
<div className="relative w-full">
|
||||
<label className="absolute left-[24px] top-0 transform -translate-y-1/2 text-xs text-gray-500 pointer-events-none transition-all duration-200 bg-white px-1">
|
||||
Выход
|
||||
</label>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none" />
|
||||
<input
|
||||
type="time"
|
||||
value={departureTime}
|
||||
onChange={(e) =>
|
||||
setDepartureTime(e.target.value)
|
||||
}
|
||||
className="w-full h-12 px-3 border border-gray-300 rounded-full text-gray-700 font-medium text-center focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex-1">
|
||||
<div className="relative">
|
||||
<input
|
||||
type="time"
|
||||
value={arrivalTime}
|
||||
onChange={(e) =>
|
||||
setArrivalTime(e.target.value)
|
||||
}
|
||||
className="w-full h-12 px-3 border border-gray-300 rounded-full text-gray-700 font-medium text-center focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent"
|
||||
/>
|
||||
<label className="absolute left-[24px] top-0 transform -translate-y-1/2 text-xs text-gray-500 pointer-events-none transition-all duration-200 bg-white px-1">
|
||||
Заход
|
||||
</label>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none" />
|
||||
</div>
|
||||
|
||||
<div className="relative w-full">
|
||||
<label className="absolute left-[24px] top-0 transform -translate-y-1/2 text-xs text-gray-500 pointer-events-none transition-all duration-200 bg-white px-1">
|
||||
Заход
|
||||
</label>
|
||||
<ChevronDownIcon className="absolute right-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-gray-500 pointer-events-none" />
|
||||
<input
|
||||
type="time"
|
||||
value={arrivalTime}
|
||||
onChange={(e) => setArrivalTime(e.target.value)}
|
||||
className="w-full h-12 px-3 border border-gray-300 rounded-full text-gray-700 font-medium text-center focus:outline-none focus:ring-2 focus:ring-[#008299] focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import StarIcon from "../../../public/images/icons/star.svg";
|
|||
import VkIcon from "../../../public/images/icons/vk.svg";
|
||||
import DzenIcon from "../../../public/images/icons/dzen.svg";
|
||||
import TgIcon from "../../../public/images/icons/tg.svg";
|
||||
import AdIcon from "../../../public/images/icons/ad.svg";
|
||||
|
||||
// Объект с иконками для удобного доступа
|
||||
const icons = {
|
||||
|
|
@ -31,6 +32,7 @@ const icons = {
|
|||
vk: VkIcon,
|
||||
dzen: DzenIcon,
|
||||
tg: TgIcon,
|
||||
ad: AdIcon,
|
||||
};
|
||||
|
||||
export type IconName =
|
||||
|
|
@ -46,7 +48,8 @@ export type IconName =
|
|||
| "star"
|
||||
| "vk"
|
||||
| "dzen"
|
||||
| "tg";
|
||||
| "tg"
|
||||
| "ad";
|
||||
|
||||
export interface IconProps
|
||||
extends Omit<SVGProps<SVGSVGElement>, "name" | "preserveAspectRatio"> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue