mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
merge: QA fix mental-health into release/v1.25.0
This commit is contained in:
commit
8e4c107a18
19 files changed
+606
-104
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
Activity,
|
||||
Bell,
|
||||
Brain,
|
||||
Droplets,
|
||||
FileScan,
|
||||
FlaskConical,
|
||||
@@ -82,6 +83,19 @@ export const NAV_DESTINATIONS: ReadonlyArray<NavDestination> = [
|
||||
tourId: "nav-mood",
|
||||
requiresModule: "mood",
|
||||
},
|
||||
// v1.25.0 — opt-in mental-health screeners (PHQ-9 / GAD-7), beside mood.
|
||||
// Born-gated: `requiresModule: "mentalHealth"` reads the opt-in (default-off)
|
||||
// key from the resolved module map, so the entry is absent until the account
|
||||
// turns the module on from the Modules hub. The destination is the dedicated
|
||||
// `/insights/mental-wellbeing` check-in surface (its own nav home — the
|
||||
// active-detection helper defers `/insights` to it on that path).
|
||||
{
|
||||
href: "/insights/mental-wellbeing",
|
||||
tKey: "nav.mentalWellbeing",
|
||||
icon: Brain,
|
||||
tourId: "nav-mental-wellbeing",
|
||||
requiresModule: "mentalHealth",
|
||||
},
|
||||
{
|
||||
href: "/cycle",
|
||||
tKey: "nav.cycle",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* positive PHQ-9 item-9 the server returns a calm, locale-aware crisis-resource
|
||||
* set which is rendered immediately below the result.
|
||||
*/
|
||||
import { useMemo, useState } from "react";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { useTranslations, useFormatters } from "@/lib/i18n/context";
|
||||
@@ -63,6 +63,16 @@ export function MentalWellbeing() {
|
||||
const [functional, setFunctional] = useState<number | null>(null);
|
||||
const [result, setResult] = useState<CreateResponse | null>(null);
|
||||
|
||||
// a11y: on submit the form (incl. the submit button) unmounts and `phase`
|
||||
// flips to "result". Move focus to the result heading so keyboard / screen-
|
||||
// reader users are not dropped to `<body>` and land on the new content.
|
||||
const resultHeadingRef = useRef<HTMLDivElement | null>(null);
|
||||
useEffect(() => {
|
||||
if (phase === "result") {
|
||||
resultHeadingRef.current?.focus();
|
||||
}
|
||||
}, [phase]);
|
||||
|
||||
const lower = (id: InstrumentId) => (id === "PHQ9" ? "phq9" : "gad7");
|
||||
|
||||
const { data: history } = useQuery({
|
||||
@@ -191,6 +201,9 @@ export function MentalWellbeing() {
|
||||
key={v}
|
||||
type="button"
|
||||
size="sm"
|
||||
// 44px touch-target floor (WCAG 2.5.5) — these are the
|
||||
// questionnaire option controls a full PHQ-9 taps 36 times.
|
||||
className="min-h-11"
|
||||
variant={items[i] === v ? "default" : "outline"}
|
||||
aria-pressed={items[i] === v}
|
||||
onClick={() =>
|
||||
@@ -221,6 +234,8 @@ export function MentalWellbeing() {
|
||||
key={v}
|
||||
type="button"
|
||||
size="sm"
|
||||
// 44px touch-target floor (WCAG 2.5.5), matching the scale.
|
||||
className="min-h-11"
|
||||
variant={functional === v ? "default" : "outline"}
|
||||
aria-pressed={functional === v}
|
||||
onClick={() => setFunctional(v)}
|
||||
@@ -251,7 +266,13 @@ export function MentalWellbeing() {
|
||||
</p>
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{t("mentalHealth.result.title")}</CardTitle>
|
||||
<CardTitle
|
||||
ref={resultHeadingRef}
|
||||
tabIndex={-1}
|
||||
className="scroll-mt-4 outline-none"
|
||||
>
|
||||
{t("mentalHealth.result.title")}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3 text-sm">
|
||||
<div className="flex items-baseline justify-between">
|
||||
@@ -281,7 +302,11 @@ export function MentalWellbeing() {
|
||||
</Card>
|
||||
|
||||
{result.crisis && (
|
||||
<Card className="border-amber-400/50">
|
||||
<Card
|
||||
className="border-amber-400/50"
|
||||
role="alert"
|
||||
aria-live="assertive"
|
||||
>
|
||||
<CardHeader>
|
||||
<CardTitle className="text-base">
|
||||
{t("mentalHealth.crisis.title")}
|
||||
|
||||
@@ -28,6 +28,7 @@ import {
|
||||
Activity,
|
||||
Award,
|
||||
Blocks,
|
||||
Brain,
|
||||
CalendarHeart,
|
||||
Droplet,
|
||||
CloudSun,
|
||||
@@ -80,6 +81,8 @@ const MODULE_ICONS: Record<ModuleKey, LucideIcon> = {
|
||||
mcp: Plug,
|
||||
// v1.25.0 (W-DOCS-IN) — inbound clinical documents (opt-in).
|
||||
inboundDocuments: FileScan,
|
||||
// v1.25.0 — opt-in mental-health screeners (PHQ-9 / GAD-7).
|
||||
mentalHealth: Brain,
|
||||
};
|
||||
|
||||
export function ModulesSection() {
|
||||
|
||||
Reference in new issue
Block a user