Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
111 lines
4.7 KiB
TypeScript
111 lines
4.7 KiB
TypeScript
import { createT, formatAmd, isLocale, LOCALES, type Locale } from '@barev/i18n';
|
|
import { Icon } from '@barev/ui';
|
|
import type { Metadata } from 'next';
|
|
import { getCatalog, type LandingOffer } from '../lib/data';
|
|
import { BotLink } from './client';
|
|
import { SERVICE_PAGES } from '../lib/services';
|
|
import { LegalLinks } from './legal';
|
|
import { FooterContacts, LegalLine } from './seo';
|
|
|
|
/** Главная (/) и «Уже живу» (/live): индексируются, у каждой свой canonical и hreflang */
|
|
export async function homeMetadata(params: Promise<{ locale: string }>, path: '' | '/live'): Promise<Metadata> {
|
|
const { locale } = await params;
|
|
if (!isLocale(locale)) return {};
|
|
const t = createT(locale);
|
|
const { offer } = await getCatalog();
|
|
const title = t(path ? 'landing.live.metaTitle' : 'landing.home.metaTitle');
|
|
const description = t(path ? 'landing.live.metaDescription' : 'landing.home.metaDescription', { pct: offer.eliteMaxPct });
|
|
return {
|
|
title,
|
|
description,
|
|
alternates: {
|
|
canonical: `/${locale}${path}`,
|
|
languages: Object.fromEntries([...LOCALES.map((l) => [l, `/${l}${path}`]), ['x-default', `/ru${path}`]]),
|
|
},
|
|
openGraph: { title, description, locale, type: 'website', siteName: 'Barev Club' },
|
|
};
|
|
}
|
|
|
|
/** Переключатель аудитории: две версии главной — «Переезжаю» и «Уже живу в Армении» */
|
|
export function AudienceSwitch({ locale, current }: { locale: Locale; current: 'move' | 'live' }) {
|
|
const t = createT(locale);
|
|
return (
|
|
<nav className="h-switch" aria-label={t('landing.home.switchLabel')}>
|
|
<a href={`/${locale}`} aria-current={current === 'move' ? 'page' : undefined}>
|
|
{t('landing.home.switchMove')}
|
|
</a>
|
|
<a href={`/${locale}/live`} aria-current={current === 'live' ? 'page' : undefined}>
|
|
{t('landing.home.switchLive')}
|
|
</a>
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Тарифы как клубные карты: Barev — прозрачная, Barev+ — розовая, Elite — жёлтая.
|
|
* Оформление подписки — в боте, поэтому все кнопки ведут туда.
|
|
*/
|
|
export function ClubPlans({ locale, plusPrice, offer }: { locale: Locale; plusPrice: number; offer: LandingOffer }) {
|
|
const t = createT(locale);
|
|
const amd = (n: number) => formatAmd(locale, n);
|
|
const plans = [
|
|
{ id: 'free', name: 'Barev', price: t('landing.club.free'), cta: t('landing.club.freeCta') },
|
|
{ id: 'plus', name: 'Barev+', price: t('landing.club.perMonth', { price: amd(plusPrice) }), cta: t('landing.club.plusCta') },
|
|
{ id: 'elite', name: 'Barev Elite', price: t('landing.club.perMonth', { price: amd(offer.elitePrice) }), cta: t('landing.club.eliteCta') },
|
|
] as const;
|
|
return (
|
|
<section id="plans" className="h-plans" aria-labelledby="plans-title">
|
|
<div className="h-section-head">
|
|
<h2 id="plans-title">{t('landing.club.title')}</h2>
|
|
<p>{t('landing.club.sub')}</p>
|
|
</div>
|
|
<div className="h-plans__grid">
|
|
{plans.map((p) => (
|
|
<article key={p.id} className="h-plan" data-plan={p.id}>
|
|
<div className="h-card">
|
|
<span className="h-card__club">Barev Club</span>
|
|
<span className="h-card__chip" aria-hidden="true" />
|
|
<h3 className="h-card__name">{p.name}</h3>
|
|
<span className="h-card__price">{p.price}</span>
|
|
</div>
|
|
<ul className="h-plan__list">
|
|
{[1, 2, 3].map((n) => (
|
|
<li key={n}>
|
|
<Icon name="check" size={18} strokeWidth={2.6} />
|
|
{t(`landing.club.${p.id}F${n}`, { pct: p.id === 'elite' ? offer.eliteMaxPct : offer.plusMaxPct })}
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<BotLink className="bc-btn h-plan__cta">{p.cta}</BotLink>
|
|
</article>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|
|
|
|
export function HomeFooter({ locale }: { locale: Locale }) {
|
|
const t = createT(locale);
|
|
return (
|
|
<footer className="v-footer v-footer--dark">
|
|
<nav className="h-footer__services" aria-label={t('landing.footer.services')}>
|
|
{Object.values(SERVICE_PAGES).map((p) => (
|
|
<a key={p.id} href={`/${locale}${p.path}`}>
|
|
{t(`landing.svc.${p.id}.crumb`)}
|
|
</a>
|
|
))}
|
|
<a href={`/${locale}/clean`}>{t('landing.svc.common.clean')}</a>
|
|
</nav>
|
|
<span className="h-footer__brand">
|
|
{t('landing.footer.brand')}
|
|
<LegalLine locale={locale} className="h-footer__legal" />
|
|
</span>
|
|
<span className="h-footer__links">
|
|
<FooterContacts />
|
|
<BotLink>{t('landing.footer.partner')}</BotLink>
|
|
<LegalLinks locale={locale} />
|
|
</span>
|
|
</footer>
|
|
);
|
|
}
|