Implement ST-203 budget logic and tests

This commit is contained in:
Janpeter Visser 2026-04-18 19:00:24 +02:00
parent 2c9344a94f
commit 07afbc3213
11 changed files with 1057 additions and 9 deletions

View file

@ -7,6 +7,7 @@ import {
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { formatEnergyLevelLabel } from "@/lib/check-in/budget";
import type { MorningCheckInRecord } from "@/lib/check-in/types";
import { cn } from "@/lib/utils";
@ -29,7 +30,7 @@ function formatSleepQualityLabel(value: MorningCheckInRecord["sleepQuality"]) {
export function CheckInCard({ todayCheckIn }: CheckInCardProps) {
const title = todayCheckIn ? "Vandaag ingevuld" : "Nog niet ingevuld";
const description = todayCheckIn
? `Energie ${todayCheckIn.energyScore}/10, slaap ${formatSleepQualityLabel(todayCheckIn.sleepQuality).toLowerCase()}.`
? `Energie ${todayCheckIn.energyScore}/10, slaap ${formatSleepQualityLabel(todayCheckIn.sleepQuality).toLowerCase()}, niveau ${formatEnergyLevelLabel(todayCheckIn.energyLevel).toLowerCase()}, budget ${todayCheckIn.dailyBudget} punten.`
: "Leg je energiestart en slaapkwaliteit van vandaag vast.";
return (

View file

@ -12,6 +12,10 @@ import {
} from "@/components/ui/card";
import { Label } from "@/components/ui/label";
import { Separator } from "@/components/ui/separator";
import {
deriveBudgetSnapshot,
formatEnergyLevelLabel,
} from "@/lib/check-in/budget";
import { ENERGY_SCORE_VALUES, SLEEP_QUALITY_OPTIONS } from "@/lib/check-in/options";
import type {
MorningCheckInRecord,
@ -47,6 +51,7 @@ export function CheckInForm({ todayCheckIn }: CheckInFormProps) {
const [sleepQuality, setSleepQuality] = useState<SleepQuality | null>(
todayCheckIn?.sleepQuality ?? null,
);
const predictedBudget = energyScore === null ? null : deriveBudgetSnapshot(energyScore);
return (
<form action={formAction} className="space-y-6" aria-busy={isPending}>
@ -75,6 +80,12 @@ export function CheckInForm({ todayCheckIn }: CheckInFormProps) {
<p className="text-sm leading-7 text-muted-foreground">
{getEnergyScorePrompt(energyScore)}
</p>
{predictedBudget ? (
<p className="text-sm leading-7 text-slate-700">
Voor vandaag geeft dit niveau <strong>{formatEnergyLevelLabel(predictedBudget.energyLevel).toLowerCase()}</strong> en een startbudget van{" "}
<strong>{predictedBudget.dailyBudget} punten</strong>.
</p>
) : null}
</div>
<div className="grid grid-cols-5 gap-2 sm:grid-cols-10">
@ -156,7 +167,7 @@ export function CheckInForm({ todayCheckIn }: CheckInFormProps) {
{isPending
? "Je ochtendcheck-in wordt opgeslagen..."
: todayCheckIn
? "Je kunt de check-in van vandaag nog aanpassen."
? "Je kunt de check-in van vandaag nog aanpassen. Budget en niveau worden dan opnieuw afgeleid."
: "Je vult voor vandaag één check-in in, die je later nog kunt aanpassen."}
</p>