fix: Render ProfileModal in App.jsx and support guest display name editing from Navbar
This commit is contained in:
Vendored
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=JetBrains+Mono:wght@400;500;600;700&family=Plus+Jakarta+Sans:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||||
<title>Schichtplaner — Veranstaltungsschichtpläne</title>
|
<title>Schichtplaner — Veranstaltungsschichtpläne</title>
|
||||||
<script type="module" crossorigin src="/assets/index-BUskNRc4.js"></script>
|
<script type="module" crossorigin src="/assets/index-AKhcitQN.js"></script>
|
||||||
<link rel="stylesheet" crossorigin href="/assets/index-DHeBvKbG.css">
|
<link rel="stylesheet" crossorigin href="/assets/index-DHeBvKbG.css">
|
||||||
</head>
|
</head>
|
||||||
<body class="bg-paper text-main font-sans antialiased min-h-screen">
|
<body class="bg-paper text-main font-sans antialiased min-h-screen">
|
||||||
|
|||||||
@@ -651,6 +651,20 @@ export default function App() {
|
|||||||
onSubmit={handleGuestSubmit}
|
onSubmit={handleGuestSubmit}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{showProfileModal && (
|
||||||
|
<ProfileModal
|
||||||
|
user={user}
|
||||||
|
skills={skills}
|
||||||
|
onClose={() => setShowProfileModal(false)}
|
||||||
|
onUserUpdated={(updatedUser) => {
|
||||||
|
setUser(updatedUser);
|
||||||
|
setShowProfileModal(false);
|
||||||
|
refreshEvents();
|
||||||
|
}}
|
||||||
|
onRefreshSkills={refreshSkills}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,13 +62,17 @@ export default function Navbar({
|
|||||||
</h1>
|
</h1>
|
||||||
<div className="text-[10px] font-mono text-muted mt-1 uppercase tracking-wider flex items-center gap-1.5">
|
<div className="text-[10px] font-mono text-muted mt-1 uppercase tracking-wider flex items-center gap-1.5">
|
||||||
{user ? (
|
{user ? (
|
||||||
<span className="text-emerald-500 font-semibold">[ {user.display_name || user.username} ]</span>
|
<span onClick={(e) => { e.stopPropagation(); onOpenProfile(); }} className="text-emerald-500 font-semibold hover:underline cursor-pointer">
|
||||||
|
[ {user.display_name || user.username} ]
|
||||||
|
</span>
|
||||||
) : savedGuestName ? (
|
) : savedGuestName ? (
|
||||||
<span className="text-amber-400 font-semibold flex items-center gap-1">
|
<span onClick={(e) => { e.stopPropagation(); onOpenProfile(); }} className="text-amber-400 font-semibold flex items-center gap-1 hover:underline cursor-pointer" title="Klicken um Gast-Name zu ändern">
|
||||||
[ 👤 GAST: {savedGuestName} ]
|
[ 👤 GAST: {savedGuestName} ✏️ ]
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-amber-500 font-semibold">[ GAST-MODUS ]</span>
|
<span onClick={(e) => { e.stopPropagation(); onOpenProfile(); }} className="text-amber-500 font-semibold hover:underline cursor-pointer" title="Klicken um Gast-Name einzutragen">
|
||||||
|
[ GAST-MODUS ✏️ ]
|
||||||
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import { apiFetch } from '../api/client';
|
|||||||
import { getRandomSkillColor } from '../utils/colors';
|
import { getRandomSkillColor } from '../utils/colors';
|
||||||
|
|
||||||
export default function ProfileModal({ user, skills, onClose, onUserUpdated, onRefreshSkills }) {
|
export default function ProfileModal({ user, skills, onClose, onUserUpdated, onRefreshSkills }) {
|
||||||
const [displayName, setDisplayName] = useState(user?.display_name || '');
|
const [displayName, setDisplayName] = useState(
|
||||||
|
user?.display_name || localStorage.getItem('guest_display_name') || ''
|
||||||
|
);
|
||||||
const [selectedSkillIds, setSelectedSkillIds] = useState(
|
const [selectedSkillIds, setSelectedSkillIds] = useState(
|
||||||
user?.skills ? user.skills.map(s => s.id) : []
|
user?.skills ? user.skills.map(s => s.id) : []
|
||||||
);
|
);
|
||||||
@@ -26,6 +28,7 @@ export default function ProfileModal({ user, skills, onClose, onUserUpdated, onR
|
|||||||
setSavingProfile(true);
|
setSavingProfile(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
if (user) {
|
||||||
const updatedUser = await apiFetch('/users/me/', {
|
const updatedUser = await apiFetch('/users/me/', {
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -34,7 +37,13 @@ export default function ProfileModal({ user, skills, onClose, onUserUpdated, onR
|
|||||||
})
|
})
|
||||||
});
|
});
|
||||||
setSuccess('Profil und Anzeigename erfolgreich aktualisiert!');
|
setSuccess('Profil und Anzeigename erfolgreich aktualisiert!');
|
||||||
onUserUpdated(updatedUser);
|
if (onUserUpdated) onUserUpdated(updatedUser);
|
||||||
|
} else {
|
||||||
|
localStorage.setItem('guest_display_name', displayName.trim());
|
||||||
|
window.dispatchEvent(new Event('guest_name_updated'));
|
||||||
|
setSuccess('Gast-Name erfolgreich gespeichert!');
|
||||||
|
setTimeout(() => onClose(), 600);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setError(err.message || 'Speichern des Profils fehlgeschlagen.');
|
setError(err.message || 'Speichern des Profils fehlgeschlagen.');
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
Reference in New Issue
Block a user