frontend_nyla/src/components/OnboardingWizard.tsx
2026-04-09 00:11:35 +02:00

125 lines
5 KiB
TypeScript

import React, { useState } from 'react';
import api from '../api';
import { useLanguage } from '../providers/language/LanguageContext';
interface OnboardingWizardProps {
onComplete: () => void;
onDismiss: () => void;
}
const OnboardingWizard: React.FC<OnboardingWizardProps> = ({ onComplete, onDismiss }) => {
const { t } = useLanguage();
const [planKey, setPlanKey] = useState<'TRIAL_7D' | 'STANDARD_MONTHLY'>('TRIAL_7D');
const [mandateName, setMandateName] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const _handleSubmit = async () => {
setLoading(true);
setError(null);
try {
const res = await api.post('/api/local/onboarding', {
planKey,
companyName: mandateName.trim() || undefined,
});
if (res.data?.alreadyProvisioned) {
setError(t('onboardingWizard.duHastBereitsEinenMandanten'));
return;
}
window.dispatchEvent(new CustomEvent('features-changed'));
onComplete();
} catch (err: any) {
setError(err?.response?.data?.detail || 'Fehler bei der Einrichtung');
} finally {
setLoading(false);
}
};
return (
<div style={{
position: 'fixed', top: 0, left: 0, right: 0, bottom: 0,
background: 'rgba(0,0,0,0.6)', display: 'flex', alignItems: 'center', justifyContent: 'center',
zIndex: 9999,
}}>
<div style={{
background: 'var(--bg-primary, #fff)', borderRadius: '12px', padding: '32px',
maxWidth: '480px', width: '90%', boxShadow: '0 8px 32px rgba(0,0,0,0.2)',
}}>
<h2 style={{ margin: '0 0 8px', fontSize: '1.5rem' }}>{t('onboardingWizard.mandantErstellen')}</h2>
<p style={{ color: 'var(--text-secondary, #666)', margin: '0 0 24px' }}>
Erstelle deinen eigenen Arbeitsbereich mit Abo-Auswahl.
</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px', marginBottom: '20px' }}>
<label style={{
display: 'flex', alignItems: 'center', gap: '12px', padding: '16px',
border: planKey === 'TRIAL_7D' ? '2px solid var(--accent, #4f46e5)' : '2px solid var(--border, #e5e7eb)',
borderRadius: '8px', cursor: 'pointer',
}}>
<input type="radio" name="plan" checked={planKey === 'TRIAL_7D'}
onChange={() => setPlanKey('TRIAL_7D')} />
<div>
<strong>{t('onboardingWizard.kostenlosTesten')}</strong>
<div style={{ fontSize: '0.85rem', color: 'var(--text-secondary, #666)' }}>
7 Tage gratis, danach flexibel upgraden
</div>
</div>
</label>
<label style={{
display: 'flex', alignItems: 'center', gap: '12px', padding: '16px',
border: planKey === 'STANDARD_MONTHLY' ? '2px solid var(--accent, #4f46e5)' : '2px solid var(--border, #e5e7eb)',
borderRadius: '8px', cursor: 'pointer',
}}>
<input type="radio" name="plan" checked={planKey === 'STANDARD_MONTHLY'}
onChange={() => setPlanKey('STANDARD_MONTHLY')} />
<div>
<strong>{t('onboardingWizard.standardMonatlich')}</strong>
<div style={{ fontSize: '0.85rem', color: 'var(--text-secondary, #666)' }}>
Team-Workspace mit vollem Funktionsumfang
</div>
</div>
</label>
</div>
<div style={{ marginBottom: '20px' }}>
<label style={{ display: 'block', marginBottom: '6px', fontWeight: 500 }}>
Name des Mandanten <span style={{ fontWeight: 400, color: 'var(--text-secondary, #666)' }}>(optional)</span>
</label>
<input
type="text" value={mandateName}
onChange={(e) => setMandateName(e.target.value)}
placeholder={t('onboardingWizard.zBFirmennameOderProjektname')}
style={{
width: '100%', padding: '10px 12px', borderRadius: '6px',
border: '1px solid var(--border, #d1d5db)', fontSize: '1rem',
boxSizing: 'border-box',
}}
/>
</div>
{error && <p style={{ color: '#ef4444', margin: '0 0 16px' }}>{error}</p>}
<div style={{ display: 'flex', gap: '12px', justifyContent: 'flex-end' }}>
<button onClick={onDismiss} style={{
padding: '10px 20px', borderRadius: '6px', border: '1px solid var(--border, #d1d5db)',
background: 'transparent', cursor: 'pointer',
}}>
Abbrechen
</button>
<button onClick={_handleSubmit} disabled={loading}
style={{
padding: '10px 20px', borderRadius: '6px', border: 'none',
background: 'var(--accent, #4f46e5)', color: '#fff', cursor: 'pointer',
opacity: loading ? 0.6 : 1,
}}>
{loading ? t('onboardingWizard.wirdEingerichtet') : t('onboardingWizard.mandantErstellen')}
</button>
</div>
</div>
</div>
);
};
export default OnboardingWizard;