Invio best-effort il risultato dello scout finalizzato a Strapi
Nuova route server /api/public/scout-finale: proxy verso il content type scout-match-finale con un token Strapi di sola scrittura, mai esposto al client. Il salvataggio in localStorage (già chiamato da finePartita() in scout.tsx nel commit precedente) resta la fonte per le statistiche; questo invio è additivo e non bloccante, se fallisce la partita resta comunque salvata sul device come già accadeva prima. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import { z } from "zod";
|
||||
|
||||
const schema = z.object({
|
||||
id: z.string().min(1).max(50),
|
||||
data: z.string().min(1).max(20),
|
||||
avversario: z.string().min(1).max(80),
|
||||
casa: z.boolean(),
|
||||
setNostri: z.number().int().min(0),
|
||||
setLoro: z.number().int().min(0),
|
||||
parziali: z.array(z.tuple([z.number().int(), z.number().int()])),
|
||||
mvp: z.string().max(80),
|
||||
azioni: z.array(
|
||||
z.object({
|
||||
id: z.string(),
|
||||
tipo: z.enum(["attacco", "ace", "muro", "errore", "punto_avv", "errore_avv"]),
|
||||
giocatoreId: z.string().optional(),
|
||||
set: z.number().int(),
|
||||
ts: z.number(),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* Proxy verso Strapi per il risultato finale di una partita scoutata: additivo, il localStorage
|
||||
* del device resta la fonte usata da useRosa/giocatoriConScout. Best-effort: nessun retry, nessun
|
||||
* upsert (un doppio invio crea al più una entry doppia in Strapi, da cancellare a mano).
|
||||
*/
|
||||
export const Route = createFileRoute("/api/public/scout-finale")({
|
||||
server: {
|
||||
handlers: {
|
||||
POST: async ({ request }) => {
|
||||
const parsed = schema.safeParse(await request.json());
|
||||
if (!parsed.success) return new Response("Dati non validi", { status: 400 });
|
||||
|
||||
const strapiUrl = process.env["VITE_STRAPI_URL"];
|
||||
const token = process.env["STRAPI_WRITE_TOKEN"];
|
||||
if (!strapiUrl || !token) {
|
||||
console.error("scout-finale: STRAPI_URL o STRAPI_WRITE_TOKEN mancanti");
|
||||
return new Response("CMS non configurato", { status: 503 });
|
||||
}
|
||||
|
||||
const m = parsed.data;
|
||||
const res = await fetch(`${strapiUrl}/api/scout-match-finales`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
data: {
|
||||
match_id: m.id,
|
||||
data: m.data,
|
||||
avversario: m.avversario,
|
||||
casa: m.casa,
|
||||
set_nostri: m.setNostri,
|
||||
set_loro: m.setLoro,
|
||||
parziali: m.parziali,
|
||||
mvp: m.mvp,
|
||||
azioni: m.azioni,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
console.error("scout-finale: Strapi ha risposto", res.status, await res.text());
|
||||
return new Response("Salvataggio su CMS non riuscito", { status: 502 });
|
||||
}
|
||||
|
||||
return Response.json({ ok: true });
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user