75 lines
3.4 KiB
TypeScript
75 lines
3.4 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { generateRoast } from '../services/roastClient';
|
|
import { ENABLE_ROAST_GENERATOR } from '../lib/flags';
|
|
|
|
export const RoastGenerator: React.FC = () => {
|
|
if (!ENABLE_ROAST_GENERATOR) return null;
|
|
const [input, setInput] = useState('');
|
|
const [output, setOutput] = useState('');
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleCritique = async () => {
|
|
if (!input.trim()) return;
|
|
setLoading(true);
|
|
try {
|
|
const result = await generateRoast(input);
|
|
setOutput(result);
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<section id="review" className="py-16 md:py-20 px-6 bg-[rgba(247,245,240,0.6)] border-t hairline">
|
|
<div className="max-w-6xl mx-auto">
|
|
<div className="mb-10">
|
|
<div className="mono text-[11px] uppercase tracking-[0.18em] text-slate-500 mb-2">Quick critique</div>
|
|
<h2 className="text-3xl md:text-4xl font-extrabold tracking-tight text-slate-900">Preliminary “truth audit” (AI-assisted)</h2>
|
|
<p className="text-slate-700 mt-3 max-w-3xl">
|
|
Paste a short excerpt from a policy, whitepaper, control description, or vendor claim. This produces a rough critique to help you
|
|
decide whether a custom dossier is worthwhile. Do not paste secrets.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid md:grid-cols-2 gap-6">
|
|
<div className="rounded-xl border hairline bg-white p-6">
|
|
<label className="mono text-[11px] uppercase tracking-[0.18em] text-slate-500">Input</label>
|
|
<textarea
|
|
value={input}
|
|
onChange={(e) => setInput(e.target.value)}
|
|
className="mt-3 w-full h-48 rounded-lg border hairline bg-slate-50 p-4 text-sm focus:outline-none focus:ring-2 focus:ring-[rgba(185,28,28,0.25)] resize-none"
|
|
placeholder="Paste an excerpt here…"
|
|
/>
|
|
<button
|
|
onClick={handleCritique}
|
|
disabled={loading}
|
|
className="mt-4 w-full rounded-md bg-slate-900 text-white py-3 text-sm font-semibold hover:bg-slate-800 disabled:opacity-50 transition-colors"
|
|
>
|
|
{loading ? 'Generating…' : 'Generate critique'}
|
|
</button>
|
|
<p className="mt-3 text-xs text-slate-500">
|
|
Output is best-effort commentary. For a real engagement, request availability via email.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="rounded-xl border hairline bg-white p-6 relative">
|
|
<div className="flex items-center justify-between mb-3">
|
|
<span className="mono text-[11px] uppercase tracking-[0.18em] text-slate-500">Output</span>
|
|
<a href="mailto:dave@infrafabric.io" className="text-xs font-semibold underline hover:no-underline">Request custom dossier</a>
|
|
</div>
|
|
|
|
<div className="h-52 md:h-[19.5rem] overflow-auto rounded-lg border hairline bg-slate-50 p-4 text-sm leading-relaxed text-slate-800">
|
|
{output ? output : <span className="text-slate-400">No output yet.</span>}
|
|
</div>
|
|
|
|
{loading && (
|
|
<div className="absolute inset-0 bg-white/60 backdrop-blur-sm flex items-center justify-center rounded-xl">
|
|
<div className="w-8 h-8 border-2 border-slate-900 border-t-transparent rounded-full animate-spin"></div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|