Apps, web, i18n, UI, partners, payouts, backoffice, bariki, prod infra
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
45d7512d2b
commit
3489e0b816
319 files changed
+45483
-121
No files matched your search
@@ -0,0 +1,111 @@
|
||||
import '../../variants.css';
|
||||
import { createT, formatAmd, isLocale, LOCALES, type Locale } from '@barev/i18n';
|
||||
import { Icon } from '@barev/ui';
|
||||
import { notFound } from 'next/navigation';
|
||||
import { BotLink, BotLinkProvider } from '../../../components/client';
|
||||
import { GiftCode } from '../../../components/gift-code';
|
||||
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, '/land3', 'landing.v3.title');
|
||||
}
|
||||
|
||||
/** Версия 3 «Подарок от агентства»: для тех, кто пришёл по QR из договора аренды. Бирка для ключей с месяцем Barev+ */
|
||||
export default async function Land3({ 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 home = catalog.categories.find((c) => c.code === 'HOME');
|
||||
const cleaningFrom = home?.services.find((s) => s.code === 'cleaning')?.fromPrice ?? 0;
|
||||
const homePct = home?.barevPlusDiscountPct ?? 0;
|
||||
// так же округляет скидку сервер: вниз до целого драма
|
||||
const cleaningWithPlus = cleaningFrom - Math.floor((cleaningFrom * homePct) / 100);
|
||||
const discounts = catalog.categories.filter((c) => c.barevPlusDiscountPct > 0);
|
||||
|
||||
return (
|
||||
<BotLinkProvider locale={locale} bot={catalog.botUsername}>
|
||||
<div className="v3">
|
||||
<div className="v-wrap">
|
||||
<VariantHeader locale={locale} path="/land3" />
|
||||
|
||||
<section className="v3-hero">
|
||||
<div className="v3-hero__text">
|
||||
<span className="v3-kicker">{t('landing.v3.tag')}</span>
|
||||
<h1 className="v3-title">{t('landing.v3.title')}</h1>
|
||||
<p className="v3-sub">{t('landing.v3.sub')}</p>
|
||||
<BotLink className="bc-btn bc-btn--accent v3-cta">{t('landing.v3.cta')}</BotLink>
|
||||
</div>
|
||||
<div className="v3-tagwrap" aria-hidden="true">
|
||||
<svg className="v3-string" viewBox="0 0 120 160" fill="none">
|
||||
<path d="M60 0 C 20 40, 100 80, 60 132" stroke="currentColor" strokeWidth="3" strokeLinecap="round" />
|
||||
</svg>
|
||||
<div className="v3-tag">
|
||||
<span className="v3-tag__hole" />
|
||||
<span className="v3-tag__label">{t('landing.agency.gift')}</span>
|
||||
<span className="v3-tag__title">{t('landing.v3.giftTitle')}</span>
|
||||
<GiftCode withCode={t('landing.v3.giftCode')} withoutCode={t('landing.v3.giftNoCode')} />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="v3-steps">
|
||||
<h2 className="v3-h2">{t('landing.v3.stepsTitle')}</h2>
|
||||
<ol>
|
||||
{([1, 2, 3] as const).map((n) => (
|
||||
<li key={n}>
|
||||
<span className="v3-num">{n}</span>
|
||||
<b>{t(`landing.v3.step${n}`)}</b>
|
||||
<span>{t(`landing.v3.step${n}Sub`)}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section className="v3-benefits">
|
||||
<div className="v3-deal">
|
||||
<h2 className="v3-h2">{t('landing.v3.benefitsTitle')}</h2>
|
||||
{homePct > 0 && cleaningFrom > 0 && (
|
||||
<a href={`/${locale}/clean`} className="v3-deal__card">
|
||||
<b>{t('landing.v3.cleaningDeal', { price: amd(cleaningWithPlus), full: amd(cleaningFrom) })}</b>
|
||||
<span>{t('landing.v3.cleaningDealSub')}</span>
|
||||
<span className="v3-deal__go">{t('landing.hero.cleanCta')}</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<ul className="v3-list">
|
||||
{discounts.map((c) => (
|
||||
<li key={c.code}>
|
||||
<Icon name="check" size={20} strokeWidth={2.6} />
|
||||
{t('plans.plus.discount', { pct: c.barevPlusDiscountPct, category: t(`categories.${c.code}.name`) })}
|
||||
</li>
|
||||
))}
|
||||
<li>
|
||||
<Icon name="check" size={20} strokeWidth={2.6} />
|
||||
{t('plans.free.perks')}
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<section className="v3-final">
|
||||
<p>{t('landing.v3.noCode')}</p>
|
||||
<BotLink className="bc-btn bc-btn--dark">{t('landing.v3.cta')}</BotLink>
|
||||
</section>
|
||||
|
||||
<footer className="v-footer">
|
||||
<span>{t('landing.footer.brand')}</span>
|
||||
<a href={`/${locale}/privacy`}>{t('landing.footer.privacy')}</a>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</BotLinkProvider>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user