Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
137 lines
5.6 KiB
TypeScript
137 lines
5.6 KiB
TypeScript
import '../../variants.css';
|
|
import { createT, formatAmd, isLocale, LOCALES, type Locale } from '@barev/i18n';
|
|
import { notFound } from 'next/navigation';
|
|
import { BotLink, BotLinkProvider } from '../../../components/client';
|
|
import { VariantHeader, variantMetadata } from '../../../components/variant';
|
|
import { getCatalog } from '../../../lib/data';
|
|
|
|
export const revalidate = 300;
|
|
export const dynamicParams = false;
|
|
export function generateStaticParams() {
|
|
return LOCALES.map((locale) => ({ locale }));
|
|
}
|
|
export function generateMetadata({ params }: { params: Promise<{ locale: string }> }) {
|
|
return variantMetadata(params, '/land4', 'landing.v4.title');
|
|
}
|
|
|
|
/** Текст табло: каждая буква — отдельная перекидная пластинка, при загрузке они один раз «перещёлкиваются» по очереди */
|
|
function Flaps({ text, start = 0 }: { text: string; start?: number }) {
|
|
return (
|
|
<span className="v4-flaps" aria-label={text}>
|
|
{Array.from(text).map((ch, i) =>
|
|
ch === ' ' ? (
|
|
<span key={i} className="v4-gap" aria-hidden="true" />
|
|
) : (
|
|
<span key={i} className="v4-flap" aria-hidden="true" style={{ ['--i' as string]: start + i }}>
|
|
{ch}
|
|
</span>
|
|
),
|
|
)}
|
|
</span>
|
|
);
|
|
}
|
|
|
|
/** Версия 4 «Табло прилёта»: для тех, кто только прилетел. Услуги клуба — как рейсы на табло, CTA — посадочный талон */
|
|
export default async function Land4({ params }: { params: Promise<{ locale: string }> }) {
|
|
const { locale: raw } = await params;
|
|
if (!isLocale(raw)) notFound();
|
|
const locale: Locale = raw;
|
|
const t = createT(locale);
|
|
const amd = (n: number) => formatAmd(locale, n);
|
|
const catalog = await getCatalog();
|
|
const rows = catalog.categories
|
|
.filter((c) => c.code !== 'PERKS')
|
|
.flatMap((c) => c.services)
|
|
.sort((a, b) => Number(b.active) - Number(a.active));
|
|
|
|
return (
|
|
<BotLinkProvider locale={locale} bot={catalog.botUsername}>
|
|
<div className="v4">
|
|
<div className="v-wrap">
|
|
<VariantHeader locale={locale} path="/land4" />
|
|
|
|
<section className="v4-hero">
|
|
<h1 className="v4-title">{t('landing.v4.title')}</h1>
|
|
<p className="v4-sub">{t('landing.v4.sub')}</p>
|
|
</section>
|
|
|
|
<section className="v4-board" aria-label={`${t('landing.v4.board')}: ${t('landing.v4.city')}`}>
|
|
<div className="v4-board__head">
|
|
<span className="v4-board__name">
|
|
{t('landing.v4.board')}
|
|
</span>
|
|
<span className="v4-board__city">{t('landing.v4.city')} EVN</span>
|
|
</div>
|
|
<table className="v4-table">
|
|
<thead>
|
|
<tr>
|
|
<th>{t('landing.v4.colFlight')}</th>
|
|
<th>{t('landing.v4.colService')}</th>
|
|
<th>{t('landing.v4.colPrice')}</th>
|
|
<th>{t('landing.v4.colStatus')}</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{rows.map((s, i) => (
|
|
<tr key={s.code} data-live={s.active}>
|
|
<td className="v4-code">BC {String(i + 1).padStart(3, '0')}</td>
|
|
<td className="v4-name">
|
|
{s.code === 'cleaning' && s.active ? (
|
|
<a href={`/${locale}/clean`}>
|
|
<Flaps text={t(`services.${s.code}.name`)} start={i * 3} />
|
|
</a>
|
|
) : (
|
|
<Flaps text={t(`services.${s.code}.name`)} start={i * 3} />
|
|
)}
|
|
</td>
|
|
<td className="v4-price">{s.active ? t('common.from', { price: amd(s.fromPrice) }) : '—'}</td>
|
|
<td>
|
|
<span className="v4-status">{s.active ? t('landing.v4.live') : t('landing.v4.soon')}</span>
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
{/* посадочный талон: корешок отрывается по пунктиру, кнопка — посадка в бота */}
|
|
<section className="v4-pass">
|
|
<div className="v4-pass__main">
|
|
<div className="v4-pass__title">{t('landing.v4.passTitle')}</div>
|
|
<dl className="v4-pass__grid">
|
|
<div>
|
|
<dt>{t('landing.v4.passenger')}</dt>
|
|
<dd>{t('landing.v4.passengerValue')}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>{t('landing.v4.from')}</dt>
|
|
<dd>{t('landing.v4.fromValue')}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>{t('landing.v4.to')}</dt>
|
|
<dd>{t('landing.v4.toValue')}</dd>
|
|
</div>
|
|
<div>
|
|
<dt>{t('landing.v4.gate')}</dt>
|
|
<dd>{t('landing.v4.gateValue')}</dd>
|
|
</div>
|
|
</dl>
|
|
</div>
|
|
<div className="v4-pass__stub">
|
|
<BotLink className="bc-btn v4-pass__cta">{t('landing.v4.cta')}</BotLink>
|
|
<a href={`/${locale}/clean`} className="v4-pass__link">
|
|
{t('landing.v4.clean')}
|
|
</a>
|
|
</div>
|
|
</section>
|
|
|
|
<footer className="v-footer">
|
|
<span>{t('landing.footer.brand')}</span>
|
|
<a href={`/${locale}/privacy`}>{t('landing.footer.privacy')}</a>
|
|
</footer>
|
|
</div>
|
|
</div>
|
|
</BotLinkProvider>
|
|
);
|
|
}
|