- FastAPI backend with PostgreSQL + Redis - 4 core features: Registration, Courts, Matchmaking, Tournament - Double elimination tournament with bracket visualization - ELO-based matchmaking (Stage 1 Open, Stage 2 Skill-Based) - Real-time WebSocket updates - TV Screen display for courts - Vue 3 + Tailwind CSS frontend - Seed data: 12 players, 4 courts, active matches, tournament in progress - Docker compose stack with Nginx reverse proxy
126 lines
3.6 KiB
JavaScript
126 lines
3.6 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
import axios from 'axios'
|
|
|
|
const api = axios.create({ baseURL: '/api' })
|
|
|
|
export const useAppStore = defineStore('app', () => {
|
|
const currentPlayer = ref(null)
|
|
const players = ref([])
|
|
const courts = ref([])
|
|
const matches = ref([])
|
|
const activeTournament = ref(null)
|
|
const loading = ref(false)
|
|
|
|
// Set demo player (no auth needed)
|
|
const setCurrentPlayer = (player) => {
|
|
currentPlayer.value = player
|
|
localStorage.setItem('currentPlayerId', player.id)
|
|
}
|
|
|
|
const loadPlayers = async () => {
|
|
const res = await api.get('/players/')
|
|
players.value = res.data
|
|
// Auto-set first player as current if not set
|
|
if (!currentPlayer.value && players.value.length > 0) {
|
|
const savedId = localStorage.getItem('currentPlayerId')
|
|
const saved = savedId ? players.value.find(p => p.id == savedId) : null
|
|
currentPlayer.value = saved || players.value[0]
|
|
}
|
|
return players.value
|
|
}
|
|
|
|
const loadCourts = async () => {
|
|
const res = await api.get('/courts/')
|
|
courts.value = res.data
|
|
return courts.value
|
|
}
|
|
|
|
const loadMatches = async () => {
|
|
const res = await api.get('/matches/')
|
|
matches.value = res.data
|
|
return matches.value
|
|
}
|
|
|
|
const loadLobby = async () => {
|
|
const res = await api.get('/matches/lobby')
|
|
return res.data
|
|
}
|
|
|
|
const loadActiveMatches = async () => {
|
|
const res = await api.get('/matches/active')
|
|
return res.data
|
|
}
|
|
|
|
const createMatch = async (data) => {
|
|
const res = await api.post('/matches/', data)
|
|
return res.data
|
|
}
|
|
|
|
const joinMatch = async (matchId, playerId, team) => {
|
|
const res = await api.post(`/matches/${matchId}/join`, { player_id: playerId, team })
|
|
return res.data
|
|
}
|
|
|
|
const startMatch = async (matchId) => {
|
|
const res = await api.post(`/matches/${matchId}/start`)
|
|
return res.data
|
|
}
|
|
|
|
const updateScore = async (matchId, team1Score, team2Score) => {
|
|
const res = await api.post(`/matches/${matchId}/score`, { team1_score: team1Score, team2_score: team2Score })
|
|
return res.data
|
|
}
|
|
|
|
const completeMatch = async (matchId, team1Score, team2Score) => {
|
|
const res = await api.post(`/matches/${matchId}/complete`, { team1_score: team1Score, team2_score: team2Score })
|
|
return res.data
|
|
}
|
|
|
|
const bookCourt = async (data) => {
|
|
const res = await api.post('/courts/book', data)
|
|
return res.data
|
|
}
|
|
|
|
const loadTournaments = async () => {
|
|
const res = await api.get('/tournaments/')
|
|
return res.data
|
|
}
|
|
|
|
const loadTournament = async (id) => {
|
|
const res = await api.get(`/tournaments/${id}`)
|
|
activeTournament.value = res.data
|
|
return res.data
|
|
}
|
|
|
|
const getLeaderboard = async (limit = 10) => {
|
|
const res = await api.get(`/players/leaderboard?limit=${limit}`)
|
|
return res.data
|
|
}
|
|
|
|
const getCourtDisplay = async (courtId) => {
|
|
const res = await api.get(`/screen/court/${courtId}`)
|
|
return res.data
|
|
}
|
|
|
|
const getOverview = async () => {
|
|
const res = await api.get('/screen/overview')
|
|
return res.data
|
|
}
|
|
|
|
const completeTournamentMatch = async (tournamentId, matchId, s1, s2) => {
|
|
const res = await api.post(`/tournaments/${tournamentId}/matches/${matchId}/score`, {
|
|
team1_score: s1, team2_score: s2
|
|
})
|
|
return res.data
|
|
}
|
|
|
|
return {
|
|
currentPlayer, players, courts, matches, activeTournament, loading,
|
|
setCurrentPlayer, loadPlayers, loadCourts, loadMatches,
|
|
loadLobby, loadActiveMatches, createMatch, joinMatch, startMatch,
|
|
updateScore, completeMatch, bookCourt, loadTournaments, loadTournament,
|
|
getLeaderboard, getCourtDisplay, getOverview, completeTournamentMatch,
|
|
}
|
|
})
|