diff --git a/apps/admin/data/fitai.db b/apps/admin/data/fitai.db index 0b7bdbb..031e880 100644 Binary files a/apps/admin/data/fitai.db and b/apps/admin/data/fitai.db differ diff --git a/apps/admin/src/app/api/invitations/route.ts b/apps/admin/src/app/api/invitations/route.ts index 5c25689..f475aca 100644 --- a/apps/admin/src/app/api/invitations/route.ts +++ b/apps/admin/src/app/api/invitations/route.ts @@ -54,13 +54,13 @@ export async function GET(request: NextRequest) { // Gym filter: SuperAdmin can see all, others only their gym if (role === "superAdmin") { // If gymId param provided, filter by it - if (targetGymId && metadata?.gymId !== targetGymId) { + if (targetGymId && (metadata?.gymId ?? null) !== targetGymId) { return false; } return true; } else { - // Non-superAdmins: must match their gym - return metadata?.gymId === userGymId; + // Non-superAdmins: must match their gym (normalize null/undefined) + return (metadata?.gymId ?? null) === (userGymId ?? null); } }) .map((inv) => ({ @@ -214,9 +214,9 @@ export async function POST(req: Request) { const invitation = await client.invitations.createInvitation({ emailAddress: inviteeEmail, publicMetadata: { - roleAssigned, + role: roleAssigned, gymId: gymIdForInvite, - inviterUserId: inviter.id, + createdBy: inviter.id, }, }); diff --git a/apps/admin/src/app/api/users/create/route.ts b/apps/admin/src/app/api/users/create/route.ts index 4319126..029b8d6 100644 --- a/apps/admin/src/app/api/users/create/route.ts +++ b/apps/admin/src/app/api/users/create/route.ts @@ -85,14 +85,12 @@ export async function POST(request: NextRequest) { try { const client = await clerkClient(); - // Build publicMetadata - only include gymId if it exists + // Build publicMetadata with consistent field names const publicMetadata: Record = { role: data.role, createdBy: userId, + gymId: assignedGymId ?? null, }; - if (assignedGymId) { - publicMetadata.gymId = assignedGymId; - } // Determine redirect URL based on role // Staff (admin, trainer, superAdmin) → Admin web app diff --git a/apps/admin/src/components/users/CreateUserModal.tsx b/apps/admin/src/components/users/CreateUserModal.tsx index 53f961c..25e0851 100644 --- a/apps/admin/src/components/users/CreateUserModal.tsx +++ b/apps/admin/src/components/users/CreateUserModal.tsx @@ -174,6 +174,10 @@ export function CreateUserModal({ // Reset form resetModal(); + + // Add delay to allow Clerk API to propagate invitation + await new Promise((resolve) => setTimeout(resolve, 1000)); + onSuccess(); onOpenChange(false); } catch (error) { diff --git a/apps/admin/src/hooks/use-api.ts b/apps/admin/src/hooks/use-api.ts index 39d1397..7073f91 100644 --- a/apps/admin/src/hooks/use-api.ts +++ b/apps/admin/src/hooks/use-api.ts @@ -365,6 +365,21 @@ export function useInvitations(gymId?: string) { (res) => res.data?.invitations ?? [], ); }, + refetchInterval: (query) => { + const data = query.state.data; + const hasData = data && data.length > 0; + const fetchCount = query.state.dataUpdateCount; + + // Poll every 2 seconds if: + // 1. No invitations returned yet + // 2. Haven't exceeded 5 attempts (10 seconds total) + if (!hasData && fetchCount < 5) { + return 2000; + } + + // Stop polling after 10 seconds or when data is present + return false; + }, }); }