mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-15 06:52:04 +00:00
Close the gap between the welcome carousel's AI promise and the payoff: a fresh keyless user used to meet "No AI provider connected" on every AI surface, because the only setup prompt was a skippable card on the final screen. Add an "insights" row to the getting-started checklist, derived from real provider state — any personal key, local model, OAuth sign-in, or the operator's shared key flips it done via /api/user/ai-provider. It persists past onboarding, self-satisfies on connect, and dismisses like the others. Elevate the done-screen AI card into a value-first panel: it leads with a static, clearly-labelled example briefing (no model call, no egress, no consent), then the local-first ladder — local model, bring-your-own-key, subscription sign-in with the training caveat — and the honest line that HealthLog is fully useful without AI. All three exits stay, so the panel gates nothing. On a deployment with a shared provider it says so plainly. Extract the worked example into a shared SampleBriefingCard. Add onboarding.ai.* copy across all six locales and retire the old single-card done-screen keys.
58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { Sparkles } from "lucide-react";
|
|
|
|
import { Badge } from "@/components/ui/badge";
|
|
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
|
import { TileHeader } from "@/components/insights/tile-header";
|
|
import { cn } from "@/lib/utils";
|
|
import { useTranslations } from "@/lib/i18n/context";
|
|
|
|
/**
|
|
* The onboarding "aha" artifact — a static, clearly-labelled *example*
|
|
* daily briefing shown BEFORE any AI provider is connected.
|
|
*
|
|
* It exists so a fresh user feels the payoff of AI Insights with zero
|
|
* setup: no provider is configured yet, so this makes no model call, no
|
|
* fetch, no egress, and needs no consent. Every number is fixed copy
|
|
* from the `onboarding.ai.sample*` keys (the worked example the
|
|
* no-provider briefing empty state already carries) — it is never
|
|
* derived from the user's own record, and the "Example" badge plus the
|
|
* caption make that explicit so it is never mistaken for real data.
|
|
*
|
|
* Presentational only — no state, no effect, no data fetch. Reused by
|
|
* the onboarding done-screen panel; safe to drop into any surface that
|
|
* wants to show what a briefing reads like.
|
|
*/
|
|
export function SampleBriefingCard({ className }: { className?: string }) {
|
|
const { t } = useTranslations();
|
|
|
|
return (
|
|
<Card
|
|
data-slot="sample-briefing-card"
|
|
aria-label={t("onboarding.ai.sampleAriaLabel")}
|
|
className={cn("bg-muted/30 gap-2 py-3 md:py-4", className)}
|
|
>
|
|
<CardHeader>
|
|
<TileHeader
|
|
icon={Sparkles}
|
|
title={t("onboarding.ai.sampleTitle")}
|
|
right={
|
|
<Badge variant="secondary" data-slot="sample-briefing-tag">
|
|
{t("onboarding.ai.sampleTag")}
|
|
</Badge>
|
|
}
|
|
/>
|
|
</CardHeader>
|
|
<CardContent className="space-y-2">
|
|
<p className="text-foreground text-sm leading-relaxed">
|
|
{t("onboarding.ai.sampleBody")}
|
|
</p>
|
|
<p className="text-muted-foreground text-xs leading-relaxed">
|
|
{t("onboarding.ai.sampleCaption")}
|
|
</p>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|