feat(card): add S-tier cards — heatmap, streak, by-year, weekday, top-starred (#3)

Five new cards, all derived from data FetchProductive / FetchProfile already
pull, so zero additional API calls:

- contributions-heatmap: 7×53 calendar grid with a 5-bucket intensity ramp
  mixed from each theme's Background→Accent so palettes with no dedicated
  heat ramp still render sensibly.
- streak: current streak, longest streak with date ranges, active/total days.
- contributions-by-year: one bar per active year, peak year highlighted.
- productive-weekday + -all-time: 7-bar day-of-week mirror of the hour-of-day
  cards; FetchProductive now also fills Weekday / WeekdayAllTime histograms
  during the same commit-history pass.
- top-starred-repos: top 5 owned non-fork repos by stargazer count; threads
  Stars through RepoInfo.

Card count: 9 → 14. Registered in allCards grouped by recency (last-year
block, then all-time block). Render test extended to cover all new files
and realistic daily-series inputs.
This commit is contained in:
2026-04-19 08:58:59 +07:00
committed by GitHub
parent 9dffc2234b
commit fd4c70e53e
13 changed files with 805 additions and 8 deletions
+8
View File
@@ -43,6 +43,12 @@ type Profile struct {
Productive [24]int
ProductiveAllTime [24]int
// Same pagination also feeds day-of-week histograms (index 0 = Sunday
// to match time.Weekday). Last-year and all-time kept separately so the
// weekday cards mirror the hour-of-day pair.
Weekday [7]int
WeekdayAllTime [7]int
// CommitsByLanguageAllTime is the lifetime counterpart of
// CommitsByLanguage, computed from the same commit stream.
CommitsByLanguageAllTime []LangStat
@@ -98,6 +104,7 @@ type LangStat struct {
type RepoInfo struct {
Owner string
Name string
Stars int
IsPrivate bool
IsFork bool
PrimaryLanguage string
@@ -148,6 +155,7 @@ func (r repoNode) toRepoInfo(defaultOwner string) RepoInfo {
info := RepoInfo{
Owner: defaultOwner,
Name: r.Name,
Stars: r.StargazerCount,
IsPrivate: r.IsPrivate,
IsFork: r.IsFork,
}
+2
View File
@@ -94,9 +94,11 @@ func (c *Client) FetchProductive(ctx context.Context, p *Profile, repos []RepoIn
}
tl := t.In(loc)
p.ProductiveAllTime[tl.Hour()]++
p.WeekdayAllTime[tl.Weekday()]++
attributeCommit(repo, repoTotal, allTimeLang, langColor)
if tl.After(yearAgo) {
p.Productive[tl.Hour()]++
p.Weekday[tl.Weekday()]++
attributeCommit(repo, repoTotal, lastYearLang, langColor)
}
seen++