feat(sprint-5): Phase 2 — React Query API client layer
- @tanstack/react-query with QueryClientProvider in providers/index.tsx - Typed api-client.ts fetch wrapper with ApiError class + apiDownload - Service modules: members, distributions, stock, reports, dashboard, portal, staff - Offline banner component (onlineManager subscription) - API error boundary with retry button - Loading skeleton components (card, table, chart, form, dashboard) - i18n for error/loading states (de/en)
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { useQuery } from "@tanstack/react-query"
|
||||
|
||||
import { apiClient } from "@/lib/api-client"
|
||||
|
||||
// --- Types ---
|
||||
|
||||
export interface PortalDashboardData {
|
||||
memberName: string
|
||||
memberNumber: string
|
||||
quotaStatus: {
|
||||
dailyUsedGrams: number
|
||||
dailyLimitGrams: number
|
||||
monthlyUsedGrams: number
|
||||
monthlyLimitGrams: number
|
||||
isUnder21: boolean
|
||||
}
|
||||
lastDistribution?: {
|
||||
strainName: string
|
||||
amountGrams: number
|
||||
recordedAt: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface PortalHistoryEntry {
|
||||
id: string
|
||||
strainName: string
|
||||
amountGrams: number
|
||||
recordedAt: string
|
||||
}
|
||||
|
||||
export interface PortalHistoryPage {
|
||||
content: PortalHistoryEntry[]
|
||||
totalElements: number
|
||||
totalPages: number
|
||||
number: number
|
||||
size: number
|
||||
}
|
||||
|
||||
export interface PortalProfileData {
|
||||
firstName: string
|
||||
lastName: string
|
||||
email: string
|
||||
phone?: string
|
||||
dateOfBirth: string
|
||||
memberNumber: string
|
||||
memberSince: string
|
||||
status: "ACTIVE" | "SUSPENDED" | "EXPELLED"
|
||||
}
|
||||
|
||||
// --- Query Hooks ---
|
||||
|
||||
export function usePortalDashboardQuery() {
|
||||
return useQuery({
|
||||
queryKey: ["portal", "dashboard"],
|
||||
queryFn: () => apiClient<PortalDashboardData>("/portal/dashboard"),
|
||||
})
|
||||
}
|
||||
|
||||
export function usePortalHistoryQuery(params?: {
|
||||
page?: number
|
||||
size?: number
|
||||
month?: string
|
||||
}) {
|
||||
return useQuery({
|
||||
queryKey: ["portal", "history", params],
|
||||
queryFn: () =>
|
||||
apiClient<PortalHistoryPage>("/portal/history", {
|
||||
params: {
|
||||
page: params?.page,
|
||||
size: params?.size ?? 20,
|
||||
month: params?.month || undefined,
|
||||
},
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
export function usePortalProfileQuery() {
|
||||
return useQuery({
|
||||
queryKey: ["portal", "profile"],
|
||||
queryFn: () => apiClient<PortalProfileData>("/portal/profile"),
|
||||
staleTime: 5 * 60 * 1000, // profile rarely changes
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user