2025-12-14 02:38:35 +07:00
|
|
|
import client from './client'
|
2025-12-29 22:23:34 +03:00
|
|
|
import type { Marathon, MarathonListItem, MarathonPublicInfo, MarathonUpdate, LeaderboardEntry, ParticipantWithUser, ParticipantRole, GameProposalMode, MarathonDispute } from '@/types'
|
2025-12-14 02:38:35 +07:00
|
|
|
|
|
|
|
|
export interface CreateMarathonData {
|
|
|
|
|
title: string
|
|
|
|
|
description?: string
|
|
|
|
|
start_date: string
|
|
|
|
|
duration_days?: number
|
2025-12-14 20:21:56 +07:00
|
|
|
is_public?: boolean
|
|
|
|
|
game_proposal_mode?: GameProposalMode
|
2025-12-14 02:38:35 +07:00
|
|
|
}
|
|
|
|
|
|
2025-12-21 02:52:48 +07:00
|
|
|
export type { MarathonUpdate }
|
|
|
|
|
|
2025-12-14 02:38:35 +07:00
|
|
|
export const marathonsApi = {
|
|
|
|
|
list: async (): Promise<MarathonListItem[]> => {
|
|
|
|
|
const response = await client.get<MarathonListItem[]>('/marathons')
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
get: async (id: number): Promise<Marathon> => {
|
|
|
|
|
const response = await client.get<Marathon>(`/marathons/${id}`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 20:39:26 +07:00
|
|
|
getByCode: async (inviteCode: string): Promise<MarathonPublicInfo> => {
|
|
|
|
|
// Public endpoint - no auth required
|
|
|
|
|
const response = await client.get<MarathonPublicInfo>(`/marathons/by-code/${inviteCode}`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 02:38:35 +07:00
|
|
|
create: async (data: CreateMarathonData): Promise<Marathon> => {
|
|
|
|
|
const response = await client.post<Marathon>('/marathons', data)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-21 02:52:48 +07:00
|
|
|
update: async (id: number, data: MarathonUpdate): Promise<Marathon> => {
|
2025-12-14 02:38:35 +07:00
|
|
|
const response = await client.patch<Marathon>(`/marathons/${id}`, data)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
delete: async (id: number): Promise<void> => {
|
|
|
|
|
await client.delete(`/marathons/${id}`)
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
start: async (id: number): Promise<Marathon> => {
|
|
|
|
|
const response = await client.post<Marathon>(`/marathons/${id}/start`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
finish: async (id: number): Promise<Marathon> => {
|
|
|
|
|
const response = await client.post<Marathon>(`/marathons/${id}/finish`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
join: async (inviteCode: string): Promise<Marathon> => {
|
|
|
|
|
const response = await client.post<Marathon>('/marathons/join', { invite_code: inviteCode })
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 20:21:56 +07:00
|
|
|
joinPublic: async (id: number): Promise<Marathon> => {
|
|
|
|
|
const response = await client.post<Marathon>(`/marathons/${id}/join`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 02:38:35 +07:00
|
|
|
getParticipants: async (id: number): Promise<ParticipantWithUser[]> => {
|
|
|
|
|
const response = await client.get<ParticipantWithUser[]>(`/marathons/${id}/participants`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 20:21:56 +07:00
|
|
|
setParticipantRole: async (marathonId: number, userId: number, role: ParticipantRole): Promise<ParticipantWithUser> => {
|
|
|
|
|
const response = await client.patch<ParticipantWithUser>(
|
|
|
|
|
`/marathons/${marathonId}/participants/${userId}/role`,
|
|
|
|
|
{ role }
|
|
|
|
|
)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
2025-12-14 02:38:35 +07:00
|
|
|
getLeaderboard: async (id: number): Promise<LeaderboardEntry[]> => {
|
|
|
|
|
const response = await client.get<LeaderboardEntry[]>(`/marathons/${id}/leaderboard`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
2025-12-21 02:52:48 +07:00
|
|
|
|
|
|
|
|
uploadCover: async (id: number, file: File): Promise<Marathon> => {
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
formData.append('file', file)
|
|
|
|
|
const response = await client.post<Marathon>(`/marathons/${id}/cover`, formData, {
|
|
|
|
|
headers: {
|
|
|
|
|
'Content-Type': 'multipart/form-data',
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
deleteCover: async (id: number): Promise<Marathon> => {
|
|
|
|
|
const response = await client.delete<Marathon>(`/marathons/${id}/cover`)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
2025-12-29 22:23:34 +03:00
|
|
|
|
|
|
|
|
// Disputes management for organizers
|
|
|
|
|
listDisputes: async (id: number, status: 'open' | 'all' = 'open'): Promise<MarathonDispute[]> => {
|
|
|
|
|
const response = await client.get<MarathonDispute[]>(`/marathons/${id}/disputes`, {
|
|
|
|
|
params: { status_filter: status }
|
|
|
|
|
})
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
resolveDispute: async (marathonId: number, disputeId: number, isValid: boolean): Promise<{ message: string }> => {
|
|
|
|
|
const response = await client.post<{ message: string }>(
|
|
|
|
|
`/marathons/${marathonId}/disputes/${disputeId}/resolve`,
|
|
|
|
|
{ is_valid: isValid }
|
|
|
|
|
)
|
|
|
|
|
return response.data
|
|
|
|
|
},
|
2025-12-14 02:38:35 +07:00
|
|
|
}
|