Фильтры в каталоге, интеграция
This commit is contained in:
parent
7f6c6d1107
commit
b45f9885ab
|
|
@ -203,6 +203,12 @@ export default function CatalogPage() {
|
||||||
params.set("arrivalTime", filters.arrivalTime);
|
params.set("arrivalTime", filters.arrivalTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сохраняем сортировку, если она установлена
|
||||||
|
const sortByPrice = searchParams.get("sortByPrice");
|
||||||
|
if (sortByPrice) {
|
||||||
|
params.set("sortByPrice", sortByPrice);
|
||||||
|
}
|
||||||
|
|
||||||
// Обновляем URL без прокрутки страницы
|
// Обновляем URL без прокрутки страницы
|
||||||
const newUrl = params.toString()
|
const newUrl = params.toString()
|
||||||
? `${pathname}?${params.toString()}`
|
? `${pathname}?${params.toString()}`
|
||||||
|
|
@ -219,11 +225,29 @@ export default function CatalogPage() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
(async () => {
|
(async () => {
|
||||||
const params: Record<string, string> = {
|
const allParams: Record<string, string> = {
|
||||||
search: searchParams.get("search") ?? "",
|
search: searchParams.get("search") ?? "",
|
||||||
|
minLength: searchParams.get("lengthMin") ?? "",
|
||||||
|
maxLength: searchParams.get("lengthMax") ?? "",
|
||||||
|
minPrice: searchParams.get("priceMin") ?? "",
|
||||||
|
maxPrice: searchParams.get("priceMax") ?? "",
|
||||||
|
minYear: searchParams.get("yearMin") ?? "",
|
||||||
|
maxYear: searchParams.get("yearMax") ?? "",
|
||||||
|
guests: searchParams.get("adults") && searchParams.get("children") ? `${Number(searchParams.get("adults")) + Number(searchParams.get("children"))}` : "",
|
||||||
|
paymentType: searchParams.get("paymentType") ?? "",
|
||||||
|
quickBooking: searchParams.get("quickBooking") ?? "",
|
||||||
|
hasToilet: searchParams.get("hasToilet") ?? "",
|
||||||
|
date: searchParams.get("date") ?? "",
|
||||||
|
departureTime: searchParams.get("departureTime") ?? "",
|
||||||
|
arrivalTime: searchParams.get("arrivalTime") ?? "",
|
||||||
|
sortByPrice: searchParams.get("sortByPrice") ?? "",
|
||||||
};
|
};
|
||||||
|
|
||||||
const response = await client.get<CatalogFilteredResponseDto>("/catalog/filtered/", {
|
const params = Object.fromEntries(
|
||||||
|
Object.entries(allParams).filter(([_, value]) => value !== "")
|
||||||
|
);
|
||||||
|
|
||||||
|
const response = await client.get<CatalogFilteredResponseDto>("/catalog/filter/", {
|
||||||
params,
|
params,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -346,7 +370,21 @@ export default function CatalogPage() {
|
||||||
<div className="text-base text-[#999999]">
|
<div className="text-base text-[#999999]">
|
||||||
Сортировка:
|
Сортировка:
|
||||||
</div>
|
</div>
|
||||||
<Select defaultValue="default">
|
<Select
|
||||||
|
value={searchParams.get("sortByPrice") || "default"}
|
||||||
|
onValueChange={(value) => {
|
||||||
|
const params = new URLSearchParams(searchParams.toString());
|
||||||
|
if (value === "default") {
|
||||||
|
params.delete("sortByPrice");
|
||||||
|
} else {
|
||||||
|
params.set("sortByPrice", value);
|
||||||
|
}
|
||||||
|
const newUrl = params.toString()
|
||||||
|
? `${pathname}?${params.toString()}`
|
||||||
|
: pathname;
|
||||||
|
router.replace(newUrl, { scroll: false });
|
||||||
|
}}
|
||||||
|
>
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
className="w-full"
|
className="w-full"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|
@ -357,18 +395,12 @@ export default function CatalogPage() {
|
||||||
<SelectItem value="default">
|
<SelectItem value="default">
|
||||||
По умолчанию
|
По умолчанию
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="price-asc">
|
<SelectItem value="asc">
|
||||||
Цена: по возрастанию
|
Цена: по возрастанию
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="price-desc">
|
<SelectItem value="desc">
|
||||||
Цена: по убыванию
|
Цена: по убыванию
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value="length-asc">
|
|
||||||
Длина: по возрастанию
|
|
||||||
</SelectItem>
|
|
||||||
<SelectItem value="length-desc">
|
|
||||||
Длина: по убыванию
|
|
||||||
</SelectItem>
|
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@ import Link from "next/link";
|
||||||
export default function Hero() {
|
export default function Hero() {
|
||||||
const [adults, setAdults] = useState<number>(0);
|
const [adults, setAdults] = useState<number>(0);
|
||||||
const [children, setChildren] = useState<number>(0);
|
const [children, setChildren] = useState<number>(0);
|
||||||
|
const [selectedDate, setSelectedDate] = useState<Date | null>(null);
|
||||||
|
const [departureTime, setDepartureTime] = useState<string>("12:00");
|
||||||
|
const [arrivalTime, setArrivalTime] = useState<string>("13:00");
|
||||||
return (
|
return (
|
||||||
<section className="relative h-[600px] rounded-[24px] mx-[16px] overflow-hidden flex text-white">
|
<section className="relative h-[600px] rounded-[24px] mx-[16px] overflow-hidden flex text-white">
|
||||||
<Image
|
<Image
|
||||||
|
|
@ -63,7 +66,14 @@ export default function Hero() {
|
||||||
|
|
||||||
{/* Дата и время */}
|
{/* Дата и время */}
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<DatePicker />
|
<DatePicker
|
||||||
|
value={selectedDate || undefined}
|
||||||
|
departureTime={departureTime}
|
||||||
|
arrivalTime={arrivalTime}
|
||||||
|
onDateChange={(date) => setSelectedDate(date || null)}
|
||||||
|
onDepartureTimeChange={setDepartureTime}
|
||||||
|
onArrivalTimeChange={setArrivalTime}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Количество гостей */}
|
{/* Количество гостей */}
|
||||||
|
|
@ -79,9 +89,20 @@ export default function Hero() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Кнопка поиска */}
|
{/* Кнопка поиска */}
|
||||||
<Button variant="gradient" className="font-bold text-white h-[64px] w-[176px] px-8">
|
<Link href={(() => {
|
||||||
Найти
|
const params = new URLSearchParams();
|
||||||
</Button>
|
if (adults > 0) params.append('adults', adults.toString());
|
||||||
|
if (children > 0) params.append('children', children.toString());
|
||||||
|
if (selectedDate) params.append('date', selectedDate.toString());
|
||||||
|
if (departureTime && departureTime !== "12:00") params.append('departureTime', departureTime);
|
||||||
|
if (arrivalTime && arrivalTime !== "13:00") params.append('arrivalTime', arrivalTime);
|
||||||
|
const queryString = params.toString();
|
||||||
|
return queryString ? `/catalog?${queryString}` : '/catalog';
|
||||||
|
})()}>
|
||||||
|
<Button variant="gradient" className="font-bold text-white h-[64px] w-[176px] px-8">
|
||||||
|
Найти
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,9 @@ export function DatePicker({
|
||||||
const [internalArrivalTime, setInternalArrivalTime] = React.useState("13:00");
|
const [internalArrivalTime, setInternalArrivalTime] = React.useState("13:00");
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
|
|
||||||
|
// Определяем, является ли компонент контролируемым
|
||||||
|
const isControlled = value !== undefined || externalDepartureTime !== undefined || externalArrivalTime !== undefined;
|
||||||
|
|
||||||
// Используем внешние значения, если они предоставлены, иначе внутренние
|
// Используем внешние значения, если они предоставлены, иначе внутренние
|
||||||
const date = value !== undefined ? (value || undefined) : internalDate;
|
const date = value !== undefined ? (value || undefined) : internalDate;
|
||||||
const departureTime = externalDepartureTime !== undefined ? externalDepartureTime : internalDepartureTime;
|
const departureTime = externalDepartureTime !== undefined ? externalDepartureTime : internalDepartureTime;
|
||||||
|
|
@ -50,7 +53,7 @@ export function DatePicker({
|
||||||
const handleDateChange = (newDate: Date | undefined) => {
|
const handleDateChange = (newDate: Date | undefined) => {
|
||||||
if (onDateChange) {
|
if (onDateChange) {
|
||||||
onDateChange(newDate);
|
onDateChange(newDate);
|
||||||
} else {
|
} else if (!isControlled) {
|
||||||
setInternalDate(newDate);
|
setInternalDate(newDate);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -58,7 +61,7 @@ export function DatePicker({
|
||||||
const handleDepartureTimeChange = (time: string) => {
|
const handleDepartureTimeChange = (time: string) => {
|
||||||
if (onDepartureTimeChange) {
|
if (onDepartureTimeChange) {
|
||||||
onDepartureTimeChange(time);
|
onDepartureTimeChange(time);
|
||||||
} else {
|
} else if (!isControlled) {
|
||||||
setInternalDepartureTime(time);
|
setInternalDepartureTime(time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -66,7 +69,7 @@ export function DatePicker({
|
||||||
const handleArrivalTimeChange = (time: string) => {
|
const handleArrivalTimeChange = (time: string) => {
|
||||||
if (onArrivalTimeChange) {
|
if (onArrivalTimeChange) {
|
||||||
onArrivalTimeChange(time);
|
onArrivalTimeChange(time);
|
||||||
} else {
|
} else if (!isControlled) {
|
||||||
setInternalArrivalTime(time);
|
setInternalArrivalTime(time);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue