Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffd3aabc55 | ||
|
|
8cac57ed67 | ||
|
|
d4fae890bb |
No files matched your search
Binary file not shown.
@@ -30,7 +30,7 @@ export async function DELETE(
|
||||
const { userId } = await auth();
|
||||
|
||||
if (!userId) {
|
||||
return new NextResponse("Unauthorized", { status: 401 });
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
// Ensure user is synced
|
||||
@@ -60,9 +60,10 @@ export async function DELETE(
|
||||
|
||||
// Only superAdmin can delete gyms
|
||||
if (!currentUser || currentUser.role !== "superAdmin") {
|
||||
return new NextResponse("Forbidden - Only superAdmin can delete gyms", {
|
||||
status: 403,
|
||||
});
|
||||
return NextResponse.json(
|
||||
{ error: "Forbidden - Only superAdmin can delete gyms" },
|
||||
{ status: 403 },
|
||||
);
|
||||
}
|
||||
|
||||
await ensureGymsTable();
|
||||
@@ -70,7 +71,7 @@ export async function DELETE(
|
||||
// Check if gym exists
|
||||
const gymRows = await db.all(sql`SELECT * FROM gyms WHERE id = ${gymId}`);
|
||||
if (gymRows.length === 0) {
|
||||
return new NextResponse("Gym not found", { status: 404 });
|
||||
return NextResponse.json({ error: "Gym not found" }, { status: 404 });
|
||||
}
|
||||
|
||||
// Soft delete - mark as inactive
|
||||
@@ -84,6 +85,9 @@ export async function DELETE(
|
||||
});
|
||||
} catch (error) {
|
||||
log.error("Failed to delete gym", error);
|
||||
return new NextResponse("Internal Server Error", { status: 500 });
|
||||
return NextResponse.json(
|
||||
{ error: "Internal Server Error" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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<string, any> = {
|
||||
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
|
||||
|
||||
@@ -199,14 +199,20 @@ export default function SettingsPage() {
|
||||
setDeletingGym(true);
|
||||
setGymMessage(null);
|
||||
try {
|
||||
await axios.delete(`/api/gyms/${gymId}`);
|
||||
const response = await axios.delete(`/api/gyms/${gymId}`);
|
||||
log.info("Delete gym response:", response.data);
|
||||
setGymMessage({ type: "success", text: "Gym deleted successfully" });
|
||||
setSelectedGym(null);
|
||||
setGymStats(null);
|
||||
fetchGyms();
|
||||
} catch (error) {
|
||||
await fetchGyms();
|
||||
} catch (error: any) {
|
||||
log.error("Failed to delete gym", error);
|
||||
setGymMessage({ type: "error", text: "Failed to delete gym" });
|
||||
const errorMessage =
|
||||
error.response?.data?.error ||
|
||||
error.response?.data ||
|
||||
error.message ||
|
||||
"Failed to delete gym";
|
||||
setGymMessage({ type: "error", text: errorMessage });
|
||||
} finally {
|
||||
setDeletingGym(false);
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user