diff --git a/backend/apps/events/__pycache__/views.cpython-314.pyc b/backend/apps/events/__pycache__/views.cpython-314.pyc index 4ce723b..7451f98 100644 Binary files a/backend/apps/events/__pycache__/views.cpython-314.pyc and b/backend/apps/events/__pycache__/views.cpython-314.pyc differ diff --git a/backend/apps/events/views.py b/backend/apps/events/views.py index 7047e4e..5bca0e9 100644 --- a/backend/apps/events/views.py +++ b/backend/apps/events/views.py @@ -341,7 +341,7 @@ class ShiftSignupView(views.APIView): signup = ShiftSignup.objects.create(shift=shift, user=user) return Response({'message': 'Erfolgreich für Schicht eingetragen.', 'signup_id': signup.id}, status=status.HTTP_201_CREATED) - # Guest flow for visitors + # Guest flow for visitors or registered users adding a guest else: if not guest_name: return Response({'error': 'Bitte gib einen Namen an.'}, status=status.HTTP_400_BAD_REQUEST) @@ -350,24 +350,23 @@ class ShiftSignupView(views.APIView): if not is_manager and shift.required_skills.exists(): required_names = ", ".join([s.name for s in shift.required_skills.all()]) return Response({ - 'error': f'Gäste können keine Fähigkeiten haben. Diese Schicht erfordert: {required_names}. Bitte registriere ein Konto mit den passenden Fähigkeiten.' + 'error': f'Gäste können keine Fähigkeiten haben. Diese Schicht erfordert: {required_names}. Ein Gast kann nur durch den Veranstaltungs-Manager/Admin eingetragen werden.' }, status=status.HTTP_400_BAD_REQUEST) if not request.session.session_key: request.session.create() session_key = request.session.session_key - request.session['guest_name'] = guest_name - if ShiftSignup.objects.filter(shift=shift, guest_session_key=session_key).exists(): - return Response({'error': 'Du bist mit deiner Gast-Sitzung bereits für diese Schicht eingetragen.'}, status=status.HTTP_400_BAD_REQUEST) + import uuid + guest_session_key = f"user_{user.id}_guest_{uuid.uuid4().hex[:6]}" if user else session_key signup = ShiftSignup.objects.create( shift=shift, guest_name=guest_name, - guest_session_key=session_key + guest_session_key=guest_session_key ) return Response({ - 'message': f'Gast "{guest_name}" erfolgreich eingetragen!', + 'message': f'Gast "{guest_name}" wurde erfolgreich eingetragen!', 'signup_id': signup.id }, status=status.HTTP_201_CREATED) diff --git a/frontend/dist/index.html b/frontend/dist/index.html index dbb7cdd..f1b6143 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -11,8 +11,8 @@ Schichtplaner — Veranstaltungsschichtpläne - - + +
diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index 3800596..fd4825c 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -292,6 +292,11 @@ export default function App() { } }; + const handleGuestSignupClick = (shift) => { + setGuestTargetShift(shift); + setShowGuestModal(true); + }; + const handleGuestSubmit = async (guestData) => { if (!guestTargetShift) return; const res = await apiFetch(`/shifts/${guestTargetShift.id}/signup/`, { @@ -600,6 +605,7 @@ export default function App() { event={selectedEventData} user={user} onSignupClick={handleShiftSignupClick} + onGuestSignupClick={handleGuestSignupClick} onCancelClick={handleCancelSignup} onEditEvent={(evt) => { setEventToEdit(evt); @@ -647,6 +653,7 @@ export default function App() { {showGuestModal && ( setShowGuestModal(false)} onSubmit={handleGuestSubmit} /> diff --git a/frontend/src/components/GuestSignupModal.jsx b/frontend/src/components/GuestSignupModal.jsx index 7565096..8d279a2 100644 --- a/frontend/src/components/GuestSignupModal.jsx +++ b/frontend/src/components/GuestSignupModal.jsx @@ -1,31 +1,33 @@ import React, { useState, useEffect } from 'react'; -import { X, UserCheck, AlertCircle } from 'lucide-react'; +import { X, UserPlus, AlertCircle } from 'lucide-react'; -export default function GuestSignupModal({ shift, onClose, onSubmit }) { +export default function GuestSignupModal({ shift, user, onClose, onSubmit }) { const [guestName, setGuestName] = useState(''); const [error, setError] = useState(''); const [submitting, setSubmitting] = useState(false); useEffect(() => { - // Load saved guest name from localStorage - const savedName = localStorage.getItem('guest_display_name') || ''; - if (savedName) { - setGuestName(savedName); + // Only prefill saved guest name for unauthenticated visitors + if (!user) { + const savedName = localStorage.getItem('guest_display_name') || ''; + if (savedName) setGuestName(savedName); } - }, []); + }, [user]); const handleSubmit = async (e) => { e.preventDefault(); setError(''); if (!guestName.trim()) { - setError('Bitte gib deinen Namen ein.'); + setError('Bitte gib den Namen der Person ein.'); return; } - // Save in localStorage for guest convenience - localStorage.setItem('guest_display_name', guestName.trim()); - window.dispatchEvent(new Event('guest_name_updated')); + // Save in localStorage only for unauthenticated guest visitors + if (!user) { + localStorage.setItem('guest_display_name', guestName.trim()); + window.dispatchEvent(new Event('guest_name_updated')); + } setSubmitting(true); try { @@ -39,47 +41,54 @@ export default function GuestSignupModal({ shift, onClose, onSubmit }) { }; return ( -
-
+
+
-
-
- +
+
+
-

Als Gast eintragen

-

Schicht: {shift?.title} ({shift?.start_time} - {shift?.end_time})

+

+ {user ? 'Gast in Schicht eintragen' : 'Als Gast eintragen'} +

+

+ Schicht: {shift?.title} ({shift?.start_time} - {shift?.end_time} Uhr) +

{error && ( -
+
{error}
)} -
+
-
@@ -87,16 +96,16 @@ export default function GuestSignupModal({ shift, onClose, onSubmit }) {
diff --git a/frontend/src/components/ShiftMatrixTable.jsx b/frontend/src/components/ShiftMatrixTable.jsx index b79ab58..44dcf23 100644 --- a/frontend/src/components/ShiftMatrixTable.jsx +++ b/frontend/src/components/ShiftMatrixTable.jsx @@ -7,6 +7,7 @@ export default function ShiftMatrixTable({ event, user, onSignupClick, + onGuestSignupClick, onCancelClick, onRemoveUserFromShift, onGenerateClaimLink, @@ -263,24 +264,36 @@ export default function ShiftMatrixTable({ - {isUserSignedUp ? ( - - ) : isFull ? ( - [ VOLL ] - ) : ( - - )} +
+ {isUserSignedUp ? ( + + ) : isFull ? ( + [ VOLL ] + ) : ( + + )} + + {user && !isFull && onGuestSignupClick && ( + + )} +
);