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,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') }} />;
|
||||
}
|
||||
Reference in new issue
Block a user