Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
96 lines
4.0 KiB
TypeScript
96 lines
4.0 KiB
TypeScript
import { CATEGORY_TONE, Icon, type CategoryCode } from '@barev/ui';
|
|
import { paramsSummary, useI18n } from '@barev/web';
|
|
import type { ReactNode } from 'react';
|
|
|
|
export const toneClass = (c: string) => `bc-tone-${CATEGORY_TONE[c as CategoryCode] ?? 'white'}`;
|
|
|
|
export function PageHead({ title, back = true, right }: { title: ReactNode; back?: boolean; right?: ReactNode }) {
|
|
const { t } = useI18n();
|
|
return (
|
|
<div className="page-head">
|
|
{back && (
|
|
<button className="back" onClick={() => window.history.back()} aria-label={t('common.back')}>
|
|
<Icon name="back" />
|
|
</button>
|
|
)}
|
|
<h1 className="bc-h2" style={{ flex: 1 }}>
|
|
{title}
|
|
</h1>
|
|
{right}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export interface OrderLike {
|
|
id: string;
|
|
number: number;
|
|
serviceCode: string;
|
|
category: string;
|
|
flow: string;
|
|
status: string;
|
|
scheduledAt: Date;
|
|
params: Record<string, unknown>;
|
|
}
|
|
|
|
/** Подпись параметров: «Генеральная · 2 комнаты» */
|
|
export function useParamsSummary() {
|
|
const { t } = useI18n();
|
|
return (serviceCode: string, params: Record<string, unknown>) => paramsSummary(t, serviceCode, params);
|
|
}
|
|
|
|
/** Строка заявки как в превью «Мои заявки» макета */
|
|
export function OrderRow({ o }: { o: OrderLike }) {
|
|
const { t, dt } = useI18n();
|
|
const summary = useParamsSummary();
|
|
return (
|
|
<a href={`#/orders/${o.id}`} className={`order-row ${toneClass(o.category)}`}>
|
|
<div className="order-row__main">
|
|
<div className="order-row__title">
|
|
{t(`services.${o.serviceCode}.name`)} · {summary(o.serviceCode, o.params)}
|
|
</div>
|
|
<div className="bc-small">{dt(o.scheduledAt, { weekday: 'short', day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' })}</div>
|
|
</div>
|
|
<span className="bc-badge">{t(`status.${o.flow}.${o.status}`)}</span>
|
|
</a>
|
|
);
|
|
}
|
|
|
|
export type Level = 'BAREV' | 'BAREV_PLUS' | 'ELITE';
|
|
export const LEVEL_NAME: Record<Level, string> = { BAREV: 'Barev', BAREV_PLUS: 'Barev+', ELITE: 'Barev Elite' };
|
|
/** Цвет плашки уровня: как карты на сайте — Barev+ розовая, Elite жёлтая */
|
|
export const LEVEL_TONE: Record<Level, { bg: string; ink: string }> = {
|
|
BAREV: { bg: 'var(--bc-surface)', ink: 'var(--bc-ink)' },
|
|
BAREV_PLUS: { bg: 'var(--bc-pink)', ink: 'var(--bc-plum)' },
|
|
ELITE: { bg: 'var(--bc-perks)', ink: 'var(--bc-plum)' },
|
|
};
|
|
|
|
/** Скидка клиента на направление по его уровню; у Elite без своей скидки — скидка Barev+ */
|
|
export function levelDiscount(level: Level, c: { barevPlusDiscountPct: number; eliteDiscountPct: number }) {
|
|
if (level === 'ELITE') return Math.max(c.eliteDiscountPct, c.barevPlusDiscountPct);
|
|
return level === 'BAREV_PLUS' ? c.barevPlusDiscountPct : 0;
|
|
}
|
|
|
|
export function LevelBadge({ level }: { level: Level }) {
|
|
const tone = LEVEL_TONE[level];
|
|
return (
|
|
<a href="#/membership" style={{ textDecoration: 'none' }}>
|
|
<span className="bc-badge" style={{ background: tone.bg, color: tone.ink, padding: '8px 14px', fontSize: 13 }}>
|
|
{LEVEL_NAME[level]}
|
|
</span>
|
|
</a>
|
|
);
|
|
}
|
|
|
|
export type RelocationNames = Record<string, { name: Record<string, string>; hint: Record<string, string> | null }>;
|
|
/** Название шага или документа: своё у клиента (title) или из общего списка на языке клиента */
|
|
export function itemName(names: RelocationNames | undefined, kind: 'STEP' | 'DOC', item: { code: string; title: string | null }, locale: string) {
|
|
if (item.title) return item.title;
|
|
const n = names?.[`${kind}:${item.code}`]?.name;
|
|
return n?.[locale] || n?.ru || item.code;
|
|
}
|
|
export function itemHint(names: RelocationNames | undefined, kind: 'STEP' | 'DOC', item: { code: string; title: string | null }, locale: string) {
|
|
if (item.title) return null;
|
|
const h = names?.[`${kind}:${item.code}`]?.hint;
|
|
return h?.[locale] || h?.ru || null;
|
|
}
|