3741ce34ac
Il documento MODIFICHE_PER_SITO.pdf porta cinque cose.
1. "Small Group" si chiama "Personalized Training Group". Il nome vive anche
nel database dei contenuti, dove `resolveContent` legge prima della copia
nel codice: `scripts/testi-17-agosto.mjs` aggiorna le 19 righe rimaste,
una volta sola, correggendo anche gli articoli ("Lo Small Group" -> "Il
Personalized Training Group"). Lo slug della scheda resta `small-group`:
cambiarlo romperebbe i link gia' girati su WhatsApp.
2. Dalla pagina Servizi le card instradano dove serve. "One to One" apre la
vista Training con One to One, Personalized Training Group e Rehab;
"Class" quella con Holistic e Reformer. Le viste sono `/training/<vista>`;
una vista inventata e' 404, non l'elenco intero, altrimenti un indirizzo
rotto continuerebbe a sembrare buono.
3. La Performance Class non si eroga piu': la scheda che la spiegava
risponde 404, la card "Class" resta in griglia. Con la scheda e' caduta la
tabella prezzi, che era solo sua.
4. Il Check-up racconta Base e Avanzato: trafiletto nuovo nella card e
sezione "Check-up Avanzato" nella scheda, con la Wellness Tower e i cinque
punti. Il calendario delle class si apre ora anche dalla card Class in
griglia e dalla scheda Reformer, oltre che da Holistic.
5. "Promo ed eventi" diventa una pagina di scelta: le promozioni restano su
/promo-eventi/promo, l'inaugurazione del 19 settembre sta su
/promo-eventi/eventi. Il testo dice che il programma della giornata manca
ancora, ed e' editabile dal pannello.
Corretti due link del footer che portavano a schede inesistenti
(`/services/personal-training` non e' mai stato uno slug).
181 test verdi (157 + 24 nuovi), build ok, `astro check` invariato.
80 lines
4.9 KiB
Plaintext
80 lines
4.9 KiB
Plaintext
---
|
|
import Base from '../../layouts/Base.astro';
|
|
import PageHero from '../../components/PageHero.astro';
|
|
import type { ImageMetadata } from 'astro';
|
|
import { services } from '../../data/services';
|
|
import T from '../../components/content/T.astro';
|
|
import TImg from '../../components/content/TImg.astro';
|
|
import CalendarioModal from '../../components/CalendarioModal.astro';
|
|
import { calendariDaMostrare, CARD_CON_CALENDARIO } from '../../data/calendari';
|
|
import { t } from '../../lib/content';
|
|
const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/program-*.jpg', { eager: true });
|
|
const imgOf = (slug: string) => Object.entries(images).find(([p]) => p.includes(`program-${slug}.`))?.[1]?.default;
|
|
const gridServices = services.filter((p) => p.grid !== false);
|
|
// Foto e "Per saperne di più" della stessa card portano allo stesso posto, e lo fanno per
|
|
// costruzione: erano due espressioni diverse e sono divergute — su One to One e Performance
|
|
// Class il testo mandava a /training mentre la foto apriva la scheda del servizio, così la
|
|
// destinazione dipendeva da dove capitava il dito.
|
|
// Alcune card non portano alla propria scheda ma a una vista di /training (One to One e
|
|
// Class, deciso dal cliente il 17/08/2026): la destinazione la dichiara il servizio.
|
|
const hrefOf = (p: (typeof services)[number]) => p.href ?? `/services/${p.slug}`;
|
|
// Il calendario delle class si apre anche da qui, dalla card Class: chi guarda i servizi
|
|
// vuole sapere quando si allena prima ancora di aprire la scheda. Compare solo se c'è
|
|
// davvero una griglia da mostrare, come nelle pagine delle class.
|
|
const conCalendario = calendariDaMostrare(new Date()).length > 0;
|
|
export const prerender = false;
|
|
---
|
|
<Base title={t('services.meta.title')} description={t('services.meta.description')}>
|
|
<PageHero title={t('services.hero.title')} />
|
|
<section class="section">
|
|
<div class="container">
|
|
<div class="section-heading">
|
|
<T tag="services.intro.body" as="p" />
|
|
</div>
|
|
<div class="plist">
|
|
{gridServices.map((p, i) => (
|
|
<article class="plist__card" data-reveal style={`--reveal-delay:${((i % 3) * 0.15).toFixed(2)}s`}>
|
|
{imgOf(p.slug) && (
|
|
<a class="plist__photo" href={hrefOf(p)}>
|
|
<TImg tag={`service.${p.slug}.image`} src={imgOf(p.slug)!} alt={t(`service.${p.slug}.title`)} widths={[400, 700]} sizes="(max-width:767px) 100vw, 33vw" />
|
|
</a>
|
|
)}
|
|
<div class="plist__body">
|
|
<T tag={`service.${p.slug}.title`} as="h3" />
|
|
<T tag={`service.${p.slug}.subtitle`} as="p" class="plist__sub" />
|
|
<T tag={`service.${p.slug}.excerpt`} as="p" />
|
|
{conCalendario && CARD_CON_CALENDARIO.includes(p.slug) && (
|
|
<button type="button" class="plist__calendario" data-apri-calendario>{t('calendario.link-label')}</button>
|
|
)}
|
|
<a class="plist__more" href={hrefOf(p)}>{t('services.card.more-label')}</a>
|
|
</div>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{conCalendario && <CalendarioModal />}
|
|
</Base>
|
|
|
|
<style>
|
|
.plist { display: grid; grid-template-columns: repeat(3, 1fr); gap: 40px 30px; }
|
|
.plist__card { background: #fff; box-shadow: 0 6px 24px rgba(0,0,0,.08); display: flex; flex-direction: column; }
|
|
.plist__photo { display: block; overflow: hidden; }
|
|
.plist__photo img { aspect-ratio: 4/3; object-fit: cover; width: 100%; transition: transform .5s ease; }
|
|
.plist__card:hover .plist__photo img { transform: scale(1.05); }
|
|
.plist__body { padding: 26px 24px 30px; display: flex; flex-direction: column; align-items: flex-start; flex: 1; }
|
|
.plist__card h3 { font-size: 1rem; text-transform: uppercase; letter-spacing: .1em; margin-bottom: .3em; }
|
|
.plist__sub { font-size: .78rem; text-transform: uppercase; letter-spacing: .12em; color: var(--c-accent-dark); }
|
|
.plist__body > p:not(.plist__sub) { font-size: .9rem; white-space: pre-line; }
|
|
.plist__more { font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; text-decoration: none; color: var(--c-heading); margin-top: auto; }
|
|
.plist__more:hover { color: var(--c-accent-dark); }
|
|
/* Il calendario sta sopra "Per saperne di più" (posizione chiesta dal cliente) e apre un
|
|
popup, quindi è un bottone: qui gli si toglie l'aspetto da bottone perché nella card
|
|
stia accanto all'altra voce senza rubarle l'occhio. */
|
|
.plist__calendario { background: none; border: 0; padding: 0; margin-top: auto; cursor: pointer; text-align: left; font-family: var(--font-heading); font-size: .72rem; font-weight: 600; letter-spacing: .18em; text-transform: uppercase; color: var(--c-accent-dark); }
|
|
.plist__calendario:hover { color: var(--c-heading); }
|
|
.plist__calendario + .plist__more { margin-top: 10px; }
|
|
@media (max-width: 991px) { .plist { grid-template-columns: 1fr 1fr; } }
|
|
@media (max-width: 600px) { .plist { grid-template-columns: 1fr; } }
|
|
</style>
|