diff --git a/src/routes/api/public/scout-finale.ts b/src/routes/api/public/scout-finale.ts new file mode 100644 index 0000000..33bd071 --- /dev/null +++ b/src/routes/api/public/scout-finale.ts @@ -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 }); + }, + }, + }, +});