grantforge-api / frontend-react /src /components /project /GenerationConsentModal.tsx
GrantForge Bot
Deploy sha-565ad85979610064f6d1c18ab3b6404357d61073 — source build (no GHCR)
ce8f04a
Raw
History Blame Contribute Delete
6.46 kB
import React, { useState } from 'react';
import { AlertTriangle, FileText, ShieldAlert } from 'lucide-react';
interface Props {
open: boolean;
dossierLevel?: string;
onCancel: () => void;
onConfirm: () => Promise<void> | void;
loading?: boolean;
}
/**
* F1: explicit consent to generate structure without regulation pack.
*/
const GenerationConsentModal: React.FC<Props> = ({
open,
dossierLevel = 'blind',
onCancel,
onConfirm,
loading = false,
}) => {
const [ack, setAck] = useState(false);
if (!open) return null;
return (
<div
style={{
position: 'fixed',
inset: 0,
zIndex: 9999,
background: 'rgba(0,0,0,0.65)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
padding: '1.5rem',
}}
role="dialog"
aria-modal="true"
aria-labelledby="consent-title"
>
<div
className="glass-card"
style={{
maxWidth: 520,
width: '100%',
padding: '1.75rem',
border: '1px solid rgba(245,158,11,0.4)',
background: 'var(--bg-elevated, #1a1a2e)',
}}
>
<div style={{ display: 'flex', gap: '0.75rem', alignItems: 'flex-start', marginBottom: '1rem' }}>
<ShieldAlert size={28} color="#f59e0b" style={{ flexShrink: 0 }} />
<div>
<h2 id="consent-title" style={{ margin: 0, fontSize: '1.25rem', color: '#fff' }}>
Generacja bez regulaminu naboru
</h2>
<p style={{ margin: '0.35rem 0 0', fontSize: '0.8rem', color: 'var(--text-muted)' }}>
Status dossier: <strong style={{ color: '#f87171' }}>{dossierLevel || 'blind'}</strong>
</p>
</div>
</div>
<p style={{ color: '#e5e7eb', lineHeight: 1.65, fontSize: '0.95rem', margin: '0 0 1rem' }}>
Nie mamy w systemie regulaminu / wytycznych tego naboru.
Możemy wygenerować <strong style={{ color: '#fff' }}>szkielet sekcji</strong> na podstawie
opisu projektu i danych firmy (tryb strukturalny).
</p>
<ul style={{ color: '#d1d5db', fontSize: '0.9rem', lineHeight: 1.6, margin: '0 0 1rem', paddingLeft: '1.2rem' }}>
<li>
<strong style={{ color: '#fbbf24' }}>Nie</strong> będzie to ugruntowane w regułach naboru
</li>
<li>Limity, koszty, DNSH i checklista mogą być niekompletne</li>
<li>Ostateczna weryfikacja z oficjalnymi dokumentami leży po Twojej stronie</li>
</ul>
<div
style={{
display: 'flex',
gap: '0.5rem',
padding: '0.75rem',
background: 'rgba(245,158,11,0.1)',
borderRadius: 8,
marginBottom: '1rem',
fontSize: '0.85rem',
color: '#fde68a',
}}
>
<AlertTriangle size={16} style={{ flexShrink: 0, marginTop: 2 }} />
Preferujemy dołączenie regulaminu (URL/PDF) zamiast tej ścieżki.
</div>
<label
style={{
display: 'flex',
gap: '0.65rem',
alignItems: 'flex-start',
cursor: 'pointer',
marginBottom: '1.25rem',
color: '#e5e7eb',
fontSize: '0.9rem',
lineHeight: 1.5,
}}
>
<input
type="checkbox"
checked={ack}
onChange={(e) => setAck(e.target.checked)}
style={{ marginTop: 4, width: 16, height: 16 }}
/>
<span>
Rozumiem ryzyka i chcę wygenerować strukturę wniosku bez regulaminu w systemie.
</span>
</label>
<div style={{ display: 'flex', gap: '0.75rem', flexWrap: 'wrap', justifyContent: 'flex-end' }}>
<button
type="button"
onClick={onCancel}
disabled={loading}
className="btn"
style={{
padding: '0.65rem 1.1rem',
background: 'transparent',
border: '1px solid rgba(255,255,255,0.2)',
color: '#fff',
borderRadius: 8,
cursor: 'pointer',
}}
>
Anuluj
</button>
<button
type="button"
disabled={!ack || loading}
onClick={() => onConfirm()}
style={{
padding: '0.65rem 1.1rem',
background: ack ? 'linear-gradient(90deg, #d97706, #b45309)' : 'rgba(255,255,255,0.1)',
border: 'none',
color: '#fff',
borderRadius: 8,
fontWeight: 700,
cursor: ack ? 'pointer' : 'not-allowed',
display: 'inline-flex',
alignItems: 'center',
gap: '0.4rem',
opacity: loading ? 0.7 : 1,
}}
>
<FileText size={16} />
{loading ? 'Zapisuję…' : 'Akceptuję i generuję strukturę'}
</button>
</div>
</div>
</div>
);
};
export default GenerationConsentModal;