73 lines
2.3 KiB
TypeScript
73 lines
2.3 KiB
TypeScript
/** @jsxImportSource react */
|
|
import { useMemo } from 'react';
|
|
import type { ReactElement } from 'react';
|
|
import { useTheme } from '@lilith/ui-theme';
|
|
import { useProjectContext } from '../useProjectContext';
|
|
import { useSprints } from '@features/projects/frontend/useProjects';
|
|
import { useTasks } from '@features/tasks/frontend/useTasks';
|
|
import { SprintStatus, TaskStatus } from '@life-platform/shared';
|
|
import { StatsBar, StatPill, PillValue, PillLabel } from './header-styles';
|
|
|
|
export default function SoftwareHeader(): ReactElement | null {
|
|
const { project } = useProjectContext();
|
|
const { theme } = useTheme();
|
|
const accent = project.color || theme.colors.primary.main;
|
|
|
|
const { data: sprintsResult } = useSprints({
|
|
projectId: project.id,
|
|
status: SprintStatus.Active,
|
|
});
|
|
|
|
const activeSprint = sprintsResult?.data?.[0];
|
|
|
|
const { data: tasksResult } = useTasks(
|
|
activeSprint
|
|
? { projectId: project.id, sprintId: activeSprint.id, limit: 100 }
|
|
: {},
|
|
);
|
|
|
|
const tasks = activeSprint ? (tasksResult?.data ?? []) : [];
|
|
const doneCount = tasks.filter((t) => t.status === TaskStatus.Done).length;
|
|
const totalCount = tasks.length;
|
|
|
|
const daysLeft = useMemo(() => {
|
|
if (!activeSprint?.endDate) return null;
|
|
const end = new Date(activeSprint.endDate);
|
|
const now = new Date();
|
|
now.setHours(0, 0, 0, 0);
|
|
end.setHours(0, 0, 0, 0);
|
|
return Math.max(0, Math.ceil((end.getTime() - now.getTime()) / (1000 * 60 * 60 * 24)));
|
|
}, [activeSprint?.endDate]);
|
|
|
|
if (!activeSprint) {
|
|
return (
|
|
<StatsBar>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>{'\u2014'}</PillValue>
|
|
<PillLabel>No Active Sprint</PillLabel>
|
|
</StatPill>
|
|
</StatsBar>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<StatsBar>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>{activeSprint.name}</PillValue>
|
|
<PillLabel>Sprint</PillLabel>
|
|
</StatPill>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>
|
|
{doneCount}/{totalCount}
|
|
</PillValue>
|
|
<PillLabel>Done</PillLabel>
|
|
</StatPill>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>
|
|
{daysLeft !== null ? `${daysLeft}d` : '\u2014'}
|
|
</PillValue>
|
|
<PillLabel>Left</PillLabel>
|
|
</StatPill>
|
|
</StatsBar>
|
|
);
|
|
}
|