Files
dashboard/frontend/src/pages/Profile.tsx
2026-03-12 11:37:25 +01:00

266 lines
8.7 KiB
TypeScript

import {
Container,
Box,
Typography,
Avatar,
Grid,
TextField,
Card,
CardContent,
Divider,
Chip,
} from '@mui/material';
import { Person, Email, Badge, Group, AccessTime } from '@mui/icons-material';
import { useAuth } from '../contexts/AuthContext';
import DashboardLayout from '../components/dashboard/DashboardLayout';
function Profile() {
const { user } = useAuth();
if (!user) {
return null;
}
// Get initials for large avatar
const getInitials = () => {
const initials = (user.given_name?.[0] || '') + (user.family_name?.[0] || '');
return initials || user.name?.[0] || '?';
};
// Format date (if we had lastLogin)
const formatDate = (date?: Date | string) => {
if (!date) return 'Nicht verfügbar';
const d = typeof date === 'string' ? new Date(date) : date;
return d.toLocaleDateString('de-DE', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit',
});
};
const dashboardGroups = (user.groups ?? []).filter((g) => g.startsWith('dashboard_'));
return (
<DashboardLayout>
<Container maxWidth="lg">
<Typography variant="h4" gutterBottom sx={{ mb: 4 }}>
Mein Profil
</Typography>
<Grid container spacing={3}>
{/* User Info Card */}
<Grid item xs={12} md={4}>
<Card>
<CardContent>
<Box
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
py: 2,
}}
>
<Avatar
sx={{
bgcolor: 'primary.main',
width: 120,
height: 120,
fontSize: '3rem',
mb: 2,
}}
>
{getInitials()}
</Avatar>
<Typography variant="h5" gutterBottom>
{user.name}
</Typography>
<Typography variant="body2" color="text.secondary" gutterBottom>
{user.email}
</Typography>
{user.preferred_username && (
<Typography
variant="body2"
color="text.secondary"
sx={{ display: 'flex', alignItems: 'center', gap: 0.5, mt: 1 }}
>
<Badge fontSize="small" />
@{user.preferred_username}
</Typography>
)}
</Box>
<Divider sx={{ my: 2 }} />
{/* Groups/Roles */}
{dashboardGroups.length > 0 && (
<Box sx={{ mt: 2 }}>
<Typography
variant="subtitle2"
color="text.secondary"
gutterBottom
sx={{ display: 'flex', alignItems: 'center', gap: 0.5 }}
>
<Group fontSize="small" />
Gruppen
</Typography>
<Box sx={{ display: 'flex', flexWrap: 'wrap', gap: 1, mt: 1 }}>
{dashboardGroups.map((group) => {
const name = group.replace(/^dashboard_/, '');
const label = name.charAt(0).toUpperCase() + name.slice(1);
return <Chip key={group} label={label} size="small" color="primary" />;
})}
</Box>
</Box>
)}
</CardContent>
</Card>
</Grid>
{/* Personal Information */}
<Grid item xs={12} md={8}>
<Card>
<CardContent>
<Typography variant="h6" gutterBottom sx={{ mb: 3 }}>
Persönliche Informationen
</Typography>
<Grid container spacing={3}>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
label="Vorname"
value={user.given_name || ''}
InputProps={{
readOnly: true,
startAdornment: (
<Person sx={{ mr: 1, color: 'text.secondary' }} />
),
}}
variant="outlined"
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
fullWidth
label="Nachname"
value={user.family_name || ''}
InputProps={{
readOnly: true,
startAdornment: (
<Person sx={{ mr: 1, color: 'text.secondary' }} />
),
}}
variant="outlined"
/>
</Grid>
<Grid item xs={12}>
<TextField
fullWidth
label="E-Mail-Adresse"
value={user.email}
InputProps={{
readOnly: true,
startAdornment: (
<Email sx={{ mr: 1, color: 'text.secondary' }} />
),
}}
variant="outlined"
helperText="E-Mail-Adresse wird von Authentik verwaltet"
/>
</Grid>
{user.preferred_username && (
<Grid item xs={12}>
<TextField
fullWidth
label="Benutzername"
value={user.preferred_username}
InputProps={{
readOnly: true,
startAdornment: (
<Badge sx={{ mr: 1, color: 'text.secondary' }} />
),
}}
variant="outlined"
/>
</Grid>
)}
</Grid>
<Box
sx={{
mt: 3,
p: 2,
backgroundColor: 'info.light',
borderRadius: 1,
}}
>
<Typography variant="body2" color="info.dark">
Diese Informationen werden von Authentik verwaltet und können hier nicht
bearbeitet werden. Bitte wenden Sie sich an Ihren Administrator, um
Änderungen vorzunehmen.
</Typography>
</Box>
</CardContent>
</Card>
{/* Activity Information */}
<Card sx={{ mt: 3 }}>
<CardContent>
<Typography variant="h6" gutterBottom sx={{ mb: 3 }}>
Aktivitätsinformationen
</Typography>
<Grid container spacing={2}>
<Grid item xs={12}>
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 2,
p: 2,
backgroundColor: 'background.default',
borderRadius: 1,
}}
>
<AccessTime color="primary" />
<Box>
<Typography variant="body2" color="text.secondary">
Letzte Anmeldung
</Typography>
<Typography variant="body1">
{formatDate(new Date())}
</Typography>
</Box>
</Box>
</Grid>
</Grid>
</CardContent>
</Card>
{/* User Preferences */}
<Card sx={{ mt: 3 }}>
<CardContent>
<Typography variant="h6" gutterBottom sx={{ mb: 3 }}>
Benutzereinstellungen
</Typography>
<Typography variant="body2" color="text.secondary">
Kommende Features: Benachrichtigungseinstellungen, Anzeigeoptionen,
Spracheinstellungen
</Typography>
</CardContent>
</Card>
</Grid>
</Grid>
</Container>
</DashboardLayout>
);
}
export default Profile;