feat: enhanced timeline hover tooltip with role, dates, status
The tooltip shown when hovering over project strips in the timeline now includes additional information: - Role name (e.g. "3D Artist", "Project Manager") - Assignment date range (2026-03-01 → 2026-06-30) - Status badge when not CONFIRMED (shows PROPOSED, DRAFT, etc.) - Lead person and order type on the same line Data comes from already-loaded timeline entries — no extra API calls. Safe change: tooltip is pointer-events-none and read-only. Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -141,6 +141,10 @@ function TimelineResourcePanelInner({
|
||||
orderType: string;
|
||||
hoursPerDay: number;
|
||||
responsiblePerson?: string | null;
|
||||
role?: string | null;
|
||||
status?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}[];
|
||||
} | null>(null);
|
||||
|
||||
@@ -295,6 +299,10 @@ function TimelineResourcePanelInner({
|
||||
orderType: string;
|
||||
hours: number;
|
||||
responsiblePerson?: string | null;
|
||||
role?: string | null;
|
||||
status?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}
|
||||
>();
|
||||
for (const alloc of a) {
|
||||
@@ -314,6 +322,10 @@ function TimelineResourcePanelInner({
|
||||
hours: alloc.hoursPerDay,
|
||||
responsiblePerson:
|
||||
(alloc.project as { responsiblePerson?: string | null }).responsiblePerson ?? null,
|
||||
role: alloc.role ?? alloc.roleEntity?.name ?? null,
|
||||
status: alloc.status,
|
||||
startDate: new Date(alloc.startDate).toISOString().slice(0, 10),
|
||||
endDate: new Date(alloc.endDate).toISOString().slice(0, 10),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,10 @@ export type HeatmapHoverData = {
|
||||
orderType: string;
|
||||
hoursPerDay: number;
|
||||
responsiblePerson?: string | null;
|
||||
role?: string | null;
|
||||
status?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}[];
|
||||
};
|
||||
|
||||
@@ -81,10 +85,20 @@ export function TimelineTooltip({
|
||||
{entry.projectName}
|
||||
</div>
|
||||
<div className="truncate text-[11px] text-gray-400">
|
||||
{entry.responsiblePerson
|
||||
? `Lead: ${entry.responsiblePerson}`
|
||||
: entry.orderType}
|
||||
{[
|
||||
entry.role,
|
||||
entry.responsiblePerson ? `Lead: ${entry.responsiblePerson}` : null,
|
||||
entry.orderType,
|
||||
].filter(Boolean).join(" · ")}
|
||||
</div>
|
||||
{entry.startDate && entry.endDate && (
|
||||
<div className="text-[10px] text-gray-500">
|
||||
{entry.startDate} → {entry.endDate}
|
||||
{entry.status && entry.status !== "CONFIRMED" && (
|
||||
<span className="ml-1 uppercase text-amber-400">{entry.status}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span className="whitespace-nowrap text-[11px] font-semibold text-gray-200">
|
||||
{entry.hoursPerDay}h
|
||||
@@ -146,10 +160,20 @@ export function TimelineTooltip({
|
||||
{entry.projectName}
|
||||
</div>
|
||||
<div className="truncate text-[11px] text-gray-400">
|
||||
{entry.responsiblePerson
|
||||
? `Lead: ${entry.responsiblePerson}`
|
||||
: entry.orderType}
|
||||
{[
|
||||
entry.role,
|
||||
entry.responsiblePerson ? `Lead: ${entry.responsiblePerson}` : null,
|
||||
entry.orderType,
|
||||
].filter(Boolean).join(" · ")}
|
||||
</div>
|
||||
{entry.startDate && entry.endDate && (
|
||||
<div className="text-[10px] text-gray-500">
|
||||
{entry.startDate} → {entry.endDate}
|
||||
{entry.status && entry.status !== "CONFIRMED" && (
|
||||
<span className="ml-1 uppercase text-amber-400">{entry.status}</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<span className="whitespace-nowrap text-[11px] font-semibold text-gray-200">
|
||||
{entry.hoursPerDay}h
|
||||
|
||||
Reference in New Issue
Block a user