- {filterTrainer && (
+ {filterTrainerSet.size > 0 && (
- {filterTrainer}
+ {filterTrainerSet.size === 1 ? Array.from(filterTrainerSet)[0] : `${filterTrainerSet.size} тренеров`}
)}
{filterTypes.size > 0 && Array.from(filterTypes).map((type) => (
@@ -177,8 +177,8 @@ export function MobileSchedule({
typeDots={typeDots}
filterTypes={filterTypes}
toggleFilterType={toggleFilterType}
- filterTrainer={filterTrainer}
- setFilterTrainer={setFilterTrainer}
+ filterTrainerSet={filterTrainerSet}
+ toggleFilterTrainer={toggleFilterTrainer}
/>
))}
@@ -192,8 +192,8 @@ export function MobileSchedule({
typeDots={typeDots}
filterTypes={filterTypes}
toggleFilterType={toggleFilterType}
- filterTrainer={filterTrainer}
- setFilterTrainer={setFilterTrainer}
+ filterTrainerSet={filterTrainerSet}
+ toggleFilterTrainer={toggleFilterTrainer}
/>
))
)}
diff --git a/src/components/sections/schedule/ScheduleFilters.tsx b/src/components/sections/schedule/ScheduleFilters.tsx
index bd7c838..7fec375 100644
--- a/src/components/sections/schedule/ScheduleFilters.tsx
+++ b/src/components/sections/schedule/ScheduleFilters.tsx
@@ -1,12 +1,15 @@
"use client";
-import { useState } from "react";
-import { User, X, ChevronDown, Clock, Calendar } from "lucide-react";
+import { useState, useEffect, useRef } from "react";
+import { createPortal } from "react-dom";
+import { User, X, Clock, SlidersHorizontal } from "lucide-react";
import {
pillBase,
pillActive,
pillInactive,
TIME_PRESETS,
+ isTimeFilterActive,
+ TIME_FILTER_EMPTY,
type StatusTag,
type TimeFilter,
} from "./constants";
@@ -14,12 +17,12 @@ import {
interface ScheduleFiltersProps {
typeDots: Record
;
types: string[];
- hasAnySlots: boolean;
- hasAnyRecruiting: boolean;
+ availableStatuses: string[];
levels: string[];
filterTypes: Set;
toggleFilterType: (type: string) => void;
- filterTrainer: string | null;
+ filterTrainerSet: Set;
+ toggleFilterTrainer: (trainer: string) => void;
filterStatusSet: Set;
toggleFilterStatus: (status: StatusTag) => void;
filterLevel: string | null;
@@ -29,19 +32,23 @@ interface ScheduleFiltersProps {
availableDays: { day: string; dayShort: string }[];
filterDaySet: Set;
toggleDay: (day: string) => void;
+ trainerNames: string[];
+ scheduleConfig?: { levels: { value: string; description: string }[]; statuses: { key: string; label: string; description: string }[] };
hasActiveFilter: boolean;
clearFilters: () => void;
}
+const divider = ;
+
export function ScheduleFilters({
typeDots,
types,
- hasAnySlots,
- hasAnyRecruiting,
+ availableStatuses,
levels,
filterTypes,
toggleFilterType,
- filterTrainer,
+ filterTrainerSet,
+ toggleFilterTrainer,
filterStatusSet,
toggleFilterStatus,
filterLevel,
@@ -51,127 +58,392 @@ export function ScheduleFilters({
availableDays,
filterDaySet,
toggleDay,
+ trainerNames,
+ scheduleConfig,
hasActiveFilter,
clearFilters,
}: ScheduleFiltersProps) {
- const [showWhen, setShowWhen] = useState(false);
- const hasTimeFilter = filterDaySet.size > 0 || filterTime !== "all";
+ const [modalOpen, setModalOpen] = useState(false);
+
+ const totalActive = filterTypes.size + filterTrainerSet.size + filterStatusSet.size + (filterLevel ? 1 : 0) + filterDaySet.size + (isTimeFilterActive(filterTime) ? 1 : 0);
+
+ useEffect(() => {
+ if (modalOpen) document.body.style.overflow = "hidden";
+ else document.body.style.overflow = "";
+ return () => { document.body.style.overflow = ""; };
+ }, [modalOpen]);
+
+ useEffect(() => {
+ if (!modalOpen) return;
+ function onKey(e: KeyboardEvent) {
+ if (e.key === "Escape") setModalOpen(false);
+ }
+ document.addEventListener("keydown", onKey);
+ return () => document.removeEventListener("keydown", onKey);
+ }, [modalOpen]);
return (
<>
- {/* Single row: type + status + when + active trainer indicator + clear */}
-
- {/* Class types */}
- {types.map((type) => (
-
- ))}
-
- {/* Divider */}
-
-
- {/* Status filters */}
- {hasAnySlots && (
-
- )}
- {hasAnyRecruiting && (
-
- )}
-
- {/* Level filters */}
- {levels.length > 0 && (
- <>
-
- {levels.map((level) => (
-
- ))}
- >
- )}
-
- {/* Divider */}
-
-
- {/* When dropdown toggle */}
-
-
- {/* Active trainer indicator (set by clicking trainer in cards) */}
- {filterTrainer && (
-
-
- {filterTrainer}
+ {/* Filter button — same style as По дням / По группам buttons */}
+
- {/* Clear */}
- {hasActiveFilter && (
-
+ ,
+ document.body
)}
>
);
}
+
+function FilterSection({ title, hint, children }: { title: string; hint?: string; children: React.ReactNode }) {
+ const [showHint, setShowHint] = useState(false);
+ const hintRef = useRef