Skip to content

feat(competitions): typed loader and filters in src/lib/competitions.ts #195

Description

@AnayDhawan

Blocked by #193.

The typed loader every competitions page reads from. Mirror src/lib/places.ts (74 lines), which is the working precedent.

Files

  • src/lib/competitions.ts - new
  • src/lib/types.ts - add the competition types alongside the existing Place types

Shape

Follow src/lib/places.ts closely:

export function getCompetitions(): Competition[]
export function filterCompetitions(
  competitions: Competition[],
  filters: { categories?: CompetitionCategory[]; format?: Format; region?: string;
             participation?: Participation; feeMax?: number; age?: number;
             deadlineBefore?: string; query?: string }
): Competition[]
export function getCategories(): CompetitionCategory[]
export function upcomingDates(c: Competition, now: Date): CompetitionDate[]
export function nextDate(c: Competition, now: Date): CompetitionDate | undefined

Types go in src/lib/types.ts next to Place, following its conventions: a const tuple for the enum plus a derived union (src/lib/types.ts:1-10), and a Record<T, string> label map (:20-27).

Loading

Static ESM import of the JSON files, the way studymap.config.ts:12-17 does it. resolveJsonModule: true is already set in tsconfig.json. No fs, no ISR, no fetch. The dataset bundles at build time exactly like places.

Do not put this in studymap.config.ts. That file is the map's configuration (center, bounds, cities, places) and it already contradicts its own dataset, which is open issue #156. Competitions gets its own module.

Date flattening

upcomingDates and nextDate are what the browse cards, the countdown and the calendar all read. Flatten dates[] and country_tracks[].stages[] into one comparable list, keep the country tag on stage-derived entries so callers can filter by country, and sort ascending. Getting this right once here is what stops three components each rolling their own.

Do not add a date library. src/app/calendar/CalendarView.tsx handles a 478-line month grid with plain Date and the repo has no date-fns or dayjs on purpose.

Acceptance criteria

  • getCompetitions() returns all records from every category file
  • filterCompetitions composes: two filters at once narrow correctly
  • query matches on name, organizer and subjects, case-insensitively
  • nextDate skips past dates and returns the soonest future one
  • upcomingDates includes country stages only when a country is passed
  • npx tsc --noEmit clean, no any

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions