From 370ac0fdc21ccb0b9098b5d0e211dbfba3e2d6c5 Mon Sep 17 00:00:00 2001 From: jasonMPM Date: Thu, 5 Mar 2026 17:44:34 -0600 Subject: [PATCH] Add files via upload --- .../components/Calendar/WorkloadHeatmap.jsx | 221 +++++++++--------- 1 file changed, 111 insertions(+), 110 deletions(-) diff --git a/frontend/src/components/Calendar/WorkloadHeatmap.jsx b/frontend/src/components/Calendar/WorkloadHeatmap.jsx index 1a6f279..bf1ae8a 100644 --- a/frontend/src/components/Calendar/WorkloadHeatmap.jsx +++ b/frontend/src/components/Calendar/WorkloadHeatmap.jsx @@ -56,7 +56,7 @@ export default function WorkloadHeatmap() { }) ) - const all = projects.flatMap(p => p.deliverables || []) + const all = projects.flatMap(p => p.deliverables || []) const stats = { total: all.length, upcoming: all.filter(d => d.status === 'upcoming').length, @@ -92,127 +92,128 @@ export default function WorkloadHeatmap() { - {/* Status heatmaps */} -
+ {/* Stat cards + aligned status heatmaps */} +
{STATUS_KEYS.map((statusKey) => ( -
-
-
-

- {STATUS_LABEL[statusKey]} -

- - {stats[statusKey]} tasks - -
-
- Less - {['bg-surface border-surface-border','bg-gold/25 border-gold/40','bg-gold/55 border-gold/70','bg-gold border-gold'].map((c,i) => ( -
- ))} - More -
+
+ {/* Stat card */} +
+

+ {stats[statusKey]} +

+

{STATUS_LABEL[statusKey]}

-
- {/* Day labels */} -
- {DAY_INIT.map((d, i) => ( -
- {d} -
- ))} -
- - {/* Grid */} -
- {/* Month labels */} -
- {monthLabels.map(({ wi, label }) => ( - - {label} - + {/* Heatmap for this status */} +
+
+ {/* Day labels */} +
+ {DAY_INIT.map((d, i) => ( +
+ {d} +
))}
-
- {weeks.map((week, wi) => ( -
- {week.map(({ date, key, items, statusCounts }) => { - const countForStatus = (statusCounts || {})[statusKey] || 0 - const baseDensity = countForStatus - return ( -
{ - if (!items || !items.length) return - const match = items.find(({ deliverable }) => deliverable.status === statusKey) || items[0] - if (match) openFocus(match.project.id, match.deliverable.id) - }} - onMouseEnter={(e) => { - const filtered = (items || []).filter(({ deliverable }) => deliverable.status === statusKey) - const showItems = filtered.length ? filtered : items || [] - setTooltip({ - x: e.clientX, - y: e.clientY, - date, - statusKey, - items: showItems, - }) - }} - onMouseLeave={() => setTooltip(null)} - /> - ) - })} -
- ))} + {/* Grid */} +
+ {/* Month labels */} +
+ {monthLabels.map(({ wi, label }) => ( + + {label} + + ))} +
+ +
+ {weeks.map((week, wi) => ( +
+ {week.map(({ date, key, items, statusCounts }) => { + const countForStatus = (statusCounts || {})[statusKey] || 0 + const baseDensity = countForStatus + const hoverRing = + statusKey === 'upcoming' ? 'hover:ring-blue-300/80 hover:shadow-[0_0_0_1px_rgba(147,197,253,0.8)]' : + statusKey === 'in_progress' ? 'hover:ring-amber-300/80 hover:shadow-[0_0_0_1px_rgba(252,211,77,0.8)]' : + statusKey === 'completed' ? 'hover:ring-green-300/80 hover:shadow-[0_0_0_1px_rgba(74,222,128,0.8)]' : + statusKey === 'overdue' ? 'hover:ring-red-400/90 hover:shadow-[0_0_0_1px_rgba(248,113,113,0.9)]' : + 'hover:ring-white/60' + return ( +
{ + if (!items || !items.length) return + const match = items.find(({ deliverable }) => deliverable.status === statusKey) || items[0] + if (match) openFocus(match.project.id, match.deliverable.id) + }} + onMouseEnter={(e) => { + const filtered = (items || []).filter(({ deliverable }) => deliverable.status === statusKey) + const showItems = filtered.length ? filtered : items || [] + setTooltip({ + x: e.clientX, + y: e.clientY, + date, + statusKey, + items: showItems, + }) + }} + onMouseLeave={() => setTooltip(null)} + /> + ) + })} +
+ ))} +
))} - - {tooltip && ( -
-

- {isToday(tooltip.date) ? 'Today — ' : ''}{format(tooltip.date, 'EEE, MMM d, yyyy')} -

-

- {STATUS_LABEL[tooltip.statusKey]} · {tooltip.items.length} task{tooltip.items.length !== 1 ? 's' : ''} -

- {tooltip.items.length === 0 ? ( -

No deliverables

- ) : ( -
- {tooltip.items.slice(0, 5).map(({ deliverable, project }) => ( -
-
-
-

{deliverable.title}

-

{project.name}

-
-
- ))} - {tooltip.items.length > 5 && ( -

+{tooltip.items.length - 5} more

- )} -
- )} -
- )}
+ + {/* Tooltip */} + {tooltip && ( +
+

+ {isToday(tooltip.date) ? 'Today \u2014 ' : ''}{format(tooltip.date, 'EEE, MMM d, yyyy')} +

+

+ {STATUS_LABEL[tooltip.statusKey]} \u00b7 {tooltip.items.length} task{tooltip.items.length !== 1 ? 's' : ''} +

+ {tooltip.items.length === 0 ? ( +

No deliverables

+ ) : ( +
+ {tooltip.items.slice(0, 5).map(({ deliverable, project }) => ( +
+
+
+

{deliverable.title}

+

{project.name}

+
+
+ ))} + {tooltip.items.length > 5 && ( +

+{tooltip.items.length - 5} more

+ )} +
+ )} +
+ )}
) }