feat: rinomina sezione Programmi in Servizi (route, tag, migrazione DB)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -37,7 +37,7 @@ export const prerender = false;
|
||||
<div>
|
||||
<T tag="about.direzione.title" as="h2" />
|
||||
<T tag="about.direzione.body" as="p" />
|
||||
<a class="btn" href="/programs">{t('about.direzione.cta')}</a>
|
||||
<a class="btn" href="/services">{t('about.direzione.cta')}</a>
|
||||
</div>
|
||||
<div>
|
||||
<T tag="about.approccio.title" as="h2" />
|
||||
|
||||
@@ -9,13 +9,13 @@ export const prerender = false;
|
||||
const GROUP_BY_PREFIX: Record<string, string> = {
|
||||
home: 'Home',
|
||||
about: 'About', team: 'About', method: 'About',
|
||||
program: 'Programmi', programs: 'Programmi', pricing: 'Programmi',
|
||||
service: 'Servizi', services: 'Servizi', pricing: 'Servizi',
|
||||
training: 'Training',
|
||||
contact: 'Contatti', form: 'Contatti',
|
||||
global: 'Globali', header: 'Globali', footer: 'Globali',
|
||||
agenda: 'Globali', partner: 'Globali', notfound: 'Globali',
|
||||
};
|
||||
const GROUP_ORDER = ['Home', 'About', 'Programmi', 'Training', 'Contatti', 'Globali', 'Altro'];
|
||||
const GROUP_ORDER = ['Home', 'About', 'Servizi', 'Training', 'Contatti', 'Globali', 'Altro'];
|
||||
|
||||
interface Row { tag: string; type: string; value: string; styles: string; updated_at: string; updated_by: string | null }
|
||||
const rows = getDb().prepare(
|
||||
|
||||
@@ -5,7 +5,7 @@ import InfoColumns from '../components/home/InfoColumns.astro';
|
||||
import FeatureBlocks from '../components/home/FeatureBlocks.astro';
|
||||
import QuoteBanner from '../components/home/QuoteBanner.astro';
|
||||
import TrainingCards from '../components/home/TrainingCards.astro';
|
||||
import ProgramsGrid from '../components/home/ProgramsGrid.astro';
|
||||
import ServicesGrid from '../components/home/ServicesGrid.astro';
|
||||
import Agenda from '../components/Agenda.astro';
|
||||
import TeamSection from '../components/home/TeamSection.astro';
|
||||
import MethodSteps from '../components/home/MethodSteps.astro';
|
||||
@@ -26,7 +26,7 @@ export const prerender = false;
|
||||
</div>
|
||||
</section>
|
||||
<TrainingCards />
|
||||
<ProgramsGrid />
|
||||
<ServicesGrid />
|
||||
<Agenda />
|
||||
<TeamSection />
|
||||
<MethodSteps />
|
||||
|
||||
@@ -2,66 +2,66 @@
|
||||
import Base from '../../layouts/Base.astro';
|
||||
import PageHero from '../../components/PageHero.astro';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { programs, getProgram } from '../../data/programs';
|
||||
import { services, getService } from '../../data/services';
|
||||
import { performanceClassPricing } from '../../data/pricing';
|
||||
import { programIcons } from '../../data/program-icons';
|
||||
import { serviceIcons } from '../../data/service-icons';
|
||||
import T from '../../components/content/T.astro';
|
||||
import TImg from '../../components/content/TImg.astro';
|
||||
import { t } from '../../lib/content';
|
||||
export const prerender = false;
|
||||
|
||||
const program = getProgram(Astro.params.slug!);
|
||||
if (!program) return new Response(null, { status: 404 });
|
||||
const slug = program.slug;
|
||||
const others = programs.filter((p) => p.slug !== program.slug);
|
||||
const service = getService(Astro.params.slug!);
|
||||
if (!service) return new Response(null, { status: 404 });
|
||||
const slug = service.slug;
|
||||
const others = services.filter((p) => p.slug !== service.slug);
|
||||
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 heroImg = imgOf(program.slug);
|
||||
// Categorie come da Figma (Performance class.pdf), non quelle del blog → tag program.side.category.1-4
|
||||
const heroImg = imgOf(service.slug);
|
||||
// Categorie come da Figma (Performance class.pdf), non quelle del blog → tag service.side.category.1-4
|
||||
const categoryIndexes = [1, 2, 3, 4];
|
||||
// Ordine card pricing come da Figma: tan, taupe, dark
|
||||
const tones = ['tan', 'taupe', 'dark'];
|
||||
---
|
||||
<Base title={t(`program.${slug}.title`)} description={t(`program.${slug}.excerpt`)}>
|
||||
<PageHero title={t(`program.${slug}.title`).toUpperCase()} bgImage={heroImg} />
|
||||
<Base title={t(`service.${slug}.title`)} description={t(`service.${slug}.excerpt`)}>
|
||||
<PageHero title={t(`service.${slug}.title`).toUpperCase()} bgImage={heroImg} />
|
||||
|
||||
<section class="section">
|
||||
<div class="container prog">
|
||||
<div>
|
||||
<h2>{t(`program.${slug}.title`).toUpperCase()}</h2>
|
||||
<T tag={`program.${slug}.long-description`} as="p" />
|
||||
<h2>{t(`service.${slug}.title`).toUpperCase()}</h2>
|
||||
<T tag={`service.${slug}.long-description`} as="p" />
|
||||
<ul class="prog__features">
|
||||
{program.features.map((_, i) => <T tag={`program.${slug}.feature.${i + 1}`} as="li" />)}
|
||||
{service.features.map((_, i) => <T tag={`service.${slug}.feature.${i + 1}`} as="li" />)}
|
||||
</ul>
|
||||
{heroImg && (
|
||||
<TImg tag={`program.${slug}.image`} src={heroImg} alt={t(`program.${slug}.title`)} class="prog__img" widths={[600, 1000]} sizes="(max-width:991px) 100vw, 60vw" data-reveal="fade" />
|
||||
<TImg tag={`service.${slug}.image`} src={heroImg} alt={t(`service.${slug}.title`)} class="prog__img" widths={[600, 1000]} sizes="(max-width:991px) 100vw, 60vw" data-reveal="fade" />
|
||||
)}
|
||||
<div class="prog__faq">
|
||||
{program.faq.map((_, i) => (
|
||||
{service.faq.map((_, i) => (
|
||||
<details open={i === 0}>
|
||||
<summary><T tag={`program.${slug}.faq.${i + 1}.q`} /></summary>
|
||||
<T tag={`program.${slug}.faq.${i + 1}.a`} as="p" />
|
||||
<summary><T tag={`service.${slug}.faq.${i + 1}.q`} /></summary>
|
||||
<T tag={`service.${slug}.faq.${i + 1}.a`} as="p" />
|
||||
</details>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<aside class="prog__side">
|
||||
<T tag="program.side.categories-label" as="h3" />
|
||||
{categoryIndexes.map((n) => <T tag={`program.side.category.${n}`} as="p" class="prog__cat" />)}
|
||||
<T tag="program.side.others-label" as="h3" />
|
||||
<T tag="service.side.categories-label" as="h3" />
|
||||
{categoryIndexes.map((n) => <T tag={`service.side.category.${n}`} as="p" class="prog__cat" />)}
|
||||
<T tag="service.side.others-label" as="h3" />
|
||||
{others.map((o) => (
|
||||
<a class="prog__other" href={`/programs/${o.slug}`}>
|
||||
<a class="prog__other" href={`/services/${o.slug}`}>
|
||||
<span class="prog__icon">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" width="26" height="26" aria-hidden="true"><path d={programIcons[o.slug]} /></svg>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.4" width="26" height="26" aria-hidden="true"><path d={serviceIcons[o.slug]} /></svg>
|
||||
</span>
|
||||
<T tag={`program.${o.slug}.title`} />
|
||||
<T tag={`service.${o.slug}.title`} />
|
||||
</a>
|
||||
))}
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{program.hasPricing && (
|
||||
{service.hasPricing && (
|
||||
<section class="section section--alt">
|
||||
<div class="container">
|
||||
<div class="section-heading">
|
||||
@@ -72,18 +72,18 @@ const tones = ['tan', 'taupe', 'dark'];
|
||||
<details class="price__group" open={g.open}>
|
||||
<summary>{g.open ? '+' : '–'} <T tag={`pricing.group.${gi + 1}.label`} /></summary>
|
||||
{g.plans.length === 0 ? (
|
||||
<T tag="program.pricing.empty-note" as="p" class="price__empty" />
|
||||
<T tag="service.pricing.empty-note" as="p" class="price__empty" />
|
||||
) : (
|
||||
<div class="price__row">
|
||||
{g.plans.map((p, i) => (
|
||||
<div class:list={['price__card', `price__card--${tones[i % 3]}`]}>
|
||||
<p class="price__amount">{p.monthly}€</p>
|
||||
<T tag="program.pricing.per" as="p" class="price__per" />
|
||||
<p class="price__entries">{p.entries} {p.entries === 1 ? t('program.pricing.entries-singular') : t('program.pricing.entries-plural')}</p>
|
||||
<T tag="service.pricing.per" as="p" class="price__per" />
|
||||
<p class="price__entries">{p.entries} {p.entries === 1 ? t('service.pricing.entries-singular') : t('service.pricing.entries-plural')}</p>
|
||||
<T tag={`pricing.group.${gi + 1}.plan.${i + 1}.note`} as="p" />
|
||||
<T tag={`pricing.group.${gi + 1}.plan.${i + 1}.installments`} as="p" />
|
||||
<T tag={`pricing.group.${gi + 1}.plan.${i + 1}.best`} as="p" class="price__best" />
|
||||
<a class="btn btn--light" href="/contact">{t('program.pricing.buy-cta')}</a>
|
||||
<a class="btn btn--light" href="/contact">{t('service.pricing.buy-cta')}</a>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
@@ -2,7 +2,7 @@
|
||||
import Base from '../../layouts/Base.astro';
|
||||
import PageHero from '../../components/PageHero.astro';
|
||||
import type { ImageMetadata } from 'astro';
|
||||
import { programs } from '../../data/programs';
|
||||
import { services } from '../../data/services';
|
||||
import T from '../../components/content/T.astro';
|
||||
import TImg from '../../components/content/TImg.astro';
|
||||
import { t } from '../../lib/content';
|
||||
@@ -10,27 +10,27 @@ const images = import.meta.glob<{ default: ImageMetadata }>('../../assets/img/pr
|
||||
const imgOf = (slug: string) => Object.entries(images).find(([p]) => p.includes(`program-${slug}.`))?.[1]?.default;
|
||||
export const prerender = false;
|
||||
---
|
||||
<Base title={t('programs.meta.title')} description={t('programs.meta.description')}>
|
||||
<PageHero title={t('programs.hero.title')} />
|
||||
<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="programs.intro.title" as="h2" />
|
||||
<T tag="programs.intro.body" as="p" />
|
||||
<T tag="services.intro.title" as="h2" />
|
||||
<T tag="services.intro.body" as="p" />
|
||||
</div>
|
||||
<div class="plist">
|
||||
{programs.map((p, i) => (
|
||||
{services.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={`/programs/${p.slug}`}>
|
||||
<TImg tag={`program.${p.slug}.image`} src={imgOf(p.slug)!} alt={t(`program.${p.slug}.title`)} widths={[400, 700]} sizes="(max-width:767px) 100vw, 33vw" />
|
||||
<a class="plist__photo" href={`/services/${p.slug}`}>
|
||||
<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={`program.${p.slug}.title`} as="h3" />
|
||||
<T tag={`program.${p.slug}.subtitle`} as="p" class="plist__sub" />
|
||||
<T tag={`program.${p.slug}.excerpt`} as="p" />
|
||||
<a class="plist__more" href={`/programs/${p.slug}`}>{t('programs.card.more-label')}</a>
|
||||
<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" />
|
||||
<a class="plist__more" href={`/services/${p.slug}`}>{t('services.card.more-label')}</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
@@ -1,16 +1,16 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { getDb } from '../lib/db';
|
||||
import { programs } from '../data/programs';
|
||||
import { services } from '../data/services';
|
||||
export const prerender = false;
|
||||
|
||||
const STATIC = ['/', '/about', '/contact', '/training', '/programs', '/blog'];
|
||||
const STATIC = ['/', '/about', '/contact', '/training', '/services', '/blog'];
|
||||
|
||||
export const GET: APIRoute = ({ site }) => {
|
||||
const base = (site ?? new URL('https://insanitylab.tielogic.xyz')).toString().replace(/\/$/, '');
|
||||
const posts = getDb().prepare('SELECT slug FROM posts WHERE draft = 0').all() as { slug: string }[];
|
||||
const urls = [
|
||||
...STATIC,
|
||||
...programs.map((p) => `/programs/${p.slug}`),
|
||||
...services.map((p) => `/services/${p.slug}`),
|
||||
...posts.map((p) => `/blog/${p.slug}`),
|
||||
];
|
||||
const xml = `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${urls.map((u) => ` <url><loc>${base}${u}</loc></url>`).join('\n')}\n</urlset>`;
|
||||
|
||||
Reference in New Issue
Block a user