heyiam 0.2.28 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -0
- package/dist/config.js +10 -1
- package/dist/db.js +1 -2
- package/dist/export.js +40 -25
- package/dist/format-utils.js +5 -0
- package/dist/index.js +168 -0
- package/dist/mount.js +300 -102
- package/dist/parsers/claude.js +2 -28
- package/dist/parsers/codex.js +2 -26
- package/dist/parsers/cursor.js +2 -26
- package/dist/parsers/duration.js +35 -0
- package/dist/parsers/gemini.js +2 -20
- package/dist/parsers/types.js +0 -1
- package/dist/public/assets/index-BZ65TU_Y.js +40 -0
- package/dist/public/assets/index-CqCaW2cb.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/redact.js +4 -104
- package/dist/render/build-render-data.js +9 -2
- package/dist/render/index.js +32 -5
- package/dist/render/liquid.js +147 -7
- package/dist/render/mock-data.js +303 -0
- package/dist/render/templates/aurora/portfolio.liquid +204 -0
- package/dist/render/templates/aurora/project.liquid +260 -0
- package/dist/render/templates/aurora/session.liquid +223 -0
- package/dist/render/templates/aurora/styles.css +1178 -0
- package/dist/render/templates/bauhaus/portfolio.liquid +179 -0
- package/dist/render/templates/bauhaus/project.liquid +300 -0
- package/dist/render/templates/bauhaus/session.liquid +333 -0
- package/dist/render/templates/bauhaus/styles.css +1641 -0
- package/dist/render/templates/blueprint/portfolio.liquid +167 -0
- package/dist/render/templates/blueprint/project.liquid +286 -0
- package/dist/render/templates/blueprint/session.liquid +248 -0
- package/dist/render/templates/blueprint/styles.css +1285 -0
- package/dist/render/templates/canvas/portfolio.liquid +215 -0
- package/dist/render/templates/canvas/project.liquid +235 -0
- package/dist/render/templates/canvas/session.liquid +223 -0
- package/dist/render/templates/canvas/styles.css +1436 -0
- package/dist/render/templates/carbon/portfolio.liquid +170 -0
- package/dist/render/templates/carbon/project.liquid +249 -0
- package/dist/render/templates/carbon/session.liquid +190 -0
- package/dist/render/templates/carbon/styles.css +1091 -0
- package/dist/render/templates/chalk/portfolio.liquid +199 -0
- package/dist/render/templates/chalk/project.liquid +245 -0
- package/dist/render/templates/chalk/session.liquid +215 -0
- package/dist/render/templates/chalk/styles.css +1157 -0
- package/dist/render/templates/circuit/portfolio.liquid +162 -0
- package/dist/render/templates/circuit/project.liquid +247 -0
- package/dist/render/templates/circuit/session.liquid +205 -0
- package/dist/render/templates/circuit/styles.css +1403 -0
- package/dist/render/templates/cosmos/portfolio.liquid +232 -0
- package/dist/render/templates/cosmos/project.liquid +327 -0
- package/dist/render/templates/cosmos/session.liquid +239 -0
- package/dist/render/templates/cosmos/styles.css +1151 -0
- package/dist/render/templates/daylight/portfolio.liquid +217 -0
- package/dist/render/templates/daylight/project.liquid +229 -0
- package/dist/render/templates/daylight/session.liquid +219 -0
- package/dist/render/templates/daylight/styles.css +1311 -0
- package/dist/render/templates/editorial/portfolio.liquid +126 -0
- package/dist/render/templates/editorial/project.liquid +202 -0
- package/dist/render/templates/editorial/session.liquid +171 -0
- package/dist/render/templates/editorial/styles.css +822 -0
- package/dist/render/templates/ember/portfolio.liquid +318 -0
- package/dist/render/templates/ember/project.liquid +232 -0
- package/dist/render/templates/ember/session.liquid +202 -0
- package/dist/render/templates/ember/styles.css +1283 -0
- package/dist/render/templates/glacier/portfolio.liquid +271 -0
- package/dist/render/templates/glacier/project.liquid +288 -0
- package/dist/render/templates/glacier/session.liquid +217 -0
- package/dist/render/templates/glacier/styles.css +1200 -0
- package/dist/render/templates/grid/portfolio.liquid +265 -0
- package/dist/render/templates/grid/project.liquid +306 -0
- package/dist/render/templates/grid/session.liquid +260 -0
- package/dist/render/templates/grid/styles.css +1441 -0
- package/dist/render/templates/kinetic/portfolio.liquid +170 -0
- package/dist/render/templates/kinetic/project.liquid +242 -0
- package/dist/render/templates/kinetic/session.liquid +228 -0
- package/dist/render/templates/kinetic/styles.css +944 -0
- package/dist/render/templates/meridian/portfolio.liquid +255 -0
- package/dist/render/templates/meridian/project.liquid +376 -0
- package/dist/render/templates/meridian/session.liquid +298 -0
- package/dist/render/templates/meridian/styles.css +1369 -0
- package/dist/render/templates/minimal/portfolio.liquid +71 -0
- package/dist/render/templates/minimal/project.liquid +154 -0
- package/dist/render/templates/minimal/session.liquid +140 -0
- package/dist/render/templates/minimal/styles.css +525 -0
- package/dist/render/templates/mono/portfolio.liquid +291 -0
- package/dist/render/templates/mono/project.liquid +275 -0
- package/dist/render/templates/mono/session.liquid +276 -0
- package/dist/render/templates/mono/styles.css +1016 -0
- package/dist/render/templates/neon/portfolio.liquid +217 -0
- package/dist/render/templates/neon/project.liquid +225 -0
- package/dist/render/templates/neon/session.liquid +195 -0
- package/dist/render/templates/neon/styles.css +1265 -0
- package/dist/render/templates/noir/portfolio.liquid +137 -0
- package/dist/render/templates/noir/project.liquid +220 -0
- package/dist/render/templates/noir/session.liquid +241 -0
- package/dist/render/templates/noir/styles.css +1223 -0
- package/dist/render/templates/obsidian/portfolio.liquid +257 -0
- package/dist/render/templates/obsidian/project.liquid +280 -0
- package/dist/render/templates/obsidian/session.liquid +241 -0
- package/dist/render/templates/obsidian/styles.css +1401 -0
- package/dist/render/templates/paper/portfolio.liquid +267 -0
- package/dist/render/templates/paper/project.liquid +235 -0
- package/dist/render/templates/paper/session.liquid +271 -0
- package/dist/render/templates/paper/styles.css +1509 -0
- package/dist/render/templates/parallax/portfolio.liquid +305 -0
- package/dist/render/templates/parallax/project.liquid +275 -0
- package/dist/render/templates/parallax/session.liquid +295 -0
- package/dist/render/templates/parallax/styles.css +1874 -0
- package/dist/render/templates/parchment/portfolio.liquid +290 -0
- package/dist/render/templates/parchment/project.liquid +289 -0
- package/dist/render/templates/parchment/session.liquid +346 -0
- package/dist/render/templates/parchment/styles.css +1397 -0
- package/dist/render/templates/partials/_beats.liquid +16 -0
- package/dist/render/templates/partials/_breadcrumb.liquid +9 -0
- package/dist/render/templates/partials/_footer.liquid +7 -0
- package/dist/render/templates/partials/_growth-chart.liquid +7 -0
- package/dist/render/templates/partials/_key-decisions.liquid +20 -0
- package/dist/render/templates/partials/_links.liquid +16 -0
- package/dist/render/templates/partials/_narrative.liquid +8 -0
- package/dist/render/templates/partials/_phases.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-header.liquid +20 -0
- package/dist/render/templates/partials/_portfolio-projects.liquid +16 -0
- package/dist/render/templates/partials/_portfolio-stats.liquid +19 -0
- package/dist/render/templates/partials/_qa.liquid +13 -0
- package/dist/render/templates/partials/_screenshot.liquid +15 -0
- package/dist/render/templates/partials/_session-cards.liquid +30 -0
- package/dist/render/templates/partials/_session-header.liquid +39 -0
- package/dist/render/templates/partials/_session-sidebar.liquid +30 -0
- package/dist/render/templates/partials/_skills.liquid +12 -0
- package/dist/render/templates/partials/_source-breakdown.liquid +22 -0
- package/dist/render/templates/partials/_stats.liquid +38 -0
- package/dist/render/templates/partials/_work-timeline.liquid +7 -0
- package/dist/render/templates/project.liquid +7 -4
- package/dist/render/templates/radar/portfolio.liquid +233 -0
- package/dist/render/templates/radar/project.liquid +278 -0
- package/dist/render/templates/radar/session.liquid +300 -0
- package/dist/render/templates/radar/styles.css +1049 -0
- package/dist/render/templates/showcase/portfolio.liquid +231 -0
- package/dist/render/templates/showcase/project.liquid +237 -0
- package/dist/render/templates/showcase/session.liquid +210 -0
- package/dist/render/templates/showcase/styles.css +1279 -0
- package/dist/render/templates/signal/portfolio.liquid +227 -0
- package/dist/render/templates/signal/project.liquid +278 -0
- package/dist/render/templates/signal/session.liquid +282 -0
- package/dist/render/templates/signal/styles.css +1395 -0
- package/dist/render/templates/strata/portfolio.liquid +192 -0
- package/dist/render/templates/strata/project.liquid +282 -0
- package/dist/render/templates/strata/session.liquid +261 -0
- package/dist/render/templates/strata/styles.css +1350 -0
- package/dist/render/templates/styles.css +1190 -0
- package/dist/render/templates/terminal/portfolio.liquid +118 -0
- package/dist/render/templates/terminal/project.liquid +161 -0
- package/dist/render/templates/terminal/session.liquid +145 -0
- package/dist/render/templates/terminal/styles.css +492 -0
- package/dist/render/templates/verdant/portfolio.liquid +333 -0
- package/dist/render/templates/verdant/project.liquid +309 -0
- package/dist/render/templates/verdant/session.liquid +237 -0
- package/dist/render/templates/verdant/styles.css +1257 -0
- package/dist/render/templates/zen/portfolio.liquid +136 -0
- package/dist/render/templates/zen/project.liquid +187 -0
- package/dist/render/templates/zen/session.liquid +203 -0
- package/dist/render/templates/zen/styles.css +1207 -0
- package/dist/render/templates.js +90 -0
- package/dist/routes/context.js +15 -10
- package/dist/routes/enhance.js +17 -40
- package/dist/routes/export.js +14 -4
- package/dist/routes/preview.js +480 -108
- package/dist/routes/projects.js +11 -19
- package/dist/routes/publish.js +15 -17
- package/dist/routes/settings.js +94 -1
- package/dist/routes/sse.js +9 -0
- package/dist/server.js +8 -2
- package/dist/settings.js +17 -9
- package/package.json +2 -4
- package/dist/public/assets/index-B_d6DlEI.js +0 -21
- package/dist/public/assets/index-Dalqz2mC.css +0 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
<div class="heyiam-portfolio grid" data-render-version="2" data-template="grid" data-username="{{ user.username }}">
|
|
2
|
+
|
|
3
|
+
<div class="container">
|
|
4
|
+
<div class="bento" aria-label="Portfolio dashboard">
|
|
5
|
+
|
|
6
|
+
{%- comment -%} Cell 1: Identity (2-wide) {%- endcomment -%}
|
|
7
|
+
{% if hasProfile %}
|
|
8
|
+
<div class="bento-cell cell-identity">
|
|
9
|
+
<div class="identity-top">
|
|
10
|
+
{% if user.photoUrl %}
|
|
11
|
+
<img src="{{ user.photoUrl }}" alt="{{ user.displayName }}" class="profile-photo portfolio-photo">
|
|
12
|
+
{% endif %}
|
|
13
|
+
<div class="identity-text">
|
|
14
|
+
{% if user.displayName != blank %}
|
|
15
|
+
<h1>{{ user.displayName }}</h1>
|
|
16
|
+
{% endif %}
|
|
17
|
+
{% if user.location != blank %}
|
|
18
|
+
<p class="location portfolio-location">
|
|
19
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"/><circle cx="12" cy="10" r="3"/></svg>
|
|
20
|
+
{{ user.location }}
|
|
21
|
+
</p>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% if user.bio != blank %}
|
|
24
|
+
<p class="bio portfolio-bio">{{ user.bio }}</p>
|
|
25
|
+
{% endif %}
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div class="contact-row">
|
|
29
|
+
{% if user.email %}
|
|
30
|
+
<a href="mailto:{{ user.email }}"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="4" width="20" height="16" rx="2"/><path d="m2 4 10 8 10-8"/></svg> {{ user.email }}</a>
|
|
31
|
+
{% endif %}
|
|
32
|
+
{% if user.linkedinUrl %}
|
|
33
|
+
<a href="{{ user.linkedinUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"/></svg> LinkedIn</a>
|
|
34
|
+
{% endif %}
|
|
35
|
+
{% if user.githubUrl %}
|
|
36
|
+
<a href="{{ user.githubUrl }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z"/></svg> GitHub</a>
|
|
37
|
+
{% endif %}
|
|
38
|
+
{% if user.twitterHandle %}
|
|
39
|
+
<a href="https://x.com/{{ user.twitterHandle }}" target="_blank" rel="noopener"><svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg> @{{ user.twitterHandle }}</a>
|
|
40
|
+
{% endif %}
|
|
41
|
+
{% if user.websiteUrl %}
|
|
42
|
+
<a href="{{ user.websiteUrl }}" target="_blank" rel="noopener">{{ user.websiteUrl | stripProtocol }}</a>
|
|
43
|
+
{% endif %}
|
|
44
|
+
{% if user.resumeUrl %}
|
|
45
|
+
<a href="{{ user.resumeUrl }}" class="resume-btn" download><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="18" x2="12" y2="12"/><polyline points="9 15 12 18 15 15"/></svg> Resume (PDF)</a>
|
|
46
|
+
{% endif %}
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
{% endif %}
|
|
50
|
+
|
|
51
|
+
{%- comment -%} Cell 2: Stat -- Projects {%- endcomment -%}
|
|
52
|
+
<section class="bento-cell cell-stat" aria-label="Projects count">
|
|
53
|
+
<div class="stat-icon" aria-hidden="true">
|
|
54
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
|
|
55
|
+
</div>
|
|
56
|
+
<div>
|
|
57
|
+
<div class="stat-number" data-target="{{ projects.size }}">0</div>
|
|
58
|
+
<div class="stat-label">Projects</div>
|
|
59
|
+
</div>
|
|
60
|
+
</section>
|
|
61
|
+
|
|
62
|
+
{%- comment -%} Cell 3: Stat -- Sessions {%- endcomment -%}
|
|
63
|
+
<section class="bento-cell cell-stat" aria-label="Sessions count">
|
|
64
|
+
<div class="stat-icon" aria-hidden="true">
|
|
65
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
|
66
|
+
</div>
|
|
67
|
+
<div>
|
|
68
|
+
<div class="stat-number" data-target="{{ totalSessions }}">0</div>
|
|
69
|
+
<div class="stat-label">Sessions</div>
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
{%- comment -%} Cell 4: Stat -- Human Time {%- endcomment -%}
|
|
74
|
+
{% if efficiencyMultiplier %}
|
|
75
|
+
<section class="bento-cell cell-stat" aria-label="Human time">
|
|
76
|
+
<div class="stat-icon" aria-hidden="true">
|
|
77
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
78
|
+
</div>
|
|
79
|
+
<div>
|
|
80
|
+
<div class="stat-number">{{ totalDurationMinutes | formatDuration }}</div>
|
|
81
|
+
<div class="stat-label">You</div>
|
|
82
|
+
</div>
|
|
83
|
+
</section>
|
|
84
|
+
|
|
85
|
+
{%- comment -%} Cell 4b: Stat -- Agent Time {%- endcomment -%}
|
|
86
|
+
<section class="bento-cell cell-stat" aria-label="Agent time">
|
|
87
|
+
<div class="stat-icon" aria-hidden="true">
|
|
88
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"/><line x1="9" y1="9" x2="9" y2="9.01"/><line x1="15" y1="9" x2="15" y2="9.01"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/></svg>
|
|
89
|
+
</div>
|
|
90
|
+
<div>
|
|
91
|
+
<div class="stat-number" style="color: var(--accent);">{{ totalAgentDurationMinutes | formatDuration }}</div>
|
|
92
|
+
<div class="stat-label">Agents</div>
|
|
93
|
+
</div>
|
|
94
|
+
</section>
|
|
95
|
+
|
|
96
|
+
{%- comment -%} Cell 4c: Stat -- Multiplier {%- endcomment -%}
|
|
97
|
+
<section class="bento-cell cell-stat" aria-label="Multiplier">
|
|
98
|
+
<div class="stat-icon" aria-hidden="true">
|
|
99
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg>
|
|
100
|
+
</div>
|
|
101
|
+
<div>
|
|
102
|
+
<div class="stat-number">{{ efficiencyMultiplier }}</div>
|
|
103
|
+
<div class="stat-label">Multiplier</div>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
{% else %}
|
|
107
|
+
<section class="bento-cell cell-stat" aria-label="Total time">
|
|
108
|
+
<div class="stat-icon" aria-hidden="true">
|
|
109
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
110
|
+
</div>
|
|
111
|
+
<div>
|
|
112
|
+
<div class="stat-number">{{ totalDurationMinutes | formatDuration }}</div>
|
|
113
|
+
<div class="stat-label">Total Time</div>
|
|
114
|
+
</div>
|
|
115
|
+
</section>
|
|
116
|
+
{% endif %}
|
|
117
|
+
|
|
118
|
+
{%- comment -%} Cell 5: Stat -- LOC {%- endcomment -%}
|
|
119
|
+
<section class="bento-cell cell-stat" aria-label="Lines changed">
|
|
120
|
+
<div class="stat-icon" aria-hidden="true">
|
|
121
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
|
122
|
+
</div>
|
|
123
|
+
<div>
|
|
124
|
+
<div class="stat-number" data-target="{{ totalLoc }}" data-format="comma">0</div>
|
|
125
|
+
<div class="stat-label">Lines Changed</div>
|
|
126
|
+
</div>
|
|
127
|
+
</section>
|
|
128
|
+
|
|
129
|
+
{%- comment -%} Cell 6: Source Mix (2-wide) {%- endcomment -%}
|
|
130
|
+
{% if sourceCounts.size > 0 %}
|
|
131
|
+
<section class="bento-cell cell-source" aria-label="Source breakdown">
|
|
132
|
+
<h2>Source Mix</h2>
|
|
133
|
+
<div class="source-bars">
|
|
134
|
+
{% assign totalSourceSessions = 0 %}
|
|
135
|
+
{% for src in sourceCounts %}
|
|
136
|
+
{% assign totalSourceSessions = totalSourceSessions | plus: src.count %}
|
|
137
|
+
{% endfor %}
|
|
138
|
+
{% for src in sourceCounts %}
|
|
139
|
+
<div class="source-item">
|
|
140
|
+
<span class="source-name">{{ src.tool }}</span>
|
|
141
|
+
<div class="source-bar-track">
|
|
142
|
+
{% if totalSourceSessions > 0 %}
|
|
143
|
+
{% assign srcPct = src.count | times: 100.0 | divided_by: totalSourceSessions | round %}
|
|
144
|
+
<div class="source-bar-fill{% unless forloop.first %} source-bar-fill--secondary{% endunless %}" style="width: {{ srcPct }}%" role="progressbar" aria-valuenow="{{ srcPct }}" aria-valuemin="0" aria-valuemax="100" aria-label="{{ src.tool }} usage"></div>
|
|
145
|
+
{% endif %}
|
|
146
|
+
</div>
|
|
147
|
+
{% if totalSourceSessions > 0 %}
|
|
148
|
+
{% assign srcPctDisplay = src.count | times: 100.0 | divided_by: totalSourceSessions | round %}
|
|
149
|
+
<span class="source-pct">{{ srcPctDisplay }}%</span>
|
|
150
|
+
{% endif %}
|
|
151
|
+
</div>
|
|
152
|
+
{% endfor %}
|
|
153
|
+
</div>
|
|
154
|
+
</section>
|
|
155
|
+
{% endif %}
|
|
156
|
+
|
|
157
|
+
{%- comment -%} Cell 7: Project Cards (2-wide each) {%- endcomment -%}
|
|
158
|
+
{% for p in projects %}
|
|
159
|
+
<a href="/{{ user.username }}/{{ p.slug }}" class="bento-cell cell-project project-card" aria-label="View {{ p.title }} project">
|
|
160
|
+
<div class="project-header">
|
|
161
|
+
<h2 class="project-title">{{ p.title }}</h2>
|
|
162
|
+
<svg class="project-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="7" y1="17" x2="17" y2="7"/><polyline points="7 7 17 7 17 17"/></svg>
|
|
163
|
+
</div>
|
|
164
|
+
{% if p.narrative %}
|
|
165
|
+
<p class="project-narrative">{{ p.narrative | truncate: 120 }}</p>
|
|
166
|
+
{% endif %}
|
|
167
|
+
<div class="project-meta">
|
|
168
|
+
<span class="project-meta-item"><strong>{{ p.totalSessions }}</strong> sessions</span>
|
|
169
|
+
<span class="project-meta-item"><strong>{{ p.totalDurationMinutes | formatDuration }}</strong></span>
|
|
170
|
+
<span class="project-meta-item"><strong>{{ p.totalLoc | formatLoc }}</strong> LOC</span>
|
|
171
|
+
</div>
|
|
172
|
+
{% if p.skills.size > 0 %}
|
|
173
|
+
<div class="project-skills">
|
|
174
|
+
{% for skill in p.skills %}
|
|
175
|
+
<span class="skill-chip chip">{{ skill }}</span>
|
|
176
|
+
{% endfor %}
|
|
177
|
+
</div>
|
|
178
|
+
{% endif %}
|
|
179
|
+
{% if p.sourceCounts.size > 0 %}
|
|
180
|
+
{% assign pTotalSrc = 0 %}
|
|
181
|
+
{% for src in p.sourceCounts %}
|
|
182
|
+
{% assign pTotalSrc = pTotalSrc | plus: src.count %}
|
|
183
|
+
{% endfor %}
|
|
184
|
+
{% if pTotalSrc > 0 %}
|
|
185
|
+
<div class="project-source-bar" aria-label="Source breakdown">
|
|
186
|
+
{% for src in p.sourceCounts %}
|
|
187
|
+
{% assign pSrcPct = src.count | times: 100.0 | divided_by: pTotalSrc | round: 1 %}
|
|
188
|
+
<div class="project-source-segment" style="width: {{ pSrcPct }}%; background: var(--accent{% unless forloop.first %}-light{% endunless %});"></div>
|
|
189
|
+
{% endfor %}
|
|
190
|
+
</div>
|
|
191
|
+
{% endif %}
|
|
192
|
+
{% endif %}
|
|
193
|
+
</a>
|
|
194
|
+
{% endfor %}
|
|
195
|
+
|
|
196
|
+
{%- comment -%} Cell: Activity Heatmap (2-wide) {%- endcomment -%}
|
|
197
|
+
{% if activityByDay.size > 0 %}
|
|
198
|
+
<section class="bento-cell cell-activity" aria-label="Activity over time">
|
|
199
|
+
<h2>
|
|
200
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
|
201
|
+
Activity
|
|
202
|
+
</h2>
|
|
203
|
+
<div class="heatmap" role="img" aria-label="Activity heatmap showing session density over time">
|
|
204
|
+
{% for day in activityByDay %}
|
|
205
|
+
{% if day.count >= 4 %}{% assign level = 4 %}
|
|
206
|
+
{% elsif day.count >= 3 %}{% assign level = 3 %}
|
|
207
|
+
{% elsif day.count >= 2 %}{% assign level = 2 %}
|
|
208
|
+
{% elsif day.count >= 1 %}{% assign level = 1 %}
|
|
209
|
+
{% else %}{% assign level = 0 %}{% endif %}
|
|
210
|
+
<div class="heatmap-cell{% if level > 0 %} heatmap-cell--l{{ level }}{% endif %}" title="{{ day.date }}: {{ day.count }} sessions" aria-hidden="true"></div>
|
|
211
|
+
{% endfor %}
|
|
212
|
+
</div>
|
|
213
|
+
<div class="heatmap-legend">
|
|
214
|
+
<span class="heatmap-legend-label">Less</span>
|
|
215
|
+
<span class="heatmap-legend-cell" aria-hidden="true"></span>
|
|
216
|
+
<span class="heatmap-legend-cell heatmap-cell--l1" aria-hidden="true"></span>
|
|
217
|
+
<span class="heatmap-legend-cell heatmap-cell--l2" aria-hidden="true"></span>
|
|
218
|
+
<span class="heatmap-legend-cell heatmap-cell--l3" aria-hidden="true"></span>
|
|
219
|
+
<span class="heatmap-legend-cell heatmap-cell--l4" aria-hidden="true"></span>
|
|
220
|
+
<span class="heatmap-legend-label">More</span>
|
|
221
|
+
</div>
|
|
222
|
+
</section>
|
|
223
|
+
{% endif %}
|
|
224
|
+
|
|
225
|
+
{%- comment -%} Cell: All Skills (2-wide) {%- endcomment -%}
|
|
226
|
+
{% if allSkills.size > 0 %}
|
|
227
|
+
<section class="bento-cell cell-all-skills" aria-label="All skills across projects">
|
|
228
|
+
<h2>
|
|
229
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
|
|
230
|
+
Skills
|
|
231
|
+
</h2>
|
|
232
|
+
<div class="all-skills-grid">
|
|
233
|
+
{% for skill in allSkills %}
|
|
234
|
+
<span class="skill-chip">{{ skill }}</span>
|
|
235
|
+
{% endfor %}
|
|
236
|
+
</div>
|
|
237
|
+
</section>
|
|
238
|
+
{% endif %}
|
|
239
|
+
|
|
240
|
+
{%- comment -%} Cell: Recent Sessions (4-wide) {%- endcomment -%}
|
|
241
|
+
{% if recentSessions.size > 0 %}
|
|
242
|
+
<section class="bento-cell cell-recent" aria-label="Recent sessions">
|
|
243
|
+
<h2>
|
|
244
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
|
|
245
|
+
Recent Sessions
|
|
246
|
+
</h2>
|
|
247
|
+
<div class="recent-list" role="table" aria-label="Recent sessions list">
|
|
248
|
+
{% for rs in recentSessions %}
|
|
249
|
+
<div class="recent-row" role="row">
|
|
250
|
+
<span class="recent-title" role="cell">{{ rs.title }}</span>
|
|
251
|
+
<span class="recent-project" role="cell">{{ rs.projectTitle }}</span>
|
|
252
|
+
<span class="recent-date" role="cell">{% if rs.recordedAt %}{{ rs.recordedAt | formatDate: "short" }}{% endif %}</span>
|
|
253
|
+
<span class="recent-duration" role="cell">{{ rs.durationMinutes }}m</span>
|
|
254
|
+
</div>
|
|
255
|
+
{% endfor %}
|
|
256
|
+
</div>
|
|
257
|
+
</section>
|
|
258
|
+
{% endif %}
|
|
259
|
+
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
{%- comment -%} Stat counter animation {%- endcomment -%}
|
|
264
|
+
|
|
265
|
+
</div>
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
<div class="heyiam-project grid" data-render-version="2" data-template="grid"{% if sessionBaseUrl %} data-session-base-url="{{ sessionBaseUrl }}"{% endif %} data-username="{{ user.username }}" data-project-slug="{{ project.slug }}">
|
|
2
|
+
|
|
3
|
+
<div class="container">
|
|
4
|
+
<div class="breadcrumb" aria-label="Breadcrumb">
|
|
5
|
+
<a href="/{{ user.username }}">{{ user.username }}</a>
|
|
6
|
+
<span class="breadcrumb-sep" aria-hidden="true">/</span>
|
|
7
|
+
<span aria-current="page">{{ project.slug }}</span>
|
|
8
|
+
</div>
|
|
9
|
+
|
|
10
|
+
<div class="bento" aria-label="Project dashboard">
|
|
11
|
+
|
|
12
|
+
{%- comment -%} Cell 1: Title (3-wide) {%- endcomment -%}
|
|
13
|
+
<div class="bento-cell cell-title">
|
|
14
|
+
<h1 data-editable="title">{{ project.title }}</h1>
|
|
15
|
+
{% if project.repoUrl or project.projectUrl %}
|
|
16
|
+
<div class="project-links">
|
|
17
|
+
{% if project.repoUrl %}
|
|
18
|
+
<a href="{{ project.repoUrl }}" target="_blank" rel="noopener">
|
|
19
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"/></svg>
|
|
20
|
+
{{ project.repoUrl | stripProtocol }}
|
|
21
|
+
</a>
|
|
22
|
+
{% endif %}
|
|
23
|
+
{% if project.projectUrl %}
|
|
24
|
+
<a href="{{ project.projectUrl }}" target="_blank" rel="noopener">
|
|
25
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/><polyline points="15 3 21 3 21 9"/><line x1="10" y1="14" x2="21" y2="3"/></svg>
|
|
26
|
+
{{ project.projectUrl | stripProtocol }}
|
|
27
|
+
</a>
|
|
28
|
+
{% endif %}
|
|
29
|
+
</div>
|
|
30
|
+
{% endif %}
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
{%- comment -%} Cell 2: Screenshot (spans 2 rows) {%- endcomment -%}
|
|
34
|
+
{% if project.screenshotUrl %}
|
|
35
|
+
<div class="bento-cell cell-screenshot">
|
|
36
|
+
<div class="browser-chrome">
|
|
37
|
+
<span class="browser-dot" aria-hidden="true"></span>
|
|
38
|
+
<span class="browser-dot" aria-hidden="true"></span>
|
|
39
|
+
<span class="browser-dot" aria-hidden="true"></span>
|
|
40
|
+
{% if project.projectUrl %}
|
|
41
|
+
<span class="browser-bar">{{ project.projectUrl | stripProtocol }}</span>
|
|
42
|
+
{% else %}
|
|
43
|
+
<span class="browser-bar">{{ project.slug }}</span>
|
|
44
|
+
{% endif %}
|
|
45
|
+
</div>
|
|
46
|
+
<div class="browser-viewport">
|
|
47
|
+
<img src="{{ project.screenshotUrl }}" alt="{{ project.title }} screenshot" style="width: 100%; height: 100%; object-fit: cover; border-radius: 0 0 var(--radius-sm) var(--radius-sm);">
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
{% endif %}
|
|
51
|
+
|
|
52
|
+
{%- comment -%} Cell 3: Stat -- Sessions {%- endcomment -%}
|
|
53
|
+
<section class="bento-cell cell-stat" aria-label="Sessions count">
|
|
54
|
+
<div class="stat-icon" aria-hidden="true">
|
|
55
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>
|
|
56
|
+
</div>
|
|
57
|
+
<div>
|
|
58
|
+
<div class="stat-number" data-target="{{ project.totalSessions }}">0</div>
|
|
59
|
+
<div class="stat-label">Sessions</div>
|
|
60
|
+
</div>
|
|
61
|
+
</section>
|
|
62
|
+
|
|
63
|
+
{%- comment -%} Cell 4: Stat -- Human Time {%- endcomment -%}
|
|
64
|
+
{% if efficiencyMultiplier %}
|
|
65
|
+
<section class="bento-cell cell-stat" aria-label="Human time">
|
|
66
|
+
<div class="stat-icon" aria-hidden="true">
|
|
67
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
|
|
68
|
+
</div>
|
|
69
|
+
<div>
|
|
70
|
+
<div class="stat-number">{{ project.totalDurationMinutes | formatDuration }}</div>
|
|
71
|
+
<div class="stat-label">You</div>
|
|
72
|
+
</div>
|
|
73
|
+
</section>
|
|
74
|
+
|
|
75
|
+
{%- comment -%} Cell 4b: Stat -- Agent Time {%- endcomment -%}
|
|
76
|
+
<section class="bento-cell cell-stat" aria-label="Agent time">
|
|
77
|
+
<div class="stat-icon" aria-hidden="true">
|
|
78
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="4" width="16" height="16" rx="2"/><line x1="9" y1="9" x2="9" y2="9.01"/><line x1="15" y1="9" x2="15" y2="9.01"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/></svg>
|
|
79
|
+
</div>
|
|
80
|
+
<div>
|
|
81
|
+
<div class="stat-number" style="color: var(--accent);">{{ project.totalAgentDurationMinutes | formatDuration }}</div>
|
|
82
|
+
<div class="stat-label">Agents</div>
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
|
|
86
|
+
{%- comment -%} Cell 4c: Stat -- Multiplier {%- endcomment -%}
|
|
87
|
+
<section class="bento-cell cell-stat" aria-label="Multiplier">
|
|
88
|
+
<div class="stat-icon" aria-hidden="true">
|
|
89
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 6 13.5 15.5 8.5 10.5 1 18"/><polyline points="17 6 23 6 23 12"/></svg>
|
|
90
|
+
</div>
|
|
91
|
+
<div>
|
|
92
|
+
<div class="stat-number">{{ efficiencyMultiplier }}</div>
|
|
93
|
+
<div class="stat-label">Multiplier</div>
|
|
94
|
+
</div>
|
|
95
|
+
</section>
|
|
96
|
+
{% else %}
|
|
97
|
+
<section class="bento-cell cell-stat" aria-label="Total time">
|
|
98
|
+
<div class="stat-icon" aria-hidden="true">
|
|
99
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
|
100
|
+
</div>
|
|
101
|
+
<div>
|
|
102
|
+
<div class="stat-number">{{ project.totalDurationMinutes | formatDuration }}</div>
|
|
103
|
+
<div class="stat-label">Time</div>
|
|
104
|
+
</div>
|
|
105
|
+
</section>
|
|
106
|
+
{% endif %}
|
|
107
|
+
|
|
108
|
+
{%- comment -%} Cell 5: Stat -- LOC {%- endcomment -%}
|
|
109
|
+
<section class="bento-cell cell-stat" aria-label="Lines changed">
|
|
110
|
+
<div class="stat-icon" aria-hidden="true">
|
|
111
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="16 18 22 12 16 6"/><polyline points="8 6 2 12 8 18"/></svg>
|
|
112
|
+
</div>
|
|
113
|
+
<div>
|
|
114
|
+
<div class="stat-number" data-target="{{ project.totalLoc }}" data-format="comma">0</div>
|
|
115
|
+
<div class="stat-label">Lines Changed</div>
|
|
116
|
+
</div>
|
|
117
|
+
</section>
|
|
118
|
+
|
|
119
|
+
{%- comment -%} Cell 6: Stat -- Files {%- endcomment -%}
|
|
120
|
+
<section class="bento-cell cell-stat" aria-label="Files changed">
|
|
121
|
+
<div class="stat-icon" aria-hidden="true">
|
|
122
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>
|
|
123
|
+
</div>
|
|
124
|
+
<div>
|
|
125
|
+
<div class="stat-number" data-target="{{ project.totalFilesChanged }}">0</div>
|
|
126
|
+
<div class="stat-label">Files</div>
|
|
127
|
+
</div>
|
|
128
|
+
</section>
|
|
129
|
+
|
|
130
|
+
{%- comment -%} Cell 7: Stat -- Tokens {%- endcomment -%}
|
|
131
|
+
{% if project.totalTokens %}
|
|
132
|
+
<section class="bento-cell cell-stat" aria-label="Tokens used">
|
|
133
|
+
<div class="stat-icon" aria-hidden="true">
|
|
134
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
|
|
135
|
+
</div>
|
|
136
|
+
<div>
|
|
137
|
+
<div class="stat-number">{{ project.totalTokens | formatTokens }}</div>
|
|
138
|
+
<div class="stat-label">Tokens</div>
|
|
139
|
+
</div>
|
|
140
|
+
</section>
|
|
141
|
+
{% endif %}
|
|
142
|
+
|
|
143
|
+
{%- comment -%} Narrative (3-wide) {%- endcomment -%}
|
|
144
|
+
{% if project.narrative %}
|
|
145
|
+
<section class="bento-cell cell-narrative" aria-label="Project narrative">
|
|
146
|
+
<h2 class="cell-heading">
|
|
147
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/></svg>
|
|
148
|
+
Narrative
|
|
149
|
+
</h2>
|
|
150
|
+
<p>{{ project.narrative }}</p>
|
|
151
|
+
</section>
|
|
152
|
+
{% endif %}
|
|
153
|
+
|
|
154
|
+
{%- comment -%} Phases (2-wide) {%- endcomment -%}
|
|
155
|
+
{% if arc.size > 0 %}
|
|
156
|
+
<section class="bento-cell cell-phases" aria-label="Project phases">
|
|
157
|
+
<h2 class="cell-heading">
|
|
158
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>
|
|
159
|
+
Phases
|
|
160
|
+
</h2>
|
|
161
|
+
<ol class="phase-list" role="list">
|
|
162
|
+
{% for item in arc %}
|
|
163
|
+
<li class="phase-item">
|
|
164
|
+
<span class="phase-number" aria-hidden="true">{{ item.phase }}</span>
|
|
165
|
+
<div class="phase-content">
|
|
166
|
+
<div class="phase-name">{{ item.title }}</div>
|
|
167
|
+
{% if item.dates %}
|
|
168
|
+
<div class="phase-dates">{{ item.dates }}</div>
|
|
169
|
+
{% endif %}
|
|
170
|
+
<div class="phase-desc">{{ item.description }}</div>
|
|
171
|
+
</div>
|
|
172
|
+
</li>
|
|
173
|
+
{% endfor %}
|
|
174
|
+
</ol>
|
|
175
|
+
</section>
|
|
176
|
+
{% endif %}
|
|
177
|
+
|
|
178
|
+
{%- comment -%} Skills (2-wide) {%- endcomment -%}
|
|
179
|
+
{% if project.skills.size > 0 %}
|
|
180
|
+
<section class="bento-cell cell-skills" aria-label="Skills used">
|
|
181
|
+
<h2 class="cell-heading">
|
|
182
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/></svg>
|
|
183
|
+
Skills
|
|
184
|
+
</h2>
|
|
185
|
+
<div class="skills-grid">
|
|
186
|
+
{% for skill in project.skills %}
|
|
187
|
+
<span class="skill-chip chip">{{ skill }}</span>
|
|
188
|
+
{% endfor %}
|
|
189
|
+
</div>
|
|
190
|
+
</section>
|
|
191
|
+
{% endif %}
|
|
192
|
+
|
|
193
|
+
{%- comment -%} Key Decisions (2-wide) {%- endcomment -%}
|
|
194
|
+
{% if arc.size > 0 %}
|
|
195
|
+
<section class="bento-cell cell-decisions" aria-label="Key decisions">
|
|
196
|
+
<h2 class="cell-heading">
|
|
197
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="10"/><line x1="12" y1="16" x2="12" y2="12"/><line x1="12" y1="8" x2="12.01" y2="8"/></svg>
|
|
198
|
+
Key Decisions
|
|
199
|
+
</h2>
|
|
200
|
+
<ol class="decision-list" role="list">
|
|
201
|
+
{% for item in arc %}
|
|
202
|
+
<li class="decision-item">
|
|
203
|
+
<span class="decision-text">{{ item.description }}</span>
|
|
204
|
+
</li>
|
|
205
|
+
{% endfor %}
|
|
206
|
+
</ol>
|
|
207
|
+
</section>
|
|
208
|
+
{% endif %}
|
|
209
|
+
|
|
210
|
+
{%- comment -%} Source Breakdown (2-wide) {%- endcomment -%}
|
|
211
|
+
{% if sourceCounts.size > 0 %}
|
|
212
|
+
<section class="bento-cell cell-source" aria-label="Source breakdown">
|
|
213
|
+
<h2 class="cell-heading">
|
|
214
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><line x1="3" y1="9" x2="21" y2="9"/><line x1="9" y1="21" x2="9" y2="9"/></svg>
|
|
215
|
+
Source Breakdown
|
|
216
|
+
</h2>
|
|
217
|
+
<div class="source-bars">
|
|
218
|
+
{% assign totalSourceSessions = 0 %}
|
|
219
|
+
{% for src in sourceCounts %}
|
|
220
|
+
{% assign totalSourceSessions = totalSourceSessions | plus: src.count %}
|
|
221
|
+
{% endfor %}
|
|
222
|
+
{% for src in sourceCounts %}
|
|
223
|
+
<div class="source-item">
|
|
224
|
+
<span class="source-name">{{ src.tool }}</span>
|
|
225
|
+
<div class="source-bar-track">
|
|
226
|
+
{% if totalSourceSessions > 0 %}
|
|
227
|
+
{% assign srcPct = src.count | times: 100.0 | divided_by: totalSourceSessions | round: 1 %}
|
|
228
|
+
<div class="source-bar-fill{% unless forloop.first %} source-bar-fill--secondary{% endunless %}" style="width: {{ srcPct }}%"></div>
|
|
229
|
+
{% endif %}
|
|
230
|
+
</div>
|
|
231
|
+
{% if totalSourceSessions > 0 %}
|
|
232
|
+
{% assign srcPctDisplay = src.count | times: 100.0 | divided_by: totalSourceSessions | round: 1 %}
|
|
233
|
+
<span class="source-pct">{{ srcPctDisplay }}%</span>
|
|
234
|
+
{% endif %}
|
|
235
|
+
</div>
|
|
236
|
+
{% endfor %}
|
|
237
|
+
</div>
|
|
238
|
+
</section>
|
|
239
|
+
{% endif %}
|
|
240
|
+
|
|
241
|
+
{%- comment -%} Work Timeline table (4-wide) -- CSS-only, no JS charts {%- endcomment -%}
|
|
242
|
+
{% if featuredSessions.size > 0 %}
|
|
243
|
+
<section class="bento-cell cell-timeline" aria-label="Work timeline">
|
|
244
|
+
<h2 class="cell-heading">
|
|
245
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="20" x2="12" y2="10"/><line x1="18" y1="20" x2="18" y2="4"/><line x1="6" y1="20" x2="6" y2="16"/></svg>
|
|
246
|
+
Work Timeline
|
|
247
|
+
</h2>
|
|
248
|
+
<div class="timeline-chart" role="table" aria-label="Session timeline">
|
|
249
|
+
<div class="timeline-row timeline-header" role="row">
|
|
250
|
+
<span role="columnheader">#</span>
|
|
251
|
+
<span role="columnheader">Session</span>
|
|
252
|
+
<span role="columnheader" style="text-align:end">Date</span>
|
|
253
|
+
<span role="columnheader" style="text-align:end">Time</span>
|
|
254
|
+
<span role="columnheader" style="text-align:end">LOC</span>
|
|
255
|
+
</div>
|
|
256
|
+
{% for s in featuredSessions %}
|
|
257
|
+
<div class="timeline-row" role="row">
|
|
258
|
+
<span class="timeline-num" role="cell">{{ forloop.index }}</span>
|
|
259
|
+
<span class="timeline-title" role="cell">{{ s.title }}</span>
|
|
260
|
+
<span class="timeline-date" role="cell">{% if s.recordedAt %}{{ s.recordedAt | formatDate: "short" }}{% endif %}</span>
|
|
261
|
+
<span class="timeline-duration" role="cell">{{ s.durationMinutes }}m</span>
|
|
262
|
+
<span class="timeline-loc" role="cell">{{ s.locChanged | localeNumber }}</span>
|
|
263
|
+
</div>
|
|
264
|
+
{% endfor %}
|
|
265
|
+
</div>
|
|
266
|
+
</section>
|
|
267
|
+
{% endif %}
|
|
268
|
+
|
|
269
|
+
{%- comment -%} Featured Session Cards (2-wide each) {%- endcomment -%}
|
|
270
|
+
{% if featuredSessions.size > 0 %}
|
|
271
|
+
{% for s in featuredSessions %}
|
|
272
|
+
<a href="{{ sessionBaseUrl }}/{{ s.slug }}{{ sessionSuffix }}" class="bento-cell cell-session session-card" aria-label="View session: {{ s.title }}">
|
|
273
|
+
<div class="session-header">
|
|
274
|
+
<span class="session-title">{{ s.title }}</span>
|
|
275
|
+
{% if s.skills.size > 0 %}
|
|
276
|
+
<span class="session-tag">{{ s.skills | first }}</span>
|
|
277
|
+
{% endif %}
|
|
278
|
+
</div>
|
|
279
|
+
<div class="session-meta">
|
|
280
|
+
<span>{{ s.durationMinutes | formatDuration }}</span>
|
|
281
|
+
<span>{{ s.locChanged | localeNumber }} LOC</span>
|
|
282
|
+
{% if s.agentSummary and s.agentSummary.agents.size > 0 %}
|
|
283
|
+
<span>{{ s.agentSummary.agents.size }} agents</span>
|
|
284
|
+
{% elsif s.filesChanged %}
|
|
285
|
+
<span>{{ s.filesChanged }} files</span>
|
|
286
|
+
{% endif %}
|
|
287
|
+
</div>
|
|
288
|
+
{% if s.agentSummary and s.agentSummary.agents.size > 0 %}
|
|
289
|
+
<div class="session-agents" aria-label="Agent roles used">
|
|
290
|
+
{% assign agent_colors = '#7c3aed,#0891b2,#059669,#475569,#e11d48,#d97706' | split: ',' %}
|
|
291
|
+
{% for agent in s.agentSummary.agents %}
|
|
292
|
+
{% assign colorIdx = forloop.index0 | modulo: 6 %}
|
|
293
|
+
<span class="agent-dot" style="background: {{ agent_colors[colorIdx] }};" title="{{ agent.role }}"></span>
|
|
294
|
+
{% endfor %}
|
|
295
|
+
</div>
|
|
296
|
+
{% endif %}
|
|
297
|
+
</a>
|
|
298
|
+
{% endfor %}
|
|
299
|
+
{% endif %}
|
|
300
|
+
|
|
301
|
+
</div>
|
|
302
|
+
</div>
|
|
303
|
+
|
|
304
|
+
{%- comment -%} Stat counter animation {%- endcomment -%}
|
|
305
|
+
|
|
306
|
+
</div>
|