Sposta roster, eventi, presenze, voti, scout e palloni su PocketBase
Riscrive i moduli dati che parlavano con Supabase per usare l'SDK
PocketBase, mantenendo invariate le firme degli hook React Query così i
componenti a valle non cambiano: giocatori-squadra, eventi, presenze,
cacche, pagelle, mvp-voti, badge-social, scout (store/live/stato),
palloni.
Aggiunge due helper condivisi in src/integrations/pocketbase/:
- upsert.ts: PocketBase non ha upsert nativo, questi replicano il
pattern onConflict di Supabase (per id significativo o per filtro su
combinazione di campi), verificati contro un'istanza reale così da non
duplicare record sulla stessa scrittura ripetuta;
- formato.ts: normalizza le date PocketBase ("AAAA-MM-GG HH:MM:SS.sssZ",
spazio non "T") a ISO stretto, altrimenti Date.parse e i confronti
testuali con altre date si comportano in modo incoerente.
Corregge anche due problemi trovati testando contro un'istanza reale:
- alcune API rule confrontavano un campo relazione con @request.auth.id
senza richiedere l'autenticazione, lasciando passare richieste anonime
quando entrambi i lati erano vuoti;
- gli hook non riconoscevano il superuser PocketBase (solo il ruolo
admin applicativo), bloccando le operazioni fatte con pbAdmin.
Aggiunta la colonna "casa" mancante su eventi_app e i campi di sistema
created/updated (non generati automaticamente da PocketBase per le
collection create via migration, a differenza di quanto assunto
inizialmente).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+31
-10
@@ -1,7 +1,8 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { HandHeart, Handshake, Laugh, Scale, Users } from "lucide-react";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import { supabase } from "@/integrations/supabase/client";
|
||||
import { pb } from "@/integrations/pocketbase/client";
|
||||
import { upsertByFilter } from "@/integrations/pocketbase/upsert";
|
||||
|
||||
export type CategoriaSocial = {
|
||||
id: string;
|
||||
@@ -58,6 +59,14 @@ export type VotoSocial = {
|
||||
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. */
|
||||
@@ -66,11 +75,14 @@ export function useVotiSocial() {
|
||||
queryKey: CHIAVE,
|
||||
staleTime: 10 * 60_000,
|
||||
queryFn: async (): Promise<VotoSocial[]> => {
|
||||
const { data, error } = await supabase
|
||||
.from("badge_social_voti")
|
||||
.select("match_id, categoria, votante_id, votato_id, votato_nome");
|
||||
if (error) throw error;
|
||||
return (data ?? []) as VotoSocial[];
|
||||
const righe = await pb.collection("badge_social_voti").getFullList<RigaSocialPocketBase>();
|
||||
return righe.map((r) => ({
|
||||
match_id: r.evento,
|
||||
categoria: r.categoria,
|
||||
votante_id: r.votante,
|
||||
votato_id: r.votato,
|
||||
votato_nome: r.votato_nome,
|
||||
}));
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -79,10 +91,19 @@ export function useVotaSocial() {
|
||||
const qc = useQueryClient();
|
||||
return useMutation({
|
||||
mutationFn: async (voto: VotoSocial) => {
|
||||
const { error } = await supabase
|
||||
.from("badge_social_voti")
|
||||
.upsert(voto, { onConflict: "match_id,categoria,votante_id" });
|
||||
if (error) throw error;
|
||||
// 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.
|
||||
|
||||
Reference in New Issue
Block a user