diff --git a/backend/src/controllers/authController.ts b/backend/src/controllers/authController.ts index e678fcd..ebe8458 100644 --- a/backend/src/controllers/authController.ts +++ b/backend/src/controllers/authController.ts @@ -24,7 +24,7 @@ export interface LoginRequest { } export interface JWTPayload { - id: string; // ← VON number ZU string ÄNDERN + id: string; email: string; role: string; iat?: number; @@ -32,16 +32,26 @@ export interface JWTPayload { } export interface RegisterRequest { - // REMOVED: email - will be auto-generated password: string; firstname: string; lastname: string; - role?: string; + roles?: string[]; } function generateEmail(firstname: string, lastname: string): string { - const cleanFirstname = firstname.toLowerCase().replace(/[^a-z0-9]/g, ''); - const cleanLastname = lastname.toLowerCase().replace(/[^a-z0-9]/g, ''); + // Convert German umlauts to their expanded forms + const convertUmlauts = (str: string): string => { + return str + .toLowerCase() + .replace(/ü/g, 'ue') + .replace(/ö/g, 'oe') + .replace(/ä/g, 'ae') + .replace(/ß/g, 'ss'); + }; + + // Remove any remaining special characters and convert to lowercase + const cleanFirstname = convertUmlauts(firstname).replace(/[^a-z0-9]/g, ''); + const cleanLastname = convertUmlauts(lastname).replace(/[^a-z0-9]/g, ''); return `${cleanFirstname}.${cleanLastname}@sp.de`; } @@ -56,9 +66,17 @@ export const login = async (req: Request, res: Response) => { return res.status(400).json({ error: 'E-Mail und Passwort sind erforderlich' }); } - // Get user from database - const user = await db.get( - 'SELECT id, email, password, firstname, lastname, role, employee_type as employeeType, contract_type as contractType, can_work_alone as canWorkAlone, is_active as isActive FROM employees WHERE email = ? AND is_active = 1', + // UPDATED: Get user from database with role from employee_roles table + const user = await db.get( + `SELECT + e.id, e.email, e.password, e.firstname, e.lastname, + e.employee_type as employeeType, e.contract_type as contractType, + e.can_work_alone as canWorkAlone, e.is_active as isActive, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.email = ? AND e.is_active = 1 + LIMIT 1`, [email] ); @@ -78,11 +96,11 @@ export const login = async (req: Request, res: Response) => { return res.status(401).json({ error: 'Ungültige Anmeldedaten' }); } - // Create token payload - KORREKT: id field verwenden + // Create token payload const tokenPayload = { - id: user.id.toString(), // ← WICHTIG: Dies wird als 'id' im JWT gespeichert + id: user.id.toString(), email: user.email, - role: user.role + role: user.role || 'user' // Fallback to 'user' if no role found }; console.log('🎫 Creating JWT with payload:', tokenPayload); @@ -94,13 +112,17 @@ export const login = async (req: Request, res: Response) => { { expiresIn: '24h' } ); - // Remove password from user object + // Remove password from user object and format response const { password: _, ...userWithoutPassword } = user; + const userResponse = { + ...userWithoutPassword, + roles: user.role ? [user.role] : ['user'] // Convert single role to array for frontend compatibility + }; console.log('✅ Login successful for:', user.email); res.json({ - user: userWithoutPassword, + user: userResponse, token }); } catch (error) { @@ -121,8 +143,17 @@ export const getCurrentUser = async (req: Request, res: Response) => { return res.status(401).json({ error: 'Nicht authentifiziert' }); } - const user = await db.get( - 'SELECT id, email, firstname, lastname, role, employee_type as employeeType, contract_type as contractType, can_work_alone as canWorkAlone, is_active as isActive FROM employees WHERE id = ? AND is_active = 1', + // UPDATED: Get user with role from employee_roles table + const user = await db.get( + `SELECT + e.id, e.email, e.firstname, e.lastname, + e.employee_type as employeeType, e.contract_type as contractType, + e.can_work_alone as canWorkAlone, e.is_active as isActive, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? AND e.is_active = 1 + LIMIT 1`, [jwtUser.userId] ); @@ -133,8 +164,14 @@ export const getCurrentUser = async (req: Request, res: Response) => { return res.status(404).json({ error: 'Benutzer nicht gefunden' }); } + // Format user response with roles array + const userResponse = { + ...user, + roles: user.role ? [user.role] : ['user'] + }; + console.log('✅ Returning user:', user.email); - res.json({ user }); + res.json({ user: userResponse }); } catch (error) { console.error('Get current user error:', error); res.status(500).json({ error: 'Ein Fehler ist beim Abrufen des Benutzers aufgetreten' }); @@ -168,9 +205,9 @@ export const validateToken = async (req: Request, res: Response) => { export const register = async (req: Request, res: Response) => { try { - const { password, firstname, lastname, role = 'user' } = req.body as RegisterRequest; + const { password, firstname, lastname, roles = ['user'] } = req.body as RegisterRequest; - // Validate required fields - REMOVED email + // Validate required fields if (!password || !firstname || !lastname) { return res.status(400).json({ error: 'Password, firstname und lastname sind erforderlich' @@ -192,27 +229,60 @@ export const register = async (req: Request, res: Response) => { }); } - // Hash password and create user + // Hash password const hashedPassword = await bcrypt.hash(password, 10); + const employeeId = uuidv4(); - // Insert user with generated email - const result = await db.run( - `INSERT INTO employees (id, email, password, firstname, lastname, role, employee_type, contract_type, can_work_alone, is_active) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - [uuidv4(), email, hashedPassword, firstname, lastname, role, 'experienced', 'small', false, 1] - ); + // Start transaction for registration + await db.run('BEGIN TRANSACTION'); - if (!result.lastID) { - throw new Error('Benutzer konnte nicht erstellt werden'); + try { + // Insert user without role (role is now in employee_roles table) + const result = await db.run( + `INSERT INTO employees (id, email, password, firstname, lastname, employee_type, contract_type, can_work_alone, is_active) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [employeeId, email, hashedPassword, firstname, lastname, 'experienced', 'small', false, 1] + ); + + if (!result.lastID) { + throw new Error('Benutzer konnte nicht erstellt werden'); + } + + // UPDATED: Insert roles into employee_roles table + for (const role of roles) { + await db.run( + `INSERT INTO employee_roles (employee_id, role) VALUES (?, ?)`, + [employeeId, role] + ); + } + + await db.run('COMMIT'); + + // Get created user with role + const newUser = await db.get( + `SELECT + e.id, e.email, e.firstname, e.lastname, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? + LIMIT 1`, + [employeeId] + ); + + // Format response with roles array + const userResponse = { + ...newUser, + roles: newUser.role ? [newUser.role] : ['user'] + }; + + res.status(201).json({ user: userResponse }); + + } catch (error) { + await db.run('ROLLBACK'); + throw error; } - // Get created user - const newUser = await db.get( - 'SELECT id, email, firstname, lastname, role FROM employees WHERE id = ?', - [result.lastID] - ); - - res.status(201).json({ user: newUser }); } catch (error) { console.error('Registration error:', error); res.status(500).json({ diff --git a/backend/src/controllers/employeeController.ts b/backend/src/controllers/employeeController.ts index e41587c..3cedbcd 100644 --- a/backend/src/controllers/employeeController.ts +++ b/backend/src/controllers/employeeController.ts @@ -33,25 +33,35 @@ export const getEmployees = async (req: AuthRequest, res: Response): Promise(query); - console.log('✅ Employees found:', employees.length); - res.json(employees); + // Format employees with roles array for frontend compatibility + const employeesWithRoles = employees.map(emp => ({ + ...emp, + roles: emp.role ? [emp.role] : ['user'] + })); + + console.log('✅ Employees found:', employeesWithRoles.length); + res.json(employeesWithRoles); } catch (error) { console.error('❌ Error fetching employees:', error); res.status(500).json({ error: 'Internal server error' }); @@ -62,16 +72,21 @@ export const getEmployee = async (req: AuthRequest, res: Response): Promise(` SELECT - id, email, firstname, lastname, role, is_active as isActive, - employee_type as employeeType, - contract_type as contractType, - can_work_alone as canWorkAlone, - created_at as createdAt, - last_login as lastLogin - FROM employees - WHERE id = ? + e.id, e.email, e.firstname, e.lastname, + e.is_active as isActive, + e.employee_type as employeeType, + e.contract_type as contractType, + e.can_work_alone as canWorkAlone, + e.created_at as createdAt, + e.last_login as lastLogin, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? + LIMIT 1 `, [id]); if (!employee) { @@ -79,7 +94,13 @@ export const getEmployee = async (req: AuthRequest, res: Response): Promise(` - SELECT - id, email, firstname, lastname, role, is_active as isActive, - employee_type as employeeType, - contract_type as contractType, - can_work_alone as canWorkAlone, - created_at as createdAt, - last_login as lastLogin - FROM employees - WHERE id = ? - `, [employeeId]); + try { + // UPDATED: Insert employee without role (role is now in employee_roles table) + await db.run( + `INSERT INTO employees ( + id, email, password, firstname, lastname, employee_type, contract_type, can_work_alone, + is_active + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [ + employeeId, + email, + hashedPassword, + firstname, + lastname, + employeeType, + contractType, + canWorkAlone ? 1 : 0, + 1 + ] + ); - res.status(201).json(newEmployee); + // UPDATED: Insert roles into employee_roles table + for (const role of roles) { + await db.run( + `INSERT INTO employee_roles (employee_id, role) VALUES (?, ?)`, + [employeeId, role] + ); + } + + await db.run('COMMIT'); + + // Return created employee with role from employee_roles + const newEmployee = await db.get(` + SELECT + e.id, e.email, e.firstname, e.lastname, + e.is_active as isActive, + e.employee_type as employeeType, + e.contract_type as contractType, + e.can_work_alone as canWorkAlone, + e.created_at as createdAt, + e.last_login as lastLogin, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? + LIMIT 1 + `, [employeeId]); + + // Format response with roles array + const employeeWithRoles = { + ...newEmployee, + roles: newEmployee.role ? [newEmployee.role] : ['user'] + }; + + res.status(201).json(employeeWithRoles); + + } catch (error) { + await db.run('ROLLBACK'); + throw error; + } } catch (error) { console.error('Error creating employee:', error); res.status(500).json({ error: 'Internal server error' }); @@ -173,9 +223,9 @@ export const createEmployee = async (req: AuthRequest, res: Response): Promise => { try { const { id } = req.params; - const { firstname, lastname, role, isActive, employeeType, contractType, canWorkAlone } = req.body; + const { firstname, lastname, roles, isActive, employeeType, contractType, canWorkAlone } = req.body; - console.log('📝 Update Employee Request:', { id, firstname, lastname, role, isActive, employeeType, contractType, canWorkAlone }); + console.log('📝 Update Employee Request:', { id, firstname, lastname, roles, isActive, employeeType, contractType, canWorkAlone }); // Check if employee exists and get current data const existingEmployee = await db.get('SELECT * FROM employees WHERE id = ?', [id]); @@ -205,37 +255,71 @@ export const updateEmployee = async (req: AuthRequest, res: Response): Promise(` - SELECT - id, email, firstname, lastname, role, is_active as isActive, - employee_type as employeeType, - contract_type as contractType, - can_work_alone as canWorkAlone, - created_at as createdAt, - last_login as lastLogin - FROM employees - WHERE id = ? - `, [id]); + // UPDATED: Update roles if provided + if (roles) { + // Delete existing roles + await db.run('DELETE FROM employee_roles WHERE employee_id = ?', [id]); + + // Insert new roles + for (const role of roles) { + await db.run( + `INSERT INTO employee_roles (employee_id, role) VALUES (?, ?)`, + [id, role] + ); + } + } - res.json(updatedEmployee); + await db.run('COMMIT'); + + console.log('✅ Employee updated successfully with email:', email); + + // Return updated employee with role from employee_roles + const updatedEmployee = await db.get(` + SELECT + e.id, e.email, e.firstname, e.lastname, + e.is_active as isActive, + e.employee_type as employeeType, + e.contract_type as contractType, + e.can_work_alone as canWorkAlone, + e.created_at as createdAt, + e.last_login as lastLogin, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? + LIMIT 1 + `, [id]); + + // Format response with roles array + const employeeWithRoles = { + ...updatedEmployee, + roles: updatedEmployee.role ? [updatedEmployee.role] : ['user'] + }; + + res.json(employeeWithRoles); + + } catch (error) { + await db.run('ROLLBACK'); + throw error; + } } catch (error) { console.error('Error updating employee:', error); res.status(500).json({ error: 'Internal server error' }); @@ -247,11 +331,15 @@ export const deleteEmployee = async (req: AuthRequest, res: Response): Promise(` - SELECT id, email, name, is_active, role - FROM employees - WHERE id = ? + SELECT + e.id, e.email, e.firstname, e.lastname, e.is_active, + er.role + FROM employees e + LEFT JOIN employee_roles er ON e.id = er.employee_id + WHERE e.id = ? + LIMIT 1 `, [id]); if (!existingEmployee) { @@ -297,10 +385,13 @@ export const deleteEmployee = async (req: AuthRequest, res: Response): Promise ({ id: avail.id, employeeId: avail.employee_id, @@ -393,14 +482,13 @@ export const updateAvailabilities = async (req: AuthRequest, res: Response): Pro await db.run('COMMIT'); - console.log('✅ Successfully updated availablities employee:', ); - - // Return updated availabilities const updatedAvailabilities = await db.all(` - SELECT * FROM employee_availability - WHERE employee_id = ? AND plan_id = ? - ORDER BY day_of_week, time_slot_id + SELECT ea.*, s.day_of_week, s.time_slot_id + FROM employee_availability ea + JOIN shifts s ON ea.shift_id = s.id + WHERE ea.employee_id = ? AND ea.plan_id = ? + ORDER BY s.day_of_week, s.time_slot_id `, [employeeId, planId]); res.json(updatedAvailabilities.map(avail => ({ @@ -413,7 +501,7 @@ export const updateAvailabilities = async (req: AuthRequest, res: Response): Pro notes: avail.notes }))); - console.log('✅ Successfully updated employee:', updateAvailabilities); + console.log('✅ Successfully updated employee availabilities'); } catch (error) { await db.run('ROLLBACK'); diff --git a/backend/src/controllers/setupController.ts b/backend/src/controllers/setupController.ts index a35db8c..a1c773e 100644 --- a/backend/src/controllers/setupController.ts +++ b/backend/src/controllers/setupController.ts @@ -27,7 +27,10 @@ function generateEmail(firstname: string, lastname: string): string { export const checkSetupStatus = async (req: Request, res: Response): Promise => { try { const adminExists = await db.get<{ 'COUNT(*)': number }>( - 'SELECT COUNT(*) FROM employees WHERE role = ? AND is_active = 1', + `SELECT COUNT(*) + FROM employees e + JOIN employee_roles er ON e.id = er.employee_id + WHERE er.role = ? AND e.is_active = 1`, ['admin'] ); @@ -50,7 +53,10 @@ export const setupAdmin = async (req: Request, res: Response): Promise => try { // Check if admin already exists const adminExists = await db.get<{ 'COUNT(*)': number }>( - 'SELECT COUNT(*) FROM employees WHERE role = ? AND is_active = 1', + `SELECT COUNT(*) + FROM employees e + JOIN employee_roles er ON e.id = er.employee_id + WHERE er.role = ? AND e.is_active = 1`, ['admin'] ); @@ -62,11 +68,11 @@ export const setupAdmin = async (req: Request, res: Response): Promise => return; } - const { password, firstname, lastname } = req.body; // Changed from name to firstname/lastname + const { password, firstname, lastname } = req.body; console.log('👤 Creating admin with data:', { firstname, lastname }); - // Validation - updated for firstname/lastname + // Validation if (!password || !firstname || !lastname) { res.status(400).json({ error: 'Passwort, Vorname und Nachname sind erforderlich' }); return; @@ -78,7 +84,7 @@ export const setupAdmin = async (req: Request, res: Response): Promise => return; } - // Generate email automatically using the same pattern + // Generate email automatically const email = generateEmail(firstname, lastname); console.log('📧 Generated admin email:', email); @@ -92,11 +98,17 @@ export const setupAdmin = async (req: Request, res: Response): Promise => await db.run('BEGIN TRANSACTION'); try { - // Create admin user with generated email + // Create admin user in employees table await db.run( - `INSERT INTO employees (id, email, password, firstname, lastname, role, employee_type, contract_type, can_work_alone, is_active) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, - [adminId, email, hashedPassword, firstname, lastname, 'admin', 'manager', 'large', true, 1] + `INSERT INTO employees (id, email, password, firstname, lastname, employee_type, contract_type, can_work_alone, is_active) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [adminId, email, hashedPassword, firstname, lastname, 'manager', 'large', true, 1] + ); + + // UPDATED: Assign admin role in employee_roles table + await db.run( + `INSERT INTO employee_roles (employee_id, role) VALUES (?, ?)`, + [adminId, 'admin'] ); console.log('✅ Admin user created successfully with email:', email); diff --git a/backend/src/database/schema.sql b/backend/src/database/schema.sql index 835ad72..39f0849 100644 --- a/backend/src/database/schema.sql +++ b/backend/src/database/schema.sql @@ -25,6 +25,11 @@ CREATE TABLE IF NOT EXISTS employee_roles ( PRIMARY KEY (employee_id, role) ); +-- Insert default roles if they don't exist +INSERT OR IGNORE INTO roles (role) VALUES ('admin'); +INSERT OR IGNORE INTO roles (role) VALUES ('user'); +INSERT OR IGNORE INTO roles (role) VALUES ('maintenance'); + -- Shift plans table CREATE TABLE IF NOT EXISTS shift_plans ( id TEXT PRIMARY KEY, diff --git a/backend/src/models/Employee.ts b/backend/src/models/Employee.ts index 87623ed..0114021 100644 --- a/backend/src/models/Employee.ts +++ b/backend/src/models/Employee.ts @@ -4,20 +4,20 @@ export interface Employee { email: string; firstname: string; lastname: string; - role: 'admin' | 'maintenance' | 'user'; employeeType: 'manager' | 'trainee' | 'experienced'; contractType: 'small' | 'large'; canWorkAlone: boolean; isActive: boolean; createdAt: string; lastLogin?: string | null; + roles?: string[]; } export interface CreateEmployeeRequest { password: string; firstname: string; lastname: string; - role: 'admin' | 'maintenance' | 'user'; + roles?: string[]; employeeType: 'manager' | 'trainee' | 'experienced'; contractType: 'small' | 'large'; canWorkAlone: boolean; @@ -26,7 +26,7 @@ export interface CreateEmployeeRequest { export interface UpdateEmployeeRequest { firstname?: string; lastname?: string; - role?: 'admin' | 'maintenance' | 'user'; + roles?: string[]; employeeType?: 'manager' | 'trainee' | 'experienced'; contractType?: 'small' | 'large'; canWorkAlone?: boolean; diff --git a/backend/src/models/helpers/employeeHelpers.ts b/backend/src/models/helpers/employeeHelpers.ts index d00ecab..9c75ecf 100644 --- a/backend/src/models/helpers/employeeHelpers.ts +++ b/backend/src/models/helpers/employeeHelpers.ts @@ -57,7 +57,13 @@ export const isExperienced = (employee: Employee): boolean => employee.employeeType === 'experienced'; export const isAdmin = (employee: Employee): boolean => - employee.role === 'admin'; + employee.roles?.includes('admin') || false; + +export const isMaintenance = (employee: Employee): boolean => + employee.roles?.includes('maintenance') || false; + +export const isUser = (employee: Employee): boolean => + employee.roles?.includes('user') || false; export const canEmployeeWorkAlone = (employee: Employee): boolean => employee.canWorkAlone && isExperienced(employee); diff --git a/backend/src/scripts/initializeDatabase.ts b/backend/src/scripts/initializeDatabase.ts index cc52940..7901873 100644 --- a/backend/src/scripts/initializeDatabase.ts +++ b/backend/src/scripts/initializeDatabase.ts @@ -14,10 +14,12 @@ export async function initializeDatabase(): Promise { try { console.log('Starting database initialization...'); - // Check if users table exists and has data try { const existingAdmin = await db.get<{ count: number }>( - "SELECT COUNT(*) as count FROM employees WHERE role = 'admin'" + `SELECT COUNT(*) as count + FROM employees e + JOIN employee_roles er ON e.id = er.employee_id + WHERE er.role = 'admin' AND e.is_active = 1` ); if (existingAdmin && existingAdmin.count > 0) { @@ -40,22 +42,28 @@ export async function initializeDatabase(): Promise { console.log('Existing tables found:', existingTables.map(t => t.name).join(', ') || 'none'); - // Drop existing tables in reverse order of dependencies if they exist + // UPDATED: Drop tables in correct dependency order const tablesToDrop = [ - 'employees', - 'time_slots', - 'shifts', - 'scheduled_shifts', + 'employee_availability', 'shift_assignments', - 'employee_availability', - 'applied_migrations', - 'shift_plans' + 'scheduled_shifts', + 'shifts', + 'time_slots', + 'employee_roles', + 'shift_plans', + 'roles', + 'employees', + 'applied_migrations' ]; for (const table of tablesToDrop) { if (existingTables.some(t => t.name === table)) { console.log(`Dropping table: ${table}`); - await db.run(`DROP TABLE IF EXISTS ${table}`); + try { + await db.run(`DROP TABLE IF EXISTS ${table}`); + } catch (error) { + console.warn(`Could not drop table ${table}:`, error); + } } } } catch (error) { @@ -92,6 +100,19 @@ export async function initializeDatabase(): Promise { } } + // UPDATED: Insert default roles after creating the tables + try { + console.log('Inserting default roles...'); + await db.run(`INSERT OR IGNORE INTO roles (role) VALUES ('admin')`); + await db.run(`INSERT OR IGNORE INTO roles (role) VALUES ('user')`); + await db.run(`INSERT OR IGNORE INTO roles (role) VALUES ('maintenance')`); + console.log('✅ Default roles inserted'); + } catch (error) { + console.error('Error inserting default roles:', error); + await db.run('ROLLBACK'); + throw error; + } + await db.run('COMMIT'); console.log('✅ Database schema successfully initialized'); diff --git a/frontend/src/components/Layout/Navigation.tsx b/frontend/src/components/Layout/Navigation.tsx index 5acd217..731822e 100644 --- a/frontend/src/components/Layout/Navigation.tsx +++ b/frontend/src/components/Layout/Navigation.tsx @@ -202,7 +202,7 @@ const Navigation: React.FC = () => { {/* User Menu - Rechts */}
- {user?.name} ({user?.role}) + {user?.firstname} {user?.lastname} ({user?.roles}) - )} + {/* Bearbeiten Button */} {canEdit && ( @@ -469,7 +483,7 @@ const EmployeeList: React.FC = ({ )} {/* Platzhalter für Symmetrie */} - {!canEdit && !canDelete && (employee.role !== 'admin' && employee.role !== 'maintenance') && ( + {!canEdit && !canDelete && (
)}
diff --git a/frontend/src/pages/Settings/Settings.tsx b/frontend/src/pages/Settings/Settings.tsx index 7637240..070829f 100644 --- a/frontend/src/pages/Settings/Settings.tsx +++ b/frontend/src/pages/Settings/Settings.tsx @@ -319,7 +319,7 @@ const Settings: React.FC = () => { diff --git a/frontend/src/pages/Setup/Setup.tsx b/frontend/src/pages/Setup/Setup.tsx index b0f3c19..63d6c43 100644 --- a/frontend/src/pages/Setup/Setup.tsx +++ b/frontend/src/pages/Setup/Setup.tsx @@ -1,4 +1,4 @@ -// frontend/src/pages/Setup/Setup.tsx - KORRIGIERT +// frontend/src/pages/Setup/Setup.tsx - UPDATED import React, { useState } from 'react'; import { useAuth } from '../../contexts/AuthContext'; @@ -7,7 +7,8 @@ const Setup: React.FC = () => { const [formData, setFormData] = useState({ password: '', confirmPassword: '', - name: '' + firstname: '', + lastname: '' }); const [loading, setLoading] = useState(false); const [error, setError] = useState(''); @@ -34,8 +35,12 @@ const Setup: React.FC = () => { }; const validateStep2 = () => { - if (!formData.name.trim()) { - setError('Bitte geben Sie einen Namen ein.'); + if (!formData.firstname.trim()) { + setError('Bitte geben Sie einen Vornamen ein.'); + return false; + } + if (!formData.lastname.trim()) { + setError('Bitte geben Sie einen Nachnamen ein.'); return false; } return true; @@ -62,10 +67,11 @@ const Setup: React.FC = () => { const payload = { password: formData.password, - name: formData.name + firstname: formData.firstname, + lastname: formData.lastname }; - console.log('🚀 Sending setup request...'); + console.log('🚀 Sending setup request...', payload); const response = await fetch('http://localhost:3002/api/setup/admin', { method: 'POST', @@ -94,6 +100,17 @@ const Setup: React.FC = () => { } }; + // Helper to display generated email preview + const getEmailPreview = () => { + if (!formData.firstname.trim() || !formData.lastname.trim()) { + return 'vorname.nachname@sp.de'; + } + + const cleanFirstname = formData.firstname.toLowerCase().replace(/[^a-z0-9]/g, ''); + const cleanLastname = formData.lastname.toLowerCase().replace(/[^a-z0-9]/g, ''); + return `${cleanFirstname}.${cleanLastname}@sp.de`; + }; + return (
{ {step === 1 && (
-
- -
- admin@instandhaltung.de -
-
- Diese E-Mail wird für den Administrator-Account verwendet -
-
-
{ borderRadius: '6px', fontSize: '1rem' }} - placeholder="Max Mustermann" + placeholder="Max" required />
+ +
+ + +
+ +
+ +
+ {getEmailPreview()} +
+
+ Die E-Mail wird automatisch aus Vor- und Nachname generiert +
+
)} @@ -315,7 +359,7 @@ const Setup: React.FC = () => { border: '1px solid #b6d7e8' }}> 💡 Nach dem erfolgreichen Setup werden Sie zur Anmeldeseite weitergeleitet, - wo Sie sich mit Ihren Zugangsdaten anmelden können. + wo Sie sich mit Ihrer automatisch generierten E-Mail anmelden können.
)}