feat(mui): migrate Dashboard (Přehled) onto MUI kit
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import { Link } from "react-router-dom";
|
||||
import {
|
||||
LEAVE_TYPE_LABELS,
|
||||
STATUS_DOT_CLASS,
|
||||
STATUS_LABELS,
|
||||
} from "../../utils/dashboardHelpers";
|
||||
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;
|
||||
@@ -22,6 +22,19 @@ 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) {
|
||||
@@ -30,42 +43,96 @@ export default function DashAttendanceToday({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="admin-card dash-attendance-card">
|
||||
<div className="admin-card-header flex-between">
|
||||
<h2 className="admin-card-title">Docházka dnes</h2>
|
||||
<Link
|
||||
<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"
|
||||
className="admin-btn admin-btn-primary admin-btn-sm"
|
||||
size="small"
|
||||
sx={{ flexShrink: 0 }}
|
||||
>
|
||||
Detail →
|
||||
</Link>
|
||||
</div>
|
||||
<div className="admin-card-body" style={{ padding: 0 }}>
|
||||
{attendance.users.map((u, i) => (
|
||||
<div key={`${u.user_id}-${i}`} className="dash-presence-row">
|
||||
<div
|
||||
className={`dash-presence-avatar ${STATUS_DOT_CLASS[u.status]}`}
|
||||
>
|
||||
{u.initials || "?"}
|
||||
</div>
|
||||
<div className="dash-presence-name">{u.name}</div>
|
||||
<div className="dash-presence-end">
|
||||
<span
|
||||
className={`dash-presence-label ${STATUS_DOT_CLASS[u.status]}`}
|
||||
</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 },
|
||||
}}
|
||||
>
|
||||
{u.status === "leave"
|
||||
? LEAVE_TYPE_LABELS[u.leave_type || ""] || "Nepřítomen"
|
||||
: STATUS_LABELS[u.status]}
|
||||
</span>
|
||||
{u.arrived_at && (
|
||||
<span className="admin-mono dash-presence-time">
|
||||
{u.arrived_at}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<Avatar
|
||||
sx={{
|
||||
width: 36,
|
||||
height: 36,
|
||||
fontSize: "0.8rem",
|
||||
fontWeight: 700,
|
||||
bgcolor: isDefault ? "action.hover" : `${color}.light`,
|
||||
color: isDefault ? "text.secondary" : `${color}.main`,
|
||||
}}
|
||||
>
|
||||
{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>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user