react-query
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user