add api layer for phantom claim accept/decline

- declinePhantomClaim and getPendingPhantomClaims adapter methods
- useDeclinePhantomClaim mutation
- pendingPhantomClaims query
- crew field on PhantomPlayer type
This commit is contained in:
Justin Edmund 2025-12-17 18:29:33 -08:00
parent 4a9fc0de3c
commit ef95a294b3
4 changed files with 62 additions and 0 deletions

View file

@ -292,6 +292,33 @@ export class CrewAdapter extends BaseAdapter {
this.clearCache('/crew/members')
return response.phantom_player
}
/**
* Decline claim of a phantom player (by the assigned user)
*/
async declinePhantomClaim(crewId: string, phantomId: string, options?: RequestOptions): Promise<PhantomPlayer> {
const response = await this.request<{ phantom_player: PhantomPlayer }>(
`/crews/${crewId}/phantom_players/${phantomId}/decline_claim`,
{
...options,
method: 'POST'
}
)
this.clearCache('/crew/members')
this.clearCache('/pending_phantom_claims')
return response.phantom_player
}
/**
* Get pending phantom claims for current user (phantoms assigned but not yet confirmed)
*/
async getPendingPhantomClaims(options?: RequestOptions): Promise<PhantomPlayer[]> {
const response = await this.request<{ phantom_claims: PhantomPlayer[] }>(
'/pending_phantom_claims',
options
)
return response.phantom_claims
}
}
export const crewAdapter = new CrewAdapter(DEFAULT_ADAPTER_CONFIG)

View file

@ -268,6 +268,23 @@ export function useConfirmPhantomClaim() {
crewAdapter.confirmPhantomClaim(crewId, phantomId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: crewKeys.membersAll() })
queryClient.invalidateQueries({ queryKey: crewKeys.phantomClaims.pending() })
}
}))
}
/**
* Decline phantom claim mutation
*/
export function useDeclinePhantomClaim() {
const queryClient = useQueryClient()
return createMutation(() => ({
mutationFn: ({ crewId, phantomId }: { crewId: string; phantomId: string }) =>
crewAdapter.declinePhantomClaim(crewId, phantomId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: crewKeys.membersAll() })
queryClient.invalidateQueries({ queryKey: crewKeys.phantomClaims.pending() })
}
}))
}

View file

@ -84,6 +84,18 @@ export const crewQueries = {
queryFn: () => crewAdapter.getPendingInvitations(),
staleTime: 1000 * 60 * 2, // 2 minutes
gcTime: 1000 * 60 * 15 // 15 minutes
}),
/**
* Current user's pending phantom claims query options
* Returns phantoms assigned to the user that need to be accepted or declined
*/
pendingPhantomClaims: () =>
queryOptions({
queryKey: ['phantom_claims', 'pending'] as const,
queryFn: () => crewAdapter.getPendingPhantomClaims(),
staleTime: 1000 * 60 * 2, // 2 minutes
gcTime: 1000 * 60 * 15 // 15 minutes
})
}
@ -113,5 +125,9 @@ export const crewKeys = {
invitations: {
all: ['invitations'] as const,
pending: () => ['invitations', 'pending'] as const
},
phantomClaims: {
all: ['phantom_claims'] as const,
pending: () => ['phantom_claims', 'pending'] as const
}
}

View file

@ -65,6 +65,8 @@ export interface PhantomPlayer {
// From :with_scores view
totalScore?: number
scoreCount?: number
// From :with_crew view
crew?: CrewMinimal
}
// CrewInvitation from CrewInvitationBlueprint