151 lines
6.2 KiB
TypeScript
151 lines
6.2 KiB
TypeScript
"use client";
|
||
|
||
import { useState } from "react";
|
||
import { Calendar } from "@/components/ui/calendar";
|
||
import { format } from "date-fns";
|
||
import { ru } from "date-fns/locale";
|
||
import { ChevronLeft, ChevronRight } from "lucide-react";
|
||
import Icon from "@/components/ui/icon";
|
||
|
||
interface YachtAvailabilityProps {
|
||
price: string;
|
||
}
|
||
|
||
export function YachtAvailability({ price }: YachtAvailabilityProps) {
|
||
const [currentMonth, setCurrentMonth] = useState(new Date(2025, 3, 1)); // Апрель 2025
|
||
|
||
// Генерируем доступные даты (27, 28, 29 апреля доступны)
|
||
const availableDates = [
|
||
new Date(2025, 3, 27),
|
||
new Date(2025, 3, 28),
|
||
new Date(2025, 3, 29),
|
||
];
|
||
|
||
const unavailableDates = Array.from({ length: 26 }, (_, i) => {
|
||
return new Date(2025, 3, i + 1);
|
||
});
|
||
|
||
const isDateAvailable = (date: Date) => {
|
||
return availableDates.some(
|
||
(d) =>
|
||
d.getDate() === date.getDate() &&
|
||
d.getMonth() === date.getMonth() &&
|
||
d.getFullYear() === date.getFullYear()
|
||
);
|
||
};
|
||
|
||
const isDateUnavailable = (date: Date) => {
|
||
return unavailableDates.some(
|
||
(d) =>
|
||
d.getDate() === date.getDate() &&
|
||
d.getMonth() === date.getMonth() &&
|
||
d.getFullYear() === date.getFullYear()
|
||
);
|
||
};
|
||
|
||
const handlePreviousMonth = () => {
|
||
setCurrentMonth(
|
||
new Date(currentMonth.getFullYear(), currentMonth.getMonth() - 1, 1)
|
||
);
|
||
};
|
||
|
||
const handleNextMonth = () => {
|
||
setCurrentMonth(
|
||
new Date(currentMonth.getFullYear(), currentMonth.getMonth() + 1, 1)
|
||
);
|
||
};
|
||
|
||
return (
|
||
<div className="space-y-4">
|
||
<div className="flex items-center justify-between">
|
||
<h2 className="text-xl font-bold text-[#333333]">
|
||
Доступность яхты
|
||
</h2>
|
||
<div className="flex items-center gap-2 text-sm text-[#999999]">
|
||
<Icon name="calendar" size={16} />
|
||
<span>По местному времени яхты</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="bg-white border border-gray-200 rounded-lg p-4">
|
||
<div className="flex items-center justify-between mb-4">
|
||
<button
|
||
onClick={handlePreviousMonth}
|
||
className="p-2 hover:bg-gray-100 rounded-md transition-colors"
|
||
>
|
||
<ChevronLeft className="w-5 h-5 text-gray-600" />
|
||
</button>
|
||
<h3 className="text-lg font-semibold text-[#333333] capitalize">
|
||
{format(currentMonth, "LLLL yyyy", { locale: ru })}
|
||
</h3>
|
||
<button
|
||
onClick={handleNextMonth}
|
||
className="p-2 hover:bg-gray-100 rounded-md transition-colors"
|
||
>
|
||
<ChevronRight className="w-5 h-5 text-gray-600" />
|
||
</button>
|
||
</div>
|
||
|
||
<Calendar
|
||
mode="single"
|
||
month={currentMonth}
|
||
onMonthChange={setCurrentMonth}
|
||
className="w-full"
|
||
locale={ru}
|
||
classNames={{
|
||
root: "w-full",
|
||
month: "flex w-full flex-col gap-4",
|
||
month_caption:
|
||
"flex h-8 w-full items-center justify-center px-8 text-gray-700 font-semibold",
|
||
table: "w-full border-collapse",
|
||
weekdays: "flex",
|
||
weekday:
|
||
"flex-1 text-gray-500 text-xs font-normal p-2 text-center",
|
||
week: "mt-2 flex w-full",
|
||
day: "relative",
|
||
}}
|
||
components={{
|
||
DayButton: ({ day, ...props }) => {
|
||
const isAvailable = isDateAvailable(day.date);
|
||
const isUnavailable = isDateUnavailable(day.date);
|
||
const isDay30 = day.date.getDate() === 30;
|
||
|
||
return (
|
||
<button
|
||
{...props}
|
||
className={`relative w-full h-16 flex flex-col items-center justify-center rounded-md transition-colors ${
|
||
isAvailable
|
||
? "bg-[#008299] text-white hover:bg-[#008299]"
|
||
: isUnavailable || isDay30
|
||
? "text-gray-400 cursor-not-allowed bg-gray-100"
|
||
: "hover:bg-gray-100"
|
||
}`}
|
||
disabled={isUnavailable || isDay30}
|
||
>
|
||
<span className="text-sm font-medium">
|
||
{day.date.getDate()}
|
||
</span>
|
||
{isAvailable && (
|
||
<>
|
||
<span className="text-[10px] mt-1 text-center leading-tight">
|
||
Доступно: 08:00-20:00
|
||
</span>
|
||
<span className="text-[10px] mt-0.5 text-center leading-tight">
|
||
{price} р/час
|
||
</span>
|
||
</>
|
||
)}
|
||
{(isUnavailable || isDay30) && (
|
||
<span className="text-lg mt-1">✕</span>
|
||
)}
|
||
</button>
|
||
);
|
||
},
|
||
}}
|
||
/>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|
||
|