diff --git a/src/lib/api/mutations/grid.mutations.ts b/src/lib/api/mutations/grid.mutations.ts index 70ca02cf..945fbab7 100644 --- a/src/lib/api/mutations/grid.mutations.ts +++ b/src/lib/api/mutations/grid.mutations.ts @@ -19,6 +19,36 @@ import { } from '$lib/api/adapters/grid.adapter' import { partyKeys } from '$lib/api/queries/party.queries' import type { Party, GridWeapon, GridCharacter, GridSummon } from '$lib/types/api/party' +import { getEditKey } from '$lib/utils/editKeys' + +// ============================================================================ +// Mutation Factory +// ============================================================================ + +/** + * Wraps a grid adapter method to automatically inject edit key headers for anonymous users. + * When a party has an edit key stored in localStorage, it's automatically sent in the X-Edit-Key header. + * + * For anonymous users: + * - Edit key is retrieved from localStorage using party shortcode + * - X-Edit-Key header is automatically injected + * + * For authenticated users: + * - No edit key in localStorage + * - Falls back to Bearer token (existing behavior) + * + * @param adapterMethod - The grid adapter method to wrap + * @returns Wrapped method that automatically handles edit key injection + */ +function createGridMutation( + adapterMethod: (params: TParams, headers?: Record) => Promise +) { + return (params: TParams) => { + const editKey = typeof params.partyId === 'string' ? getEditKey(params.partyId) : null + const headers = editKey ? { 'X-Edit-Key': editKey } : undefined + return adapterMethod(params, headers) + } +} // ============================================================================ // Weapon Mutations @@ -50,7 +80,9 @@ export function useCreateGridWeapon() { const queryClient = useQueryClient() return createMutation(() => ({ - mutationFn: (params: CreateGridWeaponParams) => gridAdapter.createWeapon(params), + mutationFn: createGridMutation((params: CreateGridWeaponParams, headers?: Record) => + gridAdapter.createWeapon(params, headers) + ), onSuccess: (_data, params) => { // Invalidate the party to refetch with new weapon queryClient.invalidateQueries({ queryKey: partyKeys.detail(params.partyId) }) @@ -245,7 +277,9 @@ export function useCreateGridCharacter() { const queryClient = useQueryClient() return createMutation(() => ({ - mutationFn: (params: CreateGridCharacterParams) => gridAdapter.createCharacter(params), + mutationFn: createGridMutation((params: CreateGridCharacterParams, headers?: Record) => + gridAdapter.createCharacter(params, headers) + ), onSuccess: (_data, params) => { queryClient.invalidateQueries({ queryKey: partyKeys.detail(params.partyId) }) } @@ -422,7 +456,9 @@ export function useCreateGridSummon() { const queryClient = useQueryClient() return createMutation(() => ({ - mutationFn: (params: CreateGridSummonParams) => gridAdapter.createSummon(params), + mutationFn: createGridMutation((params: CreateGridSummonParams, headers?: Record) => + gridAdapter.createSummon(params, headers) + ), onSuccess: (_data, params) => { queryClient.invalidateQueries({ queryKey: partyKeys.detail(params.partyId) }) } diff --git a/src/routes/teams/new/+page.svelte b/src/routes/teams/new/+page.svelte index 806d5993..f9fd7455 100644 --- a/src/routes/teams/new/+page.svelte +++ b/src/routes/teams/new/+page.svelte @@ -11,6 +11,7 @@ import type { SearchResult } from '$lib/api/adapters' import { partyAdapter, gridAdapter } from '$lib/api/adapters' import { getLocalId } from '$lib/utils/localId' + import { storeEditKey } from '$lib/utils/editKeys' // TanStack Query mutations import { useCreateParty } from '$lib/api/mutations/party.mutations' @@ -136,6 +137,14 @@ partyId = createdParty.id shortcode = createdParty.shortcode + // Store edit key for anonymous editing under BOTH identifiers + // - shortcode: for Party.svelte which uses shortcode as partyId + // - UUID: for /teams/new which uses UUID as partyId + if (createdParty.editKey) { + storeEditKey(createdParty.shortcode, createdParty.editKey) + storeEditKey(createdParty.id, createdParty.editKey) + } + if (!partyId || !shortcode) { throw new Error('Party creation did not return ID or shortcode') }