feat(FE): AI Implementation Analyzer — readiness score, use-cases, roadmap, ROI via Hermes

This commit is contained in:
admin-valentin 2026-08-26 19:12:33 +00:00
parent a489e614c5
commit 979e41845b

View file

@ -0,0 +1,210 @@
'use client';
import { useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { apiFetch } from '../../../lib/api';
import { useSession } from '../../../components/session-provider';
const DEPARTMENTS = [
'Sales & Marketing', 'Customer Success', 'Finance & Accounting',
'HR & Recruitment', 'Operations & Logistics', 'Product & Engineering',
'Legal & Compliance', 'Executive & Strategy',
];
const COMPANY_SIZES = ['1-10', '11-50', '51-200', '201-1000', '1000+'];
interface AnalysisResult {
readinessScore: number;
summary: string;
useCases: string;
roadmap: string;
risks: string;
roi: string;
}
export default function AiAnalyzerPage() {
const { activeTenant } = useSession();
const tenantId = activeTenant?.tenantId ?? '';
const [form, setForm] = useState({
companyName: '', industry: '', size: '11-50', description: '',
currentTools: '', departments: [] as string[], budget: '', timeline: '6',
});
const [result, setResult] = useState<AnalysisResult | null>(null);
const analyzeMut = useMutation({
mutationFn: () => {
const prompt = [
`Analizează potențialul de implementare AI pentru această companie și generează un raport detaliat.`,
``,
`## Date companie`,
`Nume: ${form.companyName || 'Nespecificat'}`,
`Industrie: ${form.industry}`,
`Dimensiune: ${form.size} angajați`,
`Descriere: ${form.description}`,
`Tool-uri existente: ${form.currentTools || 'Nespecificate'}`,
`Departamente prioritare: ${form.departments.join(', ') || 'Toate'}`,
`Buget estimat: ${form.budget || 'Nespecificat'} EUR`,
`Timeline dorit: ${form.timeline} luni`,
``,
`Generează un raport structurat cu aceste secțiuni (format JSON valid):`,
`{`,
` "readinessScore": [0-100, scor de pregătire pentru AI],`,
` "summary": "[2-3 fraze: situația actuală și potențialul]",`,
` "useCases": "[top 5 use-case-uri specifice industriei, cu impact cuantificat]",`,
` "roadmap": "[roadmap implementare 3 faze: Quick wins 0-3 luni, Foundation 3-6 luni, Scale 6-12 luni]",`,
` "risks": "[top 3 riscuri și mitigation]",`,
` "roi": "[estimare ROI: costuri implementare vs beneficii cuantificate]"`,
`}`,
`Răspunde DOAR cu JSON valid, fără text extra.`,
].join('\n');
return apiFetch<{ reply: string }>('/v1/ai/ask', {
tenantId, method: 'POST',
body: {
messages: [{ role: 'user', content: prompt }],
context: JSON.stringify({ context: 'ai_implementation_analysis' }),
},
});
},
onSuccess: (data) => {
try {
const json = JSON.parse(data.reply.match(/\{[\s\S]*\}/)?.[0] ?? data.reply);
setResult(json);
} catch {
setResult({ readinessScore: 0, summary: data.reply, useCases: '', roadmap: '', risks: '', roi: '' });
}
},
});
function toggleDept(d: string) {
setForm(f => ({
...f,
departments: f.departments.includes(d) ? f.departments.filter(x => x !== d) : [...f.departments, d],
}));
}
const scoreColor = result
? result.readinessScore >= 70 ? 'text-signal-ok' : result.readinessScore >= 40 ? 'text-amber-600' : 'text-signal-danger'
: 'text-ink';
return (
<div className="max-w-4xl space-y-6 p-6">
<div>
<h1 className="font-display text-2xl font-semibold text-ink">AI Implementation Analyzer</h1>
<p className="text-sm text-ink-faint mt-1">
Analizează potențialul AI pentru orice companie scor, use-case-uri, roadmap, ROI
</p>
</div>
{!result ? (
<div className="card p-6 space-y-5">
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs font-medium text-ink-faint">Nume companie</label>
<input value={form.companyName} onChange={e => setForm(f => ({...f, companyName: e.target.value}))}
placeholder="Acme GmbH" className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
</div>
<div>
<label className="text-xs font-medium text-ink-faint">Industrie</label>
<input value={form.industry} onChange={e => setForm(f => ({...f, industry: e.target.value}))}
placeholder="ex: Logistică, SaaS, Healthcare, Retail…" className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
</div>
</div>
<div>
<label className="text-xs font-medium text-ink-faint">Descriere activitate</label>
<textarea value={form.description} onChange={e => setForm(f => ({...f, description: e.target.value}))}
rows={3} placeholder="Ce face compania, ce procese principale are, care sunt provocările…"
className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring resize-none" />
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs font-medium text-ink-faint">Dimensiune echipă</label>
<div className="mt-1 flex flex-wrap gap-1.5">
{COMPANY_SIZES.map(s => (
<button key={s} onClick={() => setForm(f => ({...f, size: s}))}
className={`rounded-lg border px-3 py-1 text-xs ${form.size === s ? 'bg-primary text-white border-primary' : 'bg-background text-ink-faint border-border'}`}>
{s}
</button>
))}
</div>
</div>
<div>
<label className="text-xs font-medium text-ink-faint">Tool-uri existente</label>
<input value={form.currentTools} onChange={e => setForm(f => ({...f, currentTools: e.target.value}))}
placeholder="CRM, ERP, Office365, Slack…" className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
</div>
</div>
<div>
<label className="text-xs font-medium text-ink-faint">Departamente prioritare</label>
<div className="mt-1 flex flex-wrap gap-1.5">
{DEPARTMENTS.map(d => (
<button key={d} onClick={() => toggleDept(d)}
className={`rounded-lg border px-2.5 py-1 text-xs ${form.departments.includes(d) ? 'bg-indigo-600 text-white border-indigo-600' : 'bg-background text-ink-faint border-border hover:border-indigo-300'}`}>
{d}
</button>
))}
</div>
</div>
<div className="grid grid-cols-2 gap-4">
<div>
<label className="text-xs font-medium text-ink-faint">Buget estimat (EUR)</label>
<input value={form.budget} onChange={e => setForm(f => ({...f, budget: e.target.value}))}
placeholder="ex: 50000" type="number" className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring" />
</div>
<div>
<label className="text-xs font-medium text-ink-faint">Timeline (luni)</label>
<select value={form.timeline} onChange={e => setForm(f => ({...f, timeline: e.target.value}))}
className="mt-1 w-full rounded-lg border bg-background px-3 py-2 text-sm text-ink focus:outline-none focus:ring-2 focus:ring-ring">
{['3','6','12','18','24'].map(t => <option key={t} value={t}>{t} luni</option>)}
</select>
</div>
</div>
<button onClick={() => analyzeMut.mutate()}
disabled={!form.industry || !form.description || analyzeMut.isPending}
className="w-full rounded-xl bg-primary py-3 text-sm font-semibold text-white disabled:opacity-50">
{analyzeMut.isPending ? '✦ Analizez cu Hermes AI…' : '✦ Generează Analiza AI'}
</button>
</div>
) : (
<div className="space-y-4">
{/* Score */}
<div className="card p-6 flex items-center gap-6">
<div className="text-center">
<p className={`text-6xl font-bold ${scoreColor}`}>{result.readinessScore}</p>
<p className="text-xs text-ink-faint">AI Readiness Score</p>
<p className="text-xs font-medium mt-1">
{result.readinessScore >= 70 ? '🟢 Pregătit' : result.readinessScore >= 40 ? '🟡 Parțial pregătit' : '🔴 Fundament necesar'}
</p>
</div>
<div className="flex-1">
<p className="text-sm text-ink">{result.summary}</p>
</div>
</div>
{/* Cards */}
{[
{ title: '🎯 Top Use-Case-uri', content: result.useCases, bg: 'bg-indigo-50 border-indigo-200' },
{ title: '🗺️ Roadmap Implementare', content: result.roadmap, bg: 'bg-emerald-50 border-emerald-200' },
{ title: '💰 ROI Estimat', content: result.roi, bg: 'bg-amber-50 border-amber-200' },
{ title: '⚠️ Riscuri & Mitigare', content: result.risks, bg: 'bg-red-50 border-red-200' },
].map(card => (
<div key={card.title} className={`card p-5 ${card.bg} space-y-2`}>
<p className="text-sm font-semibold text-ink">{card.title}</p>
<p className="text-xs text-ink whitespace-pre-line leading-relaxed">{card.content}</p>
</div>
))}
<button onClick={() => setResult(null)}
className="w-full rounded-xl border py-2.5 text-sm text-ink-faint hover:bg-muted/50">
Analizează altă companie
</button>
</div>
)}
</div>
);
}