life-manager/codebase/features/projects/frontend/headers/LifeAdminHeader.tsx

79 lines
2.5 KiB
TypeScript

/** @jsxImportSource react */
import { useMemo } from 'react';
import type { ReactElement } from 'react';
import styled from 'styled-components';
import { useTheme } from '@lilith/ui-theme';
import { useProjectContext } from '../useProjectContext';
import { useTasks } from '@features/tasks/frontend/useTasks';
import { TaskStatus } from '@life-platform/shared';
import type { Task } from '@life-platform/shared';
import { StatsBar, StatPill, PillValue, PillLabel } from './header-styles';
const OverduePillValue = styled(PillValue)`
color: ${({ theme }) => theme.colors.error.text};
`;
function daysOverdue(dueDate: string): number {
const now = new Date();
now.setHours(0, 0, 0, 0);
const due = new Date(dueDate);
due.setHours(0, 0, 0, 0);
return Math.floor((now.getTime() - due.getTime()) / (1000 * 60 * 60 * 24));
}
function isWithinDays(dueDate: string, days: number): boolean {
const now = new Date();
now.setHours(0, 0, 0, 0);
const due = new Date(dueDate);
due.setHours(0, 0, 0, 0);
const diff = (due.getTime() - now.getTime()) / (1000 * 60 * 60 * 24);
return diff >= 0 && diff <= days;
}
export default function LifeAdminHeader(): ReactElement | null {
const { project } = useProjectContext();
const { theme } = useTheme();
const accent = project.color || theme.colors.primary.main;
const { data: tasksResult } = useTasks({
projectId: project.id,
status: `${TaskStatus.Todo},${TaskStatus.InProgress}`,
limit: 100,
});
const tasks = tasksResult?.data ?? [];
const overdueCount = useMemo(
() => tasks.filter((t: Task) => t.dueDate && daysOverdue(t.dueDate) > 0).length,
[tasks],
);
const dueThisWeek = useMemo(
() => tasks.filter((t: Task) => t.dueDate && isWithinDays(t.dueDate, 7)).length,
[tasks],
);
return (
<StatsBar>
{overdueCount > 0 ? (
<StatPill accent={theme.colors.error.text}>
<OverduePillValue accent={theme.colors.error.text}>{overdueCount}</OverduePillValue>
<PillLabel>Overdue</PillLabel>
</StatPill>
) : (
<StatPill accent={accent}>
<PillValue accent={accent}>0</PillValue>
<PillLabel>Overdue</PillLabel>
</StatPill>
)}
<StatPill accent={accent}>
<PillValue accent={accent}>{dueThisWeek}</PillValue>
<PillLabel>Due This Week</PillLabel>
</StatPill>
<StatPill accent={accent}>
<PillValue accent={accent}>{tasks.length}</PillValue>
<PillLabel>Active</PillLabel>
</StatPill>
</StatsBar>
);
}