feat(web): questionnaires, diary and medication module in the patient app
- Focus screen renders versioned questionnaire items (iq: buttons): section chip, position (adaptive forms without "of N"), recall date, pause / help-now actions, optional skip, sleep-hours input, 0-10 scale anchors, RUS-AUDIT item 2 standard-drink table. - Paused / held-for-review questionnaires get their own screen. - Today: intake and diary tasks, review notice, therapy-day card on days 1/7/14. - Drug card /meds/:ref from data/meds/meds_reference.json (draft built from the Minzdrav guidelines: depression 2024, PTSD 2023) — expected effect, course, side effects, red flags; no doses shown. "Report a side effect" always available (med:side_effects:<ref>). - API: /instruments/catalog, /meds/reference; today gains questionnaire state, reference id, indication and therapy day; demo persona seeds the dashboard dose history. - INTAKE_DEMO=1 (demo clock only) opens the questionnaires on synthetic data without touching the clinical release gate in config/intake_runtime.yaml. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+394
-4
@@ -782,7 +782,7 @@ button.row-card:hover:not(:disabled) {
|
||||
|
||||
.numscale__row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(11, 1fr);
|
||||
grid-template-columns: repeat(var(--n, 11), 1fr);
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
@@ -1900,14 +1900,16 @@ button.row-card:hover:not(:disabled) {
|
||||
|
||||
/* Wide content (consent text, 0–10 scale) reads better in one centred column. */
|
||||
.split--consent,
|
||||
.split--number {
|
||||
.split--number,
|
||||
.split--in-number {
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
max-width: 760px;
|
||||
gap: var(--s-6);
|
||||
}
|
||||
|
||||
.split--consent .split__lead,
|
||||
.split--number .split__lead {
|
||||
.split--number .split__lead,
|
||||
.split--in-number .split__lead {
|
||||
position: static;
|
||||
}
|
||||
|
||||
@@ -1915,7 +1917,8 @@ button.row-card:hover:not(:disabled) {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.split--number .numscale__row {
|
||||
.split--number .numscale__row,
|
||||
.split--in-number .numscale__row {
|
||||
gap: var(--s-2);
|
||||
}
|
||||
|
||||
@@ -2035,6 +2038,393 @@ button.row-card:hover:not(:disabled) {
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ questionnaires (stage 1 / stage 2) */
|
||||
|
||||
.formchip {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: var(--s-2) var(--s-3);
|
||||
}
|
||||
|
||||
.formchip__title {
|
||||
font-size: var(--fs-13);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
.chip--sec {
|
||||
gap: 6px;
|
||||
padding: 5px var(--s-3) 5px 10px;
|
||||
background: var(--c-blue-soft);
|
||||
color: var(--c-blue);
|
||||
}
|
||||
|
||||
.chip--mood,
|
||||
.chip--diary {
|
||||
background: var(--c-teal-soft);
|
||||
color: var(--c-teal-strong);
|
||||
}
|
||||
|
||||
.chip--trauma {
|
||||
background: var(--c-amber-soft);
|
||||
color: #a86a00;
|
||||
}
|
||||
|
||||
.chip--alcohol,
|
||||
.chip--about {
|
||||
background: var(--c-navy-soft);
|
||||
color: var(--c-navy);
|
||||
}
|
||||
|
||||
.survey {
|
||||
gap: var(--s-3);
|
||||
}
|
||||
|
||||
.survey__instr {
|
||||
padding-left: var(--s-3);
|
||||
border-left: 3px solid var(--c-border-strong);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
.survey__instr .body-text {
|
||||
font-size: var(--fs-16);
|
||||
}
|
||||
|
||||
.survey__q {
|
||||
font-size: var(--fs-24);
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.survey__asof {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
font-size: var(--fs-13);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
.survey__aux {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--s-3);
|
||||
padding-top: var(--s-2);
|
||||
border-top: 1px solid var(--c-border);
|
||||
}
|
||||
|
||||
.survey__saved {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.btn--sm {
|
||||
width: auto;
|
||||
min-height: 40px;
|
||||
padding: 0 var(--s-3);
|
||||
font-size: var(--fs-14);
|
||||
}
|
||||
|
||||
.linkbtn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-height: 44px;
|
||||
padding: 0 var(--s-1);
|
||||
border: 0;
|
||||
background: none;
|
||||
font-weight: 600;
|
||||
font-size: var(--fs-14);
|
||||
text-decoration: underline;
|
||||
text-underline-offset: 3px;
|
||||
}
|
||||
|
||||
.linkbtn--danger {
|
||||
color: var(--c-red-strong);
|
||||
}
|
||||
|
||||
.btn--ghost-red {
|
||||
background: transparent;
|
||||
color: var(--c-red-strong);
|
||||
}
|
||||
|
||||
.btn--outline-red {
|
||||
background: var(--c-surface);
|
||||
border-color: var(--c-red);
|
||||
color: var(--c-red-strong);
|
||||
}
|
||||
|
||||
.center-self {
|
||||
align-self: center;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
/* RUS-AUDIT item 2: standard-drink table from the approved form */
|
||||
.drinks {
|
||||
display: grid;
|
||||
gap: var(--s-2);
|
||||
padding: var(--s-4);
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: var(--r-tile);
|
||||
background: var(--c-surface);
|
||||
}
|
||||
|
||||
.drinks__scroll {
|
||||
overflow-x: auto;
|
||||
margin: 0 calc(-1 * var(--s-2));
|
||||
}
|
||||
|
||||
.drinks table {
|
||||
width: 100%;
|
||||
min-width: 420px;
|
||||
border-collapse: collapse;
|
||||
font-size: var(--fs-13);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.drinks th,
|
||||
.drinks td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid var(--c-border);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.drinks thead th {
|
||||
color: var(--c-text-2);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.drinks tbody th {
|
||||
white-space: nowrap;
|
||||
color: var(--c-navy);
|
||||
}
|
||||
|
||||
/* diary: hours of sleep */
|
||||
.hours {
|
||||
display: grid;
|
||||
gap: var(--s-2);
|
||||
}
|
||||
|
||||
.hours__label {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.hours__field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s-2);
|
||||
width: 180px;
|
||||
padding: 0 var(--s-4);
|
||||
border: 1.5px solid var(--c-border-strong);
|
||||
border-radius: var(--r-btn);
|
||||
background: var(--c-surface);
|
||||
}
|
||||
|
||||
.hours__field:focus-within {
|
||||
border-color: var(--c-focus);
|
||||
box-shadow: 0 0 0 3px var(--c-blue-soft);
|
||||
}
|
||||
|
||||
.hours__field input {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
height: var(--tap);
|
||||
border: 0;
|
||||
outline: none;
|
||||
background: none;
|
||||
font-size: var(--fs-28);
|
||||
font-weight: 700;
|
||||
color: var(--c-navy);
|
||||
}
|
||||
|
||||
.hours__field span {
|
||||
font-size: var(--fs-18);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
.hours .btn {
|
||||
margin-top: var(--s-2);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------ medication: drug card, therapy day */
|
||||
|
||||
.rx__foot {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--s-2);
|
||||
padding-top: var(--s-3);
|
||||
border-top: 1px solid var(--c-border);
|
||||
}
|
||||
|
||||
.effect {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s-4);
|
||||
width: 100%;
|
||||
padding: var(--s-3) var(--s-4);
|
||||
border: 1px solid #cfe0f5;
|
||||
border-radius: var(--r-tile);
|
||||
background: var(--c-blue-soft);
|
||||
text-align: left;
|
||||
color: var(--c-text);
|
||||
}
|
||||
|
||||
.effect > svg:last-child {
|
||||
flex: none;
|
||||
color: var(--c-blue);
|
||||
}
|
||||
|
||||
.effect__day {
|
||||
flex: none;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
border-radius: 14px;
|
||||
background: var(--c-surface);
|
||||
color: var(--c-blue);
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.effect__num {
|
||||
font-size: var(--fs-24);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.effect__unit {
|
||||
font-size: var(--fs-12);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
.drug {
|
||||
display: grid;
|
||||
gap: var(--s-6);
|
||||
}
|
||||
|
||||
.drug__head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s-4);
|
||||
}
|
||||
|
||||
.drug__head .tile-icon--xl {
|
||||
width: 72px;
|
||||
height: 72px;
|
||||
}
|
||||
|
||||
.drug__rx {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
margin-top: var(--s-2);
|
||||
padding: 6px var(--s-3);
|
||||
border-radius: var(--r-chip);
|
||||
background: var(--c-teal-soft);
|
||||
color: var(--c-teal-strong);
|
||||
font-size: var(--fs-14);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.drug__grid,
|
||||
.drug__col {
|
||||
display: grid;
|
||||
gap: var(--s-4);
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.drug__sec {
|
||||
display: grid;
|
||||
gap: var(--s-3);
|
||||
padding: var(--s-5);
|
||||
border: 1px solid var(--c-border);
|
||||
border-radius: var(--r-tile);
|
||||
background: var(--c-surface);
|
||||
}
|
||||
|
||||
.drug__sec p {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.drug__sec--red {
|
||||
border-color: var(--c-red-line);
|
||||
background: var(--c-red-soft);
|
||||
}
|
||||
|
||||
.drug__h {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--s-3);
|
||||
margin: 0;
|
||||
font-size: var(--fs-18);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.drug__sub {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.badge-icon--blue {
|
||||
background: var(--c-blue);
|
||||
}
|
||||
|
||||
.timeline {
|
||||
display: grid;
|
||||
gap: var(--s-2);
|
||||
}
|
||||
|
||||
.timeline__bar {
|
||||
position: relative;
|
||||
height: 10px;
|
||||
border-radius: 999px;
|
||||
background: var(--c-tile);
|
||||
border: 1px solid var(--c-border);
|
||||
}
|
||||
|
||||
.timeline__fill {
|
||||
position: absolute;
|
||||
inset: 0 auto 0 0;
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(90deg, var(--c-teal-soft), var(--c-teal));
|
||||
}
|
||||
|
||||
.timeline__mark {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 3px solid var(--c-surface);
|
||||
border-radius: 50%;
|
||||
background: var(--c-teal);
|
||||
box-shadow: 0 1px 3px rgb(15 39 71 / 25%);
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.timeline__legend {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: var(--s-3);
|
||||
font-size: var(--fs-13);
|
||||
color: var(--c-text-2);
|
||||
}
|
||||
|
||||
@media (max-width: 1023px) {
|
||||
.btn-row--stack-phone {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.drug__grid {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: var(--s-5);
|
||||
}
|
||||
|
||||
.survey__q {
|
||||
font-size: var(--fs-28);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
|
||||
Reference in New Issue
Block a user