diff options
Diffstat (limited to 'app/routes/venues.tsx')
| -rw-r--r-- | app/routes/venues.tsx | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/app/routes/venues.tsx b/app/routes/venues.tsx new file mode 100644 index 0000000..23b052f --- /dev/null +++ b/app/routes/venues.tsx @@ -0,0 +1,68 @@ +import { useLoaderData, Link } from "react-router"; +import type { Route } from "./+types/venues"; +import { getVenues } from "~/lib/db.server"; +import { getScraperIds } from "~/lib/venue-meta.server"; + +export async function loader(_: Route.LoaderArgs) { + const venues = getVenues(); + const scraperIds = getScraperIds(); + return { venues, scraperIds }; +} + +export default function Venues() { + const { venues, scraperIds: scraperIdList } = useLoaderData<typeof loader>(); + const scraperIds = new Set(scraperIdList); + + return ( + <div className="min-h-screen bg-gray-950 text-gray-100"> + <header className="border-b border-gray-800 px-6 py-4 flex items-center justify-between"> + <Link to="/" className="text-xl font-bold tracking-tight text-white"> + 🎸 東京ライブハウス + </Link> + <nav className="flex gap-6 text-sm text-gray-400"> + <Link to="/events" className="hover:text-white transition-colors">イベント</Link> + <Link to="/venues" className="text-white font-medium">会場一覧</Link> + </nav> + </header> + + <main className="max-w-4xl mx-auto px-4 py-10"> + <div className="mb-8"> + <h1 className="text-2xl font-bold">会場一覧</h1> + <p className="mt-1 text-sm text-gray-400"> + 現在 {scraperIdList.length} 会場のスクレイパーが登録されています。 + 新しい会場を追加するには <code className="bg-gray-800 px-1 rounded">app/scrapers/</code> に + モジュールを追加して <code className="bg-gray-800 px-1 rounded">index.ts</code> に登録してください。 + </p> + </div> + + {venues.length === 0 ? ( + <p className="text-gray-500">まだ会場データがありません。「情報を更新」してください。</p> + ) : ( + <div className="grid gap-4 sm:grid-cols-2"> + {venues.map((v) => ( + <Link + key={v.id} + to={`/events?venue_id=${v.id}`} + className="flex items-center justify-between rounded-xl bg-gray-800/60 p-4 hover:bg-gray-800 transition-colors border border-gray-700/50" + > + <div> + <p className="font-semibold">{v.name}</p> + {v.area && <p className="text-sm text-gray-400">{v.area}</p>} + {scraperIds.has(v.id) && ( + <span className="mt-1 inline-block rounded-full bg-emerald-700/40 px-2 py-0.5 text-xs text-emerald-300"> + スクレイパー登録済 + </span> + )} + </div> + <span className="text-2xl font-bold text-gray-500"> + {v.event_count ?? 0} + <span className="text-sm font-normal ml-1">件</span> + </span> + </Link> + ))} + </div> + )} + </main> + </div> + ); +} |
