diff --git a/public/favicon.svg b/public/favicon.svg deleted file mode 100644 index f157bd1..0000000 --- a/public/favicon.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - diff --git a/src/assets/icons/WideCrossIcon.svg b/src/assets/icons/WideCrossIcon.svg new file mode 100644 index 0000000..52aaac7 --- /dev/null +++ b/src/assets/icons/WideCrossIcon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/logo.png b/src/assets/logo.png new file mode 100644 index 0000000..398d495 Binary files /dev/null and b/src/assets/logo.png differ diff --git a/src/components/CoachCard.astro b/src/components/CoachCard.astro index e020346..85a383d 100644 --- a/src/components/CoachCard.astro +++ b/src/components/CoachCard.astro @@ -1,22 +1,28 @@ --- +import type { coachesSchema } from '@/content.config' +import { useTranslations } from '@/i18n/utils' import { Image } from 'astro:assets' +import type { z } from 'astro:content' -type Props = { - name: string - description?: string - image: ImageMetadata - imageAlt: string -} +type Props = z.infer> & { lang?: string } -const { name, description, image, imageAlt } = Astro.props +const { lang, name, description, image, imageAlt, link } = Astro.props +const t = useTranslations(lang) --- -
-
+
+ {imageAlt} -
+

{name}

{description &&

{description}

} + { + link && ( + + {t('coaches.link')} + + ) + }
diff --git a/src/components/Footer.astro b/src/components/Footer.astro new file mode 100644 index 0000000..b62bc6b --- /dev/null +++ b/src/components/Footer.astro @@ -0,0 +1,29 @@ +--- +import { useTranslations } from '@/i18n/utils' +import { Image } from 'astro:assets' +import logoSrc from '@/assets/logo.png' + +type Props = { + lang?: string +} + +const { lang } = Astro.props +const t = useTranslations(lang) +--- + +
+ +
+ logo +

+ © {new Date().getFullYear()} + {t('footer.copyright')} +

+
+
diff --git a/src/components/Hero.astro b/src/components/Hero.astro new file mode 100644 index 0000000..a233c4a --- /dev/null +++ b/src/components/Hero.astro @@ -0,0 +1,29 @@ +--- +import type { z } from 'astro:content' +import Section from './Section.astro' +import { heroSchema } from '@/content.config' +import { Image } from 'astro:assets' + +type Props = z.infer> + +const { title, description, cta, image, imageAlt } = Astro.props +--- + +
+
+

+

{description}

+ { + cta && ( + + ) + } +

+ +
diff --git a/src/components/Marquee.astro b/src/components/Marquee.astro index b16adfe..7dea5e9 100644 --- a/src/components/Marquee.astro +++ b/src/components/Marquee.astro @@ -1,12 +1,23 @@ --- +import { Image } from 'astro:assets' +import wideCrossIconSrc from '@/assets/icons/WideCrossIcon.svg' + type Props = { texts: string[] } const { texts } = Astro.props -const repeatedTexts = texts.length < 10 ? Array.from({ length: 10 / texts.length }, () => texts).flat() : texts; +const repeatedTexts = + texts.length < 10 ? Array.from({ length: 10 / texts.length }, () => texts).flat() : texts ---
- {repeatedTexts.map((text) =>

{text}

)} + { + repeatedTexts.map((text) => ( + <> +

{text}

+ cross-icon + + )) + }
diff --git a/src/components/ServiceCard.astro b/src/components/ServiceCard.astro index 1d5aa13..05c4a08 100644 --- a/src/components/ServiceCard.astro +++ b/src/components/ServiceCard.astro @@ -23,7 +23,7 @@ const { title, charachteristics, highlighted = false, link } = Astro.props charachteristics?.map((charachteristic) => (
  • {charachteristic.text} - {charachteristic.price && {charachteristic.price}} + {charachteristic.price && }
  • )) } diff --git a/src/components/header/Header.astro b/src/components/header/Header.astro new file mode 100644 index 0000000..5901624 --- /dev/null +++ b/src/components/header/Header.astro @@ -0,0 +1,60 @@ +--- +import MobileNavigation from './MobileNavigation' +import { useTranslations } from '@/i18n/utils' + +type Props = { + lang?: string +} + +const { lang } = Astro.props + +const navItems = [ + { key: 'nav.coaches', href: '#coaches' }, + { key: 'nav.slider', href: '#image-slider' }, + { key: 'nav.services', href: '#services' }, + { key: 'nav.reviews', href: '#reviews' }, + { key: 'nav.contact', href: '#contacts' }, +] as const + +const t = useTranslations(lang) +--- + +
    + + + +
    + + diff --git a/src/components/MobileNavigation.tsx b/src/components/header/MobileNavigation.tsx similarity index 100% rename from src/components/MobileNavigation.tsx rename to src/components/header/MobileNavigation.tsx diff --git a/src/content.config.ts b/src/content.config.ts index a4a0cf8..351d642 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -1,28 +1,46 @@ import { defineCollection, z, type ImageFunction } from 'astro:content' +export const heroSchema = (image: ImageFunction) => + z.object({ + title: z.string(), + description: z.string(), + image: image(), + imageAlt: z.string(), + cta: z + .object({ + title: z.string(), + href: z.string(), + target: z.string().optional(), + }) + .optional(), + }) + export const coachesSchema = (image: ImageFunction) => z.object({ name: z.string(), description: z.string().optional(), image: image(), imageAlt: z.string(), + link: z.string().optional(), }) export const servicesSchema = z.object({ title: z.string(), - description: z.string(), - price: z.string(), + description: z.string().optional(), + price: z.string().optional(), link: z.object({ title: z.string(), href: z.string(), target: z.string().optional(), }), - charachteristics: z.array( - z.object({ - text: z.string(), - price: z.string().optional(), - }) - ), + charachteristics: z + .array( + z.object({ + text: z.string(), + price: z.string().optional(), + }) + ) + .optional(), }) export const reviewsSchema = (image: ImageFunction) => @@ -40,21 +58,7 @@ export const reviewsSchema = (image: ImageFunction) => const pages = defineCollection({ schema: ({ image }) => z.object({ - hero: z - .object({ - title: z.string(), - description: z.string(), - image: image(), - imageAlt: z.string(), - cta: z - .object({ - title: z.string(), - href: z.string(), - target: z.string().optional(), - }) - .optional(), - }) - .nullable(), + hero: heroSchema(image).optional(), marquee: z.array(z.string()).optional(), coaches: z.array(coachesSchema(image)).optional(), reviews: z.array(reviewsSchema(image)).optional(), diff --git a/src/content/pages/assets/coaches/1.jpeg b/src/content/pages/assets/coaches/1.jpeg new file mode 100644 index 0000000..4f40faa Binary files /dev/null and b/src/content/pages/assets/coaches/1.jpeg differ diff --git a/src/content/pages/assets/coaches/1.jpg b/src/content/pages/assets/coaches/1.jpg deleted file mode 100644 index 22ef61e..0000000 Binary files a/src/content/pages/assets/coaches/1.jpg and /dev/null differ diff --git a/src/content/pages/assets/coaches/2.jpeg b/src/content/pages/assets/coaches/2.jpeg new file mode 100644 index 0000000..f078fe5 Binary files /dev/null and b/src/content/pages/assets/coaches/2.jpeg differ diff --git a/src/content/pages/assets/coaches/2.jpg b/src/content/pages/assets/coaches/2.jpg deleted file mode 100644 index 98fd2a2..0000000 Binary files a/src/content/pages/assets/coaches/2.jpg and /dev/null differ diff --git a/src/content/pages/assets/coaches/3.jpg b/src/content/pages/assets/coaches/3.jpg deleted file mode 100644 index 4078e0c..0000000 Binary files a/src/content/pages/assets/coaches/3.jpg and /dev/null differ diff --git a/src/content/pages/assets/slider/1.jpeg b/src/content/pages/assets/slider/1.jpeg deleted file mode 100644 index c3a6cbe..0000000 Binary files a/src/content/pages/assets/slider/1.jpeg and /dev/null differ diff --git a/src/content/pages/assets/slider/2.jpeg b/src/content/pages/assets/slider/2.jpeg deleted file mode 100644 index ab0052e..0000000 Binary files a/src/content/pages/assets/slider/2.jpeg and /dev/null differ diff --git a/src/content/pages/assets/slider/3.jpeg b/src/content/pages/assets/slider/3.jpeg deleted file mode 100644 index de51ce8..0000000 Binary files a/src/content/pages/assets/slider/3.jpeg and /dev/null differ diff --git a/src/content/pages/assets/slider/IMG_6491.jpg b/src/content/pages/assets/slider/IMG_6491.jpg new file mode 100644 index 0000000..ebf653c Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6491.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6492.jpg b/src/content/pages/assets/slider/IMG_6492.jpg new file mode 100644 index 0000000..5105ed7 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6492.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6493.jpg b/src/content/pages/assets/slider/IMG_6493.jpg new file mode 100644 index 0000000..552a1d2 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6493.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6494.jpg b/src/content/pages/assets/slider/IMG_6494.jpg new file mode 100644 index 0000000..6da9a3a Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6494.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6495.jpg b/src/content/pages/assets/slider/IMG_6495.jpg new file mode 100644 index 0000000..21817b5 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6495.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6496.jpg b/src/content/pages/assets/slider/IMG_6496.jpg new file mode 100644 index 0000000..9b799f6 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6496.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6498.jpg b/src/content/pages/assets/slider/IMG_6498.jpg new file mode 100644 index 0000000..6adaaa8 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6498.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6499.jpg b/src/content/pages/assets/slider/IMG_6499.jpg new file mode 100644 index 0000000..8262ff4 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6499.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6500.jpg b/src/content/pages/assets/slider/IMG_6500.jpg new file mode 100644 index 0000000..59f7aad Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6500.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6506.jpg b/src/content/pages/assets/slider/IMG_6506.jpg new file mode 100644 index 0000000..72c8c92 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6506.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6507.jpg b/src/content/pages/assets/slider/IMG_6507.jpg new file mode 100644 index 0000000..447df82 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6507.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6509.jpg b/src/content/pages/assets/slider/IMG_6509.jpg new file mode 100644 index 0000000..5bbfdf5 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6509.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6510.jpg b/src/content/pages/assets/slider/IMG_6510.jpg new file mode 100644 index 0000000..566e923 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6510.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6514.jpg b/src/content/pages/assets/slider/IMG_6514.jpg new file mode 100644 index 0000000..9cdfde6 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6514.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6515.jpg b/src/content/pages/assets/slider/IMG_6515.jpg new file mode 100644 index 0000000..6e61783 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6515.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6518.jpg b/src/content/pages/assets/slider/IMG_6518.jpg new file mode 100644 index 0000000..e42e96e Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6518.jpg differ diff --git a/src/content/pages/assets/slider/IMG_6520.jpg b/src/content/pages/assets/slider/IMG_6520.jpg new file mode 100644 index 0000000..6c0f9c9 Binary files /dev/null and b/src/content/pages/assets/slider/IMG_6520.jpg differ diff --git a/src/content/pages/main.md b/src/content/pages/main.md index 96dfc6b..ef9c3f7 100644 --- a/src/content/pages/main.md +++ b/src/content/pages/main.md @@ -8,67 +8,101 @@ hero: title: 'Записаться' href: '#services' marquee: - - ВОТ И ВСЕ ЕБАТЬ - - ТЫ СЛАБ + - ДОСТИГАЙТЕ ЦЕЛЕЙ + - БУДЬТЕ СИЛЬНЕЕ + - ТРЕНИРУЙТЕСЬ С НАМИ + - МЕНЯЙТЕСЬ К ЛУЧШЕМУ + - СТАНОВИТЕСЬ ЗДОРОВЕЕ slider: - - image: './assets/slider/1.jpeg' + - image: './assets/slider/IMG_6491.jpg' imageAlt: 'first-slide' - - image: './assets/slider/2.jpeg' + - image: './assets/slider/IMG_6492.jpg' imageAlt: 'second-slide' - - image: './assets/slider/3.jpeg' + - image: './assets/slider/IMG_6493.jpg' imageAlt: 'third-slide' + - image: './assets/slider/IMG_6494.jpg' + imageAlt: 'fourth-slide' + - image: './assets/slider/IMG_6495.jpg' + imageAlt: 'fifth-slide' + - image: './assets/slider/IMG_6496.jpg' + imageAlt: 'sixth-slide' + - image: './assets/slider/IMG_6498.jpg' + imageAlt: 'seventh-slide' + - image: './assets/slider/IMG_6499.jpg' + imageAlt: 'eighth-slide' + - image: './assets/slider/IMG_6500.jpg' + imageAlt: 'ninth-slide' + - image: './assets/slider/IMG_6506.jpg' + imageAlt: 'tenth-slide' + - image: './assets/slider/IMG_6507.jpg' + imageAlt: 'eleventh-slide' + - image: './assets/slider/IMG_6509.jpg' + imageAlt: 'twelfth-slide' + - image: './assets/slider/IMG_6510.jpg' + imageAlt: 'thirteenth-slide' + - image: './assets/slider/IMG_6514.jpg' + imageAlt: 'fourteenth-slide' + - image: './assets/slider/IMG_6515.jpg' + imageAlt: 'fifteenth-slide' + - image: './assets/slider/IMG_6518.jpg' + imageAlt: 'sixteenth-slide' + - image: './assets/slider/IMG_6520.jpg' + imageAlt: 'seventeenth-slide' coaches: - - image: './assets/coaches/1.jpg' + - image: './assets/coaches/1.jpeg' imageAlt: 'first-coach' - name: 'Иванов Иван Иванович' - description: 'Тренер' - - image: './assets/coaches/2.jpg' + name: 'БАТЫР СУЛЕЙМАНОВ' + description: 'Профессиональный выступающий спортсмен и тренер. Опыт работы в фитнес индустрии более 12 лет' + link: 'https://t.me/therealskill_studio/4' + - image: './assets/coaches/2.jpeg' imageAlt: 'second-coach' - name: 'Петров Петр Петрович' - description: 'Тренер' - - image: './assets/coaches/3.jpg' - imageAlt: 'third-coach' - name: 'Сидоров Сидор Сидорович' + name: 'СУЛЕЙМАНОВА АЛЕКСАНДРА' + description: 'Спортсмен и тренер. Опыт работы в фитнес индустрии 9 лет' + link: 'https://t.me/therealskill_studio/7' services: - - title: 'Пробный день' - description: 'Идеально подходит для знакомства с нашим залом и услугами' - price: '1500 ₽' + - title: 'Разовые Персональные тренировки с тренером' link: - title: 'Начать' + title: 'Записаться' href: '/checkout/day-pass' charachteristics: - - text: 'Доступ ко всему оборудованию' - price: '500 ₽' - - text: 'Персональный шкафчик и душ' - price: '300 ₽' - - text: 'Базовая оценка физической подготовки' - price: '700 ₽' - - title: 'Месячный абонемент' - description: 'Гибкая программа тренировок на месяц' - price: '5900 ₽' + - text: 'Разовая тренировка' + price: '5 000 ₽' + - text: 'Разовая СПЛИТ (2 человека)' + price: '8 000 ₽' + - text: 'Блок из 5 тренировок' + price: '22 500 ₽' + - text: 'Блок из 5 тренировок СПЛИТ' + price: '38 500 ₽' + - text: 'Блок из 10 тренировок' + price: '42 500 ₽' + - text: 'Блок из 10 тренировок СПЛИТ' + price: '75 000 ₽' + - text: 'Блок из 15 тренировок' + price: '60 000 ₽' + - text: 'Блок из 15 тренировок СПЛИТ' + price: '110 000 ₽' + - title: 'Безлимитные Абонементы на месяц' + description: '30 календарных дней занятий с тренером' link: - title: 'Оформить' + title: 'Записаться' href: '/checkout/monthly' charachteristics: - - text: 'Полный доступ к залу и оборудованию' - price: '2500 ₽' - - text: '2 занятия с сертифицированным тренером' - price: '2000 ₽' - - text: 'Доступ ко всем групповым занятиям' - price: '1400 ₽' - - title: 'Годовой абонемент' - description: 'Лучшее предложение для постоянных клиентов' - price: '49900 ₽' + - text: 'Персональный безлимит' + price: '50 000 ₽' + - text: 'СПЛИТ безлимит' + price: '80 000 ₽' + - text: 'Мини-группа (3-5 человек) безлимит' + price: '30 000 ₽
    c человека' + - title: 'Аренда зала / Разовые посещения' + description: 'Присутствие тренера БЕСПЛАТНО' link: - title: 'Присоединиться' + title: 'Записаться' href: '/checkout/annual' charachteristics: - - text: 'Доступ ко всем зонам и премиум-оборудованию' - price: '20000 ₽' - - text: 'Ежемесячные персональные тренировки' - price: '18000 ₽' - - text: 'Индивидуальная консультация по питанию' - price: '11900 ₽' + - text: 'Разовое посещение Время 75 минут' + price: '1500 ₽
    c человека' + - text: '«Приходящий тренер» Время 75 минут' + price: '1500 ₽
    c человека' reviews: - review: 'Место силы. Комфортная студия. Для тренировок есть всё необходимое . Раздевалки уютные , так же всё продумано до мелочей . Можно после тренировки насладиться кофе . По месторасположению очень комфортно , для парковки места есть всегда. Уютно. Спортивно . Красиво . Стильно . Профессионально! От души рекомендую' author: diff --git a/src/i18n/ui.ts b/src/i18n/ui.ts index ebbfd53..b96feb5 100644 --- a/src/i18n/ui.ts +++ b/src/i18n/ui.ts @@ -5,7 +5,14 @@ export const languages = { export const ui = { ru: { - 'home.title': 'The real skill studio', + 'seo.meta.description': + 'The Real Skill Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.', + 'seo.meta.keywords': + 'фитнес, тренировки, спортзал, персональный тренер, групповые занятия, здоровье, спорт, Real Skill Studio"', + 'seo.og.title': 'THEREALSKILL', + 'seo.og.description': + 'The Real Skill Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.', + 'home.title': 'Фитнес-студия', // Header 'header.logo': 'THEREALSKILL', 'nav.coaches': 'Тренера', @@ -20,7 +27,8 @@ export const ui = { 'ticker.shapeBody': 'ТЫ СЛАБ', // Coaches Section 'coaches.title': 'НАШИ ТРЕНЕРА', - 'coaches.subtitle': 'Профессиональные тренеры с многолетним опытом', + 'coaches.subtitle': 'Вашему вниманию! Представляем наш тренерский состав', + 'coaches.link': 'Подробнее', // Slider Section 'slider.title': 'ПОСМОТРИТЕ, ГДЕ МЫ
    ВЫПОЛНЯЕМ УПРАЖНЕНИЯ', @@ -38,7 +46,14 @@ export const ui = { 'footer.copyright': 'Все права защищены. Политика конфиденциальности.', }, en: { - 'home.title': 'Home Page', + 'seo.meta.description': + 'The Real Skill Studio - professional fitness studio in Russia. Personal training, group classes, experienced trainers.', + 'seo.meta.keywords': + 'fitness, training, gym, personal trainer, group classes, health, sports, Real Skill Studio"', + 'seo.og.title': 'THEREALSKILL', + 'seo.og.description': + 'The Real Skill Studio - professional fitness studio in Russia. Personal training, group classes, experienced trainers.', + 'home.title': 'Fitness Studio', // Header 'header.logo': 'THEREALSKILL', 'nav.coaches': 'Coaches', @@ -54,6 +69,7 @@ export const ui = { // Coaches Section 'coaches.title': 'OUR COACHES', 'coaches.subtitle': 'Professional trainers with years of experience', + 'coaches.link': 'More info', // Slider Section 'slider.title': 'TAKE A LOOK WHERE WE
    EXERCISE', 'slider.subtitle': 'Modern equipment in a spacious gym', diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index 38ac8e8..411a8d9 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,4 +1,5 @@ --- +import { useTranslations } from '@/i18n/utils' import '@/styles/global.css' type Props = { @@ -6,6 +7,7 @@ type Props = { } const { title } = Astro.props +const t = useTranslations(Astro.currentLocale) --- @@ -13,9 +15,17 @@ const { title } = Astro.props - + - {title} + + + + + + + + + {`${title} | ${t('seo.og.title')}`} diff --git a/src/pages/index.astro b/src/pages/index.astro index 2b6f001..aef8b8b 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,28 +1,23 @@ --- -import MobileNavigation from '@/components/MobileNavigation.tsx' +import MobileNavigation from '@/components/header/MobileNavigation' import { useTranslations } from '@/i18n/utils' import BaseLayout from '../layouts/BaseLayout.astro' import Section from '@/components/Section.astro' import { Swiper } from '@/components/swiper' +import Header from '@/components/header/Header.astro' +import Footer from '@/components/Footer.astro' import type { CollectionEntry } from 'astro:content' import { getEntry } from 'astro:content' import CoachCard from '@/components/CoachCard.astro' import ServiceCard from '@/components/ServiceCard.astro' -import { Image } from 'astro:assets' import Marquee from '@/components/Marquee.astro' import { Reviews } from '@/components/Reviews.tsx' +import { Image } from 'astro:assets' +import Hero from '@/components/Hero.astro' type Props = CollectionEntry<'pages'>['data'] -const navItems = [ - { key: 'nav.coaches', href: '#coaches' }, - { key: 'nav.slider', href: '#image-slider' }, - { key: 'nav.services', href: '#services' }, - { key: 'nav.reviews', href: '#reviews' }, - { key: 'nav.contact', href: '#contacts' }, -] as const - const { lang } = Astro.params const page = await getEntry('pages', 'main') const { slider, coaches, services, hero, marquee, reviews } = page?.data || {} @@ -30,44 +25,9 @@ const t = useTranslations(lang) --- -
    - - - -
    +
    - { - hero && ( -
    -
    -

    -

    {hero.description}

    - {hero.cta && ( - - )} -

    - -
    - ) - } + {hero && } { marquee && ( @@ -80,9 +40,9 @@ const t = useTranslations(lang) { coaches && (
    -
    +
    {coaches.map((coach) => ( - + ))}
    @@ -97,11 +57,13 @@ const t = useTranslations(lang) description={t('slider.subtitle')} className="bg-bg-light" > - ({ ...image, alt: imageAlt }))} - /> +
    + ({ ...image, alt: imageAlt }))} + /> +
    ) } @@ -128,22 +90,5 @@ const t = useTranslations(lang) ) } -
    - -
    - -
    -
    -
    -

    - © {new Date().getFullYear()} - {t('footer.copyright')} -

    -
    -
    +