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:
zabudko-ruandClaude Opus 5.5 committed 2026-10-21 01:23:32 +04:00
1 parent 45d7512d2b
commit d452824c62
314 files changed
+44394 -121

No files matched your search

+79
View File
@@ -0,0 +1,79 @@
import { formatAmd, type Locale } from '@barev/i18n';
import type { LandingCatalog } from './data';
/** Страницы услуг под поисковые запросы: адрес, количество блоков в текстах и откуда брать цены */
export type ServicePageId = 'socialCard' | 'residence' | 'airport';
export interface ServicePageConfig {
id: ServicePageId;
path: '/social-card' | '/residence-permit' | '/airport';
/** schema.org serviceType — для JSON-LD */
serviceType: string;
steps: number;
blocks: number;
prices: number;
faq: number;
/** подстановки для текстов: цены из админки и скидки по направлениям */
vars: (c: LandingCatalog, locale: Locale) => Record<string, string>;
/** цены для разметки Offer, ֏ */
offers: (c: LandingCatalog) => { name: string; price: number; minPrice?: boolean }[];
}
const pct = (c: LandingCatalog, code: 'HOME' | 'DOCS') => String(c.categories.find((x) => x.code === code)?.barevPlusDiscountPct ?? 0);
export const SERVICE_PAGES: Record<ServicePageId, ServicePageConfig> = {
socialCard: {
id: 'socialCard',
path: '/social-card',
serviceType: 'Public Services Number (social card) registration in Armenia',
steps: 5,
blocks: 4,
prices: 2,
faq: 5,
vars: (c, l) => ({ price: formatAmd(l, c.offer.socialCard), docsPct: pct(c, 'DOCS') }),
offers: (c) => [{ name: 'Social card, end to end', price: c.offer.socialCard }],
},
residence: {
id: 'residence',
path: '/residence-permit',
serviceType: 'Residence permit support in Armenia',
steps: 6,
blocks: 5,
prices: 4,
faq: 6,
vars: (c, l) => ({
consult: formatAmd(l, c.offer.consultation),
escort: formatAmd(l, c.offer.residenceEscortFrom),
fee: formatAmd(l, c.offer.residenceStateFee),
}),
offers: (c) => [
{ name: 'Consultation', price: c.offer.consultation },
{ name: 'Residence permit support', price: c.offer.residenceEscortFrom, minPrice: true },
],
},
airport: {
id: 'airport',
path: '/airport',
serviceType: 'Airport transfer with meet and greet, Zvartnots (EVN) to Yerevan',
steps: 5,
blocks: 3,
prices: 4,
faq: 5,
vars: (c, l) => ({
standard: formatAmd(l, c.offer.transferStandard),
premium: formatAmd(l, c.offer.transferPremium),
hotelPlus: formatAmd(l, c.offer.hotelWithPlus),
hotelBase: formatAmd(l, c.offer.hotelBase),
homePct: pct(c, 'HOME'),
}),
offers: (c) => [
{ name: 'Standard', price: c.offer.transferStandard },
{ name: 'Premium', price: c.offer.transferPremium },
],
},
};
export const SERVICE_PATHS = Object.values(SERVICE_PAGES).map((p) => p.path);
/** 1..n — для перебора ключей s1, s2, … */
export const range = (n: number) => Array.from({ length: n }, (_, i) => i + 1);