bug fixes
This commit is contained in:
@@ -1,174 +0,0 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
Typography,
|
||||
List,
|
||||
ListItem,
|
||||
ListItemAvatar,
|
||||
ListItemText,
|
||||
Avatar,
|
||||
Box,
|
||||
} from '@mui/material';
|
||||
import {
|
||||
LocalFireDepartment,
|
||||
Person,
|
||||
DirectionsCar,
|
||||
Assignment,
|
||||
} from '@mui/icons-material';
|
||||
|
||||
interface Activity {
|
||||
id: string;
|
||||
type: 'incident' | 'member' | 'vehicle' | 'task';
|
||||
title: string;
|
||||
description: string;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
// Placeholder activities
|
||||
const placeholderActivities: Activity[] = [
|
||||
{
|
||||
id: '1',
|
||||
type: 'incident',
|
||||
title: 'Brandeinsatz',
|
||||
description: 'Kleinbrand in der Hauptstraße',
|
||||
timestamp: 'Vor 2 Stunden',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
type: 'member',
|
||||
title: 'Neues Mitglied',
|
||||
description: 'Max Mustermann ist der Feuerwehr beigetreten',
|
||||
timestamp: 'Vor 5 Stunden',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
type: 'vehicle',
|
||||
title: 'Fahrzeugwartung',
|
||||
description: 'LF 16/12 - Wartung abgeschlossen',
|
||||
timestamp: 'Gestern',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
type: 'task',
|
||||
title: 'Aufgabe zugewiesen',
|
||||
description: 'Neue Aufgabe: Inventur Atemschutzgeräte',
|
||||
timestamp: 'Vor 2 Tagen',
|
||||
},
|
||||
];
|
||||
|
||||
const ActivityFeed: React.FC = () => {
|
||||
const getActivityIcon = (type: Activity['type']) => {
|
||||
switch (type) {
|
||||
case 'incident':
|
||||
return <LocalFireDepartment />;
|
||||
case 'member':
|
||||
return <Person />;
|
||||
case 'vehicle':
|
||||
return <DirectionsCar />;
|
||||
case 'task':
|
||||
return <Assignment />;
|
||||
default:
|
||||
return <LocalFireDepartment />;
|
||||
}
|
||||
};
|
||||
|
||||
const getActivityColor = (type: Activity['type']) => {
|
||||
switch (type) {
|
||||
case 'incident':
|
||||
return 'error.main';
|
||||
case 'member':
|
||||
return 'success.main';
|
||||
case 'vehicle':
|
||||
return 'warning.main';
|
||||
case 'task':
|
||||
return 'info.main';
|
||||
default:
|
||||
return 'primary.main';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card sx={{ height: '100%', overflow: 'hidden' }}>
|
||||
<CardContent>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
Letzte Aktivitäten
|
||||
</Typography>
|
||||
|
||||
<List sx={{ pt: 2 }}>
|
||||
{placeholderActivities.map((activity, index) => (
|
||||
<React.Fragment key={activity.id}>
|
||||
<ListItem
|
||||
alignItems="flex-start"
|
||||
sx={{
|
||||
px: 0,
|
||||
position: 'relative',
|
||||
'&::before':
|
||||
index < placeholderActivities.length - 1
|
||||
? {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
left: 19,
|
||||
top: 56,
|
||||
bottom: 0,
|
||||
width: 2,
|
||||
bgcolor: 'divider',
|
||||
}
|
||||
: {},
|
||||
}}
|
||||
>
|
||||
<ListItemAvatar>
|
||||
<Avatar
|
||||
sx={{
|
||||
bgcolor: getActivityColor(activity.type),
|
||||
width: 40,
|
||||
height: 40,
|
||||
}}
|
||||
>
|
||||
{getActivityIcon(activity.type)}
|
||||
</Avatar>
|
||||
</ListItemAvatar>
|
||||
<ListItemText
|
||||
primary={
|
||||
<Typography variant="subtitle2" component="span">
|
||||
{activity.title}
|
||||
</Typography>
|
||||
}
|
||||
secondary={
|
||||
<Box>
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
component="span"
|
||||
sx={{ display: 'block' }}
|
||||
>
|
||||
{activity.description}
|
||||
</Typography>
|
||||
<Typography
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
component="span"
|
||||
>
|
||||
{activity.timestamp}
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
</ListItem>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</List>
|
||||
|
||||
{placeholderActivities.length === 0 && (
|
||||
<Box sx={{ textAlign: 'center', py: 4 }}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Keine Aktivitäten vorhanden
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default ActivityFeed;
|
||||
@@ -61,6 +61,9 @@ const UserProfile: React.FC<UserProfileProps> = ({ user }) => {
|
||||
{/* User Info */}
|
||||
<Box sx={{ flex: 1, textAlign: { xs: 'center', sm: 'left' } }}>
|
||||
<Typography variant="h5" component="div" gutterBottom>
|
||||
Willkommen zurück, {user.given_name || user.name.split(' ')[0]}!
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ opacity: 0.75, mb: 0.5 }}>
|
||||
{user.name}
|
||||
</Typography>
|
||||
<Typography variant="body2" sx={{ opacity: 0.9 }}>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
export { default as UserProfile } from './UserProfile';
|
||||
export { default as ServiceCard } from './ServiceCard';
|
||||
export { default as StatsCard } from './StatsCard';
|
||||
export { default as ActivityFeed } from './ActivityFeed';
|
||||
export { default as DashboardLayout } from './DashboardLayout';
|
||||
export { default as PersonalWarningsBanner } from './PersonalWarningsBanner';
|
||||
export { default as UpcomingEventsWidget } from './UpcomingEventsWidget';
|
||||
|
||||
@@ -2,8 +2,6 @@ import { useState, useEffect } from 'react';
|
||||
import {
|
||||
Container,
|
||||
Box,
|
||||
Typography,
|
||||
Grid,
|
||||
Fade,
|
||||
} from '@mui/material';
|
||||
import { useAuth } from '../contexts/AuthContext';
|
||||
@@ -12,7 +10,6 @@ import SkeletonCard from '../components/shared/SkeletonCard';
|
||||
import UserProfile from '../components/dashboard/UserProfile';
|
||||
import NextcloudTalkWidget from '../components/dashboard/NextcloudTalkWidget';
|
||||
import UpcomingEventsWidget from '../components/dashboard/UpcomingEventsWidget';
|
||||
import ActivityFeed from '../components/dashboard/ActivityFeed';
|
||||
import AtemschutzDashboardCard from '../components/atemschutz/AtemschutzDashboardCard';
|
||||
import EquipmentDashboardCard from '../components/equipment/EquipmentDashboardCard';
|
||||
import VehicleDashboardCard from '../components/vehicles/VehicleDashboardCard';
|
||||
@@ -33,25 +30,22 @@ function Dashboard() {
|
||||
return (
|
||||
<DashboardLayout>
|
||||
<Container maxWidth={false} disableGutters>
|
||||
<Grid container spacing={3}>
|
||||
{/* Welcome Message */}
|
||||
<Grid item xs={12}>
|
||||
{dataLoading ? (
|
||||
<SkeletonCard variant="basic" />
|
||||
) : (
|
||||
<Fade in={true} timeout={600}>
|
||||
<Box>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
Willkommen zurück, {user?.given_name || user?.name.split(' ')[0]}!
|
||||
</Typography>
|
||||
</Box>
|
||||
</Fade>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
{/* User Profile Card */}
|
||||
<Box
|
||||
sx={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: {
|
||||
xs: '1fr',
|
||||
sm: 'repeat(2, 1fr)',
|
||||
lg: 'repeat(3, 1fr)',
|
||||
xl: 'repeat(4, 1fr)',
|
||||
},
|
||||
gap: 2.5,
|
||||
alignItems: 'start',
|
||||
}}
|
||||
>
|
||||
{/* User Profile Card — full width, contains welcome greeting */}
|
||||
{user && (
|
||||
<Grid item xs={12}>
|
||||
<Box sx={{ gridColumn: '1 / -1' }}>
|
||||
{dataLoading ? (
|
||||
<SkeletonCard variant="detailed" />
|
||||
) : (
|
||||
@@ -61,82 +55,69 @@ function Dashboard() {
|
||||
</Box>
|
||||
</Fade>
|
||||
)}
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Personal Atemschutz Warnings — shown only when relevant */}
|
||||
{/* Personal Warnings Banner — full width, conditionally rendered */}
|
||||
{user && (
|
||||
<Grid item xs={12}>
|
||||
<Box sx={{ gridColumn: '1 / -1' }}>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '150ms' }}>
|
||||
<Box>
|
||||
<PersonalWarningsBanner user={user} />
|
||||
</Box>
|
||||
</Fade>
|
||||
</Grid>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Vehicle Status Card */}
|
||||
<Grid item xs={12} md={6} sx={{ display: 'flex' }}>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '380ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<Box>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '300ms' }}>
|
||||
<Box>
|
||||
<VehicleDashboardCard />
|
||||
</Box>
|
||||
</Fade>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{/* Equipment Status Card */}
|
||||
<Grid item xs={12} md={6} sx={{ display: 'flex' }}>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '450ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<Box>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '350ms' }}>
|
||||
<Box>
|
||||
<EquipmentDashboardCard />
|
||||
</Box>
|
||||
</Fade>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{/* Atemschutz Status Card */}
|
||||
<Grid item xs={12} md={6} sx={{ display: 'flex' }}>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '420ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<Box>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '400ms' }}>
|
||||
<Box>
|
||||
<AtemschutzDashboardCard />
|
||||
</Box>
|
||||
</Fade>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{/* Upcoming Events Widget */}
|
||||
<Grid item xs={12} md={6} sx={{ display: 'flex' }}>
|
||||
<Box>
|
||||
<Fade in={!dataLoading} timeout={600} style={{ transitionDelay: '440ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<Box>
|
||||
<UpcomingEventsWidget />
|
||||
</Box>
|
||||
</Fade>
|
||||
</Grid>
|
||||
</Box>
|
||||
|
||||
{/* Nextcloud Talk Widget */}
|
||||
<Grid item xs={12} md={6} lg={5} sx={{ display: 'flex' }}>
|
||||
<Box>
|
||||
{dataLoading ? (
|
||||
<SkeletonCard variant="basic" />
|
||||
) : (
|
||||
<Fade in={true} timeout={600} style={{ transitionDelay: '520ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<Fade in={true} timeout={600} style={{ transitionDelay: '480ms' }}>
|
||||
<Box>
|
||||
<NextcloudTalkWidget />
|
||||
</Box>
|
||||
</Fade>
|
||||
)}
|
||||
</Grid>
|
||||
|
||||
{/* Activity Feed */}
|
||||
<Grid item xs={12} md={6} lg={7} sx={{ display: 'flex' }}>
|
||||
{dataLoading ? (
|
||||
<SkeletonCard variant="detailed" />
|
||||
) : (
|
||||
<Fade in={true} timeout={600} style={{ transitionDelay: '550ms' }}>
|
||||
<Box sx={{ height: '100%' }}>
|
||||
<ActivityFeed />
|
||||
</Box>
|
||||
</Fade>
|
||||
)}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Box>
|
||||
</Container>
|
||||
</DashboardLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user