Skip to content

fix(search): distinguish UNKNOWN vs NOT-APPLICABLE Nutri-Score labels in filter panel (#980)#984

Merged
ericsocrat merged 1 commit intomainfrom
fix/980-nutri-score-label-distinction
Mar 19, 2026
Merged

fix(search): distinguish UNKNOWN vs NOT-APPLICABLE Nutri-Score labels in filter panel (#980)#984
ericsocrat merged 1 commit intomainfrom
fix/980-nutri-score-label-distinction

Conversation

@ericsocrat
Copy link
Owner

Summary

Closes #980 (child of Epic #979)

Previously, both UNKNOWN and NOT-APPLICABLE Nutri-Score values displayed as a single generic fallback ("Not Rated"), losing valuable semantic distinction. Users couldn't tell whether a product was exempt from Nutri-Score (alcohol, infant formula) or simply had missing data.

Changes

Core utility — nutri-label.ts

  • Added optional 3rd parameter notApplicableFallback to nutriScoreLabel()
  • NOT-APPLICABLE → uses notApplicableFallback when provided, otherwise falls back to fallback
  • UNKNOWN → always uses fallback (data-missing semantics)
  • Backward compatible — existing 2-arg callers (SearchAutocomplete, export) unchanged

Visual distinction — constants.ts

  • UNKNOWN: solid muted chip (bg-surface-muted text-foreground-secondary)
  • NOT-APPLICABLE: dashed-border transparent chip (border border-dashed border-strong bg-transparent text-foreground-muted)

i18n — all 3 locales (en/pl/de)

  • Added filters.unknown: "Unknown" / "Nieznany" / "Unbekannt"
  • Added filters.notApplicable: "Exempt" / "Nie dotyczy" / "Ausgenommen"

Components

  • FilterPanel.tsx — updated nutriScoreLabel call with 3 args
  • ActiveFilterChips.tsx — updated nutriScoreLabel call with 3 args

Tests (10 new/updated)

  • nutri-label.test.ts — 3 new tests for 3-param signature behavior
  • FilterPanel.test.tsx — added UNKNOWN to mock data, replaced "Not Rated" test with "Exempt" + "Unknown" distinction tests
  • ActiveFilterChips.test.tsx — updated NOT-APPLICABLE test expectation, added new UNKNOWN test

Verification

npx tsc --noEmit       → 0 errors
vitest run (3 files)   → 74/74 tests pass

File Impact

10 files changed, +59 / -9 lines

Copilot AI review requested due to automatic review settings March 19, 2026 21:52
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@vercel
Copy link

vercel bot commented Mar 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
tryvit Ready Ready Preview, Comment Mar 19, 2026 9:53pm

@github-actions
Copy link

📸 PR Screenshots

Captured 4 screenshots (2 mobile, 2 desktop) for 2 changed page(s):

  • i18n-dashboard
  • search

📥 Download screenshots from workflow artifacts.

Captured by PR Screenshots workflow • 2026-03-19

@github-actions
Copy link

Bundle Size Report

Metric Value
Main baseline 0 KB
This PR 0 KB
Delta +0 KB (+0%)
JS chunks 0
Hard limit 4000 KB

✅ Bundle size is within acceptable limits.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the Search filter UX by distinguishing Nutri-Score values that are missing data (UNKNOWN) from those that are category-exempt (NOT-APPLICABLE), both in labeling and in chip styling.

Changes:

  • Extend nutriScoreLabel() to support a dedicated fallback for NOT-APPLICABLE while keeping UNKNOWN on the standard fallback path.
  • Add distinct NUTRI_COLORS styles for UNKNOWN vs NOT-APPLICABLE.
  • Update Search filter components + i18n (en/pl/de) and adjust/add tests to verify the new distinctions.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/src/lib/nutri-label.ts Adds optional notApplicableFallback to distinguish NOT-APPLICABLE vs UNKNOWN labeling.
frontend/src/lib/nutri-label.test.ts Adds unit tests covering the new 3-arg behavior.
frontend/src/lib/constants.ts Introduces styles for UNKNOWN and NOT-APPLICABLE Nutri-Score chips.
frontend/src/components/search/FilterPanel.tsx Passes distinct i18n labels for UNKNOWN vs NOT-APPLICABLE.
frontend/src/components/search/FilterPanel.test.tsx Updates mock data + assertions for “Unknown” vs “Exempt”.
frontend/src/components/search/ActiveFilterChips.tsx Updates chip labels to reflect UNKNOWN vs NOT-APPLICABLE distinction.
frontend/src/components/search/ActiveFilterChips.test.tsx Updates/extends tests for new chip labels.
frontend/messages/en.json Adds filters.unknown and filters.notApplicable.
frontend/messages/pl.json Adds filters.unknown and filters.notApplicable.
frontend/messages/de.json Adds filters.unknown and filters.notApplicable.

);
});

it("maps UNKNOWN to fallback (not notApplicableFallback)", () => {
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

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

The test name uses a confusing double negative: "maps UNKNOWN to fallback (not notApplicableFallback)". Rewording (e.g., "ignores notApplicableFallback") would make intent clearer and easier to scan in failures.

Suggested change
it("maps UNKNOWN to fallback (not notApplicableFallback)", () => {
it("uses general fallback for UNKNOWN (ignores notApplicableFallback)", () => {

Copilot uses AI. Check for mistakes.
expect(screen.getAllByText("Exempt").length).toBeGreaterThanOrEqual(1);
});
// Raw DB value must NOT appear
expect(screen.queryAllByText(/NOT.APPLICABLE/i)).toHaveLength(0);
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

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

This regex uses a wildcard dot ("NOT.APPLICABLE") which will match any character between NOT and APPLICABLE. Using the literal hyphen (e.g., /NOT-APPLICABLE/i) would be more precise and communicates the intent of preventing the raw DB value from leaking into the UI.

Suggested change
expect(screen.queryAllByText(/NOT.APPLICABLE/i)).toHaveLength(0);
expect(screen.queryAllByText(/NOT-APPLICABLE/i)).toHaveLength(0);

Copilot uses AI. Check for mistakes.
onChange={onChange}
/>,
);
expect(screen.getByText("Nutri Unknown")).toBeTruthy();
Copy link

Copilot AI Mar 19, 2026

Choose a reason for hiding this comment

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

The new UNKNOWN chip test asserts the translated label renders, but it doesn’t assert that the raw value "UNKNOWN" is not shown (the NOT-APPLICABLE test does). Adding that assertion would better protect against regressions where raw DB values leak into the chip text.

Suggested change
expect(screen.getByText("Nutri Unknown")).toBeTruthy();
expect(screen.getByText("Nutri Unknown")).toBeTruthy();
expect(screen.queryByText(/UNKNOWN/i)).toBeNull();

Copilot uses AI. Check for mistakes.
@ericsocrat ericsocrat merged commit e42830f into main Mar 19, 2026
22 checks passed
@ericsocrat ericsocrat deleted the fix/980-nutri-score-label-distinction branch March 19, 2026 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(search): distinguish UNKNOWN vs NOT-APPLICABLE Nutri-Score labels in filter panel

2 participants