registri dei piani in git (AI-OS#309)
Refs gitea:Adriano/AI-OS#310 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,415 @@
|
||||
# Review package: 3f01721..34fd3d2
|
||||
|
||||
## Commits
|
||||
34fd3d2 feat: tag contenuti home cards, team, metodo, partner, agenda
|
||||
|
||||
## Files changed
|
||||
src/components/Agenda.astro | 11 ++++---
|
||||
src/components/content/TImg.astro | 2 +-
|
||||
src/components/home/MethodSteps.astro | 17 +++++-----
|
||||
src/components/home/PartnersStrip.astro | 5 +--
|
||||
src/components/home/ProgramsGrid.astro | 5 +--
|
||||
src/components/home/TeamSection.astro | 23 ++++++++------
|
||||
src/components/home/TrainingCards.astro | 16 +++++-----
|
||||
src/data/content-seed.ts | 55 +++++++++++++++++++++++++++++++++
|
||||
src/pages/training.astro | 14 +++++----
|
||||
9 files changed, 108 insertions(+), 40 deletions(-)
|
||||
|
||||
## Diff
|
||||
diff --git a/src/components/Agenda.astro b/src/components/Agenda.astro
|
||||
index db5839b..6dc3b68 100644
|
||||
--- a/src/components/Agenda.astro
|
||||
+++ b/src/components/Agenda.astro
|
||||
@@ -1,27 +1,28 @@
|
||||
---
|
||||
import { agenda, disciplines, days, slots } from '../data/agenda';
|
||||
+import T from './content/T.astro';
|
||||
---
|
||||
<section class="section section--dark agenda">
|
||||
<div class="container">
|
||||
- <div class="section-heading" data-reveal><h2>Agenda</h2></div>
|
||||
+ <div class="section-heading" data-reveal><T tag="agenda.title" as="h2" /></div>
|
||||
<div class="agenda__tabs" role="tablist" data-reveal style="--reveal-delay:.1s">
|
||||
{disciplines.map((d, i) => (
|
||||
- <button class:list={['agenda__tab', { 'is-active': i === 0 }]} data-filter={d} role="tab" aria-selected={i === 0 ? 'true' : 'false'}>{d}</button>
|
||||
+ <button class:list={['agenda__tab', { 'is-active': i === 0 }]} data-filter={d} role="tab" aria-selected={i === 0 ? 'true' : 'false'}><T tag={`agenda.discipline.${i + 1}`} as="span" /></button>
|
||||
))}
|
||||
</div>
|
||||
<div class="agenda__grid" data-reveal style="--reveal-delay:.2s">
|
||||
<div class="agenda__corner"></div>
|
||||
- {days.map((d) => <div class="agenda__day">{d}</div>)}
|
||||
- {slots.map((slot) => (
|
||||
+ {days.map((_, i) => <T tag={`agenda.day.${i + 1}`} as="div" class="agenda__day" />)}
|
||||
+ {slots.map((slot, si) => (
|
||||
<>
|
||||
- <div class="agenda__slot">{slot}</div>
|
||||
+ <T tag={`agenda.slot.${si + 1}`} as="div" class="agenda__slot" />
|
||||
{days.map((_, dayIdx) => {
|
||||
const entry = agenda.find((e) => e.day === dayIdx && e.slot === slot);
|
||||
return entry
|
||||
? <div class="agenda__cell" data-discipline={entry.discipline}><strong>{entry.discipline}</strong><span>{entry.time}</span><em>{entry.trainer}</em></div>
|
||||
: <div class="agenda__cell agenda__cell--empty"></div>;
|
||||
})}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
diff --git a/src/components/content/TImg.astro b/src/components/content/TImg.astro
|
||||
index 6c92a75..3fcb915 100644
|
||||
--- a/src/components/content/TImg.astro
|
||||
+++ b/src/components/content/TImg.astro
|
||||
@@ -1,14 +1,14 @@
|
||||
---
|
||||
import { Image } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { getImageOverride } from '../../lib/content';
|
||||
interface Props {
|
||||
tag: string; src: ImageMetadata; alt: string;
|
||||
- class?: string; loading?: 'lazy' | 'eager'; widths?: number[]; sizes?: string;
|
||||
+ class?: string; loading?: 'lazy' | 'eager'; widths?: number[]; sizes?: string; height?: number;
|
||||
}
|
||||
const { tag, src, alt, class: cls, ...rest } = Astro.props;
|
||||
const override = getImageOverride(tag);
|
||||
---
|
||||
{override
|
||||
? <img src={override} alt={alt} class={cls} data-tag={tag} loading={rest.loading} />
|
||||
: <Image src={src} alt={alt} class={cls} data-tag={tag} {...rest} />}
|
||||
diff --git a/src/components/home/MethodSteps.astro b/src/components/home/MethodSteps.astro
|
||||
index 2e5b670..17da6fe 100644
|
||||
--- a/src/components/home/MethodSteps.astro
|
||||
+++ b/src/components/home/MethodSteps.astro
|
||||
@@ -1,33 +1,34 @@
|
||||
---
|
||||
-import { Image } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
-import { methodIntro, methodExtraNote, methodSteps } from '../../data/method';
|
||||
+import { methodSteps } from '../../data/method';
|
||||
+import T from '../content/T.astro';
|
||||
+import TImg from '../content/TImg.astro';
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/method-*.{jpg,png}', { eager: true });
|
||||
const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(name))?.[1].default;
|
||||
---
|
||||
<section class="section section--alt">
|
||||
<div class="container">
|
||||
<div class="section-heading" data-reveal>
|
||||
- <h2>Il metodo<br />InsanityLab</h2>
|
||||
- <p set:html={methodIntro.replace('Metodo Insanitylab', '<strong>Metodo Insanitylab</strong>')} />
|
||||
+ <T tag="home.method.title" as="h2" />
|
||||
+ <T tag="method.intro" as="p" />
|
||||
</div>
|
||||
- <p class="method__note">{methodExtraNote}</p>
|
||||
+ <T tag="method.extra-note" as="p" class="method__note" />
|
||||
<div class="method__row">
|
||||
{methodSteps.map((s, i) => (
|
||||
<div class:list={['method__step', { 'method__step--extra': s.extra }]} data-reveal style={`--reveal-delay:${(i * 0.15).toFixed(2)}s`}>
|
||||
<div class="method__circle">
|
||||
- {imgOf(s.image) && <Image src={imgOf(s.image)!} alt="" widths={[220]} sizes="220px" />}
|
||||
+ {imgOf(s.image) && <TImg tag={`method.step.${s.n}.image`} src={imgOf(s.image)!} alt="" widths={[220]} sizes="220px" />}
|
||||
<span>{s.n}</span>
|
||||
</div>
|
||||
- <h3>{s.title}</h3>
|
||||
- <p>{s.text}</p>
|
||||
+ <T tag={`method.step.${s.n}.title`} as="h3" />
|
||||
+ <T tag={`method.step.${s.n}.text`} as="p" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.method__note { text-align: right; font-size: .8rem; color: var(--c-text-light); max-width: 260px; margin-left: auto; }
|
||||
.method__row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 30px; text-align: center; position: relative; }
|
||||
.method__circle { position: relative; width: 150px; height: 150px; margin: 0 auto 20px; border: 1px dashed var(--c-accent-dark); border-radius: 50%; padding: 8px; }
|
||||
diff --git a/src/components/home/PartnersStrip.astro b/src/components/home/PartnersStrip.astro
|
||||
index db60097..fea7bf5 100644
|
||||
--- a/src/components/home/PartnersStrip.astro
|
||||
+++ b/src/components/home/PartnersStrip.astro
|
||||
@@ -1,18 +1,19 @@
|
||||
---
|
||||
-import { Image } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { partners } from '../../data/partners';
|
||||
+import TImg from '../content/TImg.astro';
|
||||
+import { t } from '../../lib/content';
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/partner-*.{jpg,png}', { eager: true });
|
||||
const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(name))?.[1].default;
|
||||
---
|
||||
<section class="pstrip" aria-label="partner">
|
||||
<div class="container pstrip__in" data-reveal="fade">
|
||||
- {partners.map((p) => imgOf(p.image) && <Image src={imgOf(p.image)!} alt={p.name} height={44} />)}
|
||||
+ {partners.map((p, i) => imgOf(p.image) && <TImg tag={`partner.${i + 1}.image`} src={imgOf(p.image)!} alt={t(`partner.${i + 1}.name`)} height={44} />)}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.pstrip { background: var(--c-accent); padding-block: 40px; }
|
||||
.pstrip__in { display: flex; align-items: center; justify-content: space-around; gap: 30px; flex-wrap: wrap; }
|
||||
.pstrip img { height: 44px; width: auto; opacity: .9; }
|
||||
</style>
|
||||
diff --git a/src/components/home/ProgramsGrid.astro b/src/components/home/ProgramsGrid.astro
|
||||
index 564b2b8..058fd6a 100644
|
||||
--- a/src/components/home/ProgramsGrid.astro
|
||||
+++ b/src/components/home/ProgramsGrid.astro
|
||||
@@ -1,19 +1,20 @@
|
||||
---
|
||||
import { programs } from '../../data/programs';
|
||||
import { programIcons as icons } from '../../data/program-icons';
|
||||
+import T from '../content/T.astro';
|
||||
---
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="section-heading" data-reveal>
|
||||
- <h2>Programmi</h2>
|
||||
- <p>Questi sono i programmi delle classi di Insanity Lab selezionati per voi. Abbiamo scelto i migliori percorsi per offrirvi un’esperienza di allenamento completa e mirata.</p>
|
||||
+ <T tag="home.programs.title" as="h2" />
|
||||
+ <T tag="home.programs.body" as="p" />
|
||||
</div>
|
||||
<div class="pgrid">
|
||||
{programs.map((p, i) => (
|
||||
<a class="pgrid__item" href={`/programs/${p.slug}`} data-reveal style={`--reveal-delay:${(i % 3) * 0.15}s`}>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="var(--c-accent-dark)" stroke-width="1.4" width="52" height="52" aria-hidden="true"><path d={icons[p.slug]} /></svg>
|
||||
<h3>{p.title}</h3>
|
||||
<p>{p.subtitle}</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
diff --git a/src/components/home/TeamSection.astro b/src/components/home/TeamSection.astro
|
||||
index 64e1d19..baa0def 100644
|
||||
--- a/src/components/home/TeamSection.astro
|
||||
+++ b/src/components/home/TeamSection.astro
|
||||
@@ -1,31 +1,36 @@
|
||||
---
|
||||
-import { Image } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { team, homeTeam } from '../../data/team';
|
||||
+import T from '../content/T.astro';
|
||||
+import TImg from '../content/TImg.astro';
|
||||
+import { t } from '../../lib/content';
|
||||
const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/team-*.{jpg,png}', { eager: true });
|
||||
const members = homeTeam.map((short) => team.find((m) => m.shortName === short)!).filter((m) => m.image);
|
||||
const imgOf = (name: string) => Object.entries(images).find(([p]) => p.includes(`${name}.`))?.[1].default;
|
||||
---
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
<div class="tteam__head" data-reveal>
|
||||
- <h2>Team<br />Trainer</h2>
|
||||
- <a class="btn" href="/about">Scopri team</a>
|
||||
+ <T tag="home.team.title" as="h2" />
|
||||
+ <a class="btn" href="/about"><T tag="home.team.cta" as="span" /></a>
|
||||
</div>
|
||||
<div class="tteam__grid">
|
||||
- {members.map((m, i) => (
|
||||
- <figure class="tteam__card" data-reveal style={`--reveal-delay:${i * 0.12}s`}>
|
||||
- <Image src={imgOf(m.image!)!} alt={m.name} widths={[300, 500]} sizes="(max-width: 767px) 50vw, 25vw" />
|
||||
- <figcaption>{m.shortName}</figcaption>
|
||||
- </figure>
|
||||
- ))}
|
||||
+ {members.map((m, i) => {
|
||||
+ const slug = m.shortName.toLowerCase();
|
||||
+ return (
|
||||
+ <figure class="tteam__card" data-reveal style={`--reveal-delay:${i * 0.12}s`}>
|
||||
+ <TImg tag={`team.${slug}.image`} src={imgOf(m.image!)!} alt={t(`team.${slug}.name`)} widths={[300, 500]} sizes="(max-width: 767px) 50vw, 25vw" />
|
||||
+ <figcaption>{m.shortName}</figcaption>
|
||||
+ </figure>
|
||||
+ );
|
||||
+ })}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.tteam__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 40px; }
|
||||
.tteam__head h2 { text-transform: uppercase; letter-spacing: .1em; margin: 0; }
|
||||
.tteam__grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; }
|
||||
.tteam__card { position: relative; margin: 0; overflow: hidden; }
|
||||
.tteam__card img { aspect-ratio: 3/4; object-fit: cover; width: 100%; transition: transform .5s ease; }
|
||||
diff --git a/src/components/home/TrainingCards.astro b/src/components/home/TrainingCards.astro
|
||||
index ee5ec91..f8937a1 100644
|
||||
--- a/src/components/home/TrainingCards.astro
|
||||
+++ b/src/components/home/TrainingCards.astro
|
||||
@@ -1,33 +1,35 @@
|
||||
---
|
||||
-import { Image } from 'astro:assets';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { trainings } from '../../data/trainings';
|
||||
+import T from '../content/T.astro';
|
||||
+import TImg from '../content/TImg.astro';
|
||||
+import { t } from '../../lib/content';
|
||||
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 tones = ['taupe', 'tan', 'dark', 'charcoal'];
|
||||
// riga 1 (training 0-1): card, foto | riga 2 (training 2-3): foto, card
|
||||
const isSwapRow = (i: number) => Math.floor(i / 2) % 2 === 1;
|
||||
---
|
||||
<section class="tcards">
|
||||
- {trainings.map((t, i) => {
|
||||
- const img = imgOf(t.image);
|
||||
+ {trainings.map((tr, i) => {
|
||||
+ const img = imgOf(tr.image);
|
||||
const card = (
|
||||
<div class:list={['tcards__cell', `tcards__cell--${tones[i]}`]} data-reveal="fade" style={`--reveal-delay:${(i % 2) * 0.15}s`}>
|
||||
- <h3>{t.title}</h3>
|
||||
- <p>{t.caption}</p>
|
||||
- <a class="tcards__link" href={t.cta.href}>Scopri →</a>
|
||||
+ <T tag={`training.${tr.id}.title`} as="h3" />
|
||||
+ <T tag={`training.${tr.id}.caption`} as="p" />
|
||||
+ <a class="tcards__link" href={tr.cta.href}><T tag="home.training-cards.link-label" as="span" /> →</a>
|
||||
</div>
|
||||
);
|
||||
const photo = img ? (
|
||||
<div class="tcards__photo" data-reveal="fade" style={`--reveal-delay:${((i % 2) * 0.15 + 0.1).toFixed(2)}s`}>
|
||||
- <Image src={img} alt={t.title} class="tcards__img" widths={[400, 700]} sizes="(max-width: 767px) 50vw, 25vw" />
|
||||
+ <TImg tag={`training.${tr.id}.image`} src={img} alt={t(`training.${tr.id}.title`)} class="tcards__img" widths={[400, 700]} sizes="(max-width: 767px) 50vw, 25vw" />
|
||||
</div>
|
||||
) : null;
|
||||
return isSwapRow(i) ? <>{photo}{card}</> : <>{card}{photo}</>;
|
||||
})}
|
||||
</section>
|
||||
|
||||
<style>
|
||||
.tcards { display: grid; grid-template-columns: repeat(4, 1fr); }
|
||||
.tcards__cell { padding: 48px 36px; display: flex; flex-direction: column; justify-content: center; aspect-ratio: 1; }
|
||||
.tcards__cell--taupe { background: #6b5d5b; }
|
||||
diff --git a/src/data/content-seed.ts b/src/data/content-seed.ts
|
||||
index dfecec8..9f54a09 100644
|
||||
--- a/src/data/content-seed.ts
|
||||
+++ b/src/data/content-seed.ts
|
||||
@@ -1,12 +1,17 @@
|
||||
import type { StyleGroup } from '../lib/style-presets';
|
||||
import { site } from './site';
|
||||
+import { trainings } from './trainings';
|
||||
+import { team } from './team';
|
||||
+import { methodIntro, methodExtraNote, methodSteps } from './method';
|
||||
+import { partners } from './partners';
|
||||
+import { disciplines, days, slots } from './agenda';
|
||||
|
||||
export type ContentType = 'text' | 'html' | 'image';
|
||||
export interface SeedEntry { tag: string; type: ContentType; value: string; styleOptions?: StyleGroup[] }
|
||||
|
||||
const T = (tag: string, value: string, styleOptions: StyleGroup[] = ['size', 'color', 'weight', 'style']): SeedEntry =>
|
||||
({ tag, type: 'text', value, styleOptions });
|
||||
const H = (tag: string, value: string, styleOptions: StyleGroup[] = ['size', 'color']): SeedEntry =>
|
||||
({ tag, type: 'html', value, styleOptions });
|
||||
const I = (tag: string): SeedEntry => ({ tag, type: 'image', value: '' });
|
||||
|
||||
@@ -90,14 +95,64 @@ export const contentSeed: SeedEntry[] = [
|
||||
T('home.feature.longevity.body', 'Benessere completo tra movimento, nutrizione e stile di vita. Un percorso personalizzato che unisce prevenzione, recupero ed equilibrio. Investi nella tua salute e qualità della vita nel tempo.'),
|
||||
T('home.feature.longevity.cta', 'Scopri'),
|
||||
I('home.feature.performance.image'),
|
||||
I('home.feature.balance.image'),
|
||||
I('home.feature.longevity.image'),
|
||||
|
||||
// --- Home: quote banner ---
|
||||
H('home.quote.text', '<strong>PERFORMANCE</strong> È SPINGERE OLTRE I PROPRI LIMITI, <strong>BALANCE</strong> È SAPERLI ASCOLTARE, <strong>LONGEVITY</strong> È COSTRUIRE NEL TEMPO CIÒ CHE DAVVERO CONTA.'),
|
||||
T('home.quote.cite', 'Insanitylab', []),
|
||||
I('home.quote.image'),
|
||||
+
|
||||
+ // --- Home: training cards (data-driven da trainings.ts) ---
|
||||
+ T('home.training-cards.link-label', 'Scopri', []),
|
||||
+ ...trainings.flatMap((tr) => [
|
||||
+ T(`training.${tr.id}.title`, tr.title),
|
||||
+ T(`training.${tr.id}.caption`, tr.caption),
|
||||
+ T(`training.${tr.id}.description`, tr.description),
|
||||
+ T(`training.${tr.id}.cta-label`, tr.cta.label, []),
|
||||
+ I(`training.${tr.id}.image`),
|
||||
+ ]),
|
||||
+
|
||||
+ // --- Home: programmi ---
|
||||
+ T('home.programs.title', 'Programmi'),
|
||||
+ T('home.programs.body', 'Questi sono i programmi delle classi di Insanity Lab selezionati per voi. Abbiamo scelto i migliori percorsi per offrirvi un’esperienza di allenamento completa e mirata.'),
|
||||
+
|
||||
+ // --- Home: team (data-driven da team.ts) ---
|
||||
+ H('home.team.title', 'Team<br />Trainer'),
|
||||
+ T('home.team.cta', 'Scopri team', []),
|
||||
+ ...team.flatMap((m) => {
|
||||
+ const slug = m.shortName.toLowerCase();
|
||||
+ return [
|
||||
+ T(`team.${slug}.name`, m.name, []),
|
||||
+ T(`team.${slug}.role`, m.role, []),
|
||||
+ T(`team.${slug}.bio`, m.bio),
|
||||
+ I(`team.${slug}.image`),
|
||||
+ I(`team.${slug}.image-about`),
|
||||
+ ];
|
||||
+ }),
|
||||
+
|
||||
+ // --- Home: metodo (data-driven da method.ts) ---
|
||||
+ H('home.method.title', 'Il metodo<br />InsanityLab'),
|
||||
+ H('method.intro', methodIntro.replace('Metodo Insanitylab', '<strong>Metodo Insanitylab</strong>')),
|
||||
+ T('method.extra-note', methodExtraNote, []),
|
||||
+ ...methodSteps.flatMap((s) => [
|
||||
+ T(`method.step.${s.n}.title`, s.title),
|
||||
+ T(`method.step.${s.n}.text`, s.text),
|
||||
+ I(`method.step.${s.n}.image`),
|
||||
+ ]),
|
||||
+
|
||||
+ // --- Home: partner (data-driven da partners.ts) ---
|
||||
+ ...partners.flatMap((p, i) => [
|
||||
+ T(`partner.${i + 1}.name`, p.name, []),
|
||||
+ I(`partner.${i + 1}.image`),
|
||||
+ ]),
|
||||
+
|
||||
+ // --- Agenda (scope limitato: titolo, discipline, giorni, slot — celle escluse) ---
|
||||
+ T('agenda.title', 'Agenda'),
|
||||
+ ...disciplines.map((d, i) => T(`agenda.discipline.${i + 1}`, d, [])),
|
||||
+ ...days.map((d, i) => T(`agenda.day.${i + 1}`, d, [])),
|
||||
+ ...slots.map((s, i) => T(`agenda.slot.${i + 1}`, s, [])),
|
||||
// I task di estrazione aggiungono qui le entry di header/footer/pagine/data file.
|
||||
];
|
||||
|
||||
export const seedByTag = new Map(contentSeed.map((e) => [e.tag, e]));
|
||||
diff --git a/src/pages/training.astro b/src/pages/training.astro
|
||||
index 7819879..7ddb083 100644
|
||||
--- a/src/pages/training.astro
|
||||
+++ b/src/pages/training.astro
|
||||
@@ -1,42 +1,44 @@
|
||||
---
|
||||
import Base from '../layouts/Base.astro';
|
||||
import PageHero from '../components/PageHero.astro';
|
||||
import TrainingCards from '../components/home/TrainingCards.astro';
|
||||
import Agenda from '../components/Agenda.astro';
|
||||
import { Image } from 'astro:assets';
|
||||
import { trainings } from '../data/trainings';
|
||||
import trialImg from '../assets/img/trial-class.jpg';
|
||||
+import T from '../components/content/T.astro';
|
||||
+import { t } from '../lib/content';
|
||||
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;
|
||||
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.">
|
||||
<PageHero title="training" />
|
||||
|
||||
<section class="section" style="padding-bottom:0">
|
||||
<div class="section-heading">
|
||||
<h2>Training</h2>
|
||||
<p>Porta i tuoi allenamenti al livello successivo: programmi completi e percorsi su misura. Trova il training più adatto alle tue esigenze.</p>
|
||||
</div>
|
||||
</section>
|
||||
<TrainingCards />
|
||||
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
- {trainings.map((t, i) => (
|
||||
- <div class:list={['tblock', { 'tblock--reverse': i % 2 === 1 }]} id={t.id}>
|
||||
- {imgOf(t.image) && <Image src={imgOf(t.image)!} alt={t.title} widths={[500, 900]} sizes="(max-width:767px) 100vw, 45vw" data-reveal={i % 2 === 1 ? 'right' : 'left'} />}
|
||||
+ {trainings.map((tr, i) => (
|
||||
+ <div class:list={['tblock', { 'tblock--reverse': i % 2 === 1 }]} id={tr.id}>
|
||||
+ {imgOf(tr.image) && <Image src={imgOf(tr.image)!} alt={t(`training.${tr.id}.title`)} widths={[500, 900]} sizes="(max-width:767px) 100vw, 45vw" data-reveal={i % 2 === 1 ? 'right' : 'left'} />}
|
||||
<div data-reveal={i % 2 === 1 ? 'left' : 'right'}>
|
||||
- <h2>{t.title.toLowerCase()}</h2>
|
||||
- <p>{t.description}</p>
|
||||
- <a class="btn" href={t.cta.href}>{t.cta.label}</a>
|
||||
+ <h2 data-tag={`training.${tr.id}.title`}>{t(`training.${tr.id}.title`).toLowerCase()}</h2>
|
||||
+ <T tag={`training.${tr.id}.description`} as="p" />
|
||||
+ <a class="btn" href={tr.cta.href}><T tag={`training.${tr.id}.cta-label`} as="span" /></a>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<Agenda />
|
||||
|
||||
<section class="section section--alt">
|
||||
<div class="container trial">
|
||||
Reference in New Issue
Block a user