Skip to content

Feature Screens

Stadium (src/pages/Stadium.tsx)

The main landing screen after sign-in. Shows a grid of FIFA 2026 matches.

  • Stores read: useFlagsStore (feature gates), useAuthStore (user identity).
  • API calls: api.getMatches(), api.getInstruments() (for live price data).
  • User interactions: Select a match card → navigate to /squad?match=<id>&side=<home|away>. The match ID and side are encoded in the URL so /squad survives a page refresh.
  • The match state (pre-match, live, FT) and trade window countdown are derived from getTradeWindow() in ftl-frontend/src/lib/tradeWindow.ts.

Squad (src/pages/Squad.tsx)

Player roster for one side of a match. Shows PlayerCard flip cards with stats.

  • Stores read: useTutorialStore (swaps real roster for sandbox squad during the tour), usePriceStore (live prices per card).
  • API calls: api.getSquad(matchId, team), api.getMatchEvents(matchId) (for live event feed).
  • User interactions:
  • Click player card → open CardFlipModal (stats + chart link + trade button).
  • Click trade button on card → open BookPositionModal with direction='long'.
  • The trade window gate (getTradeWindow) blocks opening positions outside the allowed window. During the tutorial, this gate is bypassed.
  • URL params ?match=<id>&side=<home|away> are read as a refresh-recovery path when selectedMatch state is absent.

YourTeam (src/pages/YourTeam.tsx)

Shows the user's open CFD positions with live unrealized P&L.

  • Stores read: useAuthStore (cfdPositions, equity, freeMargin, marginLevel, tradesEpoch), usePriceStore (live prices for P&L recompute), useTutorialStore (sandbox positions during tour).
  • API calls: api.listPositions({ status: 'open' }) on mount and on tradesEpoch change. api.getTrades() for transaction history via TransactionHistory component.
  • User interactions:
  • Click close on a position row → open BookPositionModal with direction='short' (pre-filled with the position's instrument).
  • TransactionHistory component shows closed trade history with pagination.

Trade (src/pages/Trade.tsx)

Price chart and CFD order entry for a single instrument.

  • Components: PriceChart.tsx (canvas-based OHLC chart), CFDTradeForm.tsx (long/short order form), period tabs ('5m' | '6h' | '1d' | 'all').
  • Stores read: usePriceStore (live price), useAuthStore (freeMargin, marginHydrated).
  • API calls: api.getPriceHistory(id, period), api.getInstrument(id), api.getRecentTrades(id).
  • User interactions: Switch period tab → refetch price history. Submit trade form → api.openPosition() or api.closePosition().
  • The instrument ID is read from the ?instrument= query parameter on mount. Navigating to /trade?instrument=<id> from CardFlipModal or Squad opens this page for that player.

Ranks (src/pages/Ranks.tsx)

Leaderboard with three tabs: global, district, friends.

  • Stores read: useAuthStore (user.districtId, user.id).
  • API calls: api.getROIGlobal(), api.getROIDistrict(districtId), api.getROIFriends(), api.getDistrictStandings(), api.getSpinnerCurrent(), api.getSpinnerHistory(), api.getRankContext().
  • ROI scoring: score = ROI% × 100. Tiebreakers in order: total P&L, win-trade count, balance.
  • A "Matchups" tab shows district vs. district aggregate standings from api.getDistrictStandings().
  • The weekly spinner widget shows the current week's winner or tied candidates.

Profile (src/pages/Profile.tsx)

User profile with XP, badges, referral link, and tutorial replay.

  • Stores read: useAuthStore (user, xp, level, referralCode), useTutorialStore (for replay trigger).
  • API calls: api.getAchievements(), api.getMyRank().
  • User interactions:
  • Copy referral link → calls api.validateReferral() and constructs the share URL.
  • Invite button → navigates to /invite.
  • Replay tutorial → calls useTutorialStore.getState().start(), which sets the ftl-tutorial-active sessionStorage flag and resets all tutorial state.

Admin (src/pages/Admin.tsx)

Admin-only panel. Accessible only to users with role === 'admin'.

  • API calls:
  • Feature flags: api.adminListFlags(), api.adminSetFlag(key, enabled).
  • Settings: api.adminListSettings(), api.adminSetSetting(key, value), api.adminScoringMultiplierKeys().
  • Users: api.adminListUsers(), api.adminUsersExportUrl() (direct CSV download link).
  • Bot: api.adminGameplayBotFixtures(), api.adminGameplayBotStatus(), api.adminGameplayBotStart(fixture, speedSec), api.adminGameplayBotStop().
  • User interactions:
  • Toggle a feature flag → adminSetFlag() → flag change takes effect for all users at the next flag refresh (up to 5 min, or instantly on tab focus).
  • Edit a setting value → adminSetSetting().
  • Download users CSV → navigate to the export URL returned by adminUsersExportUrl().
  • Start / stop gameplay bot → used during development to simulate a live match.