Files
webshop/shop/app/account-kunden/AccountSettingsForm.tsx
DanielS a64b6790c6
All checks were successful
Staging Build / build (push) Successful in 3m33s
feat: Add partner account settings page under /account-kunden
2026-07-04 21:06:46 +02:00

347 lines
13 KiB
TypeScript

'use client';
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { updateUserProfile, updateCompanyDetails } from '@/lib/actions/users';
import { updatePassword } from '@/lib/actions/auth';
import { Save, KeyRound, Loader2 } from 'lucide-react';
interface AccountSettingsFormProps {
userId: string;
profile: any;
company: any;
}
export function AccountSettingsForm({ userId, profile, company }: AccountSettingsFormProps) {
// Profil State
const [firstName, setFirstName] = useState(profile?.first_name || '');
const [lastName, setLastName] = useState(profile?.last_name || '');
const [profileMessage, setProfileMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
const [isUpdatingProfile, setIsUpdatingProfile] = useState(false);
// Company State
const [street, setStreet] = useState(company?.street || '');
const [zip, setZip] = useState(company?.zip || '');
const [city, setCity] = useState(company?.city || '');
const [companyEmail, setCompanyEmail] = useState(company?.email || '');
const [companyMessage, setCompanyMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
const [isUpdatingCompany, setIsUpdatingCompany] = useState(false);
// Passwort State
const [newPassword, setNewPassword] = useState('');
const [confirmPassword, setConfirmPassword] = useState('');
const [passwordMessage, setPasswordMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
const [isUpdatingPassword, setIsUpdatingPassword] = useState(false);
// Profil speichern
const handleUpdateProfile = async (e: React.FormEvent) => {
e.preventDefault();
setProfileMessage(null);
setIsUpdatingProfile(true);
try {
const res = await updateUserProfile(userId, {
first_name: firstName || null,
last_name: lastName || null,
});
if (res.success) {
setProfileMessage({ type: 'success', text: 'Persönliche Daten erfolgreich aktualisiert.' });
} else {
setProfileMessage({ type: 'error', text: res.error || 'Fehler beim Aktualisieren des Profils.' });
}
} catch (err: any) {
setProfileMessage({ type: 'error', text: err.message || 'Ein unerwarteter Fehler ist aufgetreten.' });
} finally {
setIsUpdatingProfile(false);
}
};
// Company speichern
const handleUpdateCompany = async (e: React.FormEvent) => {
e.preventDefault();
if (!company?.id) return;
setCompanyMessage(null);
setIsUpdatingCompany(true);
try {
const res = await updateCompanyDetails(company.id, {
street: street || null,
zip: zip || null,
city: city || null,
email: companyEmail || null,
});
if (res.success) {
setCompanyMessage({ type: 'success', text: 'Unternehmensdaten erfolgreich aktualisiert.' });
} else {
setCompanyMessage({ type: 'error', text: res.error || 'Fehler beim Aktualisieren der Unternehmensdaten.' });
}
} catch (err: any) {
setCompanyMessage({ type: 'error', text: err.message || 'Ein unerwarteter Fehler ist aufgetreten.' });
} finally {
setIsUpdatingCompany(false);
}
};
// Passwort speichern
const handleUpdatePassword = async (e: React.FormEvent) => {
e.preventDefault();
setPasswordMessage(null);
if (newPassword.length < 6) {
setPasswordMessage({ type: 'error', text: 'Das Passwort muss mindestens 6 Zeichen lang sein.' });
return;
}
if (newPassword !== confirmPassword) {
setPasswordMessage({ type: 'error', text: 'Die Passwörter stimmen nicht überein.' });
return;
}
setIsUpdatingPassword(true);
try {
const res = await updatePassword(newPassword);
if (res.success) {
setPasswordMessage({ type: 'success', text: 'Passwort erfolgreich geändert.' });
setNewPassword('');
setConfirmPassword('');
} else {
setPasswordMessage({ type: 'error', text: res.error || 'Fehler beim Ändern des Passworts.' });
}
} catch (err: any) {
setPasswordMessage({ type: 'error', text: err.message || 'Ein unerwarteter Fehler ist aufgetreten.' });
} finally {
setIsUpdatingPassword(false);
}
};
return (
<div className="space-y-8">
{/* 1. Persönliche Daten */}
<Card className="glass-dark border-white/10">
<CardHeader>
<CardTitle className="text-xl">Persönliche Daten</CardTitle>
<CardDescription className="text-slate-400">
Aktualisieren Sie Ihren Vor- und Nachnamen.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleUpdateProfile} className="space-y-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="firstName">Vorname</Label>
<Input
id="firstName"
value={firstName}
onChange={(e) => setFirstName(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="Max"
/>
</div>
<div className="space-y-2">
<Label htmlFor="lastName">Nachname</Label>
<Input
id="lastName"
value={lastName}
onChange={(e) => setLastName(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="Mustermann"
/>
</div>
</div>
{profileMessage && (
<div
className={`p-3 rounded-lg text-sm border ${
profileMessage.type === 'success'
? 'bg-green-500/10 border-green-500/20 text-green-400'
: 'bg-red-500/10 border-red-500/20 text-red-400'
}`}
>
{profileMessage.text}
</div>
)}
<div className="flex justify-end">
<Button type="submit" disabled={isUpdatingProfile} className="gap-2">
{isUpdatingProfile ? (
<>
<Loader2 className="w-4 h-4 animate-spin" /> Speichern...
</>
) : (
<>
<Save className="w-4 h-4" /> Profil speichern
</>
)}
</Button>
</div>
</form>
</CardContent>
</Card>
{/* 2. Unternehmensdaten */}
{company && (
<Card className="glass-dark border-white/10">
<CardHeader>
<CardTitle className="text-xl">Unternehmensdaten</CardTitle>
<CardDescription className="text-slate-400">
Verwalten Sie die Adressdaten Ihres Partner-Unternehmens.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleUpdateCompany} className="space-y-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2 sm:col-span-2">
<Label htmlFor="companyName">Firmenname (nicht änderbar)</Label>
<Input
id="companyName"
value={company.name}
disabled
className="bg-slate-950/50 border-white/5 text-slate-400 cursor-not-allowed"
/>
</div>
<div className="space-y-2 sm:col-span-2">
<Label htmlFor="street">Straße & Hausnummer</Label>
<Input
id="street"
value={street}
onChange={(e) => setStreet(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="Musterstraße 12"
/>
</div>
<div className="space-y-2">
<Label htmlFor="zip">Postleitzahl</Label>
<Input
id="zip"
value={zip}
onChange={(e) => setZip(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="12345"
/>
</div>
<div className="space-y-2">
<Label htmlFor="city">Ort</Label>
<Input
id="city"
value={city}
onChange={(e) => setCity(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="Musterstadt"
/>
</div>
<div className="space-y-2 sm:col-span-2">
<Label htmlFor="companyEmail">E-Mail für Rechnungen / Anfragen</Label>
<Input
id="companyEmail"
type="email"
value={companyEmail}
onChange={(e) => setCompanyEmail(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="partner@firma.de"
/>
</div>
</div>
{companyMessage && (
<div
className={`p-3 rounded-lg text-sm border ${
companyMessage.type === 'success'
? 'bg-green-500/10 border-green-500/20 text-green-400'
: 'bg-red-500/10 border-red-500/20 text-red-400'
}`}
>
{companyMessage.text}
</div>
)}
<div className="flex justify-end">
<Button type="submit" disabled={isUpdatingCompany} className="gap-2">
{isUpdatingCompany ? (
<>
<Loader2 className="w-4 h-4 animate-spin" /> Speichern...
</>
) : (
<>
<Save className="w-4 h-4" /> Firmendaten speichern
</>
)}
</Button>
</div>
</form>
</CardContent>
</Card>
)}
{/* 3. Sicherheit / Passwort ändern */}
<Card className="glass-dark border-white/10">
<CardHeader>
<CardTitle className="text-xl">Passwort ändern</CardTitle>
<CardDescription className="text-slate-400">
Geben Sie ein neues Passwort für Ihren Zugang ein.
</CardDescription>
</CardHeader>
<CardContent>
<form onSubmit={handleUpdatePassword} className="space-y-4">
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="newPassword">Neues Passwort</Label>
<Input
id="newPassword"
type="password"
value={newPassword}
onChange={(e) => setNewPassword(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="••••••••"
/>
</div>
<div className="space-y-2">
<Label htmlFor="confirmPassword">Passwort bestätigen</Label>
<Input
id="confirmPassword"
type="password"
value={confirmPassword}
onChange={(e) => setConfirmPassword(e.target.value)}
className="bg-slate-950 border-white/10 focus:border-primary text-white"
placeholder="••••••••"
/>
</div>
</div>
{passwordMessage && (
<div
className={`p-3 rounded-lg text-sm border ${
passwordMessage.type === 'success'
? 'bg-green-500/10 border-green-500/20 text-green-400'
: 'bg-red-500/10 border-red-500/20 text-red-400'
}`}
>
{passwordMessage.text}
</div>
)}
<div className="flex justify-end">
<Button type="submit" disabled={isUpdatingPassword} className="gap-2">
{isUpdatingPassword ? (
<>
<Loader2 className="w-4 h-4 animate-spin" /> Ändern...
</>
) : (
<>
<KeyRound className="w-4 h-4" /> Passwort aktualisieren
</>
)}
</Button>
</div>
</form>
</CardContent>
</Card>
</div>
);
}