Skip to content

Conversation

davidhne
Copy link
Member

Closes #58

What and why

Connects the frontend to the real GraphQL API instead of filtering
frontend/src/mocks/recipes.ts in the browser, so search, category/rating
filtering, sorting and paging run server-side over the whole dataset (the
assignment's explicit requirement).

  • Apollo Client chosen as the GraphQL client (frontend/src/graphql/).
    Its normalized cache covers the assignment's state-management requirement
    for server data; the recently-merged Zustand store (Fix/59 fridge recipe matches #60) separately
    covers local Fridge UI state - the two don't overlap.
  • Vite's dev server proxies /project2/graphql to the backend, mirroring
    deploy/apache/project2.conf's production proxy, and honors
    VITE_GRAPHQL_URL the same way IngredientSearch.tsx already does.
  • HomePage: search/category/rating/sort drive the recipes query; a "Load
    more" button pages through fetchMore, using the server's totalCount
    and hasMore; loading and error states are handled; the aria-live
    result count reads the server's total.
  • RecipeDetailPage: fetches one recipe via recipe(id) instead of a mock
    lookup.
  • Real bug found while wiring this up and fixed: RecipeFilter's
    category <option> values were lowercase ("beef"), but the server does
    a case-sensitive array-contains match against Title Case data
    ("Beef") - every category filter would have silently returned zero
    results once connected. Also fixed "Soup" → "Soup/Stew", the only
    name that actually exists in the dataset.
  • frontend/src/mocks/recipes.ts removed; nothing depends on it anymore.

Rebased on top of #60 (merged during this PR's development), which
overlapped heavily in the same files (HomePage, recipeFilters, vite.config,
Apache config, CLAUDE.md/README). Resolved conflicts so both land together:
#60's any-ingredient-matches semantics, "Back to Fridge" link and Fridge
persistence are preserved as-is; my Apollo wiring sits underneath them.
HomePage.test.tsx now covers both concerns (GraphQL loading/error/paging
and the Fridge integration scenarios from #60), and FridgePage.test.tsx's
one test that mounts the full <App> now wraps it in MockedProvider.

Known gap, tracked separately: "My Fridge" still matches ingredients
client-side against whatever page the server already returned - the
backend has no ingredient filter on recipes. #60 fixed the match
semantics (any vs. all) within that constraint; true whole-dataset
ingredient filtering needs a backend change, which I'll file as a
follow-up issue.

How to test

  1. npm run lint && npm run format:check && npm run typecheck && npm test && npm run build
    • all pass.
  2. npm run dev:backend (needs an imported local database, see README
    "Data") and npm run dev:frontend, then in the browser:
    • Home: type a search term, debounced after 300 ms; pick a category
      (e.g. "Beef") and confirm results actually narrow down (this is the
      bug that's fixed); set a minimum rating; scroll down and click
      "Load more" to confirm more results append and the button disappears
      once hasMore is false.
    • Open a recipe card → detail page shows photo/placeholder, nutrition,
      ingredients, directions, fetched live.
    • My Fridge → add an ingredient manually (autocomplete needs
      npm run ingredients:refresh, unrelated to this PR) → Find recipes →
      confirm the "matching any of: ..." text and results.
    • Search for nonsense text → "Back to Fridge" link appears and works.
  3. Verified manually in a browser against a local Postgres with the real
    imported dataset (17,698 recipes), both before and after rebasing onto
    Fix/59 fridge recipe matches #60.

AI usage

Done together with Claude Code in an interactive session. Claude wrote the
Apollo Client setup, the HomePage/RecipeDetailPage rewiring, the category
bug fix, and the test updates (including resolving the merge conflicts with
#60 and adapting its tests to the new GraphQL-backed HomePage), driven by a
plan reviewed before implementation. The human caught the overlap with #60
mid-session and directed the rebase-after-merge approach; browser
verification (screenshots, manual click-through of search/filter/paging/
Fridge) was done together via the Chrome extension, not just trusted from
the model's claims.

Checklist

  • Linked issue, labels and milestone set
  • Lint and tests pass locally
  • Tests added/updated for new logic
  • Accessible (keyboard, labels, contrast, screen reader) - loading/error
    states and result count are in the existing aria-live region;
    category/rating selects and search input unchanged
  • README/CLAUDE.md updated if setup, commands or decisions changed
  • No secrets or personal data committed

Replaces frontend/src/mocks/recipes.ts with Apollo Client queries against
the backend, so search, category/rating filtering, sorting and "Load
more" paging all run server-side over the whole dataset, as required.

- Apollo Client chosen as the GraphQL client; its cache also satisfies the
  assignment's state-management requirement for server data (Zustand,
  merged separately via #60, covers local Fridge UI state)
- Vite dev proxy for /project2/graphql mirrors the Apache proxy in
  production, and honors VITE_GRAPHQL_URL like IngredientSearch.tsx does
- Fixed a real bug found while wiring this up: RecipeFilter's category
  values were lowercase ("beef"), but the server does a case-sensitive
  array-contains match against Title Case data ("Beef") - every category
  filter would have silently returned zero results
- "My Fridge" ingredient matching still happens client-side on the loaded
  page only; the backend has no ingredient filter yet (follow-up issue).
  The any-ingredient-matches semantics and "Back to Fridge" link are from
  #60, rebased on top of here together with their HomePage/test changes
- Loading and error states, aria-live reads the server's totalCount

Closes #58

AI usage: Claude Code wrote the implementation and tests in this commit,
driven by a reviewed plan; manually verified end-to-end in a browser
against a local backend/Postgres with the real dataset (search, category
filter, pagination, detail page, Fridge flow), both before and after
rebasing onto #60's merged ingredient-autocomplete/Fridge-persistence work.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@davidhne davidhne requested a review from a team as a code owner October 15, 2026 10:32
@davidhne davidhne added this to the Innlevering 2 milestone Oct 15, 2026
@davidhne davidhne added enhancement New feature or request frontend React/Vite client a11y Accessibility / universell utforming labels Oct 15, 2026
@davidhne davidhne self-assigned this Oct 15, 2026
Copy link
Member

@jonhella jonhella left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! This is a huge step to the final product!

@jonhella jonhella merged commit 3fe34a1 into main Oct 15, 2026
Sign in to join this conversation on GitHub.
Labels
a11y Accessibility / universell utforming enhancement New feature or request frontend React/Vite client
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Connect the frontend to the real GraphQL API (replace mock data)
2 participants