fix: guard data.sessions against undefined and enlarge tiles to 13px with 920px minimum width
This commit is contained in:
parent
d332848d73
commit
0a4ae66c92
3 changed files with 119 additions and 117 deletions
|
|
@ -101,7 +101,7 @@ function HeatmapView() {
|
||||||
sessionTitle: "All Sessions (Global)"
|
sessionTitle: "All Sessions (Global)"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const session = data.sessions.find((s) => s.id === selectedSessionId);
|
const session = (data.sessions || []).find((s) => s.id === selectedSessionId);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return {
|
return {
|
||||||
summary: data.summary,
|
summary: data.summary,
|
||||||
|
|
@ -320,8 +320,8 @@ function HeatmapView() {
|
||||||
maxWidth: 240
|
maxWidth: 240
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* @__PURE__ */ import_react.default.createElement("option", { value: "all" }, "All Sessions (", data.sessions.length, " total)"),
|
/* @__PURE__ */ import_react.default.createElement("option", { value: "all" }, "All Sessions (", (data.sessions || []).length, " total)"),
|
||||||
data.sessions.map((s) => /* @__PURE__ */ import_react.default.createElement("option", { key: s.id, value: s.id }, new Date(s.createdAt).toLocaleDateString(), " \xB7 ", s.title.slice(0, 32)))
|
(data.sessions || []).map((s) => /* @__PURE__ */ import_react.default.createElement("option", { key: s.id, value: s.id }, new Date(s.createdAt).toLocaleDateString(), " \xB7 ", s.title.slice(0, 32)))
|
||||||
)), /* @__PURE__ */ import_react.default.createElement(
|
)), /* @__PURE__ */ import_react.default.createElement(
|
||||||
"button",
|
"button",
|
||||||
{
|
{
|
||||||
|
|
@ -450,17 +450,17 @@ function HeatmapView() {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
overflowX: "auto",
|
overflowX: "auto",
|
||||||
WebkitOverflowScrolling: "touch",
|
WebkitOverflowScrolling: "touch",
|
||||||
paddingBottom: "8px"
|
paddingBottom: "10px"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/* @__PURE__ */ import_react.default.createElement(
|
/* @__PURE__ */ import_react.default.createElement("div", { style: { minWidth: "920px", width: "100%", display: "inline-block" } }, /* @__PURE__ */ import_react.default.createElement(
|
||||||
"svg",
|
"svg",
|
||||||
{
|
{
|
||||||
viewBox: "0 0 895 142",
|
viewBox: "0 0 920 152",
|
||||||
style: {
|
style: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
minWidth: "860px",
|
minWidth: "920px",
|
||||||
height: "142px",
|
height: "152px",
|
||||||
display: "block",
|
display: "block",
|
||||||
overflow: "visible"
|
overflow: "visible"
|
||||||
}
|
}
|
||||||
|
|
@ -469,7 +469,7 @@ function HeatmapView() {
|
||||||
"text",
|
"text",
|
||||||
{
|
{
|
||||||
key: i,
|
key: i,
|
||||||
x: 34 + m.col * 16,
|
x: 36 + m.col * 16.5,
|
||||||
y: 12,
|
y: 12,
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
fill: "var(--dsw-alias-label-tertiary, #888888)",
|
fill: "var(--dsw-alias-label-tertiary, #888888)",
|
||||||
|
|
@ -477,25 +477,25 @@ function HeatmapView() {
|
||||||
},
|
},
|
||||||
m.label
|
m.label
|
||||||
)),
|
)),
|
||||||
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 49, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Mon"),
|
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 51, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Mon"),
|
||||||
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 81, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Wed"),
|
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 85, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Wed"),
|
||||||
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 113, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Fri"),
|
/* @__PURE__ */ import_react.default.createElement("text", { x: 4, y: 119, fontSize: 10, fill: "var(--dsw-alias-label-tertiary, #888888)", fontFamily: "inherit" }, "Fri"),
|
||||||
calendarGrid.map((week, colIdx) => /* @__PURE__ */ import_react.default.createElement("g", { key: colIdx, transform: `translate(${34 + colIdx * 16}, 22)` }, week.map((day, rowIdx) => {
|
calendarGrid.map((week, colIdx) => /* @__PURE__ */ import_react.default.createElement("g", { key: colIdx, transform: `translate(${36 + colIdx * 16.5}, 22)` }, week.map((day, rowIdx) => {
|
||||||
if (!day) return null;
|
if (!day) return null;
|
||||||
const lvl = day.stats.level || 0;
|
const lvl = day.stats.level || 0;
|
||||||
const bg = DEEPSEEK_LEVELS[lvl];
|
const bg = DEEPSEEK_LEVELS[lvl];
|
||||||
const isSelected = selectedDate === day.date;
|
const isSelected = selectedDate === day.date;
|
||||||
const isHovered = hoveredDay?.date === day.date;
|
const isHovered = hoveredDay?.date === day.date;
|
||||||
const strokeColor = isSelected ? "#ffffff" : isHovered ? "#5686fe" : lvl === 0 ? "rgba(255, 255, 255, 0.06)" : "transparent";
|
const strokeColor = isSelected ? "#ffffff" : isHovered ? "#5686fe" : lvl === 0 ? "rgba(255, 255, 255, 0.06)" : "transparent";
|
||||||
const strokeWidth = isSelected ? 1.8 : isHovered ? 1.4 : 1;
|
const strokeWidth = isSelected ? 2 : isHovered ? 1.5 : 1;
|
||||||
return /* @__PURE__ */ import_react.default.createElement(
|
return /* @__PURE__ */ import_react.default.createElement(
|
||||||
"rect",
|
"rect",
|
||||||
{
|
{
|
||||||
key: rowIdx,
|
key: rowIdx,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: rowIdx * 16,
|
y: rowIdx * 17,
|
||||||
width: 12.5,
|
width: 13,
|
||||||
height: 12.5,
|
height: 13,
|
||||||
rx: 2.5,
|
rx: 2.5,
|
||||||
ry: 2.5,
|
ry: 2.5,
|
||||||
fill: bg,
|
fill: bg,
|
||||||
|
|
@ -521,7 +521,7 @@ function HeatmapView() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
})))
|
})))
|
||||||
),
|
)),
|
||||||
/* @__PURE__ */ import_react.default.createElement(
|
/* @__PURE__ */ import_react.default.createElement(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -127,7 +127,7 @@ export function HeatmapView() {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = data.sessions.find((s) => s.id === selectedSessionId);
|
const session = (data.sessions || []).find((s) => s.id === selectedSessionId);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
return {
|
return {
|
||||||
summary: data.summary,
|
summary: data.summary,
|
||||||
|
|
@ -383,8 +383,8 @@ export function HeatmapView() {
|
||||||
maxWidth: 240,
|
maxWidth: 240,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="all">All Sessions ({data.sessions.length} total)</option>
|
<option value="all">All Sessions ({(data.sessions || []).length} total)</option>
|
||||||
{data.sessions.map((s) => (
|
{(data.sessions || []).map((s) => (
|
||||||
<option key={s.id} value={s.id}>
|
<option key={s.id} value={s.id}>
|
||||||
{new Date(s.createdAt).toLocaleDateString()} · {s.title.slice(0, 32)}
|
{new Date(s.createdAt).toLocaleDateString()} · {s.title.slice(0, 32)}
|
||||||
</option>
|
</option>
|
||||||
|
|
@ -537,7 +537,7 @@ export function HeatmapView() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Comfortably sized GitHub-Style Calendar SVG with smooth horizontal scroll */}
|
{/* Generously sized GitHub-Style Calendar with smooth horizontal scroll */}
|
||||||
{calendarGrid && (
|
{calendarGrid && (
|
||||||
<div
|
<div
|
||||||
ref={scrollContainerRef}
|
ref={scrollContainerRef}
|
||||||
|
|
@ -545,107 +545,109 @@ export function HeatmapView() {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
overflowX: "auto",
|
overflowX: "auto",
|
||||||
WebkitOverflowScrolling: "touch",
|
WebkitOverflowScrolling: "touch",
|
||||||
paddingBottom: "8px",
|
paddingBottom: "10px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svg
|
<div style={{ minWidth: "920px", width: "100%", display: "inline-block" }}>
|
||||||
viewBox="0 0 895 142"
|
<svg
|
||||||
style={{
|
viewBox="0 0 920 152"
|
||||||
width: "100%",
|
style={{
|
||||||
minWidth: "860px",
|
width: "100%",
|
||||||
height: "142px",
|
minWidth: "920px",
|
||||||
display: "block",
|
height: "152px",
|
||||||
overflow: "visible",
|
display: "block",
|
||||||
}}
|
overflow: "visible",
|
||||||
>
|
}}
|
||||||
{/* Month labels */}
|
>
|
||||||
{monthHeaders.map((m, i) => (
|
{/* Month labels */}
|
||||||
<text
|
{monthHeaders.map((m, i) => (
|
||||||
key={i}
|
<text
|
||||||
x={34 + m.col * 16}
|
key={i}
|
||||||
y={12}
|
x={36 + m.col * 16.5}
|
||||||
fontSize={11}
|
y={12}
|
||||||
fill="var(--dsw-alias-label-tertiary, #888888)"
|
fontSize={11}
|
||||||
fontFamily="inherit"
|
fill="var(--dsw-alias-label-tertiary, #888888)"
|
||||||
>
|
fontFamily="inherit"
|
||||||
{m.label}
|
>
|
||||||
|
{m.label}
|
||||||
|
</text>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* Day of week labels */}
|
||||||
|
<text x={4} y={51} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
||||||
|
Mon
|
||||||
|
</text>
|
||||||
|
<text x={4} y={85} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
||||||
|
Wed
|
||||||
|
</text>
|
||||||
|
<text x={4} y={119} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
||||||
|
Fri
|
||||||
</text>
|
</text>
|
||||||
))}
|
|
||||||
|
|
||||||
{/* Day of week labels */}
|
{/* Day Tiles: Generously sized 13px tiles with 16.5px step */}
|
||||||
<text x={4} y={49} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
{calendarGrid.map((week, colIdx) => (
|
||||||
Mon
|
<g key={colIdx} transform={`translate(${36 + colIdx * 16.5}, 22)`}>
|
||||||
</text>
|
{week.map((day, rowIdx) => {
|
||||||
<text x={4} y={81} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
if (!day) return null;
|
||||||
Wed
|
|
||||||
</text>
|
|
||||||
<text x={4} y={113} fontSize={10} fill="var(--dsw-alias-label-tertiary, #888888)" fontFamily="inherit">
|
|
||||||
Fri
|
|
||||||
</text>
|
|
||||||
|
|
||||||
{/* Day Tiles: comfortable 12.5px size with 16px step */}
|
const lvl = day.stats.level || 0;
|
||||||
{calendarGrid.map((week, colIdx) => (
|
const bg = DEEPSEEK_LEVELS[lvl];
|
||||||
<g key={colIdx} transform={`translate(${34 + colIdx * 16}, 22)`}>
|
const isSelected = selectedDate === day.date;
|
||||||
{week.map((day, rowIdx) => {
|
const isHovered = hoveredDay?.date === day.date;
|
||||||
if (!day) return null;
|
|
||||||
|
|
||||||
const lvl = day.stats.level || 0;
|
// GitHub-style glow & outline
|
||||||
const bg = DEEPSEEK_LEVELS[lvl];
|
const strokeColor = isSelected
|
||||||
const isSelected = selectedDate === day.date;
|
? "#ffffff"
|
||||||
const isHovered = hoveredDay?.date === day.date;
|
: isHovered
|
||||||
|
? "#5686fe"
|
||||||
|
: lvl === 0
|
||||||
|
? "rgba(255, 255, 255, 0.06)"
|
||||||
|
: "transparent";
|
||||||
|
|
||||||
// GitHub-style glow & outline
|
const strokeWidth = isSelected ? 2 : isHovered ? 1.5 : 1;
|
||||||
const strokeColor = isSelected
|
|
||||||
? "#ffffff"
|
|
||||||
: isHovered
|
|
||||||
? "#5686fe"
|
|
||||||
: lvl === 0
|
|
||||||
? "rgba(255, 255, 255, 0.06)"
|
|
||||||
: "transparent";
|
|
||||||
|
|
||||||
const strokeWidth = isSelected ? 1.8 : isHovered ? 1.4 : 1;
|
return (
|
||||||
|
<rect
|
||||||
return (
|
key={rowIdx}
|
||||||
<rect
|
x={0}
|
||||||
key={rowIdx}
|
y={rowIdx * 17}
|
||||||
x={0}
|
width={13}
|
||||||
y={rowIdx * 16}
|
height={13}
|
||||||
width={12.5}
|
rx={2.5}
|
||||||
height={12.5}
|
ry={2.5}
|
||||||
rx={2.5}
|
fill={bg}
|
||||||
ry={2.5}
|
stroke={strokeColor}
|
||||||
fill={bg}
|
strokeWidth={strokeWidth}
|
||||||
stroke={strokeColor}
|
style={{
|
||||||
strokeWidth={strokeWidth}
|
cursor: "pointer",
|
||||||
style={{
|
transition: "fill 0.12s ease, stroke 0.12s ease",
|
||||||
cursor: "pointer",
|
filter: isSelected
|
||||||
transition: "fill 0.12s ease, stroke 0.12s ease",
|
? "drop-shadow(0 0 6px rgba(86, 134, 254, 0.9))"
|
||||||
filter: isSelected
|
: isHovered
|
||||||
? "drop-shadow(0 0 6px rgba(86, 134, 254, 0.9))"
|
? "drop-shadow(0 0 4px rgba(86, 134, 254, 0.7))"
|
||||||
: isHovered
|
: lvl === 4
|
||||||
? "drop-shadow(0 0 4px rgba(86, 134, 254, 0.7))"
|
? "drop-shadow(0 0 4px rgba(79, 133, 255, 0.6))"
|
||||||
: lvl === 4
|
: "none",
|
||||||
? "drop-shadow(0 0 4px rgba(79, 133, 255, 0.6))"
|
}}
|
||||||
: "none",
|
onClick={() => {
|
||||||
}}
|
setSelectedDate(isSelected ? null : day.date);
|
||||||
onClick={() => {
|
}}
|
||||||
setSelectedDate(isSelected ? null : day.date);
|
onMouseEnter={(e) => {
|
||||||
}}
|
setHoveredDay({ date: day.date, stats: day.stats });
|
||||||
onMouseEnter={(e) => {
|
const rect = e.currentTarget.getBoundingClientRect();
|
||||||
setHoveredDay({ date: day.date, stats: day.stats });
|
setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top - 8 });
|
||||||
const rect = e.currentTarget.getBoundingClientRect();
|
}}
|
||||||
setTooltipPos({ x: rect.left + rect.width / 2, y: rect.top - 8 });
|
onMouseLeave={() => {
|
||||||
}}
|
setHoveredDay(null);
|
||||||
onMouseLeave={() => {
|
setTooltipPos(null);
|
||||||
setHoveredDay(null);
|
}}
|
||||||
setTooltipPos(null);
|
/>
|
||||||
}}
|
);
|
||||||
/>
|
})}
|
||||||
);
|
</g>
|
||||||
})}
|
))}
|
||||||
</g>
|
</svg>
|
||||||
))}
|
</div>
|
||||||
</svg>
|
|
||||||
|
|
||||||
{/* Bottom Legend */}
|
{/* Bottom Legend */}
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue