Files
knur-app/components/ai-analysis-card.tsx

61 lines
2.1 KiB
TypeScript
Raw Normal View History

2026-06-16 09:43:48 +02:00
"use client";
import { useActionState } from "react";
import { Sparkles } from "lucide-react";
import { generateAnalysisAction } from "@/app/ai/actions";
import { formatDate } from "@/lib/format";
2026-06-16 11:51:10 +02:00
import type { AiAnalysisTargetType, SerializedAiAnalysis } from "@/lib/models/analysis";
2026-06-16 09:43:48 +02:00
type AiAnalysisCardProps = {
targetType: AiAnalysisTargetType;
targetId: string;
2026-06-16 11:51:10 +02:00
analysis: SerializedAiAnalysis | null;
2026-06-16 09:43:48 +02:00
};
export function AiAnalysisCard({ targetType, targetId, analysis }: AiAnalysisCardProps) {
const [state, formAction, pending] = useActionState(
() => generateAnalysisAction(targetType, targetId),
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" />
Analiza AI
</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 ? "Generowanie..." : analysis ? "Wygeneruj ponownie" : "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">Brak analizy. Wygeneruj podsumowanie i wskazówki AI.</p>
)}
</section>
);
}