diff --git a/README.md b/README.md index 67bb2b4..61baefe 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ The database URL is `postgresql://forum:forum_password@localhost:5434/the_forum` Optionally fill the database with realistic demo data: ```bash -cd apps/database && bun run db:seed +bun run db:seed ``` ### 4. Run the app @@ -124,6 +124,7 @@ bun run build # build all packages bun run db:up # start Postgres db:down stop it (data persists) bun run db:push # push schema (dev) db:generate generate SQL migrations bun run db:migrate # apply migrations db:studio visual DB browser +bun run db:seed # seed demo data (safe to re-run any time) ``` Pre-commit hooks (Husky + lint-staged) automatically run Biome on staged files — @@ -186,4 +187,4 @@ Re-run `bun install` from the repo root (the `prepare` script reinstalls hooks). Expected unless you've run `uv sync` in `backends/fastapi` and `uv` is on your PATH. **Wipe the database and start fresh** -`docker compose down -v` (deletes the data volume), then `bun run db:up && bun run db:push`. +`docker compose down -v` (deletes the data volume), then `bun run db:up && bun run db:push && bun run db:seed`. diff --git a/apps/database/package.json b/apps/database/package.json index 01b9253..fe5e459 100644 --- a/apps/database/package.json +++ b/apps/database/package.json @@ -10,7 +10,7 @@ "db:migrate": "drizzle-kit migrate", "db:push": "drizzle-kit push", "db:studio": "drizzle-kit studio", - "db:seed": "tsx src/seed.ts", + "db:seed": "bun run src/seed.ts", "lint": "biome check .", "check-types": "tsc --noEmit" }, @@ -21,7 +21,6 @@ "devDependencies": { "@types/node": "^22.13.4", "drizzle-kit": "^0.31.10", - "tsx": "^4.21.0", "typescript": "^5.7.3" } } diff --git a/apps/database/src/seed.ts b/apps/database/src/seed.ts index b15cd16..74002f8 100644 --- a/apps/database/src/seed.ts +++ b/apps/database/src/seed.ts @@ -4,6 +4,7 @@ * Run: bun run db:seed (from apps/database) */ +import { eq } from "drizzle-orm"; import { db } from "./db"; import { events, @@ -755,16 +756,30 @@ async function seed() { }, ]; - // Events have no unique constraint on title, so skip ones that already - // exist to keep re-runs of the seed from inserting duplicates. - const existingTitles = new Set( - (await db.select({ title: events.title }).from(events)).map((e) => e.title), + // Events have no unique constraint on title, so re-runs match on title. Events + // that already exist get their datetime/endDatetime refreshed (so the seed + // stays future-facing no matter how long ago it was first run); new titles + // get a full insert + tags. + const existingEventsByTitle = new Map( + (await db.select({ id: events.id, title: events.title }).from(events)).map((e) => [ + e.title, + e.id, + ]), ); const insertedEvents: { id: string; tags: Tag[] }[] = []; + let refreshedCount = 0; for (const e of eventList) { - if (existingTitles.has(e.title)) continue; const { tags: tagList, ...vals } = e; + const existingId = existingEventsByTitle.get(e.title); + if (existingId) { + await db + .update(events) + .set({ datetime: vals.datetime, endDatetime: vals.endDatetime }) + .where(eq(events.id, existingId)); + refreshedCount++; + continue; + } const [inserted] = await db.insert(events).values(vals).returning({ id: events.id }); if (inserted) { insertedEvents.push({ id: inserted.id, tags: tagList }); @@ -776,9 +791,7 @@ async function seed() { } } } - console.log( - ` Events: ${insertedEvents.length} inserted, ${existingTitles.size} already present`, - ); + console.log(` Events: ${insertedEvents.length} inserted, ${refreshedCount} dates refreshed`); /* ═══ 9. RSVPs ═══ */ const allUserIds = [...userMap.values()]; diff --git a/apps/web/src/app/(app)/events/my-events-client.tsx b/apps/web/src/app/(app)/events/my-events-client.tsx index 99b30af..14560df 100644 --- a/apps/web/src/app/(app)/events/my-events-client.tsx +++ b/apps/web/src/app/(app)/events/my-events-client.tsx @@ -10,6 +10,7 @@ import { cn } from "~/lib/utils"; const TABS = [ { id: "created", label: "Events Created" }, + { id: "rsvped", label: "Events RSVP'd" }, { id: "saved", label: "Events Saved" }, ] as const; @@ -83,7 +84,7 @@ function EventListCard({ event }: { event: FeedEvent }) { export function MyEventsClient({ created, rsvped, saved }: MyEventsClientProps) { const [activeTab, setActiveTab] = useState("created"); - const eventMap: Record = { created, saved }; + const eventMap: Record = { created, rsvped, saved }; const events = eventMap[activeTab]; return ( @@ -131,12 +132,18 @@ export function MyEventsClient({ created, rsvped, saved }: MyEventsClientProps) ) : (

- {activeTab === "created" ? "No events created yet" : "No saved events"} + {activeTab === "created" + ? "No events created yet" + : activeTab === "rsvped" + ? "No RSVP'd events" + : "No saved events"}

{activeTab === "created" ? "Share something with campus — create your first event." - : "Bookmark events you're interested in."} + : activeTab === "rsvped" + ? "Events you've RSVP'd to will show up here." + : "Bookmark events you're interested in."}

)} diff --git a/bun.lock b/bun.lock index 1250d06..783828f 100644 --- a/bun.lock +++ b/bun.lock @@ -39,14 +39,9 @@ "devDependencies": { "@types/node": "^22.13.4", "drizzle-kit": "^0.31.10", - "tsx": "^4.21.0", "typescript": "^5.7.3", }, }, - "apps/listserv-mcp-experimental": { - "name": "@the-forum/listserv-mcp-experimental", - "version": "0.0.1", - }, "apps/listserv-scraper": { "name": "@the-forum/listserv-scraper", "version": "0.0.1", @@ -793,8 +788,6 @@ "@the-forum/fastapi": ["@the-forum/fastapi@workspace:backends/fastapi"], - "@the-forum/listserv-mcp-experimental": ["@the-forum/listserv-mcp-experimental@workspace:apps/listserv-mcp-experimental"], - "@the-forum/listserv-scraper": ["@the-forum/listserv-scraper@workspace:apps/listserv-scraper"], "@the-forum/mpu-scraper": ["@the-forum/mpu-scraper@workspace:apps/mpu-scraper"], diff --git a/package.json b/package.json index 4096968..42f46a4 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "db:migrate": "turbo db:migrate", "db:push": "turbo db:push", "db:studio": "turbo db:studio", + "db:seed": "turbo db:seed", "prepare": "husky" }, "devDependencies": { diff --git a/turbo.json b/turbo.json index d9de495..cbf008a 100644 --- a/turbo.json +++ b/turbo.json @@ -29,6 +29,9 @@ "db:studio": { "cache": false, "persistent": true + }, + "db:seed": { + "cache": false } } }