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:
1 parent
45d7512d2b
commit
d452824c62
314 files changed
+44394
-121
No files matched your search
@@ -0,0 +1,73 @@
|
||||
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, PageHead, 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">
|
||||
<PageHead title={t('client.services.title')} back={false} />
|
||||
{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>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user