Snapshot of uncommitted work: landing, bots, prod infra, partner cabinet, backoffice stage 1
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
45d7512d2b
commit
d452824c62
314 files changed
+44394
-121
No files matched your search
@@ -0,0 +1,130 @@
|
||||
import '../../variants.css';
|
||||
import { quote } from '@barev/core';
|
||||
import { createT, formatAmd, formatDateTime, 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, getCleaning } 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, '/land6', 'landing.v6.tag');
|
||||
}
|
||||
|
||||
/** Пример дохода агентства: условные клиенты и заказы, цена и процент — настоящие из каталога и настроек */
|
||||
const EXAMPLE = { clients: 20, orders: 2 };
|
||||
|
||||
/** Печать клуба: текст по кругу и «Barev» в центре */
|
||||
function Stamp() {
|
||||
return (
|
||||
<svg className="v6-stamp" viewBox="0 0 160 160" aria-hidden="true">
|
||||
<defs>
|
||||
<path id="v6-ring" d="M80 80 m-58 0 a58 58 0 1 1 116 0 a58 58 0 1 1 -116 0" />
|
||||
</defs>
|
||||
<circle cx="80" cy="80" r="74" fill="none" stroke="currentColor" strokeWidth="3" />
|
||||
<circle cx="80" cy="80" r="44" fill="none" stroke="currentColor" strokeWidth="2" />
|
||||
{/* длина текста = окружность r=58 (2π·58 ≈ 364), чтобы конец не наезжал на начало */}
|
||||
<text fontSize="14" fontWeight="700" fill="currentColor">
|
||||
<textPath href="#v6-ring" textLength="356" lengthAdjust="spacing">
|
||||
BAREV CLUB ✦ YEREVAN ✦ PARTNER ✦
|
||||
</textPath>
|
||||
</text>
|
||||
<text x="80" y="88" textAnchor="middle" fontSize="24" fontWeight="800" fontStyle="italic" fill="currentColor">
|
||||
Barev
|
||||
</text>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
/** Версия 6 «Для агентств»: B2B-страница главного канала привлечения, оформленная как договор с пунктами и печатью */
|
||||
export default async function Land6({ 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, cleaning] = await Promise.all([getCatalog(), getCleaning()]);
|
||||
const agency = catalog.agency ?? { commissionPct: 10, attributionMonths: 12 };
|
||||
const price = quote(cleaning.pricing, { cleaningType: 'regular', rooms: 2, bathrooms: 1 }).totalPrice;
|
||||
const amount = Math.round((EXAMPLE.clients * EXAMPLE.orders * price * agency.commissionPct) / 100);
|
||||
const vars = { pct: agency.commissionPct, months: agency.attributionMonths, days: catalog.barevPlus.giftDays };
|
||||
const sections = [
|
||||
{ key: 's1', items: ['s1i1', 's1i2', 's1i3'] },
|
||||
{ key: 's2', items: ['s2i1', 's2i2', 's2i3'] },
|
||||
{ key: 's3', items: ['s3i1', 's3i2', 's3i3'] },
|
||||
];
|
||||
|
||||
return (
|
||||
<BotLinkProvider locale={locale} bot={catalog.botUsername}>
|
||||
<div className="v6">
|
||||
<div className="v-wrap">
|
||||
<VariantHeader locale={locale} path="/land6" />
|
||||
|
||||
<article className="v6-doc">
|
||||
<div className="v6-doc__top">
|
||||
<span className="v6-tag">{t('landing.v6.tag')}</span>
|
||||
<span className="v6-date">
|
||||
{t('landing.v6.docDate')}, {formatDateTime(locale, new Date(), { day: 'numeric', month: 'long', year: 'numeric' })}
|
||||
</span>
|
||||
</div>
|
||||
<h1 className="v6-title">{t('landing.v6.title')}</h1>
|
||||
<p className="v6-sub">{t('landing.v6.sub')}</p>
|
||||
|
||||
<div className="v6-body">
|
||||
<div className="v6-clauses">
|
||||
{sections.map((s, i) => (
|
||||
<section key={s.key} className="v6-clause">
|
||||
<h2>
|
||||
<span>{i + 1}.</span> {t(`landing.v6.${s.key}`)}
|
||||
</h2>
|
||||
<ol>
|
||||
{s.items.map((item, j) => (
|
||||
<li key={item}>
|
||||
<span className="v6-num">
|
||||
{i + 1}.{j + 1}
|
||||
</span>
|
||||
<span>{t(`landing.v6.${item}`, vars)}</span>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<aside className="v6-example">
|
||||
<div className="v6-example__title">{t('landing.v6.exampleTitle')}</div>
|
||||
<div className="v6-example__calc">{t('landing.v6.exampleText', { clients: EXAMPLE.clients, orders: EXAMPLE.orders, price: amd(price) })}</div>
|
||||
<div className="v6-example__pct">× {agency.commissionPct}%</div>
|
||||
<div className="v6-example__result">{t('landing.v6.exampleResult', { amount: amd(amount) })}</div>
|
||||
<p>{t('landing.v6.exampleNote')}</p>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<div className="v6-sign">
|
||||
<div className="v6-sign__line">
|
||||
<span />
|
||||
{t('landing.v6.signAgency')}
|
||||
</div>
|
||||
<div className="v6-sign__line v6-sign__line--us">
|
||||
<Stamp />
|
||||
<span />
|
||||
{t('landing.v6.signUs')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BotLink className="bc-btn bc-btn--accent v6-cta">{t('landing.v6.cta')}</BotLink>
|
||||
</article>
|
||||
|
||||
<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