/** * Challonge Tests Composable * * Manages tournament testing operations including: * - Loading tournament lists with pagination * - Tournament detail fetching * - Search/filtering * - Helper utilities for tournament data access * * @example * ```js * const { * tournaments, * loading, * error, * testListTournaments, * loadMoreTournaments, * toggleTournamentDetails * } = useChallongeTests(client, apiVersion, tournamentScope); * * await testListTournaments(); * ``` */ import { ref, computed } from 'vue'; import { useAsyncState } from './useAsyncState.js'; import { queryAllTournaments } from '../utilities/tournament-query.js'; export function useChallongeTests(client, apiVersion, tournamentScope) { // Async state management const tournamentListState = useAsyncState(); const loadMoreState = useAsyncState(); const tournamentDetailsState = useAsyncState(); // Destructure for easier access const { data: tournaments, loading, error } = tournamentListState; const { loading: loadingMore } = loadMoreState; // Search and filter const searchQuery = ref(''); const expandedTournamentId = ref(null); // Pagination state const currentPage = ref(1); const perPage = ref(100); const totalTournaments = ref(0); const hasNextPage = ref(false); /** * Pagination info string */ const paginationInfo = computed(() => { if (!tournaments.value) return ''; const start = (currentPage.value - 1) * perPage.value + 1; const end = Math.min( start + tournaments.value.length - 1, totalTournaments.value || tournaments.value.length ); const total = totalTournaments.value || tournaments.value.length; return `Showing ${start}-${end} of ${total}`; }); /** * Filtered tournaments based on search query */ const filteredTournaments = computed(() => { if (!tournaments.value) return null; if (!searchQuery.value.trim()) return tournaments.value; const query = searchQuery.value.toLowerCase(); return tournaments.value.filter(t => { const name = getTournamentName(t).toLowerCase(); return name.includes(query); }); }); /** * Tournament details from async state */ const tournamentDetails = computed(() => tournamentDetailsState.data.value); /** * Helper to get tournament name (handles both v1 and v2.1 structures) */ function getTournamentName(tournament) { return tournament.tournament?.name || tournament.name || ''; } /** * Helper to get tournament ID */ function getTournamentId(tournament) { return tournament.tournament?.id || tournament.id; } /** * Helper to get tournament property */ function getTournamentProp(tournament, prop) { return tournament.tournament?.[prop] || tournament[prop]; } /** * Test listing tournaments with pagination support */ async function testListTournaments(resetPagination = true) { if (!client.value) { console.error('No API client available'); return; } if (resetPagination) { currentPage.value = 1; searchQuery.value = ''; expandedTournamentId.value = null; tournamentDetailsState.reset(); } await tournamentListState.execute(async () => { if (apiVersion.value === 'v1') { // v1 doesn't support pagination const result = await client.value.tournaments.list(); totalTournaments.value = result.length; hasNextPage.value = false; return result; } else { // v2.1 - Query all tournament states in parallel const result = await queryAllTournaments(client.value, { page: currentPage.value, per_page: perPage.value, scopeType: tournamentScope.value }); console.log('📊 Tournament API Response:', { page: currentPage.value, perPage: perPage.value, scope: tournamentScope.value, resultsCount: result.length }); totalTournaments.value = result.length; hasNextPage.value = result.length >= perPage.value; return result; } }); } /** * Load more tournaments (pagination) */ async function loadMoreTournaments() { if (apiVersion.value === 'v1') return; // v1 doesn't support pagination if (!client.value) return; currentPage.value++; const result = await loadMoreState.execute(async () => { const newResults = await queryAllTournaments(client.value, { page: currentPage.value, per_page: perPage.value, scopeType: tournamentScope.value }); hasNextPage.value = newResults.length === perPage.value; return newResults; }); if (result) { // Append new results to existing tournaments tournaments.value = [...tournaments.value, ...result]; } else { // Revert page increment on error currentPage.value--; } } /** * Change results per page */ async function changePerPage(newLimit) { perPage.value = newLimit; await testListTournaments(true); } /** * Toggle tournament details view */ async function toggleTournamentDetails(tournamentId) { if (!client.value) return; if (expandedTournamentId.value === tournamentId) { expandedTournamentId.value = null; tournamentDetailsState.reset(); return; } expandedTournamentId.value = tournamentId; await tournamentDetailsState.execute(async () => { if (apiVersion.value === 'v1') { return await client.value.tournaments.get(tournamentId, { includeParticipants: true, includeMatches: true }); } else { // v2.1 get tournament return await client.value.tournaments.get(tournamentId); } }); // Reset expanded state if there was an error if (tournamentDetailsState.error.value) { expandedTournamentId.value = null; } } /** * Reset all test state */ function resetState() { tournamentListState.reset(); loadMoreState.reset(); tournamentDetailsState.reset(); searchQuery.value = ''; expandedTournamentId.value = null; currentPage.value = 1; } /** * Format date string */ function formatDate(dateString) { if (!dateString) return ''; return new Date(dateString).toLocaleString(); } return { // State tournaments, loading, loadingMore, error, searchQuery, expandedTournamentId, currentPage, perPage, totalTournaments, hasNextPage, tournamentDetails, tournamentDetailsState, // Expose for direct access to loading/error // Computed paginationInfo, filteredTournaments, // Methods testListTournaments, loadMoreTournaments, changePerPage, toggleTournamentDetails, resetState, // Helpers getTournamentName, getTournamentId, getTournamentProp, formatDate }; }