lobo bad11807e0 test: component tests with jsdom and Testing Library
First tests cover the library search debounce (fails on the old looping
version), the Pile of Shame states and the backlog save body. jsdom is
enabled per test file, so the plain util tests stay in the node environment.
2026-09-24 12:06:34 +02:00
2026-03-21 10:47:53 +01:00

To Be Played - Frontend

A modern web application to manage your game backlog, built with React and Vite.

🚀 Tech Stack

📂 Project Structure

├── public/          # Static assets (favicons, icons)
├── src/
│   ├── assets/      # Images and global media
│   ├── components/  # Reusable React components
│   ├── App.jsx      # Main application layout and entry component
│   ├── main.jsx     # App initialization (React DOM, Styles)
│   └── style.css    # Global Tailwind and custom CSS
├── index.html       # Entry HTML file
├── package.json     # Dependencies and scripts
└── vite.config.js   # Vite configuration

🛠️ Development

Setup

npm install

Start Development Server

npm run dev

Build for Production

npm run build

🗺️ Roadmap / Open Topics

Tracking known work that is not yet implemented. Each item is independently actionable.

Security

  • Move JWT out of localStorage. Today the token is stored under localStorage["tbp_jwt"], which makes it readable by any script running on the page — a single XSS in an npm dependency exfiltrates every session. Switch to an httpOnly Secure SameSite=Lax cookie set by tbp-auth-service on login. The SPA no longer touches the token directly; the browser attaches it automatically to requests to *.tbp.andreas-dahm.eu. Requires coordinated changes in Auth (set the cookie) and Deployment (cookie domain + CORS allowCredentials=true).
  • Add CSRF handling. Once auth rides on a cookie, the SPA must echo a CSRF token in a header on state-changing requests. Spring Security's CookieCsrfTokenRepository.withHttpOnlyFalse() on the server pairs with a small fetch interceptor on the client that reads XSRF-TOKEN and sets X-XSRF-TOKEN.
  • Content Security Policy. Add a CSP header in nginx.conf so XSS exfiltration paths are blocked even if a vulnerability slips in. Minimum starting point: default-src 'self'; img-src 'self' data: https://*.steamstatic.com; object-src 'none'; base-uri 'self'; frame-ancestors 'none'. Tighten further by replacing inline styles/scripts (Tailwind is already build-time, so this should be feasible).

Testing

The project has no test runner today. Suggested setup:

  • Unit / component tests: Vitest + React Testing Library. Tests live next to the component (Component.test.jsx).
  • API mocking: MSW (Mock Service Worker) so component tests don't hit the real backend and the same handlers can drive Storybook later.
  • End-to-end tests: Playwright, scoped to the golden paths (login → see library → log out, registration with invitation code, settings update). Run against the real tbp-auth-service + tbp-core-service via docker-compose.dev.yml in CI.
  • First test targets: the auth context / token-handling code, the dark-mode toggle (localStorage["tbp_dark_mode"]), and i18n string resolution.

Other

  • Audit localStorage usage. Currently used for tbp_jwt (planned to move) and tbp_dark_mode. Document any other keys before they accumulate.
  • API base URL handling. VITE_API_URL covers Auth; Core's base URL is implicit. Make both explicit (e.g. VITE_AUTH_URL, VITE_API_URL) so dev / prod / preview environments are unambiguous.

🎯 Product Roadmap (Frontend-owned slices)

The full cross-service product roadmap lives in ToBePlayed-Deployment/README.md. This section lists only the UI / UX slices that land in the Frontend.

1. Backlog tracking UI

Today GameLibrary.jsx is a paginated grid of synced Steam games — there is no per-game state. Once Core exposes status + notes + rating, the Frontend needs:

  • Status chips on each game card (BACKLOG / PLAYING / COMPLETED / DROPPED / ON_HOLD / WISHLIST) with one-click cycling or a popover for explicit selection.
  • Status filter bar above the grid; multi-select; persisted to URL search params so links are shareable and back-button works.
  • Game detail page (GameDetail.jsx exists — extend it) with rating widget (stars or 1–10), completion date picker, markdown notes editor with preview. Optimistic update on save, server reconciliation on failure.
  • Drag-to-reorder within BACKLOG for priority. Use a small library (@dnd-kit/core) — well-maintained, accessible.

2. "What to play next" page

  • New route: /play-next (or surface from Dashboard).
  • Form: time budget radio (15 min / 1 h / weekend), mood tag multi-select.
  • On submit: call Core's picker endpoint, render 3 cards. "Reroll" button calls again.
  • One-tap "Start playing" sets game status to PLAYING.

This page is the single best mobile entry point — design mobile-first.

3. Achievement views

Data is already in Core. The Frontend needs:

  • Achievement progress ring on each game card + game detail.
  • New route /achievements showing library-wide unlocked / total / percent.
  • "Closest to 100%" widget on Dashboard.

4. Public profile + sharing

  • New route /u/:username rendered server-friendly (consider SSR / pre-render for SEO, or at least set proper <title> / <meta> via react-router loaders so link previews work).
  • "Currently playing" + "Recently completed" sections.
  • "Share my profile" button (copies URL).
  • Settings toggle for profile_public.

5. Friends + compare

  • /friends page: list, request, accept, remove.
  • "Add friend" search by username (autocomplete against Auth endpoint).
  • "Compare backlogs with X" page: lists games both own, intersected with BACKLOG status on either side — i.e. "next co-op night candidates".

6. Mobile / PWA

  • Verify the SPA is installable as a PWA: manifest, icons (already in public/?), service worker via vite-plugin-pwa.
  • Test core flows (login, picker, status update) on a real phone, not just devtools. The "what to play tonight" use case is mobile-primary.

7. UX details that compound

  • Search: client-side fuzzy search across library (Fuse.js or similar) on the already-loaded page; server-side search if the library gets large enough that pagination hurts.
  • Empty states: every list should have an empty state with a clear next action ("Connect Steam to import games", "No completed games yet — mark one!").
  • Optimistic updates for any status / rating / notes change — they should feel instant.
  • Keyboard shortcuts for power users (j/k to navigate, s to set status, ? to show shortcut list).
  • i18n is already wired (i18next); make sure every new string lands in the translation files, not hardcoded.
S
Description
Frontend für mein ToBePlayed Projekt
Readme
6.5 MiB
0 Stars 3 Watchers 0 Forks
Languages
JavaScript 96.7%
CSS 3.2%