mirror of
https://github.com/donpat1to/Schichtenplaner.git
synced 2025-11-30 22:45:46 +01:00
added stepsetup for initial admin setup
This commit is contained in:
@@ -1,12 +1,27 @@
|
||||
// frontend/src/pages/Setup/Setup.tsx - UPDATED
|
||||
import React, { useState } from 'react';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
import StepSetup, { Step } from '../../components/StepSetup/StepSetup';
|
||||
|
||||
const API_BASE_URL = '/api';
|
||||
|
||||
const Setup: React.FC = () => {
|
||||
const [step, setStep] = useState(1);
|
||||
const [formData, setFormData] = useState({
|
||||
// ===== TYP-DEFINITIONEN =====
|
||||
interface SetupFormData {
|
||||
password: string;
|
||||
confirmPassword: string;
|
||||
firstname: string;
|
||||
lastname: string;
|
||||
}
|
||||
|
||||
interface SetupStep {
|
||||
id: string;
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
// ===== HOOK FÜR SETUP-LOGIK =====
|
||||
const useSetup = () => {
|
||||
const [currentStep, setCurrentStep] = useState(0);
|
||||
const [formData, setFormData] = useState<SetupFormData>({
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
firstname: '',
|
||||
@@ -16,15 +31,26 @@ const Setup: React.FC = () => {
|
||||
const [error, setError] = useState('');
|
||||
const { checkSetupStatus } = useAuth();
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value
|
||||
}));
|
||||
};
|
||||
const steps: SetupStep[] = [
|
||||
{
|
||||
id: 'password-setup',
|
||||
title: 'Passwort erstellen',
|
||||
subtitle: 'Legen Sie ein sicheres Passwort fest'
|
||||
},
|
||||
{
|
||||
id: 'profile-setup',
|
||||
title: 'Profilinformationen',
|
||||
subtitle: 'Geben Sie Ihre persönlichen Daten ein'
|
||||
},
|
||||
{
|
||||
id: 'confirmation',
|
||||
title: 'Bestätigung',
|
||||
subtitle: 'Setup abschließen'
|
||||
}
|
||||
];
|
||||
|
||||
const validateStep1 = () => {
|
||||
// ===== VALIDIERUNGS-FUNKTIONEN =====
|
||||
const validateStep1 = (): boolean => {
|
||||
if (formData.password.length < 6) {
|
||||
setError('Das Passwort muss mindestens 6 Zeichen lang sein.');
|
||||
return false;
|
||||
@@ -36,7 +62,7 @@ const Setup: React.FC = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const validateStep2 = () => {
|
||||
const validateStep2 = (): boolean => {
|
||||
if (!formData.firstname.trim()) {
|
||||
setError('Bitte geben Sie einen Vornamen ein.');
|
||||
return false;
|
||||
@@ -48,21 +74,66 @@ const Setup: React.FC = () => {
|
||||
return true;
|
||||
};
|
||||
|
||||
const handleNext = () => {
|
||||
setError('');
|
||||
if (step === 1 && validateStep1()) {
|
||||
setStep(2);
|
||||
} else if (step === 2 && validateStep2()) {
|
||||
handleSubmit();
|
||||
const validateCurrentStep = (stepIndex: number): boolean => {
|
||||
switch (stepIndex) {
|
||||
case 0:
|
||||
return validateStep1();
|
||||
case 1:
|
||||
return validateStep2();
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
const handleBack = () => {
|
||||
// ===== NAVIGATIONS-FUNKTIONEN =====
|
||||
const goToNextStep = async (): Promise<void> => {
|
||||
setError('');
|
||||
setStep(1);
|
||||
|
||||
if (!validateCurrentStep(currentStep)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Wenn wir beim letzten Schritt sind, Submit ausführen
|
||||
if (currentStep === steps.length - 1) {
|
||||
await handleSubmit();
|
||||
return;
|
||||
}
|
||||
|
||||
// Ansonsten zum nächsten Schritt gehen
|
||||
setCurrentStep(prev => prev + 1);
|
||||
};
|
||||
|
||||
const handleSubmit = async () => {
|
||||
const goToPrevStep = (): void => {
|
||||
setError('');
|
||||
if (currentStep > 0) {
|
||||
setCurrentStep(prev => prev - 1);
|
||||
}
|
||||
};
|
||||
|
||||
const handleStepChange = (stepIndex: number): void => {
|
||||
setError('');
|
||||
|
||||
// Nur erlauben, zu bereits validierten Schritten zu springen
|
||||
// oder zum nächsten Schritt nach dem aktuellen
|
||||
if (stepIndex <= currentStep + 1) {
|
||||
// Vor dem Wechsel validieren
|
||||
if (stepIndex > currentStep && !validateCurrentStep(currentStep)) {
|
||||
return;
|
||||
}
|
||||
setCurrentStep(stepIndex);
|
||||
}
|
||||
};
|
||||
|
||||
// ===== FORM HANDLER =====
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>): void => {
|
||||
const { name, value } = e.target;
|
||||
setFormData(prev => ({
|
||||
...prev,
|
||||
[name]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const handleSubmit = async (): Promise<void> => {
|
||||
try {
|
||||
setLoading(true);
|
||||
setError('');
|
||||
@@ -102,8 +173,8 @@ const Setup: React.FC = () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Helper to display generated email preview
|
||||
const getEmailPreview = () => {
|
||||
// ===== HELPER FUNCTIONS =====
|
||||
const getEmailPreview = (): string => {
|
||||
if (!formData.firstname.trim() || !formData.lastname.trim()) {
|
||||
return 'vorname.nachname@sp.de';
|
||||
}
|
||||
@@ -113,6 +184,299 @@ const Setup: React.FC = () => {
|
||||
return `${cleanFirstname}.${cleanLastname}@sp.de`;
|
||||
};
|
||||
|
||||
const isStepCompleted = (stepIndex: number): boolean => {
|
||||
switch (stepIndex) {
|
||||
case 0:
|
||||
return formData.password.length >= 6 &&
|
||||
formData.password === formData.confirmPassword;
|
||||
case 1:
|
||||
return !!formData.firstname.trim() && !!formData.lastname.trim();
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
// State
|
||||
currentStep,
|
||||
formData,
|
||||
loading,
|
||||
error,
|
||||
steps,
|
||||
|
||||
// Actions
|
||||
goToNextStep,
|
||||
goToPrevStep,
|
||||
handleStepChange,
|
||||
handleInputChange,
|
||||
|
||||
// Helpers
|
||||
getEmailPreview,
|
||||
isStepCompleted
|
||||
};
|
||||
};
|
||||
|
||||
// ===== STEP-INHALTS-KOMPONENTEN =====
|
||||
interface StepContentProps {
|
||||
formData: SetupFormData;
|
||||
onInputChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||
getEmailPreview: () => string;
|
||||
currentStep: number;
|
||||
}
|
||||
|
||||
const Step1Content: React.FC<StepContentProps> = ({
|
||||
formData,
|
||||
onInputChange
|
||||
}) => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Passwort
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={onInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem',
|
||||
transition: 'border-color 0.3s ease'
|
||||
}}
|
||||
placeholder="Mindestens 6 Zeichen"
|
||||
required
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Passwort bestätigen
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="confirmPassword"
|
||||
value={formData.confirmPassword}
|
||||
onChange={onInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem',
|
||||
transition: 'border-color 0.3s ease'
|
||||
}}
|
||||
placeholder="Passwort wiederholen"
|
||||
required
|
||||
autoComplete="new-password"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Step2Content: React.FC<StepContentProps> = ({
|
||||
formData,
|
||||
onInputChange,
|
||||
getEmailPreview
|
||||
}) => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Vorname
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="firstname"
|
||||
value={formData.firstname}
|
||||
onChange={onInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem'
|
||||
}}
|
||||
placeholder="Max"
|
||||
required
|
||||
autoComplete="given-name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Nachname
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="lastname"
|
||||
value={formData.lastname}
|
||||
onChange={onInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem'
|
||||
}}
|
||||
placeholder="Mustermann"
|
||||
required
|
||||
autoComplete="family-name"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Automatisch generierte E-Mail
|
||||
</label>
|
||||
<div style={{
|
||||
padding: '0.75rem',
|
||||
backgroundColor: '#e9ecef',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
color: '#495057',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'monospace'
|
||||
}}>
|
||||
{getEmailPreview()}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: '0.875rem',
|
||||
color: '#6c757d',
|
||||
marginTop: '0.25rem'
|
||||
}}>
|
||||
Die E-Mail wird automatisch aus Vor- und Nachname generiert
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const Step3Content: React.FC<StepContentProps> = ({
|
||||
formData,
|
||||
getEmailPreview
|
||||
}) => (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||
<div style={{
|
||||
backgroundColor: '#f8f9fa',
|
||||
padding: '1.5rem',
|
||||
borderRadius: '8px',
|
||||
border: '1px solid #e9ecef'
|
||||
}}>
|
||||
<h3 style={{
|
||||
marginBottom: '1rem',
|
||||
color: '#2c3e50',
|
||||
fontSize: '1.1rem',
|
||||
fontWeight: '600'
|
||||
}}>
|
||||
Zusammenfassung
|
||||
</h3>
|
||||
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '0.75rem' }}>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ color: '#6c757d' }}>E-Mail:</span>
|
||||
<span style={{ fontWeight: '500' }}>{getEmailPreview()}</span>
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ color: '#6c757d' }}>Vorname:</span>
|
||||
<span style={{ fontWeight: '500' }}>{formData.firstname || '-'}</span>
|
||||
</div>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ color: '#6c757d' }}>Nachname:</span>
|
||||
<span style={{ fontWeight: '500' }}>{formData.lastname || '-'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style={{
|
||||
padding: '1rem',
|
||||
backgroundColor: '#e7f3ff',
|
||||
borderRadius: '6px',
|
||||
border: '1px solid #b6d7e8',
|
||||
color: '#2c3e50'
|
||||
}}>
|
||||
<strong>💡 Wichtig:</strong> Nach dem Setup können Sie sich mit Ihrer
|
||||
automatisch generierten E-Mail anmelden.
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
// ===== HAUPTKOMPONENTE =====
|
||||
const Setup: React.FC = () => {
|
||||
const {
|
||||
currentStep,
|
||||
formData,
|
||||
loading,
|
||||
error,
|
||||
steps,
|
||||
goToNextStep,
|
||||
goToPrevStep,
|
||||
handleStepChange,
|
||||
handleInputChange,
|
||||
getEmailPreview
|
||||
} = useSetup();
|
||||
|
||||
const renderStepContent = (): React.ReactNode => {
|
||||
const stepProps = {
|
||||
formData,
|
||||
onInputChange: handleInputChange,
|
||||
getEmailPreview,
|
||||
currentStep
|
||||
};
|
||||
|
||||
switch (currentStep) {
|
||||
case 0:
|
||||
return <Step1Content {...stepProps} />;
|
||||
case 1:
|
||||
return <Step2Content {...stepProps} />;
|
||||
case 2:
|
||||
return <Step3Content {...stepProps} />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getNextButtonText = (): string => {
|
||||
if (loading) return '⏳ Wird verarbeitet...';
|
||||
|
||||
switch (currentStep) {
|
||||
case 0:
|
||||
return 'Weiter →';
|
||||
case 1:
|
||||
return 'Weiter →';
|
||||
case 2:
|
||||
return 'Setup abschließen';
|
||||
default:
|
||||
return 'Weiter →';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{
|
||||
minHeight: '100vh',
|
||||
@@ -128,10 +492,10 @@ const Setup: React.FC = () => {
|
||||
borderRadius: '12px',
|
||||
boxShadow: '0 10px 30px rgba(0,0,0,0.1)',
|
||||
width: '100%',
|
||||
maxWidth: '500px',
|
||||
maxWidth: '600px',
|
||||
border: '1px solid #e9ecef'
|
||||
}}>
|
||||
<div style={{ textAlign: 'center', marginBottom: '2rem' }}>
|
||||
<div style={{ textAlign: 'center', marginBottom: '1rem' }}>
|
||||
<h1 style={{
|
||||
fontSize: '2rem',
|
||||
fontWeight: 'bold',
|
||||
@@ -142,12 +506,47 @@ const Setup: React.FC = () => {
|
||||
</h1>
|
||||
<p style={{
|
||||
color: '#6c757d',
|
||||
fontSize: '1.1rem'
|
||||
fontSize: '1.1rem',
|
||||
marginBottom: '2rem'
|
||||
}}>
|
||||
Richten Sie Ihren Administrator-Account ein
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Aktueller Schritt Titel und Beschreibung */}
|
||||
<div style={{ textAlign: 'center', marginBottom: '1.5rem' }}>
|
||||
<h2 style={{
|
||||
fontSize: '1.5rem',
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '0.5rem',
|
||||
color: '#2c3e50'
|
||||
}}>
|
||||
{steps[currentStep].title}
|
||||
</h2>
|
||||
{steps[currentStep].subtitle && (
|
||||
<p style={{
|
||||
color: '#6c757d',
|
||||
fontSize: '1rem'
|
||||
}}>
|
||||
{steps[currentStep].subtitle}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* StepSetup Komponente - nur die Steps ohne Beschreibung */}
|
||||
<div style={{ marginBottom: '2.5rem' }}>
|
||||
<StepSetup
|
||||
steps={steps.map(step => ({ ...step, subtitle: undefined }))}
|
||||
current={currentStep}
|
||||
onChange={handleStepChange}
|
||||
orientation="horizontal"
|
||||
clickable={true}
|
||||
size="md"
|
||||
animated={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Fehleranzeige */}
|
||||
{error && (
|
||||
<div style={{
|
||||
backgroundColor: '#f8d7da',
|
||||
@@ -161,175 +560,37 @@ const Setup: React.FC = () => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 1 && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Passwort
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="password"
|
||||
value={formData.password}
|
||||
onChange={handleInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem',
|
||||
transition: 'border-color 0.3s ease'
|
||||
}}
|
||||
placeholder="Mindestens 6 Zeichen"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Passwort bestätigen
|
||||
</label>
|
||||
<input
|
||||
type="password"
|
||||
name="confirmPassword"
|
||||
value={formData.confirmPassword}
|
||||
onChange={handleInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem',
|
||||
transition: 'border-color 0.3s ease'
|
||||
}}
|
||||
placeholder="Passwort wiederholen"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{step === 2 && (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Vorname
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="firstname"
|
||||
value={formData.firstname}
|
||||
onChange={handleInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem'
|
||||
}}
|
||||
placeholder="Max"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Nachname
|
||||
</label>
|
||||
<input
|
||||
type="text"
|
||||
name="lastname"
|
||||
value={formData.lastname}
|
||||
onChange={handleInputChange}
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '0.75rem',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
fontSize: '1rem'
|
||||
}}
|
||||
placeholder="Mustermann"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{
|
||||
display: 'block',
|
||||
marginBottom: '0.5rem',
|
||||
fontWeight: '600',
|
||||
color: '#495057'
|
||||
}}>
|
||||
Automatisch generierte E-Mail
|
||||
</label>
|
||||
<div style={{
|
||||
padding: '0.75rem',
|
||||
backgroundColor: '#e9ecef',
|
||||
border: '1px solid #ced4da',
|
||||
borderRadius: '6px',
|
||||
color: '#495057',
|
||||
fontWeight: '500',
|
||||
fontFamily: 'monospace'
|
||||
}}>
|
||||
{getEmailPreview()}
|
||||
</div>
|
||||
<div style={{
|
||||
fontSize: '0.875rem',
|
||||
color: '#6c757d',
|
||||
marginTop: '0.25rem'
|
||||
}}>
|
||||
Die E-Mail wird automatisch aus Vor- und Nachname generiert
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{/* Schritt-Inhalt */}
|
||||
<div style={{ minHeight: '200px' }}>
|
||||
{renderStepContent()}
|
||||
</div>
|
||||
|
||||
{/* Navigations-Buttons */}
|
||||
<div style={{
|
||||
marginTop: '2rem',
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center'
|
||||
}}>
|
||||
{step === 2 && (
|
||||
<button
|
||||
onClick={handleBack}
|
||||
style={{
|
||||
padding: '0.75rem 1.5rem',
|
||||
color: '#6c757d',
|
||||
border: '1px solid #6c757d',
|
||||
background: 'none',
|
||||
borderRadius: '6px',
|
||||
cursor: 'pointer',
|
||||
fontWeight: '500'
|
||||
}}
|
||||
disabled={loading}
|
||||
>
|
||||
← Zurück
|
||||
</button>
|
||||
)}
|
||||
<button
|
||||
onClick={goToPrevStep}
|
||||
disabled={loading || currentStep === 0}
|
||||
style={{
|
||||
padding: '0.75rem 1.5rem',
|
||||
color: loading || currentStep === 0 ? '#adb5bd' : '#6c757d',
|
||||
border: `1px solid ${loading || currentStep === 0 ? '#adb5bd' : '#6c757d'}`,
|
||||
background: 'none',
|
||||
borderRadius: '6px',
|
||||
cursor: loading || currentStep === 0 ? 'not-allowed' : 'pointer',
|
||||
fontWeight: '500',
|
||||
opacity: loading || currentStep === 0 ? 0.6 : 1
|
||||
}}
|
||||
>
|
||||
← Zurück
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={handleNext}
|
||||
onClick={goToNextStep}
|
||||
disabled={loading}
|
||||
style={{
|
||||
padding: '0.75rem 2rem',
|
||||
@@ -340,28 +601,25 @@ const Setup: React.FC = () => {
|
||||
cursor: loading ? 'not-allowed' : 'pointer',
|
||||
fontWeight: '600',
|
||||
fontSize: '1rem',
|
||||
marginLeft: step === 1 ? 'auto' : '0',
|
||||
transition: 'background-color 0.3s ease'
|
||||
}}
|
||||
>
|
||||
{loading ? '⏳ Wird verarbeitet...' :
|
||||
step === 1 ? 'Weiter →' : 'Setup abschließen'}
|
||||
{getNextButtonText()}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{step === 2 && (
|
||||
{/* Zusätzliche Informationen */}
|
||||
{currentStep === 2 && !loading && (
|
||||
<div style={{
|
||||
marginTop: '1.5rem',
|
||||
textAlign: 'center',
|
||||
color: '#6c757d',
|
||||
fontSize: '0.9rem',
|
||||
padding: '1rem',
|
||||
backgroundColor: '#e7f3ff',
|
||||
borderRadius: '6px',
|
||||
border: '1px solid #b6d7e8'
|
||||
backgroundColor: '#f8f9fa',
|
||||
borderRadius: '6px'
|
||||
}}>
|
||||
💡 Nach dem erfolgreichen Setup werden Sie zur Anmeldeseite weitergeleitet,
|
||||
wo Sie sich mit Ihrer automatisch generierten E-Mail anmelden können.
|
||||
Überprüfen Sie Ihre Daten, bevor Sie das Setup abschließen
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user