Files
servesync-demo/frontend/src/stores/app.js
Forge 46fd2953c3 🏓 Initial ServeSync demo build
- 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
2026-03-19 00:58:17 +08:00

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,
}
})