invitation flow basis

This commit is contained in:
dimitar committed 2026-03-18 23:08:55 +01:00
1 parent b1f01208fa
commit 0817e8e72b
8 files changed
+507 -26

No files matched your search

+55 -5
View File
@@ -61,6 +61,21 @@ export interface AttendanceRecord {
type?: string;
}
export interface Invitation {
id: string;
emailAddress: string;
publicMetadata: {
role?: string;
gymId?: string;
createdBy?: string;
} | null;
status: "pending" | "accepted" | "revoked" | "expired";
url?: string;
createdAt: number;
updatedAt: number;
revoked?: boolean;
}
async function fetchApi<T>(url: string, options?: RequestInit): Promise<T> {
const response = await fetch(url, {
...options,
@@ -339,13 +354,17 @@ export function useCheckOut() {
});
}
export function useInvitations() {
export function useInvitations(gymId?: string) {
return useQuery({
queryKey: ["invitations"],
queryFn: () =>
fetchApi<{ data: { invitations: unknown[] } }>("/api/invitations").then(
queryKey: ["invitations", gymId],
queryFn: () => {
const url = gymId
? `/api/invitations?gymId=${gymId}`
: "/api/invitations";
return fetchApi<{ data: { invitations: Invitation[] } }>(url).then(
(res) => res.data?.invitations ?? [],
),
);
},
});
}
@@ -364,6 +383,37 @@ export function useSendInvitation() {
});
}
export function useRevokeInvitation() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (invitationId: string) =>
fetchApi<{ data: { success: boolean } }>(
`/api/invitations/${invitationId}`,
{ method: "DELETE" },
),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["invitations"] });
queryClient.invalidateQueries({ queryKey: ["users"] });
},
});
}
export function useResendInvitation() {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (invitationId: string) =>
fetchApi<{ data: { invitation: any } }>(
`/api/invitations/${invitationId}/resend`,
{ method: "POST" },
),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["invitations"] });
},
});
}
export interface AnalyticsData {
userGrowth: { label: string; value: number }[];
membershipDistribution: { label: string; value: number; color: string }[];