feat: Implement Phase 4 - Application Architecture & Routing
Phase 4 establishes the core application structure with SvelteKit routing, data loading, error handling, and state management. ## Routing & Data Loading - Created root layout load function (+layout.ts) with app version and feature flags - Implemented comprehensive error boundary (+error.svelte) with status-based messages - Added page loaders for homepage, matches, players, and about routes - Homepage loader fetches featured matches via API with error fallback - Matches loader supports URL query parameters (map, player_id, limit) ## State Management (Svelte Stores) - preferences.ts: User settings with localStorage persistence * Theme selection (cs2dark, cs2light, auto) * Favorite players tracking * Advanced stats toggle, date format preferences - search.ts: Search state with recent searches (localStorage) - toast.ts: Toast notification system with auto-dismiss * Success, error, warning, info types * Configurable duration and dismissibility ## UI Components - Toast.svelte: Individual notification with Lucide icons - ToastContainer.svelte: Fixed top-right toast display - Integrated ToastContainer into root layout ## Fixes - Fixed Svelte 5 deprecation warnings (removed <svelte:component> in runes mode) - Updated homepage to use PageData from loader - Added proper type safety across all load functions ## Testing - Type check: 0 errors, 0 warnings - Production build: Successful - All Phase 4 core objectives completed 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
49
src/routes/matches/+page.ts
Normal file
49
src/routes/matches/+page.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import type { PageLoad } from './$types';
|
||||
import { api } from '$lib/api';
|
||||
|
||||
/**
|
||||
* Matches listing page data loader
|
||||
*/
|
||||
export const load: PageLoad = async ({ url }) => {
|
||||
// Get query parameters
|
||||
const map = url.searchParams.get('map') || undefined;
|
||||
const playerIdStr = url.searchParams.get('player_id');
|
||||
const playerId = playerIdStr ? Number(playerIdStr) : undefined;
|
||||
const limit = Number(url.searchParams.get('limit')) || 50;
|
||||
|
||||
try {
|
||||
// Load matches with filters
|
||||
const matchesData = await api.matches.getMatches({
|
||||
limit,
|
||||
map,
|
||||
player_id: playerId
|
||||
});
|
||||
|
||||
return {
|
||||
matches: matchesData.matches,
|
||||
hasMore: matchesData.has_more,
|
||||
nextPageTime: matchesData.next_page_time,
|
||||
filters: {
|
||||
map,
|
||||
playerId
|
||||
},
|
||||
meta: {
|
||||
title: 'Browse Matches - CS2.WTF',
|
||||
description: 'Browse and search through CS2 matchmaking games with detailed filters.'
|
||||
}
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Failed to load matches:', error);
|
||||
|
||||
// Return empty state on error
|
||||
return {
|
||||
matches: [],
|
||||
hasMore: false,
|
||||
filters: { map, playerId },
|
||||
meta: {
|
||||
title: 'Browse Matches - CS2.WTF',
|
||||
description: 'Browse and search through CS2 matchmaking games with detailed filters.'
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user