Files
BarevClub/apps/miniapp-client/src/screens/Services.tsx
T
zabudko-ruandClaude Opus 5.5 bbb25d3d0d Stage 6 (part 2): rest of the client app in the new style, promo code in the order form
Profile with club card, plum theme for buttons/selections and the sticky total,
move screens with the full-width hero, services/docs headers, empty docs fix.
Promo code field: applies to the quote, shows why a code is rejected,
says when the membership discount is bigger.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-21 04:08:47 +04:00

76 lines
3.2 KiB
TypeScript

import { useQuery } from '@tanstack/react-query';
import { CATEGORY_ICON, Center, Icon, Spinner, type CategoryCode } from '@barev/ui';
import { useI18n, useLocation, useTRPC } from '@barev/web';
import { useEffect } from 'react';
import { levelDiscount, toneClass, type Level } from '../lib.tsx';
/** Каталог: направления со скидкой по уровню клиента; услуги без онлайн-записи — заявка «перезвоните» */
export function Services() {
const { t, amd } = useI18n();
const trpc = useTRPC();
const { query } = useLocation();
const focus = query.get('c');
const catalog = useQuery(trpc.client.catalog.queryOptions());
useEffect(() => {
if (focus && catalog.data) document.getElementById(`cat-${focus}`)?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, [focus, catalog.data]);
if (!catalog.data)
return (
<Center>
<Spinner />
</Center>
);
const level = catalog.data.level as Level;
return (
<main className="app">
<header className="screen-head">
<h1 className="screen-head__title">{t('client.services.title')}</h1>
</header>
{catalog.data.categories
.filter((c) => c.code !== 'PERKS')
.map((c) => (
<section key={c.code} id={`cat-${c.code}`} className={`bc-card ${toneClass(c.code)}`} style={{ padding: 20, scrollMarginTop: 12 }}>
<div className="bc-between" style={{ marginBottom: 12 }}>
<h2 className="bc-h2">{t(`categories.${c.code}.name`)}</h2>
<Icon name={CATEGORY_ICON[c.code as CategoryCode]} size={26} />
</div>
<div className="bc-stack" style={{ gap: 6 }}>
{c.services.map((s) =>
s.active ? (
<a key={s.code} href={`#/order/${s.code}`} className="bc-row-pill">
<span style={{ fontWeight: 600 }}>{t(`services.${s.code}.name`)}</span>
<span className="bc-row">
{t('common.from', { price: amd(s.fromPrice) })}
<Icon name="arrow" size={16} />
</span>
</a>
) : (
<a key={s.code} href={`#/request/${s.code}`} className="bc-row-pill">
<span style={{ fontWeight: 600 }}>{t(`services.${s.code}.name`)}</span>
<span className="bc-row bc-small">
{t('client.services.callback')}
<Icon name="arrow" size={16} />
</span>
</a>
),
)}
</div>
{levelDiscount(level, c) > 0 ? (
<div className="bc-small" style={{ marginTop: 10, fontWeight: 600 }}>
{t('client.services.yourDiscount', { pct: levelDiscount(level, c) })}
</div>
) : (
c.eliteDiscountPct > 0 && (
<a href="#/membership" className="bc-small" style={{ display: 'block', marginTop: 10, fontWeight: 600, color: 'inherit' }}>
{t('client.services.withElite', { pct: c.eliteDiscountPct })}
</a>
)
)}
</section>
))}
</main>
);
}