Semplifica il calendario e mostra le note solo sulle card Evento.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Cacciari
2026-09-07 11:38:03 +02:00
co-authored by Cursor
parent 10915d04fc
commit a06c5ed281
3 changed files with 40 additions and 55 deletions
+7
View File
@@ -84,6 +84,9 @@ export function EventoCard({
const isCompleanno = evento.tipo === "compleanno"; const isCompleanno = evento.tipo === "compleanno";
const passato = evento.data < dataOggi(); const passato = evento.data < dataOggi();
const cliccabile = Boolean(linkTo); const cliccabile = Boolean(linkTo);
/** Solo gli eventi extra-campo non hanno scheda dedicata: le note restano sulla card. */
const noteCard =
evento.tipo === "evento" ? evento.note.trim() : "";
const stati = const stati =
evento.tipo === "evento" evento.tipo === "evento"
? // Se resta un vecchio "infortunato", mostra il bottone solo per poterlo togliere. ? // Se resta un vecchio "infortunato", mostra il bottone solo per poterlo togliere.
@@ -171,6 +174,10 @@ export function EventoCard({
</span> </span>
</div> </div>
{noteCard ? (
<p className="mt-2.5 line-clamp-2 text-xs text-muted-foreground">📝 {noteCard}</p>
) : null}
{metaStato ? ( {metaStato ? (
<p <p
className="mt-3 flex items-center gap-1.5 border-t border-border pt-2.5 text-left text-xs font-semibold text-muted-foreground" className="mt-3 flex items-center gap-1.5 border-t border-border pt-2.5 text-left text-xs font-semibold text-muted-foreground"
+7 -5
View File
@@ -96,17 +96,19 @@ export function Section({
children, children,
indice = 0, indice = 0,
}: { }: {
titolo: string; titolo?: string;
azione?: ReactNode; azione?: ReactNode;
children: ReactNode; children: ReactNode;
indice?: number; indice?: number;
}) { }) {
return ( return (
<Reveal as="section" indice={indice} className="px-5 py-4"> <Reveal as="section" indice={indice} className="px-5 py-4">
<div className="mb-3 flex items-center justify-between gap-3"> {titolo || azione ? (
<h2 className="font-display-sm text-lg uppercase">{titolo}</h2> <div className="mb-3 flex items-center justify-between gap-3">
{azione} {titolo ? <h2 className="font-display-sm text-lg uppercase">{titolo}</h2> : <span />}
</div> {azione}
</div>
) : null}
{children} {children}
</Reveal> </Reveal>
); );
+26 -50
View File
@@ -9,7 +9,6 @@ import { EventoCard, linkPerEvento } from "@/components/crapp/EventoCard";
import { Card, PageHeader, Section } from "@/components/crapp/ui-bits"; import { Card, PageHeader, Section } from "@/components/crapp/ui-bits";
import { compleanniEventi, useEventi, type Evento } from "@/lib/eventi"; import { compleanniEventi, useEventi, type Evento } from "@/lib/eventi";
import { useRosa } from "@/lib/rosa"; import { useRosa } from "@/lib/rosa";
import { useGiocatoreCorrente } from "@/lib/user-store";
import { useIsAdmin } from "@/lib/ruoli"; import { useIsAdmin } from "@/lib/ruoli";
import { import {
Drawer, Drawer,
@@ -25,12 +24,12 @@ export const Route = createFileRoute("/calendario")({
{ title: "Calendario squadra — CrAPP" }, { title: "Calendario squadra — CrAPP" },
{ {
name: "description", name: "description",
content: "Allenamenti, partite ed eventi extra del CRAP Volley con vista mensile e lista.", content: "Allenamenti, partite ed eventi extra del CRAP Volley con vista mensile.",
}, },
{ property: "og:title", content: "Calendario squadra — CrAPP" }, { property: "og:title", content: "Calendario squadra — CrAPP" },
{ {
property: "og:description", property: "og:description",
content: "Vista mensile e lista eventi con promemoria per la squadra.", content: "Vista mensile e prossimi eventi con promemoria per la squadra.",
}, },
], ],
}), }),
@@ -105,7 +104,6 @@ function pad2(n: number) {
} }
function Calendario() { function Calendario() {
const [vista, setVista] = useState<"mese" | "lista">("mese");
// SSR-safe: la data di oggi arriva solo dopo il mount. // SSR-safe: la data di oggi arriva solo dopo il mount.
const [oggi, setOggi] = useState<{ anno: number; mese: number; giorno: number } | null>(null); const [oggi, setOggi] = useState<{ anno: number; mese: number; giorno: number } | null>(null);
useEffect(() => { useEffect(() => {
@@ -114,7 +112,6 @@ function Calendario() {
}, []); }, []);
const [giornoSelezionato, setGiornoSelezionato] = useState<number | null>(null); const [giornoSelezionato, setGiornoSelezionato] = useState<number | null>(null);
const [drawerAperto, setDrawerAperto] = useState(false); const [drawerAperto, setDrawerAperto] = useState(false);
const io = useGiocatoreCorrente();
const admin = useIsAdmin(); const admin = useIsAdmin();
const { eventi } = useEventi(); const { eventi } = useEventi();
const rosa = useRosa(); const rosa = useRosa();
@@ -153,55 +150,35 @@ function Calendario() {
<> <>
<PageHeader titolo="Calendario" sottotitolo={`${mesiIT[mese]} ${anno} · Stagione 2026/27`} /> <PageHeader titolo="Calendario" sottotitolo={`${mesiIT[mese]} ${anno} · Stagione 2026/27`} />
<div className="px-5 pt-4"> <Section>
<div className="flex rounded-full bg-secondary p-1"> <Card>
{(["mese", "lista"] as const).map((v) => ( <div className="mb-3 flex items-center justify-between">
<button <button
key={v}
type="button" type="button"
onClick={() => setVista(v)} onClick={precedente}
aria-pressed={vista === v} className="grid h-11 w-11 place-items-center rounded-full bg-secondary text-foreground active:scale-95"
className={cn( aria-label="Mese precedente"
"min-h-11 flex-1 rounded-full text-sm font-bold uppercase tracking-wide transition-colors",
vista === v ? "bg-card shadow-card text-foreground" : "text-muted-foreground",
)}
> >
{v === "mese" ? "Vista mese" : "Lista eventi"} <ChevronLeft className="h-5 w-5" />
</button> </button>
))} <span className="font-display-sm text-xl uppercase">
</div> {mesiIT[mese]} {anno}
</div> </span>
<button
type="button"
onClick={successivo}
className="grid h-11 w-11 place-items-center rounded-full bg-secondary text-foreground active:scale-95"
aria-label="Mese successivo"
>
<ChevronRight className="h-5 w-5" />
</button>
</div>
{vista === "mese" ? ( <div className="grid grid-cols-7 gap-1 text-center text-xs font-bold text-muted-foreground">
<Section titolo={mesiIT[mese]!}> {giorniIT.map((g, i) => (
<Card> <span key={i}>{g}</span>
<div className="mb-3 flex items-center justify-between"> ))}
<button </div>
type="button"
onClick={precedente}
className="grid h-11 w-11 place-items-center rounded-full bg-secondary text-foreground active:scale-95"
aria-label="Mese precedente"
>
<ChevronLeft className="h-5 w-5" />
</button>
<span className="font-display-sm text-xl uppercase">
{mesiIT[mese]} {anno}
</span>
<button
type="button"
onClick={successivo}
className="grid h-11 w-11 place-items-center rounded-full bg-secondary text-foreground active:scale-95"
aria-label="Mese successivo"
>
<ChevronRight className="h-5 w-5" />
</button>
</div>
<div className="grid grid-cols-7 gap-1 text-center text-xs font-bold text-muted-foreground">
{giorniIT.map((g, i) => (
<span key={i}>{g}</span>
))}
</div>
{/* {/*
Il mese si cambia anche con lo swipe: il punto d'arrivo si Il mese si cambia anche con lo swipe: il punto d'arrivo si
decide proiettando la velocità di rilascio (come la decide proiettando la velocità di rilascio (come la
@@ -321,7 +298,6 @@ function Calendario() {
</div> </div>
</Card> </Card>
</Section> </Section>
) : null}
{admin ? ( {admin ? (
<div className="px-5 pt-4"> <div className="px-5 pt-4">