Files
Gabriel Kaszewski 4683a408d7
All checks were successful
CI / Check / Test (push) Successful in 38m33s
fix(spa): use import type for UpdateUserSettingsRequest
2026-06-12 02:29:50 +02:00
..
2026-06-04 15:58:03 +02:00

Movies Diary — SPA

Mobile-first single page application for Movies Diary, served at /app/.

Stack

  • React 19 + TypeScript
  • TanStack Router — file-based routing
  • TanStack Query — data fetching, caching, mutations
  • Tailwind CSS v4 + shadcn/ui — styling and components
  • Vaul — mobile drawers
  • date-fns — date formatting
  • i18next — internationalization
  • Zod — API response validation

Routes

Path Page
/login Login
/register Registration
/ Home — Feed / Watchlist / Queue tabs
/diary Diary with month navigation + CSV export
/search Search movies and people
/profile Own profile with trends
/social Following / Followers / Pending
/movies/:id Movie detail — cast, crew, stats, reviews
/people/:id Person detail — filmography
/users/:id Other user's profile
/wrapup/:id Year in Review report
/settings/ Settings hub
/settings/edit-profile Edit display name, bio, avatar, banner
/settings/import CSV/JSON/XLSX import wizard
/settings/webhooks Jellyfin/Plex webhook tokens
/settings/wrapup Generate/manage year wrap-ups
/settings/blocked Blocked users and domains (admin)

Development

npm install
npm run dev

The SPA expects the backend API at the URL defined by VITE_API_URL (defaults to empty string = same origin).

Create spa/.env for local development:

VITE_API_URL=http://localhost:3000

Build

npm run build

Output goes to dist/, served by the backend at /app/.

Project Structure

src/
├── components/        # Reusable UI components
│   ├── ui/           # shadcn/ui primitives
│   ├── back-button   # History-aware back navigation
│   ├── movie-card    # Movie display (compact/full)
│   ├── review-card   # Review with user, rating, date
│   ├── person-row    # Person search result
│   ├── log-sheet     # Log review drawer
│   ├── star-rating   # Interactive star input (with haptics)
│   ├── swipe-to-delete
│   └── ...
├── hooks/             # TanStack Query hooks
│   ├── use-diary      # Feed, diary, log/delete review
│   ├── use-movies     # Movie detail, profile, history
│   ├── use-search     # Search with infinite scroll
│   ├── use-social     # Follow/unfollow, block
│   ├── use-users      # User profiles, admin reindex
│   ├── use-watchlist   # Watchlist CRUD
│   ├── use-webhooks   # Webhook tokens, watch queue
│   └── use-wrapup     # Wrap-up generation/reports
├── lib/
│   ├── api/           # Typed API client (get/post/put/del)
│   ├── auth.ts        # Token storage
│   ├── date.ts        # timeAgo, shortDate formatters
│   ├── haptics.ts     # Vibration feedback
│   └── query-client.ts # QueryClient with error toasts
├── locales/           # i18n translations
└── routes/            # File-based TanStack Router pages

Features

  • Federation-aware — globe badge on federated reviews, @user@instance handles
  • Admin tools — search reindex, user picker for wrap-ups, domain blocking
  • Offline-friendly — stale-while-revalidate caching, retry on 5xx
  • Mobile UX — swipe-to-delete, haptic feedback, iOS keyboard-safe drawers
  • Interactivity — clickable cast/crew → people pages, movie highlights → detail