feat: tag contenuti training, contact e 404

This commit is contained in:
2026-07-05 17:04:17 +02:00
parent 31354c4457
commit bf38fc865c
5 changed files with 62 additions and 27 deletions
+3 -3
View File
@@ -2,11 +2,11 @@
import type { ImageMetadata } from 'astro'; import type { ImageMetadata } from 'astro';
import { getImage } from 'astro:assets'; import { getImage } from 'astro:assets';
interface Props { title: string; eyebrow?: string; bgImage?: ImageMetadata } interface Props { title: string; eyebrow?: string; bgImage?: ImageMetadata | string }
const { title, eyebrow, bgImage } = Astro.props; const { title, eyebrow, bgImage } = Astro.props;
const bg = bgImage ? await getImage({ src: bgImage, width: 1920 }) : null; const bgUrl = typeof bgImage === 'string' ? bgImage : bgImage ? (await getImage({ src: bgImage, width: 1920 })).src : null;
--- ---
<section class:list={['phero', { 'phero--photo': bg }]} style={bg ? `background-image:url(${bg.src})` : undefined}> <section class:list={['phero', { 'phero--photo': bgUrl }]} style={bgUrl ? `background-image:url(${bgUrl})` : undefined}>
<div class="container" data-reveal> <div class="container" data-reveal>
{eyebrow && <p class="eyebrow">{eyebrow}</p>} {eyebrow && <p class="eyebrow">{eyebrow}</p>}
<h1>{title}</h1> <h1>{title}</h1>
+30
View File
@@ -270,6 +270,36 @@ export const contentSeed: SeedEntry[] = [
]), ]),
]), ]),
// --- Training: meta, hero, intro, trial ---
T('training.meta.title', 'Training', []),
T('training.meta.description', 'One to One, Small Groups, Performance Class e Fit Remote: trova il training InsanityLab più adatto a te.', []),
T('training.hero.title', 'training', []),
T('training.intro.title', 'Training'),
T('training.intro.subtitle', 'Porta i tuoi allenamenti al livello successivo: programmi completi e percorsi su misura. Trova il training più adatto alle tue esigenze.'),
T('training.trial.title', 'Prenota la lezione di prova'),
T('training.trial.body', "La lezione di prova è l'occasione perfetta per conoscere il metodo, vivere l'esperienza in prima persona e capire il percorso più adatto a te. Inizia oggi il tuo percorso: prenota la tua lezione di prova."),
T('training.trial.cta', 'Prenota', []),
I('training.trial.image'),
// --- Contact ---
T('contact.meta.title', 'Contatti', []),
T('contact.meta.description', 'Contatta InsanityLab: Via Leandro Alberti 76, Bologna. Compila il form o chiamaci per una consulenza iniziale.', []),
T('contact.hero.title', 'Contattaci', []),
I('contact.hero.image'),
T('contact.map.button', 'Carica la mappa (Google Maps)', []),
T('contact.map.note', 'La mappa viene caricata da Google solo dopo il tuo consenso.', []),
T('contact.info.address-label', 'Indirizzo'),
T('contact.info.phone-label', 'Telefono'),
T('contact.info.email-label', 'E-mail'),
T('contact.invite', 'Per informazioni o per richiedere una consulenza iniziale, compila il form. Un team specializzato ti accoglierà e ti ricontatterà al più presto, oppure lasciaci il tuo contatto.'),
// --- 404 ---
T('notfound.meta.title', 'Pagina non trovata', []),
T('notfound.eyebrow', 'Errore 404', []),
T('notfound.title', 'Pagina non trovata'),
T('notfound.body', 'La pagina che cerchi non esiste o è stata spostata.'),
T('notfound.cta', 'Torna alla home', []),
// I task di estrazione aggiungono qui le entry di header/footer/pagine/data file. // I task di estrazione aggiungono qui le entry di header/footer/pagine/data file.
]; ];
+7 -5
View File
@@ -1,14 +1,16 @@
--- ---
import Base from '../layouts/Base.astro'; import Base from '../layouts/Base.astro';
import T from '../components/content/T.astro';
import { t } from '../lib/content';
export const prerender = true; export const prerender = true;
--- ---
<Base title="Pagina non trovata"> <Base title={t('notfound.meta.title')}>
<section class="section" style="text-align:center; padding-block:140px;"> <section class="section" style="text-align:center; padding-block:140px;">
<div class="container"> <div class="container">
<p class="eyebrow">Errore 404</p> <T tag="notfound.eyebrow" as="p" class="eyebrow" />
<h1>Pagina non trovata</h1> <T tag="notfound.title" as="h1" />
<p>La pagina che cerchi non esiste o è stata spostata.</p> <T tag="notfound.body" as="p" />
<a class="btn" href="/">Torna alla home</a> <a class="btn" href="/">{t('notfound.cta')}</a>
</div> </div>
</section> </section>
</Base> </Base>
+13 -11
View File
@@ -4,35 +4,37 @@ import PageHero from '../components/PageHero.astro';
import ContactForm from '../components/ContactForm.astro'; import ContactForm from '../components/ContactForm.astro';
import { site } from '../data/site'; import { site } from '../data/site';
import contactHero from '../assets/img/contact-hero.jpg'; import contactHero from '../assets/img/contact-hero.jpg';
import T from '../components/content/T.astro';
import { t, contentImageUrl } from '../lib/content';
export const prerender = true; export const prerender = true;
const mapsQuery = encodeURIComponent(`${site.address}, ${site.cityLine}`); const mapsQuery = encodeURIComponent(`${site.address}, ${site.cityLine}`);
--- ---
<Base title="Contatti" description="Contatta InsanityLab: Via Leandro Alberti 76, Bologna. Compila il form o chiamaci per una consulenza iniziale."> <Base title={t('contact.meta.title')} description={t('contact.meta.description')}>
<PageHero title="Contattaci" bgImage={contactHero} /> <PageHero title={t('contact.hero.title')} bgImage={contentImageUrl('contact.hero.image', contactHero.src)} />
<section class="section"> <section class="section">
<div class="container cgrid"> <div class="container cgrid">
<div class="cmap" id="map-box"> <div class="cmap" id="map-box">
<button class="btn btn--dark" id="map-load">Carica la mappa (Google Maps)</button> <button class="btn btn--dark" id="map-load">{t('contact.map.button')}</button>
<p class="cmap__note">La mappa viene caricata da Google solo dopo il tuo consenso.</p> <p class="cmap__note">{t('contact.map.note')}</p>
</div> </div>
<ContactForm variant="full" /> <ContactForm variant="full" />
</div> </div>
<div class="container cinfo"> <div class="container cinfo">
<div> <div>
<h3>Indirizzo</h3> <T tag="contact.info.address-label" as="h3" />
<p>{site.address} {site.cityLine}</p> <p>{t('global.contact.address')} {t('global.contact.city-line')}</p>
</div> </div>
<div> <div>
<h3>Telefono</h3> <T tag="contact.info.phone-label" as="h3" />
<p>{site.phone}</p> <p>{t('global.contact.phone')}</p>
</div> </div>
<div> <div>
<h3>E-mail</h3> <T tag="contact.info.email-label" as="h3" />
<p><a href={`mailto:${site.email}`}>{site.email}</a></p> <p><a href={`mailto:${t('global.contact.email')}`}>{t('global.contact.email')}</a></p>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<p class="cinvite">Per informazioni o per richiedere una consulenza iniziale, compila il form. Un team specializzato ti accoglierà e ti ricontatterà al più presto, oppure lasciaci il tuo contatto.</p> <T tag="contact.invite" as="p" class="cinvite" />
</div> </div>
</section> </section>
</Base> </Base>
+9 -8
View File
@@ -7,18 +7,19 @@ import { Image } from 'astro:assets';
import { trainings } from '../data/trainings'; import { trainings } from '../data/trainings';
import trialImg from '../assets/img/trial-class.jpg'; import trialImg from '../assets/img/trial-class.jpg';
import T from '../components/content/T.astro'; import T from '../components/content/T.astro';
import TImg from '../components/content/TImg.astro';
import { t } from '../lib/content'; import { t } from '../lib/content';
const images = import.meta.glob<{ default: ImageMetadata }>('../assets/img/training-*.{jpg,png}', { eager: true }); const images = import.meta.glob<{ default: ImageMetadata }>('../assets/img/training-*.{jpg,png}', { eager: true });
const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(name))?.[1]?.default; const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(name))?.[1]?.default;
export const prerender = true; export const prerender = true;
--- ---
<Base title="Training" description="One to One, Small Groups, Performance Class e Fit Remote: trova il training InsanityLab più adatto a te."> <Base title={t('training.meta.title')} description={t('training.meta.description')}>
<PageHero title="training" /> <PageHero title={t('training.hero.title')} />
<section class="section" style="padding-bottom:0"> <section class="section" style="padding-bottom:0">
<div class="section-heading"> <div class="section-heading">
<h2>Training</h2> <T tag="training.intro.title" as="h2" />
<p>Porta i tuoi allenamenti al livello successivo: programmi completi e percorsi su misura. Trova il training più adatto alle tue esigenze.</p> <T tag="training.intro.subtitle" as="p" />
</div> </div>
</section> </section>
<TrainingCards /> <TrainingCards />
@@ -42,11 +43,11 @@ export const prerender = true;
<section class="section section--alt"> <section class="section section--alt">
<div class="container trial"> <div class="container trial">
<Image src={trialImg} alt="Lezione di prova InsanityLab" widths={[500, 900]} sizes="(max-width:767px) 100vw, 45vw" data-reveal="left" /> <TImg tag="training.trial.image" src={trialImg} alt="Lezione di prova InsanityLab" widths={[500, 900]} sizes="(max-width:767px) 100vw, 45vw" data-reveal="left" />
<div data-reveal="right"> <div data-reveal="right">
<h2>Prenota la lezione di prova</h2> <T tag="training.trial.title" as="h2" />
<p>La lezione di prova è l'occasione perfetta per conoscere il metodo, vivere l'esperienza in prima persona e capire il percorso più adatto a te. Inizia oggi il tuo percorso: prenota la tua lezione di prova.</p> <T tag="training.trial.body" as="p" />
<a class="btn btn--dark" href="/contact">Prenota</a> <a class="btn btn--dark" href="/contact">{t('training.trial.cta')}</a>
</div> </div>
</div> </div>
</section> </section>