import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { HandHeart, Handshake, Laugh, Scale, Users } from "lucide-react"; import type { LucideIcon } from "lucide-react"; import { pb } from "@/integrations/pocketbase/client"; import { upsertByFilter } from "@/integrations/pocketbase/upsert"; export type CategoriaSocial = { id: string; nome: string; descrizione: string; emoji: string; icon: LucideIcon; }; /** Categorie votate dai compagni a fine partita: un voto a testa per categoria. */ export const categorieSocial: CategoriaSocial[] = [ { id: "affidabile", nome: "Compagno affidabile", descrizione: "Sempre presente, sempre sul pezzo", emoji: "🛡️", icon: Handshake, }, { id: "spirito", nome: "Miglior spirito di squadra", descrizione: "Carica il gruppo dal primo all'ultimo punto", emoji: "📣", icon: Users, }, { id: "fairplay", nome: "Fair play", descrizione: "Rispetto per compagni, avversari e arbitro", emoji: "🤝", icon: Scale, }, { id: "meme", nome: "Meme della partita", descrizione: "La scena che rivedremo per tutta la stagione", emoji: "😂", icon: Laugh, }, { id: "cuore", nome: "Cuore del gruppo", descrizione: "Chi tiene unita la squadra anche fuori dal campo", emoji: "❤️", icon: HandHeart, }, ]; export type VotoSocial = { match_id: string; categoria: string; votante_id: string; votato_id: string; votato_nome: string; }; type RigaSocialPocketBase = { evento: string; categoria: string; votante: string; votato: string; votato_nome: string; }; const CHIAVE = ["badge-social-voti"] as const; /** Tutti i voti social (poche righe): nessun polling, cache lunga. */ export function useVotiSocial() { return useQuery({ queryKey: CHIAVE, staleTime: 10 * 60_000, queryFn: async (): Promise => { const righe = await pb.collection("badge_social_voti").getFullList(); return righe.map((r) => ({ match_id: r.evento, categoria: r.categoria, votante_id: r.votante, votato_id: r.votato, votato_nome: r.votato_nome, })); }, }); } export function useVotaSocial() { const qc = useQueryClient(); return useMutation({ mutationFn: async (voto: VotoSocial) => { // No autovoto e convocazione li valida l'hook voti_convocati.pb.js. await upsertByFilter( "badge_social_voti", "evento = {:evento} && categoria = {:categoria} && votante = {:votante}", { evento: voto.match_id, categoria: voto.categoria, votante: voto.votante_id }, { evento: voto.match_id, categoria: voto.categoria, votante: voto.votante_id, votato: voto.votato_id, votato_nome: voto.votato_nome, }, ); return voto; }, // Aggiornamento locale della cache: zero riletture. onSuccess: (voto) => { qc.setQueryData(CHIAVE, (prec) => { const altri = (prec ?? []).filter( (v) => !( v.match_id === voto.match_id && v.categoria === voto.categoria && v.votante_id === voto.votante_id ), ); return [...altri, voto]; }); }, }); } export type ConteggioSocial = { id: string; nome: string; voti: number }; export function conteggioCategoria( voti: VotoSocial[], matchId: string, categoria: string, ): ConteggioSocial[] { const map = new Map(); for (const v of voti) { if (v.match_id !== matchId || v.categoria !== categoria) continue; const cur = map.get(v.votato_id) ?? { id: v.votato_id, nome: v.votato_nome, voti: 0 }; cur.voti += 1; map.set(v.votato_id, cur); } return [...map.values()].sort((a, b) => b.voti - a.voti || a.nome.localeCompare(b.nome)); } /** Vincitore di una categoria: serve un vantaggio netto, altrimenti parità. */ export function vincitoreCategoria( voti: VotoSocial[], matchId: string, categoria: string, ): ConteggioSocial | null { const c = conteggioCategoria(voti, matchId, categoria); if (c.length === 0) return null; if (c.length > 1 && c[1]!.voti === c[0]!.voti) return null; return c[0]!; } export function mioVotoSocial( voti: VotoSocial[], matchId: string, categoria: string, votanteId: string, ) { return ( voti.find( (v) => v.match_id === matchId && v.categoria === categoria && v.votante_id === votanteId, ) ?? null ); } /** Badge social vinti da un giocatore in tutte le partite: categoria -> numero. */ export function badgeSocialVinti(voti: VotoSocial[], giocatoreId: string) { const matchIds = [...new Set(voti.map((v) => v.match_id))]; const out: Record = {}; for (const m of matchIds) { for (const cat of categorieSocial) { const v = vincitoreCategoria(voti, m, cat.id); if (v?.id === giocatoreId) out[cat.id] = (out[cat.id] ?? 0) + 1; } } return out; }