Files
real-skill-landing/src/pages/index.astro

108 lines
3.1 KiB
Plaintext

---
import { useTranslations } from '@/i18n/utils'
import BaseLayout from '../layouts/BaseLayout.astro'
import Section from '@/components/Section.astro'
import Header, { type HeaderProps } from '@/components/header/Header.astro'
import Footer from '@/components/Footer.astro'
import type { CollectionEntry } from 'astro:content'
import { getEntry } from 'astro:content'
import Marquee from '@/components/Marquee.astro'
import { Reviews, type OptimizedReview } from '@/components/Reviews.tsx'
import Hero from '@/components/Hero.astro'
import { getImage } from 'astro:assets'
import { imageResultToImageAttributes, optimizeSliderImages } from '@/libs/image'
import { getCollection } from 'astro:content'
import { Services } from '@/components/services/Services'
import { GymGallery } from '@/components/GymGallery'
import { Coaches } from '@/components/coaches/Coaches'
type Props = CollectionEntry<'pages'>['data']
const { lang } = Astro.params
const [page, coaches] = await Promise.all([
getEntry('pages', 'main'),
getCollection('coaches').then((coaches) =>
coaches.sort((a, b) => (a.data.order ?? -1) - (b.data.order ?? -1))
),
])
const { slider, services, hero, marquee, reviews, footer } = page?.data || {}
const optimizedSlider = slider
? await optimizeSliderImages(slider.map(({ image, imageAlt }) => ({ src: image, alt: imageAlt })))
: undefined
const optimizedReviews = reviews
? await Promise.all(
reviews.map(async (review): Promise<OptimizedReview> => {
if (!review.author?.image)
return { ...review, author: { ...review.author, image: undefined } }
const optimizedImage = await getImage({
src: review.author?.image,
alt: review.author?.imageAlt,
width: 64,
height: 64,
format: 'webp',
loading: 'lazy',
}).then(imageResultToImageAttributes)
return { ...review, author: { ...review.author, image: optimizedImage } }
})
)
: undefined
const t = useTranslations(lang)
---
<BaseLayout title={t('home.title')}>
<Header lang={lang} />
{hero && <Hero {...hero} />}
{
marquee && (
<section class="h-[var(--marquee-height)] overflow-clip bg-brand">
<Marquee texts={marquee} />
</section>
)
}
{
coaches.length > 0 && (
<Section id="coaches" title={t('coaches.title')} description={t('coaches.subtitle')}>
<Coaches client:load coaches={coaches} lang={lang} />
</Section>
)
}
{
optimizedSlider && (
<Section
id="image-slider"
title={t('slider.title')}
description={t('slider.subtitle')}
className="bg-bg-light"
>
<GymGallery client:only="react" images={optimizedSlider} />
</Section>
)
}
{
services && (
<Section id="services" title={t('services.title')}>
<Services client:visible services={services} />
</Section>
)
}
{
optimizedReviews && (
<Section id="reviews" title={t('reviews.title')}>
<Reviews client:only="react" reviews={optimizedReviews} lang={lang} />
</Section>
)
}
<Footer lang={lang} {...footer} />
</BaseLayout>