Commit graph

311 commits

Author SHA1 Message Date
b78ee7ca20 move routes to (app) route group 2025-11-30 22:28:17 -08:00
3498b7d966 add signup redirect to register 2025-11-30 22:28:13 -08:00
765a9b358a add auth page translations 2025-11-30 22:28:13 -08:00
93efc9946a add registration page with validation 2025-11-30 22:26:32 -08:00
fd10dcfb15 add login page with contained inputs 2025-11-30 22:26:32 -08:00
762d5c0fc0 add auth layout with centered container 2025-11-30 22:26:32 -08:00
06dd832ada add AuthCard component for auth pages 2025-11-30 22:26:25 -08:00
33fa9f9c9c reset fieldset border/padding/margin in Input component 2025-11-30 22:26:25 -08:00
d2cb4c5052 routes: update layout and teams page 2025-11-30 20:06:49 -08:00
af659b9760 components: update party and character components 2025-11-30 20:06:44 -08:00
c3ed9b2885 api: update entity adapter and queries 2025-11-30 20:06:40 -08:00
db5bfe9f7f sidebar: remove unused modification components 2025-11-30 20:06:36 -08:00
a858877545 sidebar: refactor details components 2025-11-30 20:06:31 -08:00
47885b1429 sidebar: wire up edit sidebars in openDetailsSidebar feature 2025-11-30 20:06:26 -08:00
8ac9dea2d3 sidebar: add EditCharacterSidebar and EditWeaponSidebar 2025-11-30 20:06:21 -08:00
4f132f9947 sidebar: add edit form components for character/weapon modifications 2025-11-30 20:06:15 -08:00
ad10d3fe73 stores: add partyStore for character/weapon updates 2025-11-30 20:06:09 -08:00
393bbdbcb0 sidebar: add MasteryRow component for rings/earring selects 2025-11-30 20:06:04 -08:00
5784b9638d sidebar: add DetailRow and DetailsSection components 2025-11-30 20:05:59 -08:00
c0dc3d0bc1 utils: update grid helpers and modification utilities 2025-11-30 20:05:54 -08:00
8bfa31d925 types: add NO_AWAKENING sentinel and update entity types 2025-11-30 20:05:50 -08:00
c1974c1d40 data: add ax skill definitions 2025-11-30 20:05:46 -08:00
f815ca4f30 ui: update Input, Select, Button, Sidebar components 2025-11-30 20:05:42 -08:00
5df563198b fix: render related characters 2025-11-30 14:57:43 -08:00
d5a22baa0a use Checkbox component in database edit pages with element theming 2025-11-30 13:59:45 -08:00
b8ad70229d fix database dropdown item rendering 2025-11-30 13:59:40 -08:00
3007aadbb0 sync pictureData with available profile images 2025-11-30 06:02:56 -08:00
7406f80edd use contained selects in settings modal 2025-11-30 06:02:56 -08:00
92e93309bf add typeahead component 2025-11-30 06:02:56 -08:00
66b03c9108 fix dropdown trigger props, add onClose alias to sidebar 2025-11-30 06:02:50 -08:00
fcc0a884f5 fix icon color inheritance, tweak select chevron 2025-11-30 06:02:50 -08:00
bc67d22c4b checkbox and switch theming with hover states 2025-11-30 06:02:50 -08:00
8a4bac542b update deps 2025-11-30 06:02:41 -08:00
bbec620d00 add storybook setup and initial stories 2025-11-30 06:02:41 -08:00
94fdcf1c6b docs: update CLAUDE.md 2025-11-30 02:32:15 -08:00
ef980b9084 chore: theme colors and svelte config tweaks 2025-11-30 02:32:11 -08:00
5e77bb3093 feat: add weapon series utility and i18n messages 2025-11-30 02:32:07 -08:00
8b078cdfd8 feat: add conflict dialog for duplicate characters/weapons 2025-11-30 02:32:03 -08:00
ff7199fbbb fix: add is-active state to weapon and summon units 2025-11-30 02:31:58 -08:00
2f0b67cb44 feat: add JobSection to /teams/new
- import JobSection and job selection handlers
- add context methods for slot selection glow
- render JobSection in character tab
2025-11-30 02:31:54 -08:00
d51fe03905 fix: character slot selection glow and empty protagonist
- character grid starts at position 1 (skip protagonist)
- add isEmptySelected state for glow on empty slots
- empty protagonist shows relief.png background only
2025-11-30 02:31:48 -08:00
18328e2d38 fix: party mutation parameter types
- favorite/unfavorite take shortcode string directly
- delete takes {id, shortcode} since API expects UUID
- remix takes shortcode string directly
- update spreads updates at top level
2025-11-30 02:31:42 -08:00
f346a73b61 fix: handle 204 No Content responses in base adapter 2025-11-30 02:31:37 -08:00
2275daec61 fix: PartySegmentedControl rep components now update reactively
The WeaponRep (and other rep components) weren't visually updating when
new items were added to the party. The issue was that Svelte's reactivity
wasn't properly propagating through the {#each} blocks.

Changes:
- PartySegmentedControl: Add derived values for party sub-properties to
  ensure reactivity propagates through snippet boundaries
- WeaponRep: Pre-compute rows as explicit $derived value and use keyed
  {#each} blocks for proper change detection

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-30 00:23:44 -08:00
f457343e26
Complete TanStack Query v6 migration (#445)
## Overview

Complete migration from service layer to TanStack Query v6 with
mutations, queries, and automatic cache management.

## What Was Completed

### Phase 1: Entity Queries & Database Pages 
- Created `entity.queries.ts` with query options for weapons,
characters, and summons
- Migrated all database detail pages to use TanStack Query with
`withInitialData()` pattern
- SSR with client-side hydration working correctly

### Phase 2: Server Load Cleanup 
- Removed PartyService dependency from teams detail server load
- Server loads now use adapters directly instead of service layer
- Cleaner separation of concerns

### Phase 3: Party.svelte Refactoring 
- Removed all PartyService, GridService, and ConflictService
dependencies
- Migrated to TanStack Query mutations for all operations:
  - Grid operations: create, update, delete, swap, move
  - Party operations: update, delete, remix, favorite, unfavorite
- Added swap/move mutations for drag-and-drop operations
- Automatic cache invalidation and query refetching

### Phase 4: Service Layer Removal 
- Deleted all service layer files (~1,345 lines removed):
  - `party.service.ts` (620 lines)
  - `grid.service.ts` (450 lines)
  - `conflict.service.ts` (120 lines)
  - `gridOperations.ts` (unused utility)
- Deleted empty `services/` directory
- Created utility functions for cross-cutting concerns:
  - `localId.ts`: Anonymous user local ID management
  - `editKeys.ts`: Edit key management for anonymous editing
  - `party-context.ts`: Extracted PartyContext type

### Phase 5: /teams/new Migration 
- Migrated party creation wizard to use TanStack Query mutations
- Replaced all direct adapter calls with mutations (7 locations)
- Maintains existing behavior and flow
- Automatic cache invalidation for newly created parties

## Benefits

### Performance
- Automatic request deduplication
- Better cache utilization across pages
- Background refetching for fresh data
- Optimistic updates for instant UI feedback

### Developer Experience
- Single source of truth for data fetching
- Consistent patterns across entire app
- Query devtools for debugging
- Less boilerplate code

### Code Quality
- ~1,088 net lines removed
- Simpler mental model (no service layer)
- Better TypeScript inference
- Easier to test

### Architecture
- **100% TanStack Query coverage** - no service layer, no direct adapter
calls
- Clear separation: UI ← Queries/Mutations ← Adapters ← API
- Automatic cache management
- Consistent mutation patterns everywhere

## Testing

All features verified:
- Party creation (anonymous & authenticated)
- Grid operations (add, remove, update, swap, move)
- Party operations (update, delete, remix, favorite)
- Cache invalidation across tabs
- Error handling and rollback
- SSR with hydration

## Files Modified

### Created (3)
- `src/lib/types/party-context.ts`
- `src/lib/utils/editKeys.ts`
- `src/lib/utils/localId.ts`

### Deleted (4)
- `src/lib/services/party.service.ts`
- `src/lib/services/grid.service.ts`
- `src/lib/services/conflict.service.ts`
- `src/lib/utils/gridOperations.ts`

### Modified (13)
- `src/lib/api/mutations/grid.mutations.ts`
- `src/lib/components/grids/CharacterGrid.svelte`
- `src/lib/components/grids/SummonGrid.svelte`
- `src/lib/components/grids/WeaponGrid.svelte`
- `src/lib/components/party/Party.svelte`
- `src/routes/teams/new/+page.svelte`
- Database entity pages (characters, weapons, summons)
- Other supporting files

## Migration Complete

This PR completes the TanStack Query migration. The entire application
now uses TanStack Query v6 for all data fetching and mutations, with
zero remaining service layer code.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-11-29 22:32:15 -08:00
c06c8135ed feat: add TanStack Query devtools for development
added @tanstack/svelte-query-devtools (dev only)
- shows in dev mode only, tree-shaken from production
- provides visual debugging of queries, cache, and mutations
- accessible via floating icon in bottom-right corner
2025-11-29 03:44:59 -08:00
6ad3b65f7f chore: remove unused resource pattern files (Phase 3)
removed ~27kb of completely unused code:
- search.resource.svelte.ts and test (custom query pattern)
- party.resource.svelte.ts (deprecated, unused)
- job.resource.svelte.ts (unused)
- CLEANUP_PLAN.md (outdated)

all functionality replaced by TanStack Query patterns in phases 1 & 2
2025-11-29 03:39:50 -08:00
149f30c538
Make parties more DRY (#444)
We extracted utility functions from the Party.svelte component in order
to make things more DRY.
2025-11-29 03:29:28 -08:00
devin-ai-integration[bot]
f9bb43f214
feat: migrate components to TanStack Query v6 (Phase 2) (#442)
# feat: migrate components to TanStack Query v6 (Phase 2)

## Summary

This PR migrates 4 components from the custom
`createInfiniteScrollResource` pattern to TanStack Query v6's
`createInfiniteQuery`:

- **JobSkillSelectionSidebar** - Job skill search with infinite scroll
and category filtering
- **SearchContent** - Search modal for weapons/characters/summons with
element/rarity/proficiency filters
- **User Profile Page** (`[username]/+page.svelte`) - User's teams and
favorites with tab switching
- **Teams Explore Page** (`teams/explore/+page.svelte`) - Public teams
listing

All components now use:
- TanStack Query v6 infinite query pattern with thunk for reactivity
- `IsInViewport` from runed for intersection-based infinite scroll
- Debounced search (debounce the value, not the query)
- Proper loading, error, and empty states
- SSR integration with `initialData` pattern

## Updates since last revision

- **Fixed duplicate key error in SearchContent.svelte** - The API can
return the same item across multiple pages during infinite scroll (e.g.,
due to items being added/removed between page fetches). This caused
Svelte's keyed each block to throw `each_key_duplicate` errors. Fixed by
deduplicating results by `id` using a Map before rendering.

## Review & Testing Checklist for Human

This is a medium-risk change affecting core user-facing pages. Please
verify:

- [ ] **Infinite scroll works on all 4 pages** - Scroll to bottom and
verify more items load automatically
- [ ] **No duplicate items appear in search results** - After the fix,
scrolling through many pages of search results should not show
duplicates
- [ ] **SSR hydration** - Verify no flash of loading state on initial
page load (data should be pre-rendered)
- [ ] **User profile tab switching** - Test switching between "Teams"
and "Favorites" tabs; verify correct data loads
- [ ] **Search debouncing** - Type quickly in JobSkillSelectionSidebar
and SearchContent; verify queries aren't fired on every keystroke
- [ ] **Error states** - Simulate network failure and verify retry
button works

**Recommended Test Plan:**
1. Navigate to `/teams/explore` - verify teams load and infinite scroll
works
2. Navigate to a user profile page - verify teams load, switch to
favorites tab, verify favorites load
3. Open the search sidebar - search for weapons/characters/summons,
scroll through many pages, verify no duplicate key errors and no
duplicate items
4. Open job skill selection - search and filter skills, verify results

### Notes

- The Party component mutations migration (Follow-Up Prompt 5) was
deferred to a follow-up PR due to complexity
- Deprecated resource classes remain in codebase for now; removal
planned for separate PR
- Pre-existing paraglide module errors in build are unrelated to this PR
- Type assertions (`as unknown as`, `as any`) are used to handle
different query result structures between favorites and parties queries

**Link to Devin run:**
https://app.devin.ai/sessions/5aa7ea29edf34f569f95f13acee9e0d9
**Requested by:** Justin Edmund (justin@jedmund.com) / @jedmund

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Justin Edmund <justin@jedmund.com>
2025-11-29 01:11:24 -08:00
devin-ai-integration[bot]
5764161803
feat: add TanStack Query v6 integration with SSR support (#441)
## Summary

This PR establishes the foundation for migrating from custom Svelte 5
resource classes to TanStack Query v6 for server state management. It
adds:

**Query Options Factories** (in `src/lib/api/queries/`):
- `party.queries.ts` - Party fetching with infinite scroll support
- `job.queries.ts` - Job and skill queries with pagination
- `user.queries.ts` - User profile, parties, and favorites queries

**Mutation Configurations** (in `src/lib/api/mutations/`):
- `party.mutations.ts` - Party CRUD with cache invalidation
- `grid.mutations.ts` - Weapon/character/summon mutations with
optimistic updates
- `job.mutations.ts` - Job and skill update mutations

**Deprecation Notices**:
- Added `@deprecated` JSDoc to `search.resource.svelte.ts` and
`party.resource.svelte.ts` with migration examples

**SSR Integration** (Phase 4):
- Created `+layout.ts` to initialize QueryClient for SSR support
- Updated `+layout.svelte` to receive QueryClient from load function
- Added SSR utilities in `src/lib/query/ssr.ts`:
  - `withInitialData()` - for pages using +page.server.ts
- `prefetchQuery()` / `prefetchInfiniteQuery()` - for pages using
+page.ts
  - `setQueryData()` - for direct cache population
- Added documentation in `src/lib/query/README.md`

**Component Wiring Examples** (Phase 5):
- `JobSelectionSidebar.svelte` - Migrated from `createJobResource()` to
`createQuery(() => jobQueries.list())`. Demonstrates client-side query
pattern with automatic loading/error states.
- `teams/[id]/+page.svelte` - Added `withInitialData()` pattern for SSR
integration. Server-fetched party data is used as initial cache value
with background refetching support.

**Migration Guide**:
- Added `src/lib/query/MIGRATION.md` with follow-up prompts for
remaining component migrations (JobSkillSelectionSidebar, search modal,
user profile, teams explore, Party mutations, resource class removal)

## Updates Since Last Revision

Fixed TypeScript type errors in the TanStack Query integration:
- `party.queries.ts`: Made `total` and `perPage` optional in
`PartyPageResult` interface to match adapter return type
- `ssr.ts`: Fixed `withInitialData` to properly handle null values using
`NonNullable<TData>` return type
- `job.mutations.ts`: Fixed slot indexing by casting through `unknown`
to `keyof typeof updatedSkills`

Type checks now pass for all files modified in this PR (16 remaining
errors are pre-existing project issues unrelated to this PR - paraglide
modules not generated, hooks.ts implicit anys).

## Review & Testing Checklist for Human

- [ ] **Verify app loads correctly**: The `+layout.ts` and
`+layout.svelte` changes are critical path - confirm the app still
renders
- [ ] **Test JobSelectionSidebar**: Open job selection sidebar and
verify jobs load correctly, search/filter works, and retry button works
on error
- [ ] **Test teams/[id] page**: Navigate to a party detail page and
verify it renders without loading flash (SSR data should be immediate)
- [ ] **Review type casts**: Check `job.mutations.ts:135` - the `as
unknown as keyof typeof` cast for slot indexing is a workaround for
jobSkills having string literal keys ('0', '1', '2', '3') while slot is
a number
- [ ] **Verify withInitialData behavior**: The `NonNullable<TData>`
return type change in `ssr.ts` should work correctly with `data.party`
which can be `Party | null`

**Recommended test plan**: 
1. Run `pnpm install` to ensure dependencies are up to date
2. Start dev server and verify the app loads without errors
3. Navigate to a party detail page (`/teams/[shortcode]`) - should
render immediately without loading state
4. Open job selection sidebar (click job icon on a party you can edit) -
verify jobs load and filtering works
5. Test error handling by temporarily breaking network - verify retry
button appears

### Notes


- Pre-existing project issues remain (paraglide modules not generated,
hooks.ts implicit anys) - these are unrelated to this PR
- Local testing could not run due to missing node_modules (vite not
found) - project setup issue
- TanStack Query devtools installation was skipped due to Storybook
version conflicts
- The existing `search.queries.ts` file was used as the pattern
reference for new query factories
- SSR approach uses hybrid pattern: existing `+page.server.ts` files
work with `withInitialData()`, while new pages can use `prefetchQuery()`
in `+page.ts`
- Migration guide includes 6 follow-up prompts for completing the
remaining component migrations

**Link to Devin run**:
https://app.devin.ai/sessions/33e97a98ae3e415aa4dc35378cad3a2b
**Requested by**: Justin Edmund (justin@jedmund.com) / @jedmund

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Justin Edmund <justin@jedmund.com>
2025-11-29 00:36:59 -08:00