re-voice/site/red-team-shadow-dossiers/components/RoastGenerator.tsx

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>
);
};