mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-13 06:32:03 +00:00
- Add CYCLE_FERTILE_SOON to the cycle-purge push_attempts eventType list so a data reset leaves no dated reproductive-intent delivery trace. - Rate-limit the custom-symptom mutations (POST create, PATCH, DELETE) under a shared cycle:symptom:custom:<userId> bucket (30/min), mirroring the insights route, so a session can't flood the encrypted-label catalogue. - Re-run the active-count cap inside PATCH when a symptom reactivates (hidden → active); a hidden row doesn't count toward the cap, so without the recheck a user could exceed it by hiding then re-enabling rows. - Gate the log-day "limit reached" copy on the cap errorCode rather than any create failure, so a transient/validation error no longer masquerades as the cap being hit; thread the returned key so a new custom symptom auto-selects. - Move the history-chart bar fill alphas into named phase-tokens (HISTORY_REST_OPACITY / HISTORY_PERIOD_OPACITY) so bar intensity lives in one token source alongside FLOW_OPACITY. - Strengthen the confirmed-ovulation calendar marker (ring 1.5px → 2px, fill alpha 0.16 → 0.22) so it stays distinct from the predicted dot on small light screens; keeps its data-attr + aria naming. - Raise the phase-education chip border from /10 to /15 for legible contrast on the tinted tile.
64 lines
2.6 KiB
TypeScript
64 lines
2.6 KiB
TypeScript
/**
|
|
* v1.15.0 — cycle-phase hue tokens.
|
|
*
|
|
* Each phase maps to a dedicated, per-theme CSS custom property defined in
|
|
* `globals.css` (Dracula dark + Alucard light), so the hue is hand-tuned for
|
|
* contrast in both themes — exactly the wellness-ring pattern. The phase
|
|
* semantic is never colour-only: every surface that uses a hue also renders
|
|
* the phase word + an aria-label.
|
|
*/
|
|
import type { CyclePhase, FlowLevel } from "./types";
|
|
|
|
export const PHASE_HUE: Record<CyclePhase, string> = {
|
|
MENSTRUAL: "var(--cycle-phase-menstrual)",
|
|
FOLLICULAR: "var(--cycle-phase-follicular)",
|
|
OVULATORY: "var(--cycle-phase-ovulatory)",
|
|
LUTEAL: "var(--cycle-phase-luteal)",
|
|
};
|
|
|
|
/** Flow-intensity tint for the calendar period dots (rose family). */
|
|
export const FLOW_HUE = "var(--cycle-phase-menstrual)";
|
|
/** Fertile-window tint (follicular green family). */
|
|
export const FERTILE_HUE = "var(--cycle-phase-follicular)";
|
|
/** Ovulation marker tint (amber-gold family). */
|
|
export const OVULATION_HUE = "var(--cycle-phase-ovulatory)";
|
|
|
|
/**
|
|
* Flow-intensity shading — a SINGLE-HUE OPACITY LADDER on the menstrual rose
|
|
* (`FLOW_HUE`), never a rainbow of hues. Heavier flow = a denser fill of the
|
|
* same colour, so the calendar reads as one calm field that deepens with
|
|
* intensity. The ladder is the alpha applied to the period cell's filled pip;
|
|
* every step keeps the day number (foreground, z-10) above it at WCAG AA. The
|
|
* marker is never colour-only — each period day still restates its flow level
|
|
* in the cell aria-label + carries a `data-flow-level` attribute for e2e.
|
|
*
|
|
* SPOTTING (lightest) → HEAVY (densest). NONE keeps no fill (not a period day).
|
|
*/
|
|
export const FLOW_OPACITY: Record<Exclude<FlowLevel, "NONE">, number> = {
|
|
SPOTTING: 0.14,
|
|
LIGHT: 0.26,
|
|
MEDIUM: 0.42,
|
|
HEAVY: 0.62,
|
|
};
|
|
|
|
/** The default period-day fill alpha when a logged day carries no flow grade. */
|
|
export const FLOW_OPACITY_DEFAULT = 0.32;
|
|
|
|
/**
|
|
* History-chart bar fill alphas — the two-segment stacked bar (rest-of-cycle
|
|
* upper, period lower) keeps its intensity here so the chart and the calendar
|
|
* draw their fills from one token source rather than inline literals. The
|
|
* period segment sits denser than the rest span so the bleeding portion reads
|
|
* as the anchor of each bar.
|
|
*/
|
|
export const HISTORY_REST_OPACITY = 0.5;
|
|
export const HISTORY_PERIOD_OPACITY = 0.85;
|
|
|
|
/** Resolve the flow-shading alpha for a logged period day (graceful fallback). */
|
|
export function flowOpacity(flow: string | null | undefined): number {
|
|
if (flow && flow !== "NONE" && flow in FLOW_OPACITY) {
|
|
return FLOW_OPACITY[flow as Exclude<FlowLevel, "NONE">];
|
|
}
|
|
return FLOW_OPACITY_DEFAULT;
|
|
}
|