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:
zabudko-ruandClaude Opus 5.5 committed 2026-10-25 22:55:29 +04:00
1 parent 45d7512d2b
commit 3489e0b816
319 files changed
+45483 -121

No files matched your search

+80
View File
@@ -0,0 +1,80 @@
import { createT, LOCALES, type Locale } from '@barev/i18n';
import type { LandingOffer } from '../lib/data';
import { CONTACTS, SITE } from '../lib/seo';
/** Телефон и почта для подвала: видны текстом, чтобы их могли прочитать люди, поисковики и ИИ */
export function FooterContacts() {
return (
<>
<a href={`tel:${CONTACTS.phone}`}>{CONTACTS.phoneDisplay}</a>
<a href={`mailto:${CONTACTS.email}`}>{CONTACTS.email}</a>
</>
);
}
/** Строка с реквизитами ИП — сигнал доверия для клиентов и E-E-A-T для Google */
export function LegalLine({ locale, className }: { locale: Locale; className?: string }) {
return <small className={className}>{createT(locale)('landing.footer.legal', { tin: CONTACTS.tin })}</small>;
}
/**
* Структурированные данные (JSON-LD) для Google и ИИ-поиска: кто мы, где работаем, на каких языках
* и сколько стоит подписка. Цены берутся из настроек админки, как и на самой странице.
*/
export function ClubJsonLd({ locale, path, bot, plusPrice, offer }: { locale: Locale; path: '' | '/live'; bot: string; plusPrice: number; offer: LandingOffer }) {
const t = createT(locale);
const org = `${SITE}/#org`;
const telegram = `https://t.me/${bot}`;
const { email, phone: telephone } = CONTACTS;
const plan = (name: string, price: number) => ({
'@type': 'Offer',
name,
price,
priceCurrency: 'AMD',
...(price > 0 && { priceSpecification: { '@type': 'UnitPriceSpecification', price, priceCurrency: 'AMD', unitCode: 'MON' } }),
url: `${SITE}/${locale}${path}#plans`,
});
const data = {
'@context': 'https://schema.org',
'@graph': [
{
'@type': 'Organization',
'@id': org,
name: 'Barev Club',
legalName: CONTACTS.legalName,
taxID: CONTACTS.tin,
url: SITE,
logo: `${SITE}/apple-icon`,
description: t('landing.seo.org'),
sameAs: [telegram],
email,
telephone,
address: { '@type': 'PostalAddress', addressLocality: 'Yerevan', addressCountry: 'AM' },
contactPoint: { '@type': 'ContactPoint', contactType: 'customer support', url: telegram, telephone, email, availableLanguage: [...LOCALES] },
},
{
'@type': 'ProfessionalService',
'@id': `${SITE}/#service`,
name: 'Barev Club',
url: `${SITE}/${locale}`,
image: `${SITE}/${locale}${path}/opengraph-image`,
description: t('landing.seo.org'),
parentOrganization: { '@id': org },
telephone,
email,
address: { '@type': 'PostalAddress', addressLocality: 'Yerevan', addressCountry: 'AM' },
areaServed: { '@type': 'City', name: 'Yerevan' },
availableLanguage: [...LOCALES],
currenciesAccepted: 'AMD',
hasOfferCatalog: {
'@type': 'OfferCatalog',
name: t('landing.club.title'),
itemListElement: [plan('Barev', 0), plan('Barev+', plusPrice), plan('Barev Elite', offer.elitePrice)],
},
},
{ '@type': 'WebSite', '@id': `${SITE}/#website`, url: SITE, name: 'Barev Club', inLanguage: locale, publisher: { '@id': org } },
],
};
// «<» экранируем, чтобы текст из настроек не мог закрыть тег script
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(data).replace(/</g, '\\u003c') }} />;
}