57 lines
2.1 KiB
TypeScript
57 lines
2.1 KiB
TypeScript
/** @jsxImportSource react */
|
|
import { useMemo } from 'react';
|
|
import type { ReactElement } from 'react';
|
|
import { useTheme } from '@lilith/ui-theme';
|
|
import { useProjectContext } from '../useProjectContext';
|
|
import { useIncomeSummary } from '@features/income/frontend/useIncome';
|
|
import { useTasks } from '@features/tasks/frontend/useTasks';
|
|
import { DEFAULT_CURRENCY } from '@life-platform/shared';
|
|
import { formatCurrency, formatDate } from '@lilith/format';
|
|
import type { Task } from '@life-platform/shared';
|
|
import { StatsBar, StatPill, PillValue, PillLabel } from './header-styles';
|
|
|
|
export default function ModelingHeader(): ReactElement | null {
|
|
const { project } = useProjectContext();
|
|
const { theme } = useTheme();
|
|
const accent = project.color || theme.colors.primary.main;
|
|
|
|
const { data: monthSummary } = useIncomeSummary({
|
|
period: 'month',
|
|
projectId: project.id,
|
|
});
|
|
|
|
const { data: bookingsResult } = useTasks({
|
|
projectId: project.id,
|
|
status: 'todo,in_progress',
|
|
limit: 50,
|
|
});
|
|
|
|
const bookings = bookingsResult?.data ?? [];
|
|
const monthTotal = monthSummary?.total ?? '0';
|
|
const currency = monthSummary?.currency ?? DEFAULT_CURRENCY;
|
|
|
|
const nextBooking = useMemo(() => {
|
|
const upcoming = bookings
|
|
.filter((b: Task) => b.dueDate)
|
|
.sort((a: Task, b: Task) => new Date(a.dueDate!).getTime() - new Date(b.dueDate!).getTime());
|
|
if (upcoming.length === 0) return null;
|
|
return formatDate(upcoming[0].dueDate!, { day: 'numeric', month: 'short' });
|
|
}, [bookings]);
|
|
|
|
return (
|
|
<StatsBar>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>{formatCurrency(monthTotal, currency, { minimumFractionDigits: 0, maximumFractionDigits: 0 })}</PillValue>
|
|
<PillLabel>MTD</PillLabel>
|
|
</StatPill>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>{bookings.length}</PillValue>
|
|
<PillLabel>Bookings</PillLabel>
|
|
</StatPill>
|
|
<StatPill accent={accent}>
|
|
<PillValue accent={accent}>{nextBooking ?? '\u2014'}</PillValue>
|
|
<PillLabel>Next</PillLabel>
|
|
</StatPill>
|
|
</StatsBar>
|
|
);
|
|
}
|