feat: restructure frontend routes — vendor/tenant persona split

Splits the flat 3-page UI into /vendor/* (platform:admin) and /tenant/*
(all authenticated users) route trees, with stub pages, new API hooks,
updated Layout with persona-aware sidebar, and SpaController forwarding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
hsiegeln
2026-04-09 21:52:34 +02:00
parent e56e3fca8a
commit bf3aa57274
19 changed files with 329 additions and 496 deletions

View File

@@ -0,0 +1,63 @@
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { api } from './client';
import type { DashboardData, TenantLicenseData, TenantSettings } from '../types/api';
export function useTenantDashboard() {
return useQuery<DashboardData>({
queryKey: ['tenant', 'dashboard'],
queryFn: () => api.get('/tenant/dashboard'),
refetchInterval: 30_000,
});
}
export function useTenantLicense() {
return useQuery<TenantLicenseData>({
queryKey: ['tenant', 'license'],
queryFn: () => api.get('/tenant/license'),
});
}
export function useTenantOidc() {
return useQuery<Record<string, unknown>>({
queryKey: ['tenant', 'oidc'],
queryFn: () => api.get('/tenant/oidc'),
});
}
export function useUpdateOidc() {
const qc = useQueryClient();
return useMutation<void, Error, Record<string, unknown>>({
mutationFn: (config) => api.post('/tenant/oidc', config),
onSuccess: () => qc.invalidateQueries({ queryKey: ['tenant', 'oidc'] }),
});
}
export function useTenantTeam() {
return useQuery<Array<Record<string, unknown>>>({
queryKey: ['tenant', 'team'],
queryFn: () => api.get('/tenant/team'),
});
}
export function useInviteTeamMember() {
const qc = useQueryClient();
return useMutation<{ userId: string }, Error, { email: string; roleId: string }>({
mutationFn: (body) => api.post('/tenant/team/invite', body),
onSuccess: () => qc.invalidateQueries({ queryKey: ['tenant', 'team'] }),
});
}
export function useRemoveTeamMember() {
const qc = useQueryClient();
return useMutation<void, Error, string>({
mutationFn: (userId) => api.delete(`/tenant/team/${userId}`),
onSuccess: () => qc.invalidateQueries({ queryKey: ['tenant', 'team'] }),
});
}
export function useTenantSettings() {
return useQuery<TenantSettings>({
queryKey: ['tenant', 'settings'],
queryFn: () => api.get('/tenant/settings'),
});
}