diff --git a/src/api/types.ts b/src/api/types.ts index 3432193..72ace3e 100644 --- a/src/api/types.ts +++ b/src/api/types.ts @@ -15,4 +15,9 @@ interface CatalogItemDto { interface MainPageCatalogResponseDto { featuredYacht: CatalogItemDto; restYachts: CatalogItemDto[]; - } \ No newline at end of file +} + +interface CatalogFilteredResponseDto { + items: CatalogItemDto[]; + total: number; +} \ No newline at end of file diff --git a/src/app/catalog/components/CatalogSidebar.tsx b/src/app/catalog/components/CatalogSidebar.tsx index 1d29f87..c52e293 100644 --- a/src/app/catalog/components/CatalogSidebar.tsx +++ b/src/app/catalog/components/CatalogSidebar.tsx @@ -1,7 +1,5 @@ "use client"; -import { useState, useEffect } from "react"; -import { useSearchParams, useRouter, usePathname } from "next/navigation"; import { Slider } from "@/components/ui/slider"; import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; @@ -10,191 +8,37 @@ import { Button } from "@/components/ui/button"; import { DatePicker } from "@/components/ui/date-picker"; import { GuestPicker } from "@/components/form/guest-picker"; import Icon from "@/components/ui/icon"; +import { CatalogFilters, defaultFilters } from "@/app/catalog/page"; interface CatalogSidebarProps { + filters: CatalogFilters; + setFilters: (filters: CatalogFilters | ((prev: CatalogFilters) => CatalogFilters)) => void; onApply?: () => void; + onReset?: () => void; } -export default function CatalogSidebar({ onApply }: CatalogSidebarProps) { - const searchParams = useSearchParams(); - const router = useRouter(); - const pathname = usePathname(); - - const [lengthRange, setLengthRange] = useState([7, 50]); - const [priceRange, setPriceRange] = useState([3000, 200000]); - const [yearRange, setYearRange] = useState([1991, 2025]); - const [adults, setAdults] = useState(0); - const [children, setChildren] = useState(0); - const [paymentType, setPaymentType] = useState("all"); - const [quickBooking, setQuickBooking] = useState(false); - const [hasToilet, setHasToilet] = useState(false); - const [vesselType, setVesselType] = useState(""); - const [date, setDate] = useState(null); - const [departureTime, setDepartureTime] = useState("12:00"); - const [arrivalTime, setArrivalTime] = useState("13:00"); - - // Загрузка фильтров из searchParams при монтировании и изменении URL - useEffect(() => { - const lengthMin = searchParams.get("lengthMin"); - const lengthMax = searchParams.get("lengthMax"); - if (lengthMin && lengthMax) { - setLengthRange([parseInt(lengthMin), parseInt(lengthMax)]); - } else { - setLengthRange([7, 50]); - } - - const priceMin = searchParams.get("priceMin"); - const priceMax = searchParams.get("priceMax"); - if (priceMin && priceMax) { - setPriceRange([parseInt(priceMin), parseInt(priceMax)]); - } else { - setPriceRange([3000, 200000]); - } - - const yearMin = searchParams.get("yearMin"); - const yearMax = searchParams.get("yearMax"); - if (yearMin && yearMax) { - setYearRange([parseInt(yearMin), parseInt(yearMax)]); - } else { - setYearRange([1991, 2025]); - } - - const adultsParam = searchParams.get("adults"); - setAdults(adultsParam ? parseInt(adultsParam) : 0); - - const childrenParam = searchParams.get("children"); - setChildren(childrenParam ? parseInt(childrenParam) : 0); - - const paymentTypeParam = searchParams.get("paymentType"); - setPaymentType(paymentTypeParam || "all"); - - const quickBookingParam = searchParams.get("quickBooking"); - setQuickBooking(quickBookingParam === "true"); - - const hasToiletParam = searchParams.get("hasToilet"); - setHasToilet(hasToiletParam === "true"); - - const vesselTypeParam = searchParams.get("vesselType"); - setVesselType(vesselTypeParam || ""); - - const dateParam = searchParams.get("date"); - if (dateParam) { - const parsedDate = new Date(dateParam); - if (!isNaN(parsedDate.getTime())) { - setDate(parsedDate); - } else { - setDate(null); - } - } else { - setDate(null); - } - - const departureTimeParam = searchParams.get("departureTime"); - setDepartureTime(departureTimeParam || "12:00"); - - const arrivalTimeParam = searchParams.get("arrivalTime"); - setArrivalTime(arrivalTimeParam || "13:00"); - }, [searchParams]); - - // Функция для сохранения фильтров в searchParams - const handleApplyFilters = () => { - const params = new URLSearchParams(); - - // Сохраняем только нестандартные значения - if (lengthRange[0] !== 7 || lengthRange[1] !== 50) { - params.set("lengthMin", lengthRange[0].toString()); - params.set("lengthMax", lengthRange[1].toString()); - } - - if (priceRange[0] !== 3000 || priceRange[1] !== 200000) { - params.set("priceMin", priceRange[0].toString()); - params.set("priceMax", priceRange[1].toString()); - } - - if (yearRange[0] !== 1991 || yearRange[1] !== 2025) { - params.set("yearMin", yearRange[0].toString()); - params.set("yearMax", yearRange[1].toString()); - } - - if (adults > 0) { - params.set("adults", adults.toString()); - } - - if (children > 0) { - params.set("children", children.toString()); - } - - if (paymentType !== "all") { - params.set("paymentType", paymentType); - } - - if (quickBooking) { - params.set("quickBooking", "true"); - } - - if (hasToilet) { - params.set("hasToilet", "true"); - } - - if (vesselType) { - params.set("vesselType", vesselType); - } - - if (date) { - params.set("date", date.toISOString()); - } - - if (departureTime !== "12:00") { - params.set("departureTime", departureTime); - } - - if (arrivalTime !== "13:00") { - params.set("arrivalTime", arrivalTime); - } - - // Обновляем URL без прокрутки страницы - const newUrl = params.toString() - ? `${pathname}?${params.toString()}` - : pathname; - router.replace(newUrl, { scroll: false }); - - // Вызываем callback, если он есть - onApply?.(); - }; - +export default function CatalogSidebar({ + filters, + setFilters, + onApply, + onReset, +}: CatalogSidebarProps) { const formatPrice = (value: number) => { return new Intl.NumberFormat("ru-RU").format(value) + " Р"; }; - const handleReset = () => { - setLengthRange([7, 50]); - setPriceRange([3000, 200000]); - setYearRange([1991, 2025]); - setAdults(0); - setChildren(0); - setPaymentType("all"); - setQuickBooking(false); - setHasToilet(false); - setVesselType(""); - setDate(null); - setDepartureTime("12:00"); - setArrivalTime("13:00"); - // Очищаем URL параметры без прокрутки страницы - router.replace(pathname, { scroll: false }); - }; - const activeFiltersCount = [ - lengthRange[0] !== 7 || lengthRange[1] !== 50, - priceRange[0] !== 3000 || priceRange[1] !== 200000, - yearRange[0] !== 1991 || yearRange[1] !== 2025, - adults !== 0 || children !== 0, - paymentType !== "all", - quickBooking, - hasToilet, - vesselType !== "", - date !== null, - departureTime !== "12:00", - arrivalTime !== "13:00", + filters.lengthRange[0] !== defaultFilters.lengthRange[0] || filters.lengthRange[1] !== defaultFilters.lengthRange[1], + filters.priceRange[0] !== defaultFilters.priceRange[0] || filters.priceRange[1] !== defaultFilters.priceRange[1], + filters.yearRange[0] !== defaultFilters.yearRange[0] || filters.yearRange[1] !== defaultFilters.yearRange[1], + filters.adults !== 0 || filters.children !== 0, + filters.paymentType !== defaultFilters.paymentType, + filters.quickBooking, + filters.hasToilet, + filters.search !== "", + filters.date !== null, + filters.departureTime !== defaultFilters.departureTime, + filters.arrivalTime !== defaultFilters.arrivalTime, ].filter(Boolean).length; return ( @@ -202,7 +46,7 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) {

Искать

@@ -234,8 +78,8 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) {
setFilters({ ...filters, lengthRange: value as [number, number] })} min={7} max={50} step={1} @@ -244,10 +88,10 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) {
- {lengthRange[0]} m + {filters.lengthRange[0]} m
- {lengthRange[1]} m + {filters.lengthRange[1]} m
@@ -259,12 +103,12 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) { setDate(newDate || null)} - onDepartureTimeChange={setDepartureTime} - onArrivalTimeChange={setArrivalTime} + value={filters.date} + departureTime={filters.departureTime} + arrivalTime={filters.arrivalTime} + onDateChange={(newDate) => setFilters({ ...filters, date: newDate || null })} + onDepartureTimeChange={(time) => setFilters({ ...filters, departureTime: time })} + onArrivalTimeChange={(time) => setFilters({ ...filters, arrivalTime: time })} />
@@ -272,11 +116,10 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) {
{ - setAdults(adults); - setChildren(children); + setFilters({ ...filters, adults, children }); }} />
@@ -286,9 +129,9 @@ export default function CatalogSidebar({ onApply }: CatalogSidebarProps) { - setQuickBooking(checked === true) + setFilters({ ...filters, quickBooking: checked === true }) } />