Skip to content

Add patient information factsheet vertical slice (home, search, detail)#751

Closed
BigSimmo wants to merge 5 commits into
mainfrom
codex/design-three-patient-information-pages
Closed

Add patient information factsheet vertical slice (home, search, detail)#751
BigSimmo wants to merge 5 commits into
mainfrom
codex/design-three-patient-information-pages

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 17, 2026

Copy link
Copy Markdown
Owner

Motivation

  • Provide a calm, clinically credible patient-facing factsheet experience with browse, search and printable/shareable detail pages that fit the existing Clinical KB shell and design system.
  • Demonstrate the vertical slice using clearly labelled non-clinical sample content so the UI can be reviewed without introducing unapproved clinical guidance.

Description

  • Add a factsheet data layer and sample records in src/components/factsheets/factsheets-data.ts and a small lookup helper findFactsheet that the routes consume.
  • Implement the three public routes: src/app/factsheets/page.tsx (Home), src/app/factsheets/search/page.tsx (Search), and src/app/factsheets/[slug]/page.tsx (Detail), with a layout src/app/factsheets/layout.tsx that reuses a FactsheetShell (src/components/factsheets/factsheet-shell.tsx).
  • Build UI components: FactsheetsHomePage (src/components/factsheets/factsheets-home-page.tsx), FactsheetsSearchPage (src/components/factsheets/factsheets-search-page.tsx), and FactsheetDetailPage (src/components/factsheets/factsheet-detail-page.tsx) using existing primitives (ui-primitives) and the Sheet overlay for accessible share interactions.
  • Include a tiny unit test to protect the sample data contract at tests/factsheets-data.test.ts and update docs/site-map.md to list the new routes; all sample records are explicitly labelled Sample content and the UI contains prominent copy stating these are not clinical guidance.

Testing

  • Ran git diff --check to validate whitespace/merge markers and found no issues. (success)
  • Ran a focused Prettier pass via npx --yes prettier@3.6.2 --check ... against the added factsheet files, which passed for the new files though unrelated docs in the repo had existing format warnings. (new files OK)
  • Executed the repository workflow helpers npm run workflow:lifecycle -- --phase start, npm run workflow:flightplan -- --write-evidence, and npm run workflow:design-sweep to generate the planned verification steps and confirm the change is covered by the repo's UI/design-sweep plan. (planning/sweep output produced)
  • Performed a PR-local dry-run with npm run verify:pr-local -- --dry-run --files ... which printed the verification plan for this change. (dry-run succeeded)
  • Attempted unit/e2e runs but they could not be completed in this environment: npm run test failed because the project dependencies (e.g. vitest) are not installed here, and npm run ensure / npm run verify:ui could not start the app because the local Node runtime is 20.20.2 while the repo requires Node 24.x. (could not run runtime/browser tests)
  • Added one focused Vitest test file tests/factsheets-data.test.ts; running npm run test:focused -- --files tests/factsheets-data.test.ts was refused by the repo scripts because test/fixture paths changed and the full suite is required. (test not executed here)

If requested, the next steps are to: run npm run ensure and the verify:ui matrix on a Node 24 environment to visually validate mobile/desktop/dark-mode/keyboard/reduced-motion/forced-colors states and to run the full test suite (npm run test) to confirm all automated checks pass.


Codex Task

Summary by CodeRabbit

  • New Features
    • Launched a Patient Information library with a “Patient information” shell, browse-by-topic links, and query-based search across factsheets.
    • Added factsheet routes: library landing, searchable results, and individual detail pages with sections, audience/status, and read-time.
    • Added share and print actions on detail pages, including a copy-link modal with error handling.
  • Documentation
    • Updated the sitemap for /factsheets, /factsheets/search, and /factsheets/[slug].
  • Tests
    • Added Vitest coverage for factsheet lookup and sample “updated” status.

@supabase

supabase Bot commented Jul 17, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a Clinical KB patient information library with sample factsheet data, browse and search routes, dynamic detail pages, shared navigation, metadata, sharing and printing actions, sitemap entries, and data tests.

Changes

Clinical factsheets

Layer / File(s) Summary
Factsheet data and lookup
src/components/factsheets/factsheets-data.ts, tests/factsheets-data.test.ts
Defines the Factsheet model, sample records, topics, slug lookup, and tests for lookup and sample-content status.
Factsheet routes and shell
src/app/factsheets/..., src/components/factsheets/factsheet-shell.tsx, scripts/generate-site-map.ts, docs/site-map.md
Adds route modules, metadata, shared navigation, and sitemap entries for factsheets.
Browse and search experiences
src/components/factsheets/factsheets-home-page.tsx, src/components/factsheets/factsheets-search-page.tsx
Adds topic browsing, featured factsheet links, URL-based search, result rendering, and empty-state handling.
Detail route and actions
src/app/factsheets/[slug]/page.tsx, src/components/factsheets/factsheet-detail-page.tsx
Resolves dynamic slugs, generates metadata, handles missing factsheets, renders sections and metadata, and supports sharing and printing.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Visitor
  participant FactsheetsHomePage
  participant FactsheetsSearchPage
  participant factsheets
  Visitor->>FactsheetsHomePage: Submit search query
  FactsheetsHomePage->>FactsheetsSearchPage: Navigate with q parameter
  FactsheetsSearchPage->>factsheets: Filter factsheets
  factsheets-->>FactsheetsSearchPage: Matching records
  FactsheetsSearchPage-->>Visitor: Render results or empty state
Loading

Suggested reviewers: cursoragent

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the change, but it omits the template's Summary, Verification checklist, Risk and rollout, Clinical Governance Preflight, and Notes sections. Add the missing template sections: Summary, Verification checkboxes, Risk and rollout, Clinical Governance Preflight, and Notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the added patient-information factsheet home, search, and detail routes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/design-three-patient-information-pages

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

CI triage

CI failed on this PR. Automated classification of the 3 failed job(s):

  • Static PR checksneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • Unit coverageneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.
  • PR requiredneeds investigation: inspect the failing step and uploaded diagnostics; rerun only after classifying the cause.

Compared with main CI run #2920 (success).

Classification is evidence routing, not permission to ignore a failure. Exact quarantined Playwright identities remain governed by the flake ledger.

@BigSimmo
BigSimmo marked this pull request as ready for review July 17, 2026 19:35
@BigSimmo
BigSimmo enabled auto-merge July 17, 2026 19:35

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/app/factsheets/page.tsx`:
- Around line 5-8: Update the metadata description in the factsheets page’s
Metadata declaration to describe the content as sample layouts only, removing
the claim that it contains approved local resources and clarifying that it is
not clinical guidance.

In `@src/components/factsheets/factsheets-search-page.tsx`:
- Around line 27-33: Update the loading effect keyed by submittedQuery so
clearing the query explicitly calls setLoading(false) before returning. Preserve
the existing timer-based reset and cleanup behavior for non-empty queries,
ensuring the skeleton cannot remain visible after “Clear search”.
🪄 Autofix (Beta)

❌ Autofix failed (check again to retry)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f1b1fc4-1a90-49a5-a2d6-742bf0e69bb5

📥 Commits

Reviewing files that changed from the base of the PR and between b04c95f and a6ae1fd.

📒 Files selected for processing (11)
  • docs/site-map.md
  • src/app/factsheets/[slug]/page.tsx
  • src/app/factsheets/layout.tsx
  • src/app/factsheets/page.tsx
  • src/app/factsheets/search/page.tsx
  • src/components/factsheets/factsheet-detail-page.tsx
  • src/components/factsheets/factsheet-shell.tsx
  • src/components/factsheets/factsheets-data.ts
  • src/components/factsheets/factsheets-home-page.tsx
  • src/components/factsheets/factsheets-search-page.tsx
  • tests/factsheets-data.test.ts

Comment on lines +5 to +8
export const metadata: Metadata = {
title: "Patient Information Sheets | Clinical KB",
description: "Browse patient information sheet layouts and approved local resources.",
};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not describe sample content as approved resources.

Line 7 claims the route contains “approved local resources,” while the rendered page explicitly says it contains sample layouts only. Metadata can appear outside the app, so make this description clearly sample-only and not clinical guidance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/factsheets/page.tsx` around lines 5 - 8, Update the metadata
description in the factsheets page’s Metadata declaration to describe the
content as sample layouts only, removing the claim that it contains approved
local resources and clarifying that it is not clinical guidance.

Comment on lines +27 to +33
useEffect(() => setInput(submittedQuery), [submittedQuery]);
useEffect(() => {
if (!submittedQuery) return;
setLoading(true);
const timeout = window.setTimeout(() => setLoading(false), 180);
return () => window.clearTimeout(timeout);
}, [submittedQuery]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

sed -n '1,220p' src/components/factsheets/factsheets-search-page.tsx

Repository: BigSimmo/Database

Length of output: 6669


🏁 Script executed:

ast-grep outline src/components/factsheets/factsheets-search-page.tsx --view expanded

Repository: BigSimmo/Database

Length of output: 253


🏁 Script executed:

rg -n "loading|submittedQuery|setLoading|useEffect" src/components/factsheets/factsheets-search-page.tsx

Repository: BigSimmo/Database

Length of output: 1011


🏁 Script executed:

python3 - <<'PY'
from pathlib import Path
p = Path('src/components/factsheets/factsheets-search-page.tsx')
print(p.read_text())
PY

Repository: BigSimmo/Database

Length of output: 6670


🏁 Script executed:

sed -n '1,220p' src/components/factsheets/factsheets-search-page.tsx | nl -ba

Repository: BigSimmo/Database

Length of output: 195


Clear search should reset loading.

When submittedQuery becomes empty, the cleanup clears the pending timer and this effect returns without calling setLoading(false), so the skeleton can stay visible after clicking “Clear search”. Reset loading on the empty-query path or derive the busy state from navigation instead.

🧰 Tools
🪛 ESLint

[error] 27-27: Error: Calling setState synchronously within an effect can trigger cascading renders

Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:

  • Update external systems with the latest state from React.
  • Subscribe for updates from some external system, calling setState in a callback function when external state changes.

Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).

/home/jailuser/git/src/components/factsheets/factsheets-search-page.tsx:27:19
25 | const [loading, setLoading] = useState(false);
26 |

27 | useEffect(() => setInput(submittedQuery), [submittedQuery]);
| ^^^^^^^^ Avoid calling setState() directly within an effect
28 | useEffect(() => {
29 | if (!submittedQuery) return;
30 | setLoading(true);

(react-hooks/set-state-in-effect)


[error] 30-30: Error: Calling setState synchronously within an effect can trigger cascading renders

Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:

  • Update external systems with the latest state from React.
  • Subscribe for updates from some external system, calling setState in a callback function when external state changes.

Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).

/home/jailuser/git/src/components/factsheets/factsheets-search-page.tsx:30:5
28 | useEffect(() => {
29 | if (!submittedQuery) return;

30 | setLoading(true);
| ^^^^^^^^^^ Avoid calling setState() directly within an effect
31 | const timeout = window.setTimeout(() => setLoading(false), 180);
32 | return () => window.clearTimeout(timeout);
33 | }, [submittedQuery]);

(react-hooks/set-state-in-effect)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/factsheets/factsheets-search-page.tsx` around lines 27 - 33,
Update the loading effect keyed by submittedQuery so clearing the query
explicitly calls setLoading(false) before returning. Preserve the existing
timer-based reset and cleanup behavior for non-empty queries, ensuring the
skeleton cannot remain visible after “Clear search”.

Source: Linters/SAST tools

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

⚠️ Branch updated during autofix.

The branch was updated while autofix was in progress. Please try again.

auto-merge was automatically disabled July 17, 2026 19:47

Head branch was pushed to by a user without write access

- factsheets-search-page: replace synchronous setState-in-effect with
  the 'adjusting state during rendering' pattern for input sync; remove
  the artificial loading state (search is synchronous over in-memory
  data). Fixes two @eslint-react/hooks-extra lint errors.
- generate-site-map: register /factsheets, /factsheets/[slug], and
  /factsheets/search descriptions in routeDescriptions so the generator
  emits proper descriptions instead of 'Route discovered from app
  directory'.
- docs/site-map.md: correct entry order so factsheets/* sorts before
  favourites (alphabetical localeCompare). Fixes tests/site-map.test.ts.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/generate-site-map.ts (1)

169-186: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover template-literal redirects in the sitemap extractor. src/app/auth/callback/route.ts uses NextResponse.redirect(\${origin}...`)`, which this matcher still misses, so it lands in the app-route-handler list instead of redirects. Add a regression case for this redirect shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/generate-site-map.ts` around lines 169 - 186, Update
extractRedirectTarget to recognize NextResponse.redirect calls whose destination
is a template literal beginning with a dynamic origin or URL prefix, including
the shape used by src/app/auth/callback/route.ts, and return an appropriate
stable redirect target. Add a regression case covering this template-literal
redirect so it is classified as a redirect rather than an app-route handler.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@scripts/generate-site-map.ts`:
- Around line 169-186: Update extractRedirectTarget to recognize
NextResponse.redirect calls whose destination is a template literal beginning
with a dynamic origin or URL prefix, including the shape used by
src/app/auth/callback/route.ts, and return an appropriate stable redirect
target. Add a regression case covering this template-literal redirect so it is
classified as a redirect rather than an app-route handler.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0dfb9bd4-c87b-4a54-8dd6-08c83ecc38de

📥 Commits

Reviewing files that changed from the base of the PR and between b9d0510 and 4e03bbe.

📒 Files selected for processing (2)
  • docs/site-map.md
  • scripts/generate-site-map.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/site-map.md

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants