feat(ui): Gäste-Verwaltung UI — SettingsGuests (UI-Backlog Modul 14/16)
- api/guests.ts: useGuests, useInviteGuest, useRevokeGuest (/api/v1/guests) - SettingsGuests.tsx: Admin-Gate (Outbox-Muster), Gästeliste mit Status-Badges (invited/active/disabled), Invite-Modal (RHF+zod), Revoke-ConfirmDialog - Route /settings/guests + Nav-Eintrag in Settings.tsx - i18n de/en: 14 Keys - Vitest 8/8, tsc clean, Build OK
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Guests API client — admin guest management (UI-Backlog module 14/16).
|
||||
*
|
||||
* Backend: /api/v1/guests (app/routes/guests.py, require_admin).
|
||||
* - GET / → list guests (role=guest memberships for tenant)
|
||||
* - POST /invite → invite guest (name + email; 409 if already active)
|
||||
* - DELETE /{id} → revoke guest (status=disabled + session invalidation)
|
||||
*
|
||||
* Guests are regular users with role='guest' in user_tenants; they log in
|
||||
* via the normal login flow (password via reset flow).
|
||||
*/
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { apiGet, apiPost, apiDelete } from '@/api/client';
|
||||
|
||||
export interface Guest {
|
||||
id: string;
|
||||
email: string;
|
||||
name: string;
|
||||
status: 'invited' | 'active' | 'disabled' | string;
|
||||
role: string;
|
||||
created_at: string | null;
|
||||
}
|
||||
|
||||
export interface GuestInviteResponse {
|
||||
email: string;
|
||||
name: string;
|
||||
status: string;
|
||||
role: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface GuestInvitePayload {
|
||||
email: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function useGuests(enabled = true) {
|
||||
return useQuery({
|
||||
queryKey: ['guests'],
|
||||
queryFn: () => apiGet<Guest[]>('/guests'),
|
||||
enabled,
|
||||
});
|
||||
}
|
||||
|
||||
export function useInviteGuest() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (data: GuestInvitePayload) =>
|
||||
apiPost<GuestInviteResponse>('/guests/invite', data),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['guests'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useRevokeGuest() {
|
||||
const queryClient = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: (guestId: string) => apiDelete<{ message: string }>(`/guests/${guestId}`),
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['guests'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user