fix heatmap months legend
This commit is contained in:
@@ -106,6 +106,10 @@
|
|||||||
const now = new Date();
|
const now = new Date();
|
||||||
const years = [now.getFullYear(), now.getFullYear()-1, now.getFullYear()-2, now.getFullYear()-3];
|
const years = [now.getFullYear(), now.getFullYear()-1, now.getFullYear()-2, now.getFullYear()-3];
|
||||||
|
|
||||||
|
function localISO(d: Date): string {
|
||||||
|
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
function getWeeks(year: number): string[][] {
|
function getWeeks(year: number): string[][] {
|
||||||
const jan1 = new Date(year, 0, 1);
|
const jan1 = new Date(year, 0, 1);
|
||||||
const dec31 = new Date(year, 11, 31);
|
const dec31 = new Date(year, 11, 31);
|
||||||
@@ -118,8 +122,7 @@
|
|||||||
while (cur <= end) {
|
while (cur <= end) {
|
||||||
const week: string[] = [];
|
const week: string[] = [];
|
||||||
for (let d = 0; d < 7; d++) {
|
for (let d = 0; d < 7; d++) {
|
||||||
const iso = cur.toISOString().slice(0, 10);
|
week.push(cur.getFullYear() === year ? localISO(cur) : '');
|
||||||
week.push(cur.getFullYear() === year ? iso : '');
|
|
||||||
cur.setDate(cur.getDate() + 1);
|
cur.setDate(cur.getDate() + 1);
|
||||||
}
|
}
|
||||||
weeks.push(week);
|
weeks.push(week);
|
||||||
@@ -130,18 +133,6 @@
|
|||||||
const DOW = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
|
const DOW = ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
|
||||||
const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
|
||||||
|
|
||||||
function monthLabels(weeks: string[][]): Array<{ month: string; col: number }> {
|
|
||||||
const seen = new Set<string>();
|
|
||||||
return weeks.flatMap((week, i) => {
|
|
||||||
const day = week.find(d => d);
|
|
||||||
if (!day) return [];
|
|
||||||
const m = MONTHS[parseInt(day.slice(5, 7)) - 1];
|
|
||||||
if (seen.has(m)) return [];
|
|
||||||
seen.add(m);
|
|
||||||
return [{ month: m, col: i }];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function cellTitle(date: string): string {
|
function cellTitle(date: string): string {
|
||||||
if (!date) return '';
|
if (!date) return '';
|
||||||
const sportMap = byDateBySport.get(date);
|
const sportMap = byDateBySport.get(date);
|
||||||
@@ -205,7 +196,6 @@
|
|||||||
<!-- Heatmaps per year -->
|
<!-- Heatmaps per year -->
|
||||||
{#each years as year}
|
{#each years as year}
|
||||||
{@const weeks = getWeeks(year)}
|
{@const weeks = getWeeks(year)}
|
||||||
{@const labels = monthLabels(weeks)}
|
|
||||||
{@const yt = totalsByYear.get(year)}
|
{@const yt = totalsByYear.get(year)}
|
||||||
{#if yt}
|
{#if yt}
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
@@ -217,41 +207,38 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<div class="inline-block">
|
<div class="inline-flex gap-[3px]">
|
||||||
<!-- Month labels -->
|
<!-- Day-of-week labels: blank slot at top to align with month row -->
|
||||||
<div class="flex mb-1 ml-6">
|
<div class="flex flex-col gap-[3px] mr-1">
|
||||||
{#each labels as { month, col }}
|
<div class="h-4" />
|
||||||
<span
|
{#each DOW as d, i}
|
||||||
class="text-xs text-zinc-500 absolute"
|
<span class="text-[9px] text-zinc-600 h-[10px] leading-[10px] w-3 text-right">
|
||||||
style="left: calc({col} * 13px)"
|
{i % 2 === 1 ? d : ''}
|
||||||
>{month}</span>
|
</span>
|
||||||
{/each}
|
{/each}
|
||||||
<div style="width:{weeks.length * 13}px" />
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Week columns: month label at top, day cells below -->
|
||||||
<!-- Grid -->
|
{#each weeks as week, wi}
|
||||||
<div class="flex gap-[3px]">
|
{@const firstDay = week.find(d => d)}
|
||||||
<!-- Day-of-week labels -->
|
{@const prevFirstDay = wi > 0 ? weeks[wi - 1].find(d => d) : null}
|
||||||
<div class="flex flex-col gap-[3px] mr-1">
|
{@const showMonth = firstDay && (!prevFirstDay || prevFirstDay.slice(5, 7) !== firstDay.slice(5, 7))}
|
||||||
{#each DOW as d, i}
|
<div class="flex flex-col gap-[3px]">
|
||||||
<span class="text-[9px] text-zinc-600 h-[10px] leading-[10px] w-3 text-right">
|
<div class="h-4 relative">
|
||||||
{i % 2 === 1 ? d : ''}
|
{#if showMonth}
|
||||||
</span>
|
<span class="text-[10px] text-zinc-500 absolute left-0 top-0 whitespace-nowrap">
|
||||||
|
{MONTHS[parseInt(firstDay.slice(5, 7)) - 1]}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#each week as date}
|
||||||
|
<div
|
||||||
|
class="w-[10px] h-[10px] rounded-[2px]"
|
||||||
|
style="background:{cellColors.get(date) ?? '#27272a'}"
|
||||||
|
title={cellTitle(date)}
|
||||||
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<!-- Weeks -->
|
{/each}
|
||||||
{#each weeks as week}
|
|
||||||
<div class="flex flex-col gap-[3px]">
|
|
||||||
{#each week as date}
|
|
||||||
<div
|
|
||||||
class="w-[10px] h-[10px] rounded-[2px]"
|
|
||||||
style="background:{cellColors.get(date) ?? '#27272a'}"
|
|
||||||
title={cellTitle(date)}
|
|
||||||
/>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user