feat: add Commerce admin page for jersey/subscription/contract visibility #228
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
ldraney/westside-app!228
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "226-add-commerce-admin-page"
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
Promotes the approved playground prototype (
commerce.htmlfromwestside-playground#50) to production Svelte. Adds a Commerce page to the admin nav with three tabbed views (Jerseys, Subscriptions, Contracts), each with summary stat cards, status-based filtering, and responsive data tables — all powered by the existing/admin/playersAPI endpoint.Changes
src/routes/(app)/admin/commerce/+page.svelte— New Commerce page with three tabs,$derivedaggregations for summary counts, reactive filter buttons, and{#each}data tables. UsesonMount+apiFetch('/admin/players')consistent with other admin pages.src/routes/(app)/+layout.svelte— Added Commerce nav item ($icon) between CRM and Teams in the admin bottom nav.src/app.css— Added commerce CSS classes (tab-bar, tab-btn, summary-row, summary-stat, data-table, badge-shipped, badge-past-due, badge-canceled) copied from playgroundshared/style.css. Includes mobile-responsive table stacking at 600px.Test Plan
npm run buildpasses with no errorsReview Checklist
npm run buildpasses<style>blocks — all CSS in global app.css/admin/players$state,$derived) consistent with other admin pagesdata-labelattributesRelated
forgejo_admin/westside-playground#50(playground prototype)Related Notes
story:WS-S9— "As an admin, I want to track payment status per player so that I know who owes what."sop-capacitor-mobile-lifecycle— playground-to-Svelte promotion SOPPR #228 Review
DOMAIN REVIEW
Tech stack: SvelteKit (Svelte 5 runes), global CSS with CSS custom properties, no Tailwind.
Svelte 5 runes usage -- CORRECT
$statefor reactive primitives (allPlayers,loading,error,activeTab, filter states) -- matches codebase convention.$derived(() => ...)forfilteredJerseyPlayers,filteredSubPlayers,filteredContractPlayers-- returns a function, invoked asfilteredJerseyPlayers()in{#each}blocks. This matches the established pattern inadmin/players/+page.svelte(line 170) andadmin/users/+page.svelte(line 64).$derived(expr)for count aggregations (jerseyPaidCount, etc.) -- direct expression style, also matches codebase convention (admin/schedule/+page.sveltelines 26-27,admin/teams/+page.sveltelines 40-42).onMount+apiFetchpattern is consistent with every other admin page.CSS conventions -- CORRECT
app.css, no scoped<style>blocks.--space-*,--color-*,--font-size-*,--radius,--transition-fast).data-labelattributes for pseudo-element headers.min-width: 80pxfor summary cards and2pxpadding in mobile table cells -- minor).Nav integration -- CORRECT
class:active={currentPath === '/admin/commerce'}consistent with other nav items.$($) as icon -- consistent with how other nav items use HTML entities.API contract alignment
name,team_name,jersey_order_status,jersey_option,jersey_size,jersey_number,parent_name,parent_phone,subscription_status,contract_status,contract_signed_at-- all confirmed used in existingadmin/players/+page.svelteandadmin/players/[id]/+page.svelte.monthly_feeandcontract_signed_byare referenced in the commerce page but are NOT used anywhere else in the codebase. If the API does not return these fields, the page will display--(graceful fallback via|| '--'), so this is not a crash risk, but the columns may always show dashes.BLOCKERS
None.
NITS
DRY: Duplicate badge classes -- The PR adds
badge-shipped,badge-past-due, andbadge-canceledtoapp.css. The codebase already hasbadge-jersey-shipped(line 1384, identical styling tobadge-shipped) and could potentially reuse it. Consider whether to consolidate or keep them separate for semantic clarity. Not blocking since the naming is domain-specific ("commerce badges" vs "CRM jersey badges"), but worth noting.Unverified API fields --
monthly_feeandcontract_signed_byare not referenced in any other frontend code. Confirm the API actually returns these fields. If not, the Subscriptions "Monthly Fee" column and Contracts "Signed By" column will permanently show--.Error message placement -- The
{#if error}block is placed AFTER all tab content (line 338 in the new file). If the API call fails, the user sees an empty tab with an empty table, then the error message below. Consider moving the error display above the tab bar, or replacing the tab content entirely when error is set. This matches how other admin pages handle it -- but it is a minor UX concern shared across the codebase.Mobile nav density -- Adding Commerce brings the admin bottom nav to 6 items (Dashboard, CRM, Commerce, Teams, Schedule, Sign Out). The PR body says to test at 320px. The
bottom-navuses flexbox with nooverflow-xor wrapping, so very narrow screens may see cramped labels. Not blocking since the test plan explicitly covers 320px verification.Minor CSS hardcodes --
padding: 2px var(--space-sm)in the mobile table cell rule andmin-width: 80pxon.summary-statuse pixel values instead of CSS custom properties. Extremely minor.SOP COMPLIANCE
226-add-commerce-admin-pagefollows{issue-number}-{kebab-case-purpose}conventionstory:WS-S9andsop-capacitor-mobile-lifecyclePROCESS OBSERVATIONS
monthly_fee/contract_signed_byfields do not exist in the API response.VERDICT: APPROVED
Clean playground-to-production promotion. Svelte 5 runes usage is correct. CSS follows project conventions. API contract is mostly confirmed with two unverified fields that degrade gracefully. No blockers.