diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index b35d7fc..f0a2cdf 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "calendar-run-frontend",
- "version": "0.9.1",
+ "version": "0.9.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "calendar-run-frontend",
- "version": "0.9.1",
+ "version": "0.9.3",
"dependencies": {
"ag-charts-community": "^14.0.0",
"ag-charts-react": "^14.0.0",
diff --git a/frontend/package.json b/frontend/package.json
index 56f9ab3..d085c39 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "calendar-run-frontend",
"private": true,
- "version": "0.9.1",
+ "version": "0.9.3",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx
index 4a0b6f7..008a9dc 100644
--- a/frontend/src/pages/DashboardPage.tsx
+++ b/frontend/src/pages/DashboardPage.tsx
@@ -192,7 +192,6 @@ export function DashboardPage(): JSX.Element {
>
Календарь сезона
-
Беговой штаб
Планируйте старты, держите фокус на ближайшей гонке и сравнивайте прогресс по дистанциям.
diff --git a/frontend/src/pages/RacesPage.tsx b/frontend/src/pages/RacesPage.tsx
index ba1e293..37c19fe 100644
--- a/frontend/src/pages/RacesPage.tsx
+++ b/frontend/src/pages/RacesPage.tsx
@@ -145,6 +145,9 @@ export function RacesPage(): JSX.Element {
const [sortOrder, setSortOrder] = useState
(() => (searchParams.get("sort") as RaceSort | null) ?? "dateAsc");
const [viewMode, setViewMode] = useState(() => searchParams.get("view") === "calendar" ? "calendar" : readInitialViewMode());
const [activeListTab, setActiveListTab] = useState("upcoming");
+ const [isFiltersOpen, setIsFiltersOpen] = useState(() =>
+ ["year", "month", "status", "dateFrom", "dateTo", "distanceMin", "distanceMax", "q", "sort"].some((key) => searchParams.has(key)),
+ );
const setViewModePersist = useCallback((mode: ViewMode) => {
setViewMode(mode);
@@ -297,6 +300,17 @@ export function RacesPage(): JSX.Element {
]
.filter(Boolean)
.join(" ");
+ const activeFilterCount = [
+ viewMode === "list" ? yearFilter : "",
+ monthFilter,
+ statusFilter,
+ searchQuery,
+ dateFrom,
+ dateTo,
+ distanceMin,
+ distanceMax,
+ sortOrder !== "dateAsc" ? sortOrder : "",
+ ].filter(Boolean).length;
if (errorMessage && races.length === 0 && !isLoading) {
return (
@@ -331,7 +345,14 @@ export function RacesPage(): JSX.Element {
-
+
setIsFiltersOpen(event.currentTarget.open)}
+ >
+
+ Фильтры{activeFilterCount > 0 ? ` · ${activeFilterCount} активн.` : ""}
+
-
+
diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css
index dd6de11..b87ef9f 100644
--- a/frontend/src/styles/global.css
+++ b/frontend/src/styles/global.css
@@ -1564,8 +1564,46 @@ body {
backdrop-filter: blur(14px);
}
+.races-hero__filters-summary {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--space-3);
+ color: #ffffff;
+ font-weight: 700;
+ cursor: pointer;
+ list-style: none;
+}
+
+.races-hero__filters-summary::-webkit-details-marker {
+ display: none;
+}
+
+.races-hero__filters-summary::after {
+ content: "+";
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 1.5rem;
+ height: 1.5rem;
+ border: 1px solid rgba(255, 255, 255, 0.42);
+ border-radius: 50%;
+ font-size: 1.15rem;
+ font-weight: 400;
+ line-height: 1;
+}
+
+.races-hero__filters[open] .races-hero__filters-summary::after {
+ content: "−";
+}
+
+.races-hero__filters-summary:focus-visible {
+ outline: 2px solid var(--color-lime);
+ outline-offset: var(--space-1);
+}
+
.races-hero__filters .races-filter {
- margin-top: 0;
+ margin-top: var(--space-5);
}
.races-hero__filters .races-filter__label {