Commit Graph

40 Commits

Author SHA1 Message Date
Samuel Enocsson 98a6c6be2e feat: show cutoff rating threshold in player history accordion (#21) 2026-05-25 11:12:01 +02:00
Samuel Enocsson 9138299ae0 Merge remote-tracking branch 'origin/main' into feat/show-excluded-rounds-count-21 2026-05-25 11:01:53 +02:00
Samuel Enocsson 75b2360e96 feat: add table header row to Courses matching Players style (#8) 2026-05-25 10:33:47 +02:00
Samuel Enocsson 2035ae0efc fix: use FontAwesome icons matching Players page (#8) 2026-05-25 10:29:34 +02:00
Samuel Enocsson 88396c9220 fix: remove EJS comment inside template literal causing parse error (#8) 2026-05-25 10:25:59 +02:00
Samuel Enocsson 9cb78c9c98 fix: address code-review findings from pass 1 + 2 (#8)
- Fix saveCourseToDB returning 0 on conflict by falling back to SELECT
- Fix inactive layouts showing 'Never played' when last_played exists
- Add .icon-btn.spinning to courses.css for refresh button feedback
- Remove duplicate .btn-primary from courses.css (use shared.css version)
- Tokenize rating tier colors into --rating-tier-{high,mid,low} CSS vars
- Convert var to const/let throughout courses.js
- Fix logger.error calls to use {err} object form (pino convention)
- Extract RATING_TIER_HIGH/MID constants in course-layouts.ejs scriptlet
- Remove dead href='#' View all link from courses.ejs (deferred)
- Pass total prop explicitly from course-table.ejs to course-cards.ejs
- Remove dead #search-results-info selector from mobile.css
- Remove redundant .replace(/"/g, '"') from data attributes in course-table.ejs
2026-05-25 09:54:15 +02:00
Samuel Enocsson f2e30c62aa fix: zero excluded count in fallback, drop debug-icon orphan, align ejs guard (#21) 2026-05-25 09:44:46 +02:00
Samuel Enocsson 4bbf6d9728 feat: redesign Courses page with tabs + restore Tjing import (#8)
- Restore src/scrapers/tjing.js with AbortController timeout (8s),
  error-object returns, and verbatim GraphQL queries
- Add getOrCreateLayout() to src/models/course.js
- New /api/tjing/search and /api/tjing/import/:tjingId routes;
  course-table route now includes layoutCount/activeLayoutCount via
  LEFT JOIN aggregation
- Rewrite courses.ejs: action-card with Find/Import tabs, results bar,
  HTMX course-table-region with body:refresh trigger
- Rewrite course-table.ejs: CSS-grid div structure replacing <table>,
  lazy-load expanded layouts via JS htmx.ajax
- Rewrite course-layouts.ejs: layout-card chips with rating tier colouring,
  collapsible inactive layouts section
- Rewrite courses.js: tab switching, live client-side filter, count display,
  Tjing search/import using DOM API (no innerHTML with untrusted data)
- Rewrite courses.css: full new design system using project tokens
2026-05-25 09:39:44 +02:00
Samuel Enocsson 0beeb98002 feat: show excluded rounds count in player history accordion (#21) 2026-05-25 09:34:42 +02:00
Samuel Enocsson 088e283dcf refactor: split round spread and rating range into separate accordion rows (#19) 2026-05-25 08:02:05 +02:00
Samuel Enocsson 5791d8e34f refactor: move std-dev info to accordion, remove tooltip (#19)
- Add "Round spread" row (±stdDev, range lo–hi) to desktop accordion
  (player-history.ejs) and mobile card expanded section (ratings-cards.ejs)
- Remove .std-dev-tooltip div and .std-dev-inline span from table partial
- Remove stdDevTooltipText, updateStdDevInline, initRatingsTooltips helpers
  and all call sites from players.js
- Remove .std-dev-tooltip and .std-dev-inline CSS rules; drop cursor:help
  from .rating-value
2026-05-25 07:54:46 +02:00
Samuel Enocsson 1ff768e2fa fix: address std-dev inline span refresh + style fixes (#19)
- A: create inline span when missing in refreshRoundHistory (was silently dropped)
- B: updateStdDevInline also called from refreshHistoryThenCalculate
- C: extract stdDevTooltipText + updateStdDevInline helpers; replace 3 call sites
- D: remove margin-left: 4px and bump font-size to 12px on .std-dev-inline
- E: guard against stdDev === 0 in EJS (truthy → != null)
2026-05-23 06:45:39 +02:00
Samuel Enocsson c3fb850de3 fix: reposition std-dev tooltip and surface ±-spread inline (#19) 2026-05-23 06:40:08 +02:00
Samuel Enocsson 7ab16994c5 chore: remove dead mobile-add-bar.ejs partial (#16) 2026-05-22 21:27:57 +02:00
Samuel Enocsson b51c47dc4c fix: address mobile UI review findings (#16)
- Hide desktop .card-section on mobile, add .m-search-input with same
  HTMX attrs for mobile course search (fixes horizontal overflow)
- Remove dead layoutCount var and .m-layouts-pill block in course-cards
- Remove dead 768px breakpoints from players.css (table hidden at 880px)
- Move .mobile-section-head inside else-block for empty state in both
  ratings-cards and course-cards (fixes section head showing on empty)
- Add tabindex, role=button, aria-expanded, onkeydown to .m-card and
  .m-course-card; toggle aria-expanded in JS toggle functions
- Fix data-history attribute to use <%=  (HTML-escaped) instead of <%-
- Convert var to const/let in all new/changed JS blocks
2026-05-22 21:27:05 +02:00
Samuel Enocsson cc9d8eb4cd feat: mobile UI card layout for players and courses (#16) 2026-05-22 21:07:00 +02:00
Samuel Enocsson 1e66b9f94f feat: add target rating calculator (#2) 2026-05-22 13:21:41 +02:00
Samuel Enocsson fba1bea247 refactor: address review feedback — extract date helper, rename listener 2026-05-22 11:47:47 +02:00
Samuel Enocsson a63da6f3ca fix: preload player rating history to fix first-click chart render (#10) 2026-05-22 11:41:38 +02:00
Samuel Enocsson b6c674e4c7 wire refresh button to update both rating and prediction 2026-05-21 16:04:15 +02:00
Samuel Enocsson 4b145094bf render flat delta pill for null values per design spec 2026-05-21 15:51:17 +02:00
Samuel Enocsson 88df98f269 fix: place history chart in right grid column of expanded row (#7)
The dl + button + chart were 3 direct children of .player-detail (a
2-column grid). Auto-placement put the button in the right column,
forcing the chart to wrap to a second row in the left column.
Wrap dl + button in .player-detail-left so the chart occupies col 2.
2026-05-21 15:23:53 +02:00
Samuel Enocsson 7fb8cab5e2 feat: add 'View calculation details' link to expanded row (#4) 2026-05-21 15:16:51 +02:00
Samuel Enocsson 16d375ae10 refactor: design-fidelity pass on players page 2026-05-21 15:15:29 +02:00
Samuel Enocsson 686d7ca00c fix: use template-literal interpolation for KPI strip inside body string (#5)
The page body is assembled as a JS template literal inside <% ... %>;
EJS tags inside that string break the EJS parser (it sees the first %>
as the close of the outer tag). Switch to ${kpis.x} interpolation since
we're already inside a backtick string.
2026-05-21 15:03:02 +02:00
Samuel Enocsson 0ded27f9df fix: address code review findings — DRY delta-pill, var→const/let, tokenize colors 2026-05-21 14:38:06 +02:00
Samuel Enocsson b75e60da65 feat: redesign expanded row with detail-grid + history chart (#7) 2026-05-21 14:38:06 +02:00
Samuel Enocsson 83ceaf0ea3 feat: add KPI summary tiles above players table (#5) 2026-05-21 14:38:06 +02:00
Samuel Enocsson b51ae19ae1 feat: render sparklines + wire trend-chart pill toggle (#6) 2026-05-21 14:37:58 +02:00
Samuel Enocsson 3dcd3131a0 feat: add monthlyHistory[] per player via getMonthlyHistory + bulk fetch (#6)
Add getMonthlyHistory() to models/player for single-player use and
getAllMonthlyHistoriesFromDB() for bulk fetches (one query, grouped in
memory). Wire monthlyHistory into all player objects returned by
getPlayerDataFromDB and getAllRatingsFromDB. Bulk path pre-fetches in
one query to avoid N extra per-player queries.
2026-05-21 13:41:20 +02:00
Samuel Enocsson 3f7a1bb7bf chore: remove dead code orphaned by topbar redesign (#4)
The new topbar's "Refresh all" button replaces the old SSE-driven
"Load All" link and progress UI. With those gone, several pieces of
infrastructure had no callers left:

- GET /api/load-all-players, POST /api/populate-database, and
  GET /api/database-status — SSE endpoints with no frontend consumers
- #progress-section / #loading divs in players + courses pages
- .progress-container / .progress-bar / .progress-text / .loading CSS
- public/js/progress.js script (defines fetchRatingsWithProgress, never
  called, and loadAllPlayers, no longer wired) — to be deleted manually
  since the sandbox blocks rm
2026-05-21 13:15:53 +02:00
Samuel Enocsson 53bc6e571d chore: remove redundant "Load All" link from players page (#4)
The topbar's "Refresh all" button (introduced in #4) supersedes this
link. Leaving the gear icon for clearCache() — that's a separate
concern.
2026-05-21 13:11:28 +02:00
Samuel Enocsson de99d4ede7 fix: address code review for visual layer + topbar (#4) 2026-05-21 12:50:31 +02:00
Samuel Enocsson 8c977d6624 feat: shared visual layer + redesigned topbar (#4)
Introduce new design token set (paper/ink/line/accent + radius/shadow)
with backward-compat aliases for legacy --surface/--navy/--text names.
Swap DM Sans for Plus Jakarta Sans, add JetBrains Mono with tabular
numerics. Replace .app-header with sticky .topbar partial (brand +
segmented nav + Next update / Last refresh meta + Refresh all button).

Add POST /api/refresh-all that runs refreshAllPlayersInDB() with an
in-memory mutex and returns the rendered topbar so HTMX can swap it
in. "Next update" is computed as first Tuesday of next month
(approximation of PDGA's monthly cycle). "Last refresh" derives
from MAX(players.last_updated).
2026-05-21 12:37:31 +02:00
Samuel Enocsson 6e05d3014d refactor: remove tour feature and Tjing import
Release Please / release-please (push) Waiting to run
Release Please / docker (push) Blocked by required conditions
Tour functionality has moved to its own project (HyzrTour).
Removes all tour-related code, Tjing integration, and associated
views/styles/scripts. Keeps the saveCourseToDB ON CONFLICT fix.
2026-03-20 15:05:20 +01:00
Samuel Enocsson eb77b1f32b feat: add Tjing course import
Search and import courses with layouts from Tjing's GraphQL API.
Total par is calculated from individual hole data. Courses are saved
with a tjing.se link as unique identifier to prevent duplicates.
2026-03-20 08:45:16 +01:00
Samuel Enocsson 2ccb018bdf feat: add async tour system
Players can create tours with selected courses/layouts and a date range.
Others join via a 6-character tour code, play the courses, and report
their total strokes. Live leaderboard with points and +/- par display.

Includes: database schema, model, service, routes, views, and styling.
2026-03-20 07:39:43 +01:00
Samuel Enocsson 371a398446 Modernize UI design with new color system, typography and layout
- Add sticky dark header with nav replacing inline text links
- Introduce CSS custom properties design system (colors, spacing, shadows)
- Use DM Sans + JetBrains Mono fonts replacing Arial
- Modernize tables with uppercase headers and subtle hover states
- Add gradient fill and rounded line to rating chart
- Unify card sections across players and courses pages
- Add backdrop blur to modals
- Clean up inline styles to use CSS variables
2026-02-19 09:12:04 +01:00
Samuel Enocsson 7e5fa6cbf1 Add HTMX migration for server-rendered tables and lazy loading
- Add HTMX CDN to layout
- Replace client-side table rendering (displayRatings, displayCourses)
  with server-rendered EJS partials via hx-get
- Add server-side course search with debounced hx-trigger
- Lazy-load player history and course layouts via htmx.ajax()
- Render rating chart via htmx:afterSwap with data attributes
- Add partial routes: ratings-table, course-table, player-history,
  course-layouts
2026-02-19 08:29:56 +01:00
Samuel Enocsson 20bbdbbfcf Extract inline CSS/JS, add EJS templates with shared layout
- Extract CSS into public/css/{shared,players,courses}.css
- Extract JS into public/js/{chart,tooltips,progress,players,courses}.js
- Consolidate 5 duplicated tooltip blocks into setupTooltip() helper
- Add EJS view engine with layout partial and nav partial
- Convert HTML pages to EJS templates (index.ejs, courses.ejs)
- Add /courses route with redirect from /courses.html
- Remove old monolithic HTML files (1478 + 612 lines)
2026-02-18 22:32:03 +01:00