Compare commits

..

2 Commits

Author SHA1 Message Date
valknar a6111d7beb fix: resolve Apollo cache warning for TeamStats embedded objects
Add merge: true policy for Team.stats so InMemoryCache merges partial
TeamStats selections (e.g. search page) with fuller ones (team/stats pages)
instead of replacing and losing fields. Also align stats page query to
include goalDiff for consistency.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 21:12:13 +02:00
valknar 6e6e819718 fix: scope team page scorers by teamId instead of filtering global top 200
Teams with few goals (e.g. Qatar) were missing from the sidebar because
topScorers(limit:200) only returned all-time top scorers. Now the query
filters by teamId in SQL so every team shows their own scorers.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 21:11:16 +02:00
5 changed files with 17 additions and 13 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ const STATS_QUERY = gql`
} }
teams { teams {
id name iso2 slug id name iso2 slug
stats { appearances titles wins draws losses goalsFor goalsAgainst winPct } stats { appearances titles wins draws losses goalsFor goalsAgainst goalDiff winPct }
} }
goalsByMinute { bucket count } goalsByMinute { bucket count }
confederationStats { confederation appearances titles totalGoals } confederationStats { confederation appearances titles totalGoals }
+4 -6
View File
@@ -56,18 +56,16 @@ export default function TeamPage({ params }: { params: Promise<{ slug: string }>
skip: !team?.id, skip: !team?.id,
}) })
// Load all scorers to filter by team
const { data: scorerData } = useQuery(gql` const { data: scorerData } = useQuery(gql`
query TeamScorers { query TeamScorers($teamId: Int!) {
topScorers(limit: 200) { topScorers(teamId: $teamId, limit: 30) {
playerName goals penalties ownGoals tournaments playerName goals penalties ownGoals tournaments
team { id name iso2 } team { id name iso2 }
} }
} }
`) `, { variables: { teamId: team?.id ?? 0 }, skip: !team?.id })
const allScorers = scorerData?.topScorers ?? [] const teamScorers = scorerData?.topScorers ?? []
const teamScorers = team ? allScorers.filter((s: { team?: { id: number } | null }) => s.team?.id === team.id).slice(0, 15) : []
const teamMatches: MatchRow[] = matchesData?.matches ?? [] const teamMatches: MatchRow[] = matchesData?.matches ?? []
// Group matches by year for the history display // Group matches by year for the history display
+5 -1
View File
@@ -7,7 +7,11 @@ let client: InstanceType<typeof ApolloClient> | null = null
function createClient() { function createClient() {
return new ApolloClient({ return new ApolloClient({
link: new HttpLink({ uri: '/api/graphql' }), link: new HttpLink({ uri: '/api/graphql' }),
cache: new InMemoryCache(), cache: new InMemoryCache({
typePolicies: {
Team: { fields: { stats: { merge: true } } },
},
}),
defaultOptions: { watchQuery: { fetchPolicy: 'cache-and-network' } }, defaultOptions: { watchQuery: { fetchPolicy: 'cache-and-network' } },
}) })
} }
+6 -4
View File
@@ -152,11 +152,13 @@ export const resolvers = {
return found ? teamWithSlug(found) : null return found ? teamWithSlug(found) : null
} catch (e) { if (isMissingTable(e)) return null; throw e } } catch (e) { if (isMissingTable(e)) return null; throw e }
}, },
async topScorers(_: unknown, { year, limit = 20 }: { year?: number; limit?: number }) { async topScorers(_: unknown, { year, limit = 20, teamId }: { year?: number; limit?: number; teamId?: number }) {
try { try {
const conditions = year const conditions = sql`
? sql`AND m.tournament_year = ${year} AND m.is_quali_playoff = false` ${year ? sql`AND m.tournament_year = ${year}` : sql``}
: sql`AND m.is_quali_playoff = false` ${teamId ? sql`AND g.team_id = ${teamId}` : sql``}
AND m.is_quali_playoff = false
`
const rows = await db.execute(sql` const rows = await db.execute(sql`
SELECT SELECT
g.player_name, g.player_name,
+1 -1
View File
@@ -170,7 +170,7 @@ export const typeDefs = /* GraphQL */ `
teams: [Team!]! teams: [Team!]!
team(slug: String!): Team team(slug: String!): Team
topScorers(year: Int, limit: Int): [ScorerEntry!]! topScorers(year: Int, limit: Int, teamId: Int): [ScorerEntry!]!
player(name: String!): ScorerEntry player(name: String!): ScorerEntry
hatTricks(year: Int): [HatTrick!]! hatTricks(year: Int): [HatTrick!]!