feat: port playground prototypes to SvelteKit dashboards #31
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/westside-landing!31
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feature/10f-4-playground-port"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Changes
src/app.css: Replaced with playground's unified design system. Adds component classes (.stat-card,.player-card,.badge-*,.list-row,.info-card,.team-card,.schedule-item,.actions-row, etc.). Keeps legacy--color-*aliases for AuthStatus.svelte and landing page compatibility.src/routes/admin/+page.server.js: Replaced tryout triage grouping with payment stats derivation and overdue player filtering. AddedfetchTeams()call for teams summary. Removed tryout-specific form actions.src/routes/admin/+page.svelte: Replaced tryout triage buckets with operations dashboard: stats row, payment health bar with collection rate, overdue families list, teams summary cards, quick action buttons.src/routes/coach/+page.svelte: Replaced tryout check-in card grid with player card grid showing parent contact info and payment status badges.src/routes/player/+page.svelte: Replaced tryout card view with info-card layout: player profile, team assignment, payment status, and schedule placeholder.Test Plan
npm run buildpasses with zero errorsnpm run check-- no new errors (31 remaining are all pre-existing in untouched files)Review Checklist
Related
plan-2026-03-08-tryout-prep-- Phase 10f-4Self-Review
Reviewed all 5 changed files (100% of diff).
Verified
--color-*aliases preserved for AuthStatus.svelte and landing page<nav>elements stripped -- AuthStatus.svelte handles navigation|| '?',|| 'Not assigned')npm run buildpassesnpm run check-- no new errors (31 remaining are pre-existing in untouched files)No blocking issues found
PR #31 Review
DOMAIN REVIEW
Tech stack: SvelteKit (Svelte 5 runes), JavaScript (no TypeScript), CSS custom properties design system.
What this PR does: Replaces tryout-day UI with post-tryout operations dashboards by porting HTML/CSS prototypes from
~/westside-playground/to SvelteKit components. Five files changed:src/app.css(design system replacement),player/+page.svelte,coach/+page.svelte,admin/+page.svelte, andadmin/+page.server.js(newfetchTeams+ payment stats derivation).Playground fidelity check:
src/app.cssis a faithful port ofwestside-playground/shared/app.css. The playground nav bar (.nav,.nav-brand,.nav-logo,.nav-user,.bottom-nav) was intentionally excluded since the SvelteKit app usesAuthStatus.sveltefor navigation. Legacy--color-*aliases were correctly added forAuthStatus.svelteand landing page compatibility. Thebody { min-height: 100vh }addition is a good improvement over the playground source. Alert and empty-state classes added for Svelte error/empty states. Responsive breakpoints match playground.player/+page.sveltefaithfully portsparent.htmlinfo-card layout. Data-driven viadata.myPlayerswith proper null guards (player.position || '?'). Schedule section correctly shows placeholder ("Schedule coming soon") since schedule data is not yet API-backed. Graceful fallback for admins/coaches with no player profile.coach/+page.sveltefaithfully portscoach.htmlplayer-card grid. Search filter is reactive via$derived. Parent contact info with phone formatting. Photo support added (playground was text-only). Empty state handling is thorough (no team, no players, no matches).admin/+page.sveltefaithfully portsadmin.htmloperations dashboard. Page-specific stat-bar styles correctly kept in component<style>block (matching playground's inline<style>approach). Stats, payment health bar, overdue families list, team cards, and quick actions all data-driven. Quick action links correctly point to/admin/usersand/admin/teams.admin/+page.server.jsaddsfetchTeams()import andderivePaymentStats()/getOverduePlayers()helper functions. Auth guard is present and correct (admin role required).Promise.allfor parallel fetching is good. Error handling returns safe defaults.Data binding verification (all pass):
admin/+page.svelteaccessesdata.paymentStats.{total,current,overdue,collectionRate},data.teams,data.overduePlayers,data.apiConnected-- all returned byadmin/+page.server.js.coach/+page.svelteaccessesdata.myTeam,data.players,data.totalPlayers,data.apiConnected-- all returned bycoach/+page.server.js.player/+page.svelteaccessesdata.myPlayers,data.apiConnected,data.roles-- all returned byplayer/+page.server.js.Auth guard verification (all pass):
admin/+page.server.jscheckssession?.user(redirect to/signin) androles.includes('admin')(403).coach/+page.server.jscheckssession?.user(redirect to/signin) androles.includes('coach') || roles.includes('admin')(403).player/+page.server.jscheckssession?.user(redirect to/signin).API module verification:
fetchTeams()exists insrc/lib/server/api.js(line 58) and accepts(tenant, token). Theadmin/+page.server.jscalls it asfetchTeams(TENANT, accessToken)which matches the signature. The.catch(() => [])gracefully handles team API failures."Do not touch" files verification: Landing page (
+page.svelte,+page.server.js), auth routes (signin/,signout/),admin/teams/,admin/users/,AuthStatus.svelte,+layout.svelte,+layout.server.js,hooks.server.js,auth.js,app.html-- all unchanged. Confirmed by reading each file; no modifications detected.CSS compatibility: The
app.htmlinline styles setbackground-color: #0a0a0aandcolor: #f0f0f0which match the new--color-blackand--color-gray-100design tokens. Legacy aliases (--color-bg,--color-bg-card,--color-text,--color-brand, etc.) preserve compatibility withAuthStatus.svelteand the landing page+page.sveltescoped styles.XSS check: All dynamic values are rendered via Svelte's
{expression}syntax which auto-escapes HTML. No use of{@html}. Phone numbers inhref="tel:{player.parent_phone}"are URL-scheme references, not HTML injection vectors. Safe.BLOCKERS
None found. No build errors expected (no new dependencies, all imports resolve). Auth guards are present on all protected routes. Data bindings match server returns. No XSS vectors. No secrets committed. No "do not touch" files modified. No removed functionality that is still needed.
On test coverage: This project has zero test files (pre-existing condition across the entire repo). The PR ports visual templates from playground HTML to data-driven Svelte components -- it adds server-side data derivation logic (
derivePaymentStats,getOverduePlayers) which would benefit from unit tests, but the zero-test baseline is a repo-level gap, not a PR-introduced regression. Flagging as a nit rather than a blocker given the context.NITS
DRY violation -- utility functions duplicated across 3+ components.
getInitials()is defined inplayer/+page.svelte,coach/+page.svelte, andadmin/+page.svelte.getPaymentBadgeClass()andgetPaymentBadgeLabel()are identical in all three.formatPhone()is incoach/andadmin/.formatGradClass()is inplayer/,coach/, andadmin/teams/. These should be extracted tosrc/lib/utils.jsor similar. Not a security path, but maintenance risk -- if badge logic changes, three files need updating.Dead code in
coach/+page.server.js. Line 42 computescheckedInCountand line 48 returns it, but the newcoach/+page.sveltenever referencesdata.checkedInCount. This was used by the old tryout-day check-in UI. Should be removed.Hardcoded
$200/monthand$200amounts.player/+page.svelteline 114 andadmin/+page.svelteline 107 hardcode the payment amount. Same as playground source, but when subscription amounts vary per player, these will break. Consider deriving from API data when available.Hardcoded tenant slug.
admin/+page.server.jsline 4:const TENANT = 'westside-kings-queens'. Same pattern exists inplayer/andcoach/server files. Could be a shared constant in$lib/server/api.jsor$lib/config.js.Admin overdue list shows static "overdue" text.
admin/+page.svelteline 108:<div class="list-days">overdue</div>. The playground shows specific days overdue ("12 days overdue", "8 days overdue"). The API likely does not provide this data yet, but the placeholder text is less informative than the playground design. Consider a TODO comment.Missing
<label>for search input.coach/+page.svelteline 83 uses<input type="text" class="search" placeholder="Search players...">without an associated<label>element oraria-labelattribute. Same issue in the playground source, but SvelteKit should be more accessible. A visually-hidden label oraria-label="Search players"would help screen readers.No test coverage for
derivePaymentStats()andgetOverduePlayers(). These are pure functions with clear inputs/outputs -- ideal for unit testing.derivePaymentStatshandles edge cases (empty array, missingpayment_status) which should be verified. Low effort, high value.Playground
min-height: 100vhon body not in playground source.src/app.cssline 84 addsmin-height: 100vhto body which was not inwestside-playground/shared/app.css. This is an improvement (prevents short-page white flash at bottom), but worth noting as a deliberate deviation from playground source.SOP COMPLIANCE
feature/10f-4-playground-portreferences Phase 10f-4, issue #30)feat: port playground prototypes to SvelteKit dashboards)PROCESS OBSERVATIONS
$lib/utils.jsshould happen soon.derivePaymentStatsandgetOverduePlayersfunctions added in this PR are pure functions that are easy to test. This would be a good entry point for establishing a test baseline.VERDICT: APPROVED
The port is faithful to the playground prototypes, data bindings are correct, auth guards are intact, and no "do not touch" files were modified. The DRY violations and dead code are real quality issues but do not block merge -- they should be tracked as follow-up work (ideally as a Phase 10f-5 or similar).