Files
beauty-bookings/src/client/components/user-profile.tsx

165 lines
5.3 KiB
TypeScript

import { useState } from "react";
import { useMutation } from "@tanstack/react-query";
import { useAuth } from "@/client/components/auth-provider";
import { queryClient } from "@/client/rpc-client";
export function UserProfile() {
const { user, sessionId, logout } = useAuth();
const [showPasswordChange, setShowPasswordChange] = useState(false);
const [currentPassword, setCurrentPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [confirmPassword, setConfirmPassword] = useState("");
const [message, setMessage] = useState("");
const [error, setError] = useState("");
const { mutate: changePassword, isPending } = useMutation(
queryClient.auth.changePassword.mutationOptions()
);
const handlePasswordChange = (e: React.FormEvent) => {
e.preventDefault();
setError("");
setMessage("");
if (newPassword !== confirmPassword) {
setError("Neue Passwörter stimmen nicht überein");
return;
}
if (newPassword.length < 6) {
setError("Neues Passwort muss mindestens 6 Zeichen lang sein");
return;
}
if (!sessionId) {
setError("Keine gültige Sitzung");
return;
}
changePassword({
sessionId,
currentPassword,
newPassword,
}, {
onSuccess: () => {
setMessage("Passwort erfolgreich geändert");
setCurrentPassword("");
setNewPassword("");
setConfirmPassword("");
setShowPasswordChange(false);
},
onError: (err) => {
setError(err instanceof Error ? err.message : "Fehler beim Ändern des Passworts");
}
});
};
if (!user) return null;
return (
<div className="bg-white rounded-lg shadow-lg p-6 max-w-2xl mx-auto">
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold text-gray-900">Benutzerprofil</h2>
<button
onClick={logout}
className="bg-red-600 text-white px-4 py-2 rounded-md hover:bg-red-700 font-medium"
>
Abmelden
</button>
</div>
<div className="space-y-4 mb-6">
<div>
<label className="block text-sm font-medium text-gray-700">Benutzername</label>
<p className="mt-1 text-lg text-gray-900">{user.username}</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">E-Mail</label>
<p className="mt-1 text-lg text-gray-900">{user.email}</p>
</div>
<div>
<label className="block text-sm font-medium text-gray-700">Rolle</label>
<p className="mt-1 text-lg text-gray-900 capitalize">{user.role === "owner" ? "Inhaber" : "Kunde"}</p>
</div>
</div>
<div>
<button
onClick={() => setShowPasswordChange(!showPasswordChange)}
className="bg-pink-600 text-white px-4 py-2 rounded-md hover:bg-pink-700 font-medium"
>
{showPasswordChange ? "Abbrechen" : "Passwort ändern"}
</button>
</div>
{showPasswordChange && (
<form onSubmit={handlePasswordChange} className="mt-6 space-y-4 border-t pt-6">
<h3 className="text-lg font-semibold text-gray-900">Passwort ändern</h3>
{error && (
<div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded">
{error}
</div>
)}
{message && (
<div className="bg-green-50 border border-green-200 text-green-700 px-4 py-3 rounded">
{message}
</div>
)}
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Aktuelles Passwort
</label>
<input
type="password"
value={currentPassword}
onChange={(e) => setCurrentPassword(e.target.value)}
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-pink-500 focus:border-pink-500"
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Neues Passwort
</label>
<input
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-pink-500 focus:border-pink-500"
minLength={6}
required
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Neues Passwort bestätigen
</label>
<input
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="w-full p-3 border border-gray-300 rounded-md focus:ring-2 focus:ring-pink-500 focus:border-pink-500"
minLength={6}
required
/>
</div>
<button
type="submit"
disabled={isPending}
className="bg-pink-600 text-white px-4 py-2 rounded-md hover:bg-pink-700 disabled:opacity-50 font-medium"
>
{isPending ? "Ändern..." : "Passwort ändern"}
</button>
</form>
)}
</div>
);
}