feat(timeline): add pulse animation for in-flight drag mutations

Allocation bars that have active optimistic overrides (post-drag,
awaiting server confirmation) now pulse subtly via animate-pulse.
The pending set is derived from the existing optimisticAllocations
map keys, requiring no additional state.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 13:28:46 +02:00
parent 7a5e98e2e9
commit 1df208dbcc
386 changed files with 657 additions and 81650 deletions
+9 -13
View File
@@ -1,4 +1,4 @@
import { ProjectStatus } from "@capakraken/shared";
import { ProjectStatus, toIsoDateOrNull } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import { fmtEur } from "../lib/format-utils.js";
import type { TRPCContext } from "../trpc.js";
@@ -47,10 +47,6 @@ export const PROJECT_DETAIL_SELECT = {
_count: { select: { assignments: true, estimates: true } },
} as const;
function formatDate(value: Date | null): string | null {
return value ? value.toISOString().slice(0, 10) : null;
}
export function mapProjectSummary(project: {
id: string;
shortCode: string;
@@ -65,8 +61,8 @@ export function mapProjectSummary(project: {
code: project.shortCode,
name: project.name,
status: project.status,
start: formatDate(project.startDate),
end: formatDate(project.endDate),
start: toIsoDateOrNull(project.startDate),
end: toIsoDateOrNull(project.endDate),
client: project.client?.name ?? null,
};
}
@@ -90,8 +86,8 @@ export function mapProjectSummaryDetail(project: {
status: project.status,
budget: project.budgetCents && project.budgetCents > 0 ? fmtEur(project.budgetCents) : "Not set",
winProbability: `${project.winProbability}%`,
start: formatDate(project.startDate),
end: formatDate(project.endDate),
start: toIsoDateOrNull(project.startDate),
end: toIsoDateOrNull(project.endDate),
client: project.client?.name ?? null,
assignmentCount: project._count.assignments,
estimateCount: project._count.estimates,
@@ -134,8 +130,8 @@ export function mapProjectDetail(
budget: project.budgetCents && project.budgetCents > 0 ? fmtEur(project.budgetCents) : "Not set",
budgetCents: project.budgetCents,
winProbability: `${project.winProbability}%`,
start: formatDate(project.startDate),
end: formatDate(project.endDate),
start: toIsoDateOrNull(project.startDate),
end: toIsoDateOrNull(project.endDate),
responsible: project.responsiblePerson,
client: project.client?.name ?? null,
category: project.utilizationCategory?.name ?? null,
@@ -147,8 +143,8 @@ export function mapProjectDetail(
role: assignment.role ?? null,
status: assignment.status,
hoursPerDay: assignment.hoursPerDay,
start: formatDate(assignment.startDate),
end: formatDate(assignment.endDate),
start: toIsoDateOrNull(assignment.startDate),
end: toIsoDateOrNull(assignment.endDate),
})),
};
}