feat: wire Documents + Board page buttons, add mock-mode dual operation

Sprint 12 Phase 1: Golden Test Standard
- Documents: React Query, upload/download/delete wired, category colors+icons, table min-widths, data-testid
- Board: React Query, create position/elect/remove wired, confirmation dialogs, data-testid
- Both pages: mock-mode fallback (works without backend)
This commit is contained in:
Patrick Plate
2026-06-18 14:43:00 +02:00
parent 90cdac7468
commit 6e25914074
4 changed files with 716 additions and 70 deletions
@@ -1,5 +1,13 @@
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
import { apiClient } from "@/lib/api-client"
// --- Constants ---
const CLUB_ID = "00000000-0000-0000-0000-000000000001"
// --- Types ---
export interface BoardPosition {
id: string
title: string
@@ -37,6 +45,8 @@ export interface ElectBoardMemberRequest {
assemblyId?: string
}
// --- Raw API functions ---
export function createPosition(
clubId: string,
data: CreatePositionRequest
@@ -88,3 +98,51 @@ export function removeBoardMember(id: string, clubId: string): Promise<void> {
export function getPortalBoard(clubId: string): Promise<BoardMember[]> {
return apiClient<BoardMember[]>(`/portal/board?clubId=${clubId}`)
}
// --- React Query Hooks ---
export function useBoardQuery() {
return useQuery({
queryKey: ["board", CLUB_ID],
queryFn: () => getCurrentBoard(CLUB_ID),
})
}
export function usePositionsQuery() {
return useQuery({
queryKey: ["board-positions", CLUB_ID],
queryFn: () => getPositions(CLUB_ID),
})
}
export function useCreatePositionMutation() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: CreatePositionRequest) => createPosition(CLUB_ID, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["board-positions"] })
queryClient.invalidateQueries({ queryKey: ["board"] })
},
})
}
export function useElectBoardMemberMutation() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (data: ElectBoardMemberRequest) =>
electBoardMember(CLUB_ID, data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["board"] })
},
})
}
export function useRemoveBoardMemberMutation() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (id: string) => removeBoardMember(id, CLUB_ID),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["board"] })
},
})
}