Aggancia useRosa() a giocatori_squadra (DD-015)
useRosa()/useIo()/useObiettivi() leggono ora l'anagrafica da giocatori_squadra tramite useGiocatoriSquadra(), filtrando solo i giocatori attivo. crapp-data.ts resta il seed storico e il fallback (rosaFallback) e fornisce anche la data di nascita per id, non ancora una colonna della tabella. Aggiunge giocatori-squadra.server.ts per leggere la rosa lato route API (stesso pattern di eventi.server.ts).
This commit is contained in:
@@ -112,6 +112,14 @@ export const giocatori: Giocatore[] = rosaCSI
|
|||||||
}))
|
}))
|
||||||
.sort((a, b) => dividiNome(a.nome).cognome.localeCompare(dividiNome(b.nome).cognome, "it"));
|
.sort((a, b) => dividiNome(a.nome).cognome.localeCompare(dividiNome(b.nome).cognome, "it"));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fallback per la data di nascita: `giocatori_squadra` non ha ancora questa colonna
|
||||||
|
* (DD-015 follow-up). Un giocatore aggiunto dopo la migrazione non ha nascita nota.
|
||||||
|
*/
|
||||||
|
export const nascitaPerId: Record<string, string> = Object.fromEntries(
|
||||||
|
giocatori.map((g) => [g.id, g.nascita]),
|
||||||
|
);
|
||||||
|
|
||||||
export type RigaClassifica = {
|
export type RigaClassifica = {
|
||||||
pos: number;
|
pos: number;
|
||||||
squadra: string;
|
squadra: string;
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||||
|
import {
|
||||||
|
COLONNE_SQUADRA,
|
||||||
|
daRigaSquadra,
|
||||||
|
type GiocatoreSquadra,
|
||||||
|
type RigaGiocatoreSquadra,
|
||||||
|
} from "./giocatori-squadra";
|
||||||
|
|
||||||
|
/** Lettura squadra lato server (route API): stessa conversione del client. */
|
||||||
|
export async function leggiGiocatoriSquadra(): Promise<GiocatoreSquadra[]> {
|
||||||
|
const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
|
||||||
|
// `types.ts` non include ancora `giocatori_squadra` con le colonne di M8 (vedi client-nuove-tabelle.ts).
|
||||||
|
const client = supabaseAdmin as unknown as SupabaseClient;
|
||||||
|
const { data } = await client
|
||||||
|
.from("giocatori_squadra")
|
||||||
|
.select(COLONNE_SQUADRA)
|
||||||
|
.order("cognome")
|
||||||
|
.order("nome");
|
||||||
|
return ((data ?? []) as RigaGiocatoreSquadra[]).map(daRigaSquadra);
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ export type GiocatoreSquadra = {
|
|||||||
dataTessera: string | null;
|
dataTessera: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
type RigaGiocatoreSquadra = {
|
export type RigaGiocatoreSquadra = {
|
||||||
id: string;
|
id: string;
|
||||||
nome: string;
|
nome: string;
|
||||||
cognome: string;
|
cognome: string;
|
||||||
@@ -73,17 +73,12 @@ export function slotPerEmail(
|
|||||||
return righe.find((g) => !g.authUserId && g.email?.trim().toLowerCase() === cercata) ?? null;
|
return righe.find((g) => !g.authUserId && g.email?.trim().toLowerCase() === cercata) ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchSquadra(): Promise<GiocatoreSquadra[]> {
|
export const COLONNE_SQUADRA =
|
||||||
const { data, error } = await supabaseNuoveTabelle
|
"id, nome, cognome, numero, ruolo, auth_user_id, attivo, email, numero_tessera, data_tessera";
|
||||||
.from("giocatori_squadra")
|
|
||||||
.select(
|
/** Conversione riga database -> modello applicativo (riusabile anche lato server). */
|
||||||
"id, nome, cognome, numero, ruolo, auth_user_id, attivo, email, numero_tessera, data_tessera",
|
export function daRigaSquadra(r: RigaGiocatoreSquadra): GiocatoreSquadra {
|
||||||
)
|
return {
|
||||||
.order("cognome")
|
|
||||||
.order("nome");
|
|
||||||
if (error) throw error;
|
|
||||||
const righe = (data ?? []) as RigaGiocatoreSquadra[];
|
|
||||||
return righe.map((r) => ({
|
|
||||||
id: r.id,
|
id: r.id,
|
||||||
nome: r.nome,
|
nome: r.nome,
|
||||||
cognome: r.cognome,
|
cognome: r.cognome,
|
||||||
@@ -94,7 +89,18 @@ async function fetchSquadra(): Promise<GiocatoreSquadra[]> {
|
|||||||
email: r.email,
|
email: r.email,
|
||||||
numeroTessera: r.numero_tessera,
|
numeroTessera: r.numero_tessera,
|
||||||
dataTessera: r.data_tessera,
|
dataTessera: r.data_tessera,
|
||||||
}));
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchSquadra(): Promise<GiocatoreSquadra[]> {
|
||||||
|
const { data, error } = await supabaseNuoveTabelle
|
||||||
|
.from("giocatori_squadra")
|
||||||
|
.select(COLONNE_SQUADRA)
|
||||||
|
.order("cognome")
|
||||||
|
.order("nome");
|
||||||
|
if (error) throw error;
|
||||||
|
const righe = (data ?? []) as RigaGiocatoreSquadra[];
|
||||||
|
return righe.map(daRigaSquadra);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Anagrafica squadra: una lettura per sessione, cambia raramente. */
|
/** Anagrafica squadra: una lettura per sessione, cambia raramente. */
|
||||||
|
|||||||
+36
-32
@@ -1,5 +1,6 @@
|
|||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { giocatori, type Giocatore } from "./crapp-data";
|
import { nascitaPerId, type Giocatore } from "./crapp-data";
|
||||||
|
import { nomeCompleto, useGiocatoriSquadra } from "./giocatori-squadra";
|
||||||
import { mvpVintiPerGiocatore, useVotiMvp } from "./mvp-voti";
|
import { mvpVintiPerGiocatore, useVotiMvp } from "./mvp-voti";
|
||||||
import { mediePagelle, usePagelle } from "./pagelle";
|
import { mediePagelle, usePagelle } from "./pagelle";
|
||||||
import { statisticheCacche, useCacche } from "./cacche";
|
import { statisticheCacche, useCacche } from "./cacche";
|
||||||
@@ -8,21 +9,24 @@ import { useTurniPalloni } from "./palloni";
|
|||||||
import { useInfortuniERitardi } from "./infortuni";
|
import { useInfortuniERitardi } from "./infortuni";
|
||||||
import { useGiocatoreId } from "./user-store";
|
import { useGiocatoreId } from "./user-store";
|
||||||
import { useEventi } from "./eventi";
|
import { useEventi } from "./eventi";
|
||||||
import {
|
import { contaPresenzeGiocatore, totaliEventiGiocatore, useRispostePresenze } from "./presenze";
|
||||||
contaPresenzeGiocatore,
|
|
||||||
totaliEventiGiocatore,
|
|
||||||
useRispostePresenze,
|
|
||||||
} from "./presenze";
|
|
||||||
import { obiettiviOrdinati } from "./obiettivi";
|
import { obiettiviOrdinati } from "./obiettivi";
|
||||||
import { useCsi } from "./csi";
|
import { useCsi } from "./csi";
|
||||||
import { partiteGiocate } from "./csi-core";
|
import { partiteGiocate } from "./csi-core";
|
||||||
|
|
||||||
|
function iniziali(nome: string, cognome: string): string {
|
||||||
|
return `${nome[0] ?? ""}${cognome[0] ?? ""}`.toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rosa completa con tutte le statistiche personali (presenze, MVP, media voto,
|
* Rosa completa con tutte le statistiche personali (presenze, MVP, media voto,
|
||||||
* palloni, infortuni, ritardi, cacche). Usa solo cache già in memoria:
|
* palloni, infortuni, ritardi, cacche). Legge l'anagrafica da `giocatori_squadra`
|
||||||
* nessuna query aggiuntiva rispetto a quelle che l'app fa comunque.
|
* (DD-015): solo i giocatori attivi, gli altri restano nel database ma spariscono
|
||||||
|
* dagli elenchi correnti. Usa solo cache già in memoria: nessuna query aggiuntiva
|
||||||
|
* rispetto a quelle che l'app fa comunque.
|
||||||
*/
|
*/
|
||||||
export function useRosa(): Giocatore[] {
|
export function useRosa(): Giocatore[] {
|
||||||
|
const { righe: squadra } = useGiocatoriSquadra();
|
||||||
const voti = useVotiMvp();
|
const voti = useVotiMvp();
|
||||||
const { voti: pagelle } = usePagelle();
|
const { voti: pagelle } = usePagelle();
|
||||||
const { righe: cacche } = useCacche();
|
const { righe: cacche } = useCacche();
|
||||||
@@ -39,28 +43,30 @@ export function useRosa(): Giocatore[] {
|
|||||||
const palloni = conteggioTurni(turni);
|
const palloni = conteggioTurni(turni);
|
||||||
const mvpVinti = mvpVintiPerGiocatore(votiMvp);
|
const mvpVinti = mvpVintiPerGiocatore(votiMvp);
|
||||||
|
|
||||||
return giocatori.map((g) => ({
|
return squadra
|
||||||
...g,
|
.filter((g) => g.attivo)
|
||||||
presenze: contaPresenzeGiocatore(g.id, eventi, mappaPresenze),
|
.map((g) => ({
|
||||||
totaliEventi: totaliEventiGiocatore(g.id, eventi),
|
id: g.id,
|
||||||
mvp: mvpVinti[g.id] ?? 0,
|
nome: nomeCompleto(g),
|
||||||
mediaVoto: medie[g.id]?.media ?? 0,
|
numero: g.numero,
|
||||||
palloni: palloni[g.id] ?? 0,
|
ruolo: g.ruolo,
|
||||||
cacche: statCacche[g.id]?.giornateTop ?? 0,
|
nascita: nascitaPerId[g.id] ?? "",
|
||||||
cacchePartita: statCacche[g.id]?.media ?? 0,
|
iniziali: iniziali(g.nome, g.cognome),
|
||||||
infortuni: infortuni[g.id] ?? 0,
|
presenze: contaPresenzeGiocatore(g.id, eventi, mappaPresenze),
|
||||||
ritardi: ritardi[g.id] ?? 0,
|
totaliEventi: totaliEventiGiocatore(g.id, eventi),
|
||||||
}));
|
streak: 0,
|
||||||
}, [
|
serieAllenamenti: 0,
|
||||||
votiMvp,
|
seriePartite: 0,
|
||||||
pagelle,
|
serieConferme: 0,
|
||||||
cacche,
|
mvp: mvpVinti[g.id] ?? 0,
|
||||||
turni,
|
mediaVoto: medie[g.id]?.media ?? 0,
|
||||||
infortuni,
|
palloni: palloni[g.id] ?? 0,
|
||||||
ritardi,
|
cacche: statCacche[g.id]?.giornateTop ?? 0,
|
||||||
eventi,
|
cacchePartita: statCacche[g.id]?.media ?? 0,
|
||||||
mappaPresenze,
|
infortuni: infortuni[g.id] ?? 0,
|
||||||
]);
|
ritardi: ritardi[g.id] ?? 0,
|
||||||
|
}));
|
||||||
|
}, [squadra, votiMvp, pagelle, cacche, turni, infortuni, ritardi, eventi, mappaPresenze]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Il giocatore selezionato sul dispositivo, con le statistiche complete. */
|
/** Il giocatore selezionato sul dispositivo, con le statistiche complete. */
|
||||||
@@ -83,5 +89,3 @@ export function useObiettivi() {
|
|||||||
: 0;
|
: 0;
|
||||||
return obiettiviOrdinati(rosa, { eventi, presenze, pagelle, vittorie });
|
return obiettiviOrdinati(rosa, { eventi, presenze, pagelle, vittorie });
|
||||||
}
|
}
|
||||||
|
|
||||||
export { giocatori };
|
|
||||||
|
|||||||
Reference in New Issue
Block a user