Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92252382ac | ||
|
|
8bed920de1 | ||
|
|
9d2992b722 | ||
|
|
1ddc0feccd |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app-ts",
|
||||
"version": "2.0.6",
|
||||
"version": "2.0.8",
|
||||
"description": "",
|
||||
"main": "dist/server.js",
|
||||
"scripts": {
|
||||
|
||||
@@ -620,7 +620,6 @@ export default function PlanGrid({
|
||||
c.category,
|
||||
catMap,
|
||||
)}
|
||||
showNote={cellArr.length === 1}
|
||||
/>
|
||||
</Box>
|
||||
))}
|
||||
|
||||
@@ -6,7 +6,6 @@ interface Props {
|
||||
project: Project | null;
|
||||
readonly?: boolean;
|
||||
categoryLabel: string;
|
||||
showNote?: boolean;
|
||||
}
|
||||
|
||||
export default function PlanRangeChips({
|
||||
@@ -14,7 +13,6 @@ export default function PlanRangeChips({
|
||||
project,
|
||||
readonly,
|
||||
categoryLabel,
|
||||
showNote = true,
|
||||
}: Props) {
|
||||
void readonly;
|
||||
if (!cell) return null;
|
||||
@@ -38,9 +36,7 @@ export default function PlanRangeChips({
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{showNote && cell.note && (
|
||||
<div className="plan-cell-note">{cell.note}</div>
|
||||
)}
|
||||
{cell.note && <div className="plan-cell-note">{cell.note}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export const STATUS_LABELS: Record<string, string> = {
|
||||
away: "Přestávka",
|
||||
out: "Nepřihlášen",
|
||||
leave: "Nepřítomen",
|
||||
absent: "Nepřítomen",
|
||||
};
|
||||
|
||||
// Re-exported from the single source of truth so the dashboard activity feed
|
||||
|
||||
@@ -69,7 +69,7 @@ export default async function dashboardRoutes(
|
||||
|
||||
// Attendance admin — only for attendance.manage
|
||||
if (has("attendance.manage")) {
|
||||
const [todayAttendance, onLeaveToday, usersCount] = await Promise.all([
|
||||
const [todayAttendance, onLeaveToday, activeUsers] = await Promise.all([
|
||||
prisma.attendance.findMany({
|
||||
where: {
|
||||
shift_date: { gte: todayStart, lt: todayEnd },
|
||||
@@ -89,8 +89,13 @@ export default async function dashboardRoutes(
|
||||
users: { select: { id: true, first_name: true, last_name: true } },
|
||||
},
|
||||
}),
|
||||
prisma.users.count({ where: { is_active: true } }),
|
||||
prisma.users.findMany({
|
||||
where: { is_active: true },
|
||||
select: { id: true, first_name: true, last_name: true },
|
||||
orderBy: [{ last_name: "asc" }, { first_name: "asc" }],
|
||||
}),
|
||||
]);
|
||||
const usersCount = activeUsers.length;
|
||||
|
||||
const userAttendanceMap = new Map<number, (typeof todayAttendance)[0]>();
|
||||
for (const a of todayAttendance) {
|
||||
@@ -153,6 +158,25 @@ export default async function dashboardRoutes(
|
||||
});
|
||||
}
|
||||
|
||||
// Show every active employee — those with no attendance record today
|
||||
// appear as "absent" so the card reflects the whole team, not just those
|
||||
// who clocked in or are on leave.
|
||||
const recordedUserIds = new Set<number>([
|
||||
...userAttendanceMap.keys(),
|
||||
...leaveUserIds,
|
||||
]);
|
||||
for (const user of activeUsers) {
|
||||
if (recordedUserIds.has(user.id)) continue;
|
||||
attendanceUsers.push({
|
||||
user_id: user.id,
|
||||
name: `${user.first_name} ${user.last_name}`,
|
||||
initials:
|
||||
`${user.first_name?.charAt(0) ?? ""}${user.last_name?.charAt(0) ?? ""}`.toUpperCase(),
|
||||
status: "absent",
|
||||
arrived_at: null,
|
||||
});
|
||||
}
|
||||
|
||||
result.attendance = {
|
||||
present_today: presentCount,
|
||||
total_active: usersCount,
|
||||
|
||||
Reference in New Issue
Block a user