From 3a961122bdf64cf72cf1b3770e9d71865a3aac52 Mon Sep 17 00:00:00 2001 From: yyamashita Date: Fri, 22 May 2026 10:31:14 +0900 Subject: Add filters to date view (keyword, venue, area, capacity) Co-Authored-By: Claude Sonnet 4.6 --- app/routes/events.by-date.tsx | 114 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/routes/events.by-date.tsx b/app/routes/events.by-date.tsx index 9a59073..ee4a873 100644 --- a/app/routes/events.by-date.tsx +++ b/app/routes/events.by-date.tsx @@ -1,6 +1,7 @@ -import { useLoaderData, useSearchParams, Link } from "react-router"; -import { queryEvents, getVenues } from "~/lib/db.server"; +import { useLoaderData, useSearchParams, Link, Form } from "react-router"; +import { queryEvents, getVenues, type CapacityRange } from "~/lib/db.server"; import type { Event } from "~/lib/db.server"; +import { useVenueFilter } from "~/lib/venue-filter"; function todayJst(): string { // JST = UTC+9 @@ -32,9 +33,14 @@ function buildTimeLabel(open: string | null, start: string | null): string { export async function loader({ request }: { request: Request }) { const url = new URL(request.url); const date = url.searchParams.get("date") ?? todayJst(); + const keyword = url.searchParams.get("keyword") ?? undefined; + const venue_id = url.searchParams.get("venue_id") ?? undefined; + const capacity_range = (url.searchParams.get("capacity_range") ?? undefined) as CapacityRange | undefined; + const area = url.searchParams.get("area") ?? undefined; - const events = queryEvents({ date_from: date, date_to: date, limit: 500 }); + const events = queryEvents({ date_from: date, date_to: date, keyword, venue_id, capacity_range, area, limit: 500 }); const venues = getVenues(); + const areas = [...new Set(venues.filter((v) => v.area).map((v) => v.area as string))].sort(); const byVenue = new Map(); for (const event of events) { @@ -46,12 +52,19 @@ export async function loader({ request }: { request: Request }) { .filter((v) => byVenue.has(v.id)) .map((v) => ({ venue: v, events: byVenue.get(v.id)! })); - return { date, groups, totalEvents: events.length }; + return { date, groups, totalEvents: events.length, venues, areas }; } export default function EventsByDate() { - const { date, groups, totalEvents } = useLoaderData(); + const { date, groups, totalEvents, venues, areas } = useLoaderData(); const [searchParams] = useSearchParams(); + const { hiddenIds } = useVenueFilter(); + + const hasVenueFilter = !!searchParams.get("venue_id"); + const visibleGroups = hasVenueFilter + ? groups + : groups.filter((g) => !hiddenIds.has(g.venue.id)); + const hiddenCount = groups.length - visibleGroups.length; function dateUrl(d: string) { const p = new URLSearchParams(searchParams); @@ -59,6 +72,10 @@ export default function EventsByDate() { return `?${p.toString()}`; } + const hasFilters = ["keyword", "venue_id", "capacity_range", "area"].some( + (k) => searchParams.get(k) + ); + const prevDay = addDays(date, -1); const nextDay = addDays(date, 1); @@ -77,7 +94,7 @@ export default function EventsByDate() {
{/* Date navigation */} -
+
+ {/* Filter bar */} +
+ + +
+ + +
+ +
+ + +
+ + {areas.length > 0 && ( +
+ + +
+ )} + +
+ + +
+ + + + {hasFilters && ( + + クリア + + )} +
+ {/* Summary */} {totalEvents > 0 && (

- {groups.length} 会場 / {totalEvents} イベント + {visibleGroups.length} 会場 / {totalEvents} イベント + {hiddenCount > 0 && ( + <> — {hiddenCount} 会場非表示 + )}

)} {/* Venue groups */} - {groups.length === 0 ? ( + {visibleGroups.length === 0 ? (

この日のイベントはありません

@@ -125,7 +221,7 @@ export default function EventsByDate() {

) : (
- {groups.map(({ venue, events }) => ( + {visibleGroups.map(({ venue, events }) => (

-- cgit v1.2.3