update content
@@ -17,6 +17,7 @@ const t = useTranslations(lang)
|
||||
<footer id="contacts" class="flex flex-col items-center gap-4 text-center md:gap-6">
|
||||
<div class="flex h-[400px] w-full items-center justify-center bg-bg-light">
|
||||
<script
|
||||
transition:persist
|
||||
script-src:unsafe-inline
|
||||
is:inline
|
||||
type="text/javascript"
|
||||
@@ -27,7 +28,7 @@ const t = useTranslations(lang)
|
||||
></script>
|
||||
<div
|
||||
id="ymap-loader"
|
||||
class="h-16 w-16 animate-spin rounded-full border-8 border-brand border-t-transparent"
|
||||
class="h-16 w-16 animate-spin rounded-full border-6 border-brand border-t-transparent"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,9 +31,11 @@ const t = useTranslations(lang)
|
||||
id="main-header"
|
||||
transition:persist
|
||||
>
|
||||
<a class="text-2xl font-bold text-text-light" set:html={t('header.logo')} href="/" />
|
||||
<a class="flex flex-col items-center font-bold uppercase text-text-light" href="/">
|
||||
<span>THEREALSKILL</span><span class="tracking-widest text-brand">studio</span>
|
||||
</a>
|
||||
<nav class="hidden flex-1 md:block">
|
||||
<ul class="grid grid-flow-col place-content-end lg:place-content-start gap-10">
|
||||
<ul class="grid grid-flow-col place-content-end gap-10 lg:place-content-start">
|
||||
{
|
||||
NAV_ITEMS.map((item) => (
|
||||
<li>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { TranslationKey } from '@/i18n/ui'
|
||||
import { useTranslations } from '@/i18n/utils'
|
||||
import { cn } from '@/libs/cn'
|
||||
import React, { useState, useEffect, type ButtonHTMLAttributes } from 'react'
|
||||
@@ -11,7 +12,7 @@ type AnimatedBurgerButtonProps = ButtonHTMLAttributes<unknown> & {
|
||||
const AnimatedBurgerButton: React.FC<AnimatedBurgerButtonProps> = ({ isOpen, ...buttonProps }) => (
|
||||
<button
|
||||
{...buttonProps}
|
||||
className="fixed right-4 top-4 z-[60] flex h-8 w-8 cursor-pointer flex-col justify-around border-none bg-transparent p-0 focus:outline-none"
|
||||
className="z-[60] flex h-8 w-8 cursor-pointer flex-col justify-around border-none bg-transparent p-0 focus:outline-none"
|
||||
aria-label={isOpen ? 'Close menu' : 'Open menu'}
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
@@ -66,14 +67,14 @@ const MobileNavigation: React.FC<MobileNavigationProps> = ({ navItems }) => {
|
||||
<AnimatedBurgerButton isOpen={isOpen} onClick={toggleMenu} />
|
||||
<div
|
||||
className={cn(
|
||||
'fixed left-0 top-0 z-50 h-[100dvh] w-full transform bg-bg-main p-8 pt-16 transition-transform duration-300 ease-in-out',
|
||||
'fixed left-0 top-[var(--header-height)] z-50 h-[calc(100dvh-var(--header-height))] w-full transform bg-bg-main p-8 pt-16 transition-transform duration-300 ease-in-out',
|
||||
isOpen ? '-translate-x-0' : 'translate-x-full'
|
||||
)}
|
||||
>
|
||||
<nav className="flex h-full flex-col justify-between">
|
||||
{navItems.map((item) => (
|
||||
<a key={item.key} href={item.href} className="text-3xl" onClick={toggleMenu}>
|
||||
{t(item.key as any)}
|
||||
{t(item.key as TranslationKey)}
|
||||
</a>
|
||||
))}
|
||||
<hr />
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import type {linkSchema} from "@/content.config"
|
||||
import type {z} from "astro:content"
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
description?: string
|
||||
price?: string
|
||||
link: {
|
||||
href: string
|
||||
title: string
|
||||
target?: string
|
||||
}
|
||||
link?: z.infer<typeof linkSchema>
|
||||
}
|
||||
|
||||
export const CharachteristicCard: React.FC<Props> = ({ title, description, price, link }) => {
|
||||
|
||||
@@ -42,7 +42,7 @@ export const Services: React.FC<ServicesProps> = ({ services }) => {
|
||||
>
|
||||
<CharachteristicCard
|
||||
{...charachteristic}
|
||||
link={selectedService.link}
|
||||
link={charachteristic.link || selectedService.link}
|
||||
/>
|
||||
</SwiperSlide>
|
||||
))}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { defineCollection, z, type ImageFunction } from 'astro:content'
|
||||
|
||||
export const socialMediaLinkSchema = z.object({
|
||||
icon: z.string(),
|
||||
export const linkSchema = z.object({
|
||||
title: z.string(),
|
||||
href: z.string(),
|
||||
target: z.string().optional(),
|
||||
})
|
||||
export const socialMediaLinkSchema = linkSchema.extend({
|
||||
title: z.string().optional(),
|
||||
icon: z.string(),
|
||||
})
|
||||
|
||||
export const heroSchema = (image: ImageFunction) =>
|
||||
z.object({
|
||||
@@ -12,13 +16,7 @@ export const heroSchema = (image: ImageFunction) =>
|
||||
description: z.string(),
|
||||
image: image(),
|
||||
imageAlt: z.string(),
|
||||
cta: z
|
||||
.object({
|
||||
title: z.string(),
|
||||
href: z.string(),
|
||||
target: z.string().optional(),
|
||||
})
|
||||
.optional(),
|
||||
cta: linkSchema.optional(),
|
||||
})
|
||||
|
||||
export const coaches = defineCollection({
|
||||
@@ -38,17 +36,14 @@ export const servicesSchema = z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional(),
|
||||
price: z.string().optional(),
|
||||
link: z.object({
|
||||
title: z.string(),
|
||||
href: z.string(),
|
||||
target: z.string().optional(),
|
||||
}),
|
||||
link: linkSchema.optional(),
|
||||
charachteristics: z
|
||||
.array(
|
||||
z.object({
|
||||
title: z.string(),
|
||||
description: z.string().optional(),
|
||||
price: z.string().optional(),
|
||||
link: linkSchema.optional(),
|
||||
})
|
||||
)
|
||||
.optional(),
|
||||
|
||||
|
Before Width: | Height: | Size: 808 KiB |
BIN
src/content/pages/assets/slider/IMG_7066.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
src/content/pages/assets/slider/IMG_7067.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/content/pages/assets/slider/IMG_7068.jpg
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
src/content/pages/assets/slider/IMG_7069.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
src/content/pages/assets/slider/IMG_7070.jpg
Normal file
|
After Width: | Height: | Size: 2.3 MiB |
BIN
src/content/pages/assets/slider/IMG_7071.jpg
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
src/content/pages/assets/slider/IMG_7072.jpg
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/content/pages/assets/slider/IMG_7073.jpg
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
src/content/pages/assets/slider/IMG_7074.jpg
Normal file
|
After Width: | Height: | Size: 1.5 MiB |
BIN
src/content/pages/assets/slider/IMG_7075.jpg
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
@@ -1,7 +1,7 @@
|
||||
---
|
||||
hero:
|
||||
title: 'ПРЕОБРАЗИТЕ СВОЕ ТЕЛО <br /> <span class="text-brand">В СОВЕРШЕНСТВО</span>'
|
||||
description: 'Профессиональные тренеры The Real Skill помогут достичь ваших целей через персональные тренировки и индивидуальный подход.'
|
||||
description: 'Профессиональные тренеры THEREALSKILL studio помогут достичь ваших целей через персональные тренировки и индивидуальный подход.'
|
||||
image: './assets/hero.jpg'
|
||||
imageAlt: 'hero'
|
||||
cta:
|
||||
@@ -42,8 +42,26 @@ slider:
|
||||
imageAlt: 'fifteenth-slide'
|
||||
- image: './assets/slider/IMG_6518.jpg'
|
||||
imageAlt: 'sixteenth-slide'
|
||||
- image: './assets/slider/IMG_6520.jpg'
|
||||
- image: './assets/slider/IMG_7066.jpg'
|
||||
imageAlt: 'seventeenth-slide'
|
||||
- image: './assets/slider/IMG_7067.jpg'
|
||||
imageAlt: 'eighteenth-slide'
|
||||
- image: './assets/slider/IMG_7068.jpg'
|
||||
imageAlt: 'nineteenth-slide'
|
||||
- image: './assets/slider/IMG_7069.jpg'
|
||||
imageAlt: 'twentieth-slide'
|
||||
- image: './assets/slider/IMG_7070.jpg'
|
||||
imageAlt: 'twenty-first-slide'
|
||||
- image: './assets/slider/IMG_7071.jpg'
|
||||
imageAlt: 'twenty-second-slide'
|
||||
- image: './assets/slider/IMG_7072.jpg'
|
||||
imageAlt: 'twenty-third-slide'
|
||||
- image: './assets/slider/IMG_7073.jpg'
|
||||
imageAlt: 'twenty-fourth-slide'
|
||||
- image: './assets/slider/IMG_7074.jpg'
|
||||
imageAlt: 'twenty-fifth-slide'
|
||||
- image: './assets/slider/IMG_7075.jpg'
|
||||
imageAlt: 'twenty-sixth-slide'
|
||||
services:
|
||||
- title: 'Тренировка с тренером'
|
||||
link:
|
||||
@@ -54,63 +72,107 @@ services:
|
||||
- title: 'Разовая тренировка'
|
||||
description: 'Персональная тренировка 60 минут. Включает консультацию, обучение технике упражнений и рекомендации по питанию.'
|
||||
price: '5 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9063789057065586/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Разовая СПЛИТ'
|
||||
description: 'Тренировка 75 минут для двух человек. Обучение технике, консультации по питанию и тренировкам.'
|
||||
price: '8 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9525979067500181/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Блок 5 тренировок'
|
||||
description: 'Пять тренировок по 60 минут с планом питания и БЖУ. Срок - 40 дней.'
|
||||
price: '22 500 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/24101248972846560/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Блок 5 СПЛИТ'
|
||||
description: 'Пять парных тренировок по 75 минут. План тренировок и питания. Срок - 40 дней.'
|
||||
price: '38 500 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/79804450446?text=Здравствуйте!%20Хочу%20приобрести%20блок%205%20СПЛИТ%20тренировок'
|
||||
target: '_blank'
|
||||
- title: 'Блок 10 тренировок'
|
||||
description: 'Десять часовых тренировок. Программа тренировок и питания с регулярной корректировкой.'
|
||||
price: '42 500 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/79804450446?text=Здравствуйте!%20Хочу%20приобрести%20блок%2010%20персональных%20тренировок'
|
||||
target: '_blank'
|
||||
- title: 'Блок 10 СПЛИТ'
|
||||
description: 'Десять парных тренировок по 75 минут. Полное сопровождение с корректировкой программы.'
|
||||
price: '75 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/79804450446?text=Здравствуйте!%20Хочу%20приобрести%20блок%2010%20СПЛИТ%20тренировок'
|
||||
target: '_blank'
|
||||
- title: 'Блок 15 тренировок'
|
||||
description: 'Пятнадцать часовых тренировок. Расширенная программа тренировок и питания.'
|
||||
price: '60 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/79804450446?text=Здравствуйте!%20Хочу%20приобрести%20блок%2015%20персональных%20тренировок'
|
||||
target: '_blank'
|
||||
- title: 'Блок 15 СПЛИТ'
|
||||
description: 'Пятнадцать парных тренировок. Максимально эффективная программа с мониторингом.'
|
||||
price: '110 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/79804450446?text=Здравствуйте!%20Хочу%20приобрести%20блок%2015%20СПЛИТ%20тренировок'
|
||||
target: '_blank'
|
||||
- title: 'Безлимитные Абонементы'
|
||||
description: '30 календарных дней занятий с тренером'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://n1381542.yclients.com/'
|
||||
target: '_blank'
|
||||
charachteristics:
|
||||
- title: 'Персональный безлимит'
|
||||
description: 'Неограниченное количество персональных тренировок на 30 дней.'
|
||||
price: '50 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9194792393933300/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'СПЛИТ безлимит'
|
||||
description: 'Безлимитные парные тренировки на месяц.'
|
||||
price: '80 000 ₽'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9211908478906057/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Мини-группа безлимит'
|
||||
description: 'Безлимитные тренировки для 3-5 человек на месяц.'
|
||||
price: '30 000 ₽<br />c человека'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9767701363241058/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Аренда зала / Разовые посещения'
|
||||
description: 'Присутствие тренера БЕСПЛАТНО'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://n1381542.yclients.com/'
|
||||
target: '_blank'
|
||||
charachteristics:
|
||||
- title: 'Разовое посещение'
|
||||
description: 'Свободное посещение зала 75 минут с доступом к оборудованию.'
|
||||
price: '1500 ₽<br />c человека'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/9987000717998326/79804450446'
|
||||
target: '_blank'
|
||||
- title: 'Приходящий тренер'
|
||||
description: 'Тренировка 75 минут со своим тренером.'
|
||||
price: '1500 ₽<br />c человека'
|
||||
link:
|
||||
title: 'Записаться'
|
||||
href: 'https://wa.me/p/8974731312631431/79804450446'
|
||||
target: '_blank'
|
||||
reviews:
|
||||
- review: 'Место силы. Комфортная студия. Для тренировок есть всё необходимое . Раздевалки уютные , так же всё продумано до мелочей . Можно после тренировки насладиться кофе . По месторасположению очень комфортно , для парковки места есть всегда. Уютно. Спортивно . Красиво . Стильно . Профессионально! От души рекомендую'
|
||||
author:
|
||||
name: 'Анна'
|
||||
image: './assets/reviews/1.png'
|
||||
imageAlt: 'anna-avatar'
|
||||
description: 'Знаток города 16 уровня'
|
||||
description: 'Знаток года 16 уровня'
|
||||
rating: 5
|
||||
- review: 'Прекрасный и замечательный спортивный зал.
|
||||
Тренеру Батыру отдельная благодарность за заинтересованность к моим результатам и тренировкам.
|
||||
@@ -120,14 +182,14 @@ reviews:
|
||||
name: 'Станислав К.'
|
||||
image: './assets/reviews/2.png'
|
||||
imageAlt: 'stanislav-avatar'
|
||||
description: 'Знаток города 4 уровня'
|
||||
description: 'Знаток года 4 уровня'
|
||||
rating: 5
|
||||
- review: 'Уютно, красиво и свежо. Интересный зал, хорошие тренеры. Приятно, что большой спектр оказания услуг!!! Пробная тренировка прошла на ура 🙌!!!'
|
||||
author:
|
||||
name: 'Тимур П.'
|
||||
image: './assets/reviews/3.png'
|
||||
imageAlt: 'timur-avatar'
|
||||
description: 'Знаток города 5 уровня'
|
||||
description: 'Знаток года 5 уровня'
|
||||
rating: 5
|
||||
footer:
|
||||
socialMediaLinks:
|
||||
|
||||
@@ -8,15 +8,14 @@ export type TranslationKey = keyof (typeof ui)[keyof typeof ui]
|
||||
export const ui = {
|
||||
ru: {
|
||||
'seo.meta.description':
|
||||
'The Real Skill Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.',
|
||||
'THEREALSKILL Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.',
|
||||
'seo.meta.keywords':
|
||||
'фитнес, тренировки, спортзал, персональный тренер, групповые занятия, здоровье, спорт, Real Skill Studio"',
|
||||
'seo.og.title': 'THEREALSKILL',
|
||||
'фитнес, тренировки, спортзал, персональный тренер, групповые занятия, здоровье, спорт, THEREALSKILL Studio"',
|
||||
'seo.og.title': 'THEREALSKILL Studio',
|
||||
'seo.og.description':
|
||||
'The Real Skill Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.',
|
||||
'THEREALSKILL Studio - профессиональная фитнес-студия в России. Персональные тренировки, групповые занятия, опытные тренеры.',
|
||||
'home.title': 'Фитнес-студия',
|
||||
// Header
|
||||
'header.logo': 'THEREAL<span class="text-brand">SKILL</span>',
|
||||
'nav.coaches': 'Тренера',
|
||||
'nav.slider': 'Галерея',
|
||||
'nav.services': 'Услуги',
|
||||
@@ -50,15 +49,14 @@ export const ui = {
|
||||
},
|
||||
en: {
|
||||
'seo.meta.description':
|
||||
'The Real Skill Studio - professional fitness studio in Russia. Personal training, group classes, experienced trainers.',
|
||||
'THEREALSKILL 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"',
|
||||
'fitness, training, gym, personal trainer, group classes, health, sports, THEREALSKILL Studio"',
|
||||
'seo.og.title': 'THEREALSKILL',
|
||||
'seo.og.description':
|
||||
'The Real Skill Studio - professional fitness studio in Russia. Personal training, group classes, experienced trainers.',
|
||||
'THEREALSKILL Studio - professional fitness studio in Russia. Personal training, group classes, experienced trainers.',
|
||||
'home.title': 'Fitness Studio',
|
||||
// Header
|
||||
'header.logo': 'THEREAL<span class="text-brand">SKILL</span>',
|
||||
'nav.coaches': 'Coaches',
|
||||
'nav.slider': 'Gallery',
|
||||
'nav.services': 'Services',
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
@layer base {
|
||||
:root {
|
||||
--header-height: 4rem;
|
||||
--header-height: 6rem;
|
||||
--marquee-height: 105px;
|
||||
--swiper-theme-color: rgba(198, 15, 211, 1) !important;
|
||||
}
|
||||
|
||||