58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useActionState } from "react";
|
|
import { Sparkles } from "lucide-react";
|
|
import { generateDashboardAnalysisAction } from "@/app/ai/actions";
|
|
import { formatDate } from "@/lib/format";
|
|
import type { AiAnalysis } from "@/lib/models/analysis";
|
|
|
|
type Props = {
|
|
analysis: AiAnalysis | null;
|
|
};
|
|
|
|
export function DashboardAnalysisCard({ analysis }: Props) {
|
|
const [state, formAction, pending] = useActionState(generateDashboardAnalysisAction, null);
|
|
|
|
return (
|
|
<section className="flex flex-col gap-3 rounded-lg border border-muted/40 bg-surface p-4">
|
|
<div className="flex items-center justify-between">
|
|
<h2 className="flex items-center gap-1.5 text-lg font-semibold text-fg">
|
|
<Sparkles size={18} className="text-accent" />
|
|
Kondycja treningowa
|
|
</h2>
|
|
<form action={formAction}>
|
|
<button
|
|
type="submit"
|
|
disabled={pending}
|
|
className="rounded-md bg-accent px-3 py-1.5 text-sm font-semibold text-fg transition-opacity hover:opacity-90 disabled:opacity-50"
|
|
>
|
|
{pending ? "Analizuję..." : analysis ? "Odśwież analizę" : "Generuj analizę"}
|
|
</button>
|
|
</form>
|
|
</div>
|
|
|
|
{state && "error" in state ? <p className="text-sm text-accent">{state.error}</p> : null}
|
|
|
|
{analysis ? (
|
|
<div className="flex flex-col gap-2">
|
|
<p className="text-sm text-fg/90">{analysis.summary}</p>
|
|
{analysis.tips.length > 0 ? (
|
|
<ul className="list-disc pl-5 text-sm text-fg/80">
|
|
{analysis.tips.map((tip, index) => (
|
|
<li key={index}>{tip}</li>
|
|
))}
|
|
</ul>
|
|
) : null}
|
|
<p className="text-xs text-fg/40">
|
|
{formatDate(analysis.createdAt)} · {analysis.model}
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<p className="text-sm text-fg/60">
|
|
Wygeneruj kompleksową analizę kondycji łączącą dane biegowe, siłowe, HRV i sen.
|
|
</p>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|