react-query

This commit is contained in:
2025-12-21 01:45:17 +01:00
parent 22f28728ce
commit 13d8563feb
13 changed files with 324 additions and 296 deletions

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import {
Users,
@@ -22,7 +22,7 @@ import {
import Button from '@/components/ui/Button';
import Input from '@/components/ui/Input';
import Heading from '@/components/ui/Heading';
import { useServices } from '@/lib/services/ServiceProvider';
import { useAllTeams } from '@/hooks/useTeamService';
import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
// ============================================================================
@@ -256,28 +256,11 @@ function TopThreePodium({ teams, onTeamClick }: TopThreePodiumProps) {
export default function TeamLeaderboardPage() {
const router = useRouter();
const [teams, setTeams] = useState<TeamDisplayData[]>([]);
const [loading, setLoading] = useState(true);
const { data: teams = [], isLoading: loading } = useAllTeams();
const [searchQuery, setSearchQuery] = useState('');
const [sortBy, setSortBy] = useState<SortBy>('rating');
const [filterLevel, setFilterLevel] = useState<SkillLevel | 'all'>('all');
useEffect(() => {
const loadTeams = async () => {
try {
const { teamService } = useServices();
const teams = await teamService.getAllTeams();
setTeams(teams);
} catch (error) {
console.error('Failed to load teams:', error);
} finally {
setLoading(false);
}
};
void loadTeams();
}, []);
const handleTeamClick = (teamId: string) => {
if (teamId.startsWith('demo-team-')) {
@@ -300,8 +283,7 @@ export default function TeamLeaderboardPage() {
if (filterLevel !== 'all' && team.performanceLevel !== filterLevel) {
return false;
}
// Must have rating for leaderboard
return team.rating !== null;
return true;
})
.sort((a, b) => {
switch (sortBy) {

View File

@@ -1,6 +1,6 @@
'use client';
import { useState, useEffect } from 'react';
import { useState, useMemo } from 'react';
import { useRouter } from 'next/navigation';
import {
Users,
@@ -28,14 +28,14 @@ import Card from '@/components/ui/Card';
import Input from '@/components/ui/Input';
import Heading from '@/components/ui/Heading';
import CreateTeamForm from '@/components/teams/CreateTeamForm';
import { useServices } from '@/lib/services/ServiceProvider';
import { useAllTeams } from '@/hooks/useTeamService';
import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
// ============================================================================
// TYPES
// ============================================================================
type TeamDisplayData = TeamLeaderboardItemViewModel;
type TeamDisplayData = TeamSummaryViewModel;
// ============================================================================
// SKILL LEVEL CONFIG
@@ -430,58 +430,36 @@ function TeamLeaderboardPreview({ topTeams, onTeamClick }: TeamLeaderboardPrevie
export default function TeamsPage() {
const router = useRouter();
const [realTeams, setRealTeams] = useState<TeamDisplayData[]>([]);
const [groupsBySkillLevel, setGroupsBySkillLevel] = useState<Record<SkillLevel, TeamDisplayData[]>>({
beginner: [],
intermediate: [],
advanced: [],
pro: [],
});
const [topTeams, setTopTeams] = useState<TeamDisplayData[]>([]);
const [loading, setLoading] = useState(true);
const { data: teams = [], isLoading: loading } = useAllTeams();
const [searchQuery, setSearchQuery] = useState('');
const [showCreateForm, setShowCreateForm] = useState(false);
useEffect(() => {
loadTeams();
}, []);
// Derive groups by skill level from the loaded teams
const groupsBySkillLevel = useMemo(() => {
const byLevel: Record<string, typeof teams> = {
beginner: [],
intermediate: [],
advanced: [],
pro: [],
};
teams.forEach((team) => {
const level = team.performanceLevel || 'intermediate';
if (byLevel[level]) {
byLevel[level].push(team);
}
});
return byLevel;
}, [teams]);
const loadTeams = async () => {
try {
const { teamService } = useServices();
const teams = await teamService.getAllTeams();
setRealTeams(teams);
// Derive groups by skill level from the loaded teams
const byLevel: Record<SkillLevel, TeamDisplayData[]> = {
beginner: [],
intermediate: [],
advanced: [],
pro: [],
};
teams.forEach((team) => {
const level = (team.performanceLevel as SkillLevel) || 'intermediate';
if (byLevel[level]) {
byLevel[level].push(team as TeamDisplayData);
}
});
setGroupsBySkillLevel(byLevel);
// Select top teams by rating for the preview section
const sortedByRating = [...teams].sort((a, b) => {
const aRating = typeof a.rating === 'number' && Number.isFinite(a.rating) ? a.rating : 0;
const bRating = typeof b.rating === 'number' && Number.isFinite(b.rating) ? b.rating : 0;
return bRating - aRating;
});
setTopTeams(sortedByRating.slice(0, 5));
} catch (error) {
console.error('Failed to load teams:', error);
} finally {
setLoading(false);
}
};
const teams = realTeams;
// Select top teams by rating for the preview section
const topTeams = useMemo(() => {
const sortedByRating = [...teams].sort((a, b) => {
const aRating = typeof a.rating === 'number' && Number.isFinite(a.rating) ? a.rating : 0;
const bRating = typeof b.rating === 'number' && Number.isFinite(b.rating) ? b.rating : 0;
return bRating - aRating;
});
return sortedByRating.slice(0, 5);
}, [teams]);
const handleTeamClick = (teamId: string) => {
if (teamId.startsWith('demo-team-')) {
@@ -492,7 +470,6 @@ export default function TeamsPage() {
const handleCreateSuccess = (teamId: string) => {
setShowCreateForm(false);
void loadTeams();
router.push(`/teams/${teamId}`);
};
@@ -509,21 +486,23 @@ export default function TeamsPage() {
});
// Group teams by skill level
const teamsByLevel: Record<SkillLevel, TeamDisplayData[]> = SKILL_LEVELS.reduce(
(acc, level) => {
const fromGroup = groupsBySkillLevel[level.id] ?? [];
acc[level.id] = filteredTeams.filter((team) =>
fromGroup.some((groupTeam) => groupTeam.id === team.id),
);
return acc;
},
{
beginner: [],
intermediate: [],
advanced: [],
pro: [],
} as Record<SkillLevel, TeamDisplayData[]>,
);
const teamsByLevel = useMemo(() => {
return SKILL_LEVELS.reduce(
(acc, level) => {
const fromGroup = groupsBySkillLevel[level.id] ?? [];
acc[level.id] = filteredTeams.filter((team) =>
fromGroup.some((groupTeam) => groupTeam.id === team.id),
);
return acc;
},
{
beginner: [],
intermediate: [],
advanced: [],
pro: [],
} as Record<string, typeof teams>,
);
}, [groupsBySkillLevel, filteredTeams]);
const recruitingCount = teams.filter((t) => t.isRecruiting).length;