summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/components/FilterBar.tsx8
-rw-r--r--app/lib/scraper-runner.server.ts28
-rw-r--r--app/routes/events._index.tsx22
3 files changed, 48 insertions, 10 deletions
diff --git a/app/components/FilterBar.tsx b/app/components/FilterBar.tsx
index 97a3c02..266865d 100644
--- a/app/components/FilterBar.tsx
+++ b/app/components/FilterBar.tsx
@@ -3,9 +3,11 @@ import type { Venue } from "~/lib/db.server";
interface Props {
venues: Venue[];
+ defaultDateFrom?: string;
+ defaultDateTo?: string;
}
-export default function FilterBar({ venues }: Props) {
+export default function FilterBar({ venues, defaultDateFrom, defaultDateTo }: Props) {
const [searchParams] = useSearchParams();
return (
@@ -45,7 +47,7 @@ export default function FilterBar({ venues }: Props) {
<input
name="date_from"
type="date"
- defaultValue={searchParams.get("date_from") ?? ""}
+ defaultValue={searchParams.get("date_from") ?? defaultDateFrom ?? ""}
className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
@@ -56,7 +58,7 @@ export default function FilterBar({ venues }: Props) {
<input
name="date_to"
type="date"
- defaultValue={searchParams.get("date_to") ?? ""}
+ defaultValue={searchParams.get("date_to") ?? defaultDateTo ?? ""}
className="rounded-md bg-gray-800 border border-gray-700 px-3 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-indigo-500"
/>
</div>
diff --git a/app/lib/scraper-runner.server.ts b/app/lib/scraper-runner.server.ts
index 070a568..191dd00 100644
--- a/app/lib/scraper-runner.server.ts
+++ b/app/lib/scraper-runner.server.ts
@@ -1,6 +1,24 @@
import { upsertVenue, upsertEvent } from "./db.server";
import { generateVenueMarkdown, generateAllVenueMarkdown } from "./markdown-writer.server";
import { ALL_SCRAPERS } from "~/scrapers/index";
+import type { EventInput } from "./db.server";
+
+const SCRAPE_WINDOW_DAYS = 35; // ~1 month
+
+function scrapeWindow(): { from: string; to: string } {
+ const from = new Date();
+ from.setHours(0, 0, 0, 0);
+ const to = new Date(from);
+ to.setDate(to.getDate() + SCRAPE_WINDOW_DAYS);
+ return {
+ from: from.toISOString().slice(0, 10),
+ to: to.toISOString().slice(0, 10),
+ };
+}
+
+function withinWindow(event: EventInput, from: string, to: string): boolean {
+ return event.date >= from && event.date <= to;
+}
export interface ScrapeResult {
venue_id: string;
@@ -19,7 +37,10 @@ export async function runAllScrapers(): Promise<ScrapeResult[]> {
upsertVenue(venue.id, venue.name, venue.url, venue.area);
try {
- const events = await scraper.scrape();
+ const { from, to } = scrapeWindow();
+ const events = (await scraper.scrape()).filter((e) =>
+ withinWindow(e, from, to)
+ );
for (const event of events) {
upsertEvent(event);
}
@@ -55,7 +76,10 @@ export async function runScraper(venueId: string): Promise<ScrapeResult> {
upsertVenue(venue.id, venue.name, venue.url, venue.area);
try {
- const events = await scraper.scrape();
+ const { from, to } = scrapeWindow();
+ const events = (await scraper.scrape()).filter((e) =>
+ withinWindow(e, from, to)
+ );
for (const event of events) {
upsertEvent(event);
}
diff --git a/app/routes/events._index.tsx b/app/routes/events._index.tsx
index 3883d37..3ff441a 100644
--- a/app/routes/events._index.tsx
+++ b/app/routes/events._index.tsx
@@ -4,10 +4,22 @@ import { queryEvents, getVenues } from "~/lib/db.server";
import EventCard from "~/components/EventCard";
import FilterBar from "~/components/FilterBar";
+function defaultWindow() {
+ const today = new Date();
+ today.setHours(0, 0, 0, 0);
+ const end = new Date(today);
+ end.setDate(end.getDate() + 35);
+ return {
+ from: today.toISOString().slice(0, 10),
+ to: end.toISOString().slice(0, 10),
+ };
+}
+
export async function loader({ request }: Route.LoaderArgs) {
const url = new URL(request.url);
- const date_from = url.searchParams.get("date_from") ?? undefined;
- const date_to = url.searchParams.get("date_to") ?? undefined;
+ const { from: defaultFrom, to: defaultTo } = defaultWindow();
+ const date_from = url.searchParams.get("date_from") ?? defaultFrom;
+ const date_to = url.searchParams.get("date_to") ?? defaultTo;
const venue_id = url.searchParams.get("venue_id") ?? undefined;
const keyword = url.searchParams.get("keyword") ?? undefined;
const page = Math.max(1, parseInt(url.searchParams.get("page") ?? "1", 10));
@@ -17,11 +29,11 @@ export async function loader({ request }: Route.LoaderArgs) {
const events = queryEvents({ date_from, date_to, venue_id, keyword, limit, offset });
const venues = getVenues();
- return { events, venues, page, hasMore: events.length === limit };
+ return { events, venues, page, hasMore: events.length === limit, date_from, date_to };
}
export default function EventsIndex() {
- const { events, venues, page, hasMore } = useLoaderData<typeof loader>();
+ const { events, venues, page, hasMore, date_from, date_to } = useLoaderData<typeof loader>();
const [searchParams] = useSearchParams();
return (
@@ -49,7 +61,7 @@ export default function EventsIndex() {
</Form>
</div>
- <FilterBar venues={venues} />
+ <FilterBar venues={venues} defaultDateFrom={date_from} defaultDateTo={date_to} />
{events.length === 0 ? (
<div className="mt-16 text-center text-gray-500">