Files
BarevClub/apps/landing/components/home.tsx
T
2026-10-25 22:57:03 +04:00

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>
);
}