Refactor app architecture and clean local artifacts

This commit is contained in:
AzuTear
2026-06-24 23:43:14 +02:00
parent 17134b3b82
commit fef1d36fe8
274 changed files with 37724 additions and 6065 deletions
+10 -133
View File
@@ -1,137 +1,14 @@
import type {
AdminDashboardResponse,
AdminSeasonDetailResponse,
AdminSeasonListItem,
AuthSession,
CreateClipPayload,
CreateNominationPayload,
CreateVotePayload,
LoginPayload,
OverviewResponse,
SeasonCategoriesResponse,
UpdateSeasonPayload,
ApproveNominationPayload,
UpsertCandidatePayload,
UpsertCategoryPayload,
WinnerArchiveResponse,
} from '../types/awards'
const API_URL = import.meta.env.VITE_API_URL ?? 'http://127.0.0.1:5084'
const AUTH_TOKEN_KEY = 'vtsa-session-token'
function getAuthToken() {
if (typeof window === 'undefined') return null
return window.localStorage.getItem(AUTH_TOKEN_KEY)
}
async function getJson<T>(path: string): Promise<T> {
const token = getAuthToken()
const response = await fetch(`${API_URL}${path}`, {
headers: token
? {
Authorization: `Bearer ${token}`,
}
: undefined,
}).catch(() => {
throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`)
})
if (!response.ok) {
throw new Error(`API request failed for ${path}`)
}
return response.json() as Promise<T>
}
async function sendDelete<TResponse>(path: string): Promise<TResponse> {
const token = getAuthToken()
const response = await fetch(`${API_URL}${path}`, {
method: 'DELETE',
headers: token ? { Authorization: `Bearer ${token}` } : undefined,
}).catch(() => {
throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`)
})
if (!response.ok) {
const error = await response.text()
throw new Error(error || `API request failed for ${path}`)
}
return response.json() as Promise<TResponse>
}
async function sendJson<TResponse>(path: string, method: 'POST' | 'PUT', body: unknown): Promise<TResponse> {
const token = getAuthToken()
const response = await fetch(`${API_URL}${path}`, {
method,
headers: {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify(body),
}).catch(() => {
throw new Error(`API nicht erreichbar (${API_URL}). Bitte Backend starten.`)
})
if (!response.ok) {
const error = await response.text()
throw new Error(error || `API request failed for ${path}`)
}
return response.json() as Promise<TResponse>
}
import { adminApi } from './api/adminApi'
import { authApi } from './api/authApi'
import { publicApi } from './api/publicApi'
import { systemApi } from './api/systemApi'
export const api = {
getOverview: () => getJson<OverviewResponse>('/api/public/overview'),
getSeasonCategories: (year: number) =>
getJson<SeasonCategoriesResponse>(`/api/public/seasons/${year}/categories`),
getWinnerArchive: (year: number) =>
getJson<WinnerArchiveResponse>(`/api/public/seasons/${year}/winners`),
getAdminDashboard: () => getJson<AdminDashboardResponse>('/api/admin/dashboard'),
getAdminSeasons: () => getJson<AdminSeasonListItem[]>('/api/admin/seasons'),
getAdminSeasonDetail: (seasonId: number) =>
getJson<AdminSeasonDetailResponse>(`/api/admin/seasons/${seasonId}`),
getSession: () => getJson<AuthSession>('/api/auth/session'),
login: (payload: LoginPayload) => sendJson<AuthSession>('/api/auth/dev-login', 'POST', payload),
logout: () => sendJson<{ loggedOut: boolean }>('/api/auth/logout', 'POST', {}),
submitNomination: (payload: CreateNominationPayload) =>
sendJson<{ saved: number; category: string }>('/api/public/nominations', 'POST', payload),
submitVote: (payload: CreateVotePayload) =>
sendJson<{ ballotId: number; entries: number }>('/api/public/votes', 'POST', payload),
submitClip: (payload: CreateClipPayload) =>
sendJson<{ saved: boolean; clipId: number }>('/api/public/clips', 'POST', payload),
updateAdminSeason: (seasonId: number, payload: UpdateSeasonPayload) =>
sendJson<{ saved: boolean; seasonId: number }>(`/api/admin/seasons/${seasonId}`, 'PUT', payload),
createAdminCategory: (seasonId: number, payload: UpsertCategoryPayload) =>
sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/seasons/${seasonId}/categories`, 'POST', payload),
updateAdminCategory: (categoryId: number, payload: UpsertCategoryPayload) =>
sendJson<{ saved: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`, 'PUT', payload),
createAdminCandidate: (seasonId: number, payload: UpsertCandidatePayload) =>
sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/seasons/${seasonId}/candidates`, 'POST', payload),
updateAdminCandidate: (candidateId: number, payload: UpsertCandidatePayload) =>
sendJson<{ saved: boolean; candidateId: number }>(`/api/admin/candidates/${candidateId}`, 'PUT', payload),
deleteAdminCandidate: (candidateId: number) =>
sendDelete<{ deleted: boolean; candidateId: number }>(`/api/admin/candidates/${candidateId}`),
deleteAdminCategory: (categoryId: number) =>
sendDelete<{ deleted: boolean; categoryId: number }>(`/api/admin/categories/${categoryId}`),
deleteAdminClip: (clipId: number) =>
sendDelete<{ deleted: boolean; clipId: number }>(`/api/admin/clips/${clipId}`),
approveAdminNomination: (nominationId: number, payload: ApproveNominationPayload) =>
sendJson<{ saved: boolean; nominationId: number; candidateId: number; created: boolean }>(
`/api/admin/nominations/${nominationId}/approve`,
'POST',
payload,
),
rejectAdminNomination: (nominationId: number) =>
sendJson<{ saved: boolean; nominationId: number; rejected: boolean }>(
`/api/admin/nominations/${nominationId}/reject`,
'POST',
{},
),
resolveRiskFlag: (riskFlagId: number, status = 'resolved') =>
sendJson<{ saved: boolean; riskFlagId: number; status: string }>(
`/api/admin/risk-flags/${riskFlagId}/resolve`,
'POST',
{ status },
),
...publicApi,
...authApi,
...adminApi,
...systemApi,
}
export { AUTH_TOKEN_KEY }
export { AUTH_TOKEN_KEY } from './http'
export { ApiRequestError } from './http'