Removed MuiColorSchemeSync: it called MUI setMode which ALSO wrote data-theme, fighting ThemeContext (the other writer) → theme flip-flop loop. ThemeContext is now the sole owner; MUI's cssVariables CSS (scoped by [data-theme]) applies from the attribute, no JS bridge needed. New animated ThemeToggle kit button (sun/moon crossfade+rotate) replaces the static AppShell toggle. DashAttendanceToday avatars now solid-fill + white initials (matches StatCard/activity badges). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
139 lines
3.9 KiB
TypeScript
139 lines
3.9 KiB
TypeScript
import { Link as RouterLink } from "react-router-dom";
|
|
import Box from "@mui/material/Box";
|
|
import Typography from "@mui/material/Typography";
|
|
import Avatar from "@mui/material/Avatar";
|
|
import { Card, Button, StatusChip, EmptyState } from "../../ui";
|
|
import { LEAVE_TYPE_LABELS, STATUS_LABELS } from "../../utils/dashboardHelpers";
|
|
|
|
interface AttendanceUser {
|
|
user_id: number | string;
|
|
name: string;
|
|
initials?: string;
|
|
status: string;
|
|
leave_type?: string;
|
|
arrived_at?: string;
|
|
}
|
|
|
|
interface AttendanceData {
|
|
users: AttendanceUser[];
|
|
}
|
|
|
|
interface DashAttendanceTodayProps {
|
|
attendance: AttendanceData | null;
|
|
}
|
|
|
|
// Maps the attendance status to the StatusChip / avatar tint color.
|
|
// Mirrors the legacy dash-status-* dot classes: in→success, away→warning,
|
|
// out→default, leave→error.
|
|
const STATUS_COLOR: Record<
|
|
string,
|
|
"default" | "success" | "warning" | "error"
|
|
> = {
|
|
in: "success",
|
|
away: "warning",
|
|
out: "default",
|
|
leave: "error",
|
|
};
|
|
|
|
export default function DashAttendanceToday({
|
|
attendance,
|
|
}: DashAttendanceTodayProps) {
|
|
if (!attendance) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<Card sx={{ display: "flex", flexDirection: "column" }}>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
mb: 2,
|
|
}}
|
|
>
|
|
<Typography variant="h6">Docházka dnes</Typography>
|
|
<Button
|
|
component={RouterLink}
|
|
to="/attendance/admin"
|
|
size="small"
|
|
sx={{ flexShrink: 0 }}
|
|
>
|
|
Detail →
|
|
</Button>
|
|
</Box>
|
|
|
|
{attendance.users.length === 0 ? (
|
|
<EmptyState title="Žádná docházka" />
|
|
) : (
|
|
<Box sx={{ display: "flex", flexDirection: "column" }}>
|
|
{attendance.users.map((u, i) => {
|
|
const color = STATUS_COLOR[u.status] ?? "default";
|
|
const isDefault = color === "default";
|
|
return (
|
|
<Box
|
|
key={`${u.user_id}-${i}`}
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: 1.5,
|
|
py: 1.25,
|
|
borderBottom: 1,
|
|
borderColor: "divider",
|
|
"&:last-of-type": { borderBottom: 0 },
|
|
}}
|
|
>
|
|
<Avatar
|
|
sx={{
|
|
width: 36,
|
|
height: 36,
|
|
fontSize: "0.8rem",
|
|
fontWeight: 700,
|
|
bgcolor: isDefault ? "grey.600" : `${color}.main`,
|
|
color: "common.white",
|
|
}}
|
|
>
|
|
{u.initials || "?"}
|
|
</Avatar>
|
|
<Typography
|
|
variant="body2"
|
|
sx={{ fontWeight: 500, flex: 1, minWidth: 0 }}
|
|
noWrap
|
|
>
|
|
{u.name}
|
|
</Typography>
|
|
<Box
|
|
sx={{
|
|
display: "flex",
|
|
alignItems: "center",
|
|
gap: 1,
|
|
flexShrink: 0,
|
|
}}
|
|
>
|
|
<StatusChip
|
|
color={color}
|
|
label={
|
|
u.status === "leave"
|
|
? LEAVE_TYPE_LABELS[u.leave_type || ""] || "Nepřítomen"
|
|
: STATUS_LABELS[u.status]
|
|
}
|
|
/>
|
|
{u.arrived_at && (
|
|
<Typography
|
|
variant="caption"
|
|
color="text.secondary"
|
|
sx={{ fontFamily: "'DM Mono', Menlo, monospace" }}
|
|
>
|
|
{u.arrived_at}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
);
|
|
})}
|
|
</Box>
|
|
)}
|
|
</Card>
|
|
);
|
|
}
|