Clean up the schema: drop unused tables, rename scopes, publishable awards
Migrations 020–023, with the code that reads each: - 020 drops people_lists, people_list_members, v_chapters and v_person_affiliations. Nothing queried any of them. - 021 renames event_sections to event_scopes and events.section_id to scope_id, finishing what 015 described. The API sends `scopes` and `scope_id`, and useEvents, EventListCards and EventCalendar take `scope`. It also inserts national/regional/partner, which only the retired seed ever created: a database built from migrations alone had no scope for the Retreats bands. - 022 drops events.sort_order and people.sort_order. Events now sort by date (upcoming soonest first, past latest first, undated last) on /events, org pages and the countdown. People were only ever sorted by sort_name on the site. Every other sort_order stays. - 023 rebuilds teams with created_at and updated_at plus a touch trigger, so the teams editor gets the same optimistic concurrency as the other entities. Awards can be drafted: is_published (added in 011) is on both descriptor halves with a Publishing group, and the award list, award page, org awards and event awards leave drafts out. The migration runner now turns foreign keys off around the per-file transactions and runs foreign_key_check before each commit. PRAGMA foreign_keys is a no-op inside a transaction, so 009's warning was right and a rebuild of a referenced table (023) couldn't be written otherwise. CLAUDE.md is updated to match. Also removes the stray src/App.tsx.save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
8790f861fe
commit
25e592bfea
19 changed files with 339 additions and 423 deletions
|
|
@ -1,25 +1,25 @@
|
|||
/* ═══════════════════════════════════════════════════════════════
|
||||
EVENT DATA
|
||||
|
||||
One request, filtered per section. The Retreats page has three
|
||||
One request, filtered per band. The Retreats page has three
|
||||
bands of events, and all three call this hook — the cache in
|
||||
api.ts keys on the path, so they share a single fetch and each
|
||||
narrows the result to what it shows.
|
||||
|
||||
useEvents({ section: "national" }) one band
|
||||
useEvents({ scope: "national" }) one band
|
||||
useEvents({ host: "northwest" }) one host's events
|
||||
useEvents({ status: "upcoming" }) a home page strip
|
||||
useEvents({ type: "workshop" }) one kind, wherever it is
|
||||
useEvents({ type: ["class", "workshop"] })
|
||||
useEvents() everything
|
||||
|
||||
`section` and `type` are different questions and stack rather
|
||||
than overlap: the section is which band of the page an event
|
||||
belongs to, the type is what kind of gathering it is. A regional
|
||||
class matches both { section: "regional" } and { type: "class" }.
|
||||
`scope` and `type` are different questions and stack rather
|
||||
than overlap: the scope is whose gathering an event is, the type
|
||||
is what kind of gathering it is. A regional class matches both
|
||||
{ scope: "regional" } and { type: "class" }.
|
||||
|
||||
The event_sections rows (the scope list) come back alongside, for
|
||||
anything that offers a scope filter.
|
||||
The event_scopes rows come back alongside, for anything that
|
||||
offers a scope filter.
|
||||
|
||||
No fallback. An empty list on a failed request would read as
|
||||
"nothing scheduled" when the truth is "the server is down", so
|
||||
|
|
@ -35,15 +35,15 @@ import { useMemo } from "react";
|
|||
|
||||
import { useResource } from "../lib/useResource.ts";
|
||||
|
||||
/* One shared empty list, so a memo keyed on `sections` doesn't
|
||||
/* One shared empty list, so a memo keyed on `scopes` doesn't
|
||||
restart on every render before the data arrives. */
|
||||
const NO_SECTIONS: any[] = [];
|
||||
const NO_SCOPES: any[] = [];
|
||||
|
||||
export function useEvents({ section, host, status, type }: any = {}) {
|
||||
export function useEvents({ scope, host, status, type }: any = {}) {
|
||||
const { data, error, loading } = useResource("/events");
|
||||
|
||||
const all = data?.events;
|
||||
const sections = data?.sections ?? NO_SECTIONS;
|
||||
const scopes = data?.scopes ?? NO_SCOPES;
|
||||
|
||||
/* An array prop is a new identity on every render, which would
|
||||
restart the memo each time. Joining it gives the dependency
|
||||
|
|
@ -52,7 +52,7 @@ export function useEvents({ section, host, status, type }: any = {}) {
|
|||
|
||||
const events = useMemo(() => {
|
||||
let list = all ?? [];
|
||||
if (section) list = list.filter(e => e.section_id === section);
|
||||
if (scope) list = list.filter(e => e.scope_id === scope);
|
||||
// `host` is an organization or a person slug, and an event can
|
||||
// have several of either — co-hosting puts one event on both
|
||||
// hosts' lists, which is the point.
|
||||
|
|
@ -63,9 +63,9 @@ export function useEvents({ section, host, status, type }: any = {}) {
|
|||
list = list.filter(e => wanted.has(e.event_type));
|
||||
}
|
||||
return list;
|
||||
}, [all, section, host, status, typeKey]);
|
||||
}, [all, scope, host, status, typeKey]);
|
||||
|
||||
return { events, sections, loading, error };
|
||||
return { events, scopes, loading, error };
|
||||
}
|
||||
|
||||
/* Past and upcoming, split. `status` arrives already resolved — the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue