AI_CONTEXT_FRONTEND - AvengerDisassemble/KU-connect GitHub Wiki

Background

KU-Connect is a job board platform for Kasetsart University students and employers.

  • Users: Students, Employers, Professors, Admins
  • Features: Role-based dashboards, login with KU Gmail (OAuth), job posting, application, saved jobs, moderation.
  • Frontend Goal: Clean, responsive UI connected to backend APIs, with consistent structure and maintainable code.

Current Objective

  • Stabilize the student browse-jobs experience (quick filters, advanced sheet, tabs).
  • Keep job application dialog in sync with backend resume storage-key validation and metadata.
  • Maintain smooth Radix sheet/tab animations and consistent button theming.

Recent Wins

  • Advanced filter sheet extracted to components/advanced-filters/AdvancedFiltersSheet.tsx with forced-mount portal to stop flicker.
  • JobFilterBar.tsx now coordinates keyword search, quick filters, and advanced sheet state in one place.
  • Resume chooser dialog accepts both profile resumes and uploaded storage keys without validator conflicts.

Tech Stack

  • Vite + React + TypeScript
  • Tailwind v4 + shadcn/ui (Radix primitives)
  • React Router
  • TanStack Query for data fetching/caching
  • ESLint + Prettier
  • Alias: @ → src

Folder Structure

  • src/components/ shared layout/auth pieces (Header, Guard, Footer, upload widgets) alongside ui/ primitives.
  • src/components/ui/ wraps Radix primitives (sheet, tabs, button, etc.) with Tailwind + cva variants.
  • src/pages/student/browse-jobs/ holds the page shell, components/ (filter bar, advanced sheet, job list/detail, application dialog), types/, and utils/.
  • src/hooks/ houses global hooks like useAuth; page-specific hooks stay co-located when scoped.
  • src/services/ typed API helpers (jobs.ts, resumes, auth); no direct network calls elsewhere.
  • src/lib/ shared utilities (cn, query helpers); src/utils/ small constants/helpers shared across pages.
  • src/styles/ Tailwind globals (global.css, lovable.css); App.tsx wires routes; main.tsx bootstraps React.

Naming Conventions

  • Components: PascalCase .tsx
  • Files/helpers: camelCase
  • Types/interfaces: PascalCase
  • Constants: UPPER_CASE
  • Variables/functions: camelCase
  • Booleans: prefix is/has/can

Component Rules

  • Functional components only
  • Order: imports → state/hooks → handlers → return
  • Props typed with TS interfaces
  • Optional props with ? and defaults

Styling

  • MUST use Tailwind
  • Group class names logically
  • Conditional classes via template/clsx

State & Hooks

  • React hooks only
  • Explicit types if not inferred
  • Extract reusable logic into hooks/

Imports

  1. React
  2. External libs
  3. Local files (@/...)
  • MUST use absolute imports
  • No unused imports

Event Handlers

  • Verb-prefixed names
  • Defined above return
  • MUST type events

Routing & Guards

  • Routes in App.tsx
  • Private routes wrap with Guard + useAuth
  • Pages under src/pages/{role}/

API Layer

  • All API calls via services/api.ts
  • Typed functions
  • DO NOT use fetch directly in components

UI Components

  • Prefer shadcn/ui
  • Shared UI in components/ui/
  • Reuse before creating new

Key Surfaces

  • src/pages/student/browse-jobs/ page orchestrates data fetching, tab state, and renders filter/application components.
  • components/AdvancedFiltersSheet.tsx memoizes the sheet, forces mount, and relies on SheetClose for exits.
  • components/JobFilterBar.tsx is the single source of truth for keyword input, quick filters, and advanced sheet toggling.
  • components/JobApplicationDialog.tsx handles resume selection; ensure storage-key values flow to submit handler unchanged.
  • Filter buttons override shadcn variants via Tailwind; avoid conflicting hover/active states when tweaking colors.

Active Constraints

  • No direct fetch; all data via services/api.ts with typed helpers.
  • Keep animations glitch-free: sheet should not unmount between openings and tabs should ease without layout jumps.
  • Preserve accessibility on interactive elements (aria labels, focus trapping in sheets/dialogs).
  • Match backend resume validation (storage keys shaped like resume:student:{id}:{uuid}) and expose helpful errors.

Animation Notes

  • src/components/ui/sheet.tsx augments Radix dialogs with data-[state] slide/fade classes and 300–500 ms easing.
  • AdvancedFiltersSheet keeps SheetPortal forced-mounted to avoid close/open flicker and preserve exit animations.
  • Tab and filter interactions rely on Tailwind transitions (transition-all duration-200) and CSS variables for brand colors.
  • Mobile job detail sheet reuses the same Radix animation hooks; new sheets must respect data-[state=open|closed] classes.

Open Risks / TODOs

  • Manually verify advanced sheet close/open cycle after every major filter change.
  • Revisit quick filter button palette once design team finalizes brand colors.
  • Add UI tests around resume selection edge cases (no profile resume, multiple uploads) when time permits.

Testing

  • Vitest + React Testing Library
  • Test props, handlers, rendering conditions

PR Checklist

  • Naming/structure correct
  • Types explicit
  • Uses Tailwind + shadcn/ui
  • API calls via services/api.ts
  • Guarded routes where needed
  • ESLint + Prettier + type check pass
  • Minimal tests added
  • No unused imports/dead code

Prompt Patterns

New Page: Create src/pages/student/ProfilePage.tsx.

  • Wrap with Guard, use useAuth
  • Fetch from services/api.ts:getStudentProfile()
  • Show loading/error states
  • Use Tailwind + shadcn/ui Card
  • Types must be defined, no inline fetch

New Component: Create src/components/ui/JobCard.tsx. Props: { title: string; company: string; salary?: string; onApply?: () => void }

  • Use shadcn/ui Card, Tailwind spacing
  • Render Apply button only if onApply exists

New Hook: Create src/hooks/useJobs.ts.

  • Expose { jobs, isLoading, error, refresh }
  • Fetch via services/api.ts:getJobs()
  • Cache last result, refresh triggers refetch