Merge pull request #26 from jasonMPM/fix-heatmap-again
Add files via upload
This commit is contained in:
@@ -92,33 +92,25 @@ export default function WorkloadHeatmap() {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Status heatmaps */}
|
||||
<div className="flex flex-col gap-6 px-8 pb-8">
|
||||
{/* Stat cards + aligned status heatmaps */}
|
||||
<div className="grid grid-cols-4 gap-4 px-8 pb-8">
|
||||
{STATUS_KEYS.map((statusKey) => (
|
||||
<div key={statusKey} className="bg-surface-elevated/40 border border-surface-border rounded-xl p-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<div className="flex items-baseline gap-2">
|
||||
<h3 className="text-xs font-semibold tracking-widest uppercase text-text-muted/70">
|
||||
{STATUS_LABEL[statusKey]}
|
||||
</h3>
|
||||
<span className={`${STATUS_COLOR[statusKey]} text-[10px] font-mono`}>
|
||||
{stats[statusKey]} tasks
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 text-[9px] text-text-muted/60">
|
||||
<span>Less</span>
|
||||
{['bg-surface border-surface-border','bg-gold/25 border-gold/40','bg-gold/55 border-gold/70','bg-gold border-gold'].map((c,i) => (
|
||||
<div key={i} className={`w-3 h-3 rounded-sm border ${c}`} />
|
||||
))}
|
||||
<span>More</span>
|
||||
</div>
|
||||
<div key={statusKey} className="flex flex-col gap-3">
|
||||
{/* Stat card */}
|
||||
<div className="bg-surface-elevated border border-surface-border rounded-xl p-4 text-center">
|
||||
<p className={`text-2xl font-bold ${STATUS_COLOR[statusKey]}`}>
|
||||
{stats[statusKey]}
|
||||
</p>
|
||||
<p className="text-text-muted text-xs mt-1">{STATUS_LABEL[statusKey]}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3 overflow-x-auto pb-2">
|
||||
{/* Heatmap for this status */}
|
||||
<div className="bg-surface-elevated/40 border border-surface-border rounded-xl p-3 flex-1 min-h-[160px]">
|
||||
<div className="flex gap-2 overflow-x-auto pb-1">
|
||||
{/* Day labels */}
|
||||
<div className="flex flex-col flex-shrink-0 pt-6" style={{ gap: GAP }}>
|
||||
{DAY_INIT.map((d, i) => (
|
||||
<div key={i} style={{ height: CELL }} className="flex items-center text-[10px] text-text-muted/50 font-mono w-4">
|
||||
<div key={i} style={{ height: CELL }} className="flex items-center text-[9px] text-text-muted/50 font-mono w-3">
|
||||
{d}
|
||||
</div>
|
||||
))}
|
||||
@@ -127,11 +119,11 @@ export default function WorkloadHeatmap() {
|
||||
{/* Grid */}
|
||||
<div className="flex flex-col flex-shrink-0">
|
||||
{/* Month labels */}
|
||||
<div className="relative h-5 mb-1">
|
||||
<div className="relative h-4 mb-1">
|
||||
{monthLabels.map(({ wi, label }) => (
|
||||
<span
|
||||
key={label+wi}
|
||||
className="absolute text-[10px] text-text-muted/60 font-medium"
|
||||
className="absolute text-[9px] text-text-muted/60 font-medium"
|
||||
style={{ left: wi * (CELL + GAP) }}
|
||||
>
|
||||
{label}
|
||||
@@ -145,13 +137,20 @@ export default function WorkloadHeatmap() {
|
||||
{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 (
|
||||
<div
|
||||
key={key + statusKey}
|
||||
style={{ width: CELL, height: CELL }}
|
||||
className={`rounded-sm border cursor-pointer transition-all hover:scale-125 hover:z-10 relative
|
||||
className={`rounded-sm border cursor-pointer transition-transform duration-100 hover:scale-125 hover:z-10 relative
|
||||
${getCellClass(baseDensity, statusCounts || {})}
|
||||
${isToday(date) ? 'ring-1 ring-white/40' : ''}
|
||||
${isToday(date) ? 'ring-1 ring-white/60' : ''}
|
||||
${hoverRing}
|
||||
`}
|
||||
onClick={() => {
|
||||
if (!items || !items.length) return
|
||||
@@ -179,18 +178,21 @@ export default function WorkloadHeatmap() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Tooltip */}
|
||||
{tooltip && (
|
||||
<div
|
||||
className="fixed z-[200] pointer-events-none bg-surface-elevated border border-surface-border rounded-xl shadow-2xl px-3.5 py-3 min-w-[220px] max-w-[320px]"
|
||||
style={{ left: Math.min(tooltip.x + 14, window.innerWidth - 330), top: Math.max(tooltip.y - 100, 8) }}
|
||||
>
|
||||
<p className={`text-xs font-bold mb-1.5 ${isToday(tooltip.date) ? 'text-gold' : 'text-text-primary'}`}>
|
||||
{isToday(tooltip.date) ? 'Today — ' : ''}{format(tooltip.date, 'EEE, MMM d, yyyy')}
|
||||
{isToday(tooltip.date) ? 'Today \u2014 ' : ''}{format(tooltip.date, 'EEE, MMM d, yyyy')}
|
||||
</p>
|
||||
<p className="text-[10px] text-text-muted/60 mb-1.5">
|
||||
{STATUS_LABEL[tooltip.statusKey]} · {tooltip.items.length} task{tooltip.items.length !== 1 ? 's' : ''}
|
||||
{STATUS_LABEL[tooltip.statusKey]} \u00b7 {tooltip.items.length} task{tooltip.items.length !== 1 ? 's' : ''}
|
||||
</p>
|
||||
{tooltip.items.length === 0 ? (
|
||||
<p className="text-text-muted/50 text-xs">No deliverables</p>
|
||||
@@ -213,6 +215,5 @@ export default function WorkloadHeatmap() {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user