import { useLoaderData, Link } from "react-router"; import type { Route } from "./+types/venues"; import { getVenues, getLastScrapePerVenue, type ScrapeLog } from "~/lib/db.server"; import ScrapeButton from "~/components/ScrapeButton"; import { useVenueFilter } from "~/lib/venue-filter"; export async function loader(_: Route.LoaderArgs) { const venues = getVenues(); const scrapeStatus = getLastScrapePerVenue(); return { venues, scrapeStatus }; } export default function Venues() { const { venues, scrapeStatus } = useLoaderData(); const statusMap = new Map(scrapeStatus.map((s) => [s.venue_id, s])); const { hiddenIds, toggle } = useVenueFilter(); const hiddenCount = hiddenIds.size; return (
🎸 ライブに行くしかない

会場一覧

現在 {venues.length} 会場が登録されています。 {hiddenCount > 0 && ( {hiddenCount} 会場が非表示 )}

{venues.length === 0 ? (

まだ会場データがありません。「全会場を更新」してください。

) : (
{venues.map((v) => { const log = statusMap.get(v.id); const hidden = hiddenIds.has(v.id); return ( ); })}
)}
); } function ScrapeStatus({ log }: { log: ScrapeLog }) { if (log.status === "running") { return ⟳ 実行中...; } if (log.status === "error") { return ( ✖ エラー ); } const time = log.finished_at?.slice(0, 16).replace("T", " ") ?? ""; return ( ✔ {time} ); }