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,103 @@
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { CATEGORY_ICON, Card, Chip, Icon, Spinner, type CategoryCode } from '@barev/ui';
|
||||
import { navigate, useI18n, useTRPC } from '@barev/web';
|
||||
import { LEVEL_NAME, LevelBadge, levelDiscount, OrderRow, toneClass, type Level } from '../lib.tsx';
|
||||
|
||||
/** Главная для тех, кто уже живёт в Армении: заказы, быстрые кнопки, направления со скидкой по уровню */
|
||||
export function Home() {
|
||||
const { t, dt } = useI18n();
|
||||
const trpc = useTRPC();
|
||||
const me = useQuery(trpc.client.me.queryOptions());
|
||||
const orders = useQuery({ ...trpc.client.orders.list.queryOptions(), refetchInterval: 20_000 });
|
||||
const catalog = useQuery(trpc.client.catalog.queryOptions());
|
||||
const level = (me.data?.membership.level ?? 'BAREV') as Level;
|
||||
const plus = level !== 'BAREV';
|
||||
const lastDone = orders.data?.history.find((o) => o.status !== 'CANCELLED');
|
||||
|
||||
return (
|
||||
<main className="app">
|
||||
<header className="bc-between" style={{ alignItems: 'flex-start' }}>
|
||||
<div>
|
||||
<div className="bc-small bc-muted">{t('client.home.hello')}</div>
|
||||
<h1 className="bc-h2">{me.data?.firstName ?? t('client.home.guest')}</h1>
|
||||
</div>
|
||||
<LevelBadge level={level} />
|
||||
</header>
|
||||
|
||||
{plus && me.data?.membership.endsAt && (
|
||||
<Card tone="perks" tight>
|
||||
<div className="bc-row">
|
||||
<Icon name="gift" />
|
||||
<div className="bc-small" style={{ fontWeight: 600 }}>
|
||||
{t('client.home.levelUntil', { plan: LEVEL_NAME[level], date: dt(me.data.membership.endsAt, { day: 'numeric', month: 'long' }) })}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{!plus && (
|
||||
<a href="#/membership" className="upsell">
|
||||
<b>{t('client.home.upsellTitle', { pct: me.data?.plans.eliteMaxPct ?? 0 })}</b>
|
||||
<span className="bc-small">{t('client.home.upsellText')}</span>
|
||||
</a>
|
||||
)}
|
||||
|
||||
<Card style={{ padding: 16 }}>
|
||||
<div className="bc-between" style={{ padding: '0 4px 8px' }}>
|
||||
<h2 className="bc-h3">{t('client.home.myOrders')}</h2>
|
||||
<a href="#/orders" className="bc-small bc-muted">
|
||||
{t('client.home.allOrders')}
|
||||
</a>
|
||||
</div>
|
||||
{orders.isPending ? (
|
||||
<Spinner />
|
||||
) : orders.data && orders.data.active.length > 0 ? (
|
||||
<div className="bc-stack" style={{ gap: 8 }}>
|
||||
{orders.data.active.slice(0, 4).map((o) => (
|
||||
<OrderRow key={o.id} o={o} />
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="bc-stack" style={{ padding: '4px 4px 6px' }}>
|
||||
<p className="bc-muted" style={{ margin: 0 }}>
|
||||
{t('client.home.noOrders')}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
<div className="quick">
|
||||
<Chip onClick={() => navigate('/order/cleaning')}>
|
||||
<Icon name="home" size={18} />
|
||||
{t('services.cleaning.name')}
|
||||
</Chip>
|
||||
{lastDone && (
|
||||
<Chip onClick={() => navigate(`/order/${lastDone.serviceCode}?repeat=${lastDone.id}`)}>
|
||||
<Icon name="repeat" size={18} />
|
||||
{t('client.home.repeatLast')}
|
||||
</Chip>
|
||||
)}
|
||||
{!me.data?.agencyName && (
|
||||
<Chip onClick={() => navigate('/profile?code=1')}>
|
||||
<Icon name="gift" size={18} />
|
||||
{t('client.home.enterCode')}
|
||||
</Chip>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="tiles">
|
||||
{(catalog.data?.categories ?? []).map((c) => (
|
||||
<a key={c.code} href={c.code === 'PERKS' ? '#/perks' : `#/services?c=${c.code}`} className={`tile ${toneClass(c.code)}`}>
|
||||
<div className="bc-between" style={{ alignItems: 'flex-start' }}>
|
||||
<div className="tile__title">{t(`categories.${c.code}.name`)}</div>
|
||||
<Icon name={CATEGORY_ICON[c.code as CategoryCode]} size={24} />
|
||||
</div>
|
||||
<div className="bc-small">
|
||||
{levelDiscount(level, c) > 0 ? t('client.services.yourDiscount', { pct: levelDiscount(level, c) }) : t(`categories.${c.code}.short`)}
|
||||
</div>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user