2ec5d1b6d6
Clarify Front#45: sprout/bolt/briefcase in switcher; CalenTIQ wordmark not mark-only. Refs EventHub/EventHubFront#45
262 lines
20 KiB
Markdown
262 lines
20 KiB
Markdown
# UI parity: EventHubFront ↔ CalenTIQ board
|
||
|
||
План визуального выравнивания клиентского фронта с утверждённым бордом.
|
||
SoT: [`boards/calentiq-ui-board-final.png`](boards/calentiq-ui-board-final.png).
|
||
Эпик: [EventHubSpec#10](https://git.sabilin.com/EventHub/EventHubSpec/issues/10).
|
||
|
||
**Статус:** workstreams 1–5 закрыты в коде Front (Refs Front#25–#29). Stage smoke на `https://stage.calentiq.com` — **done** (UI `0.2.29` / `79dadfb21f98`, API `0.2.158`).
|
||
|
||
---
|
||
|
||
## Known deviations from board (Front#29)
|
||
|
||
Зафиксировано осознанно / пока не делаем (после visual pass ×3 moods + stage):
|
||
|
||
| Зона | Борд | Сейчас |
|
||
|------|------|--------|
|
||
| Pixel-perfect calendar | denser board mock + Today/Upcoming rail | Agenda rail (§B): title-case Сегодня/Предстоящие + count, time-first rows; month chips/cell wash (§B/D) по mood; не 1:1 Figma |
|
||
| Discover cards | soft cards + media thumb + CTA | mood media plane (wash/initials + `image_url` when present) + soft-card rhythm + CTA; без full photo-hero grid |
|
||
| CONTROL booking §E | отдельные mock-карточки «слот/специалист» | `EventActionCard` / specialists / bookings: steel rail (усилен), avatar, available label, Confirm/Decline; не pixel-perfect board mocks |
|
||
| Bookings list §D | список заявок с Confirm/Decline на `/bookings` | `/bookings` = **grouped inbox**: (A) К подтверждению — pending owner/specialist + Confirm/Decline; (B) Мои записи — participant upcoming/past + Cancel; empty groups hidden. Event card Confirm/Decline **остаётся** обязательным |
|
||
| Login §D phone chrome | три phone frames + (на борде) Google CTA | brand-first hero + mood `--auth-*`; email/password only; compact mood на auth; taglines — в mood sheet AppShell (не в `/more`); **без** Google OAuth |
|
||
| Mood placement | board §C switcher cards | **Front#40/#45:** mood chip в AppShell рядом с BrandWordmark (+ compact auth); mobile chip icon-only (полный CalenTIQ wordmark); **не** в `/more`, **не** в toolbar Month/Week/Day; 3 moods, без flip / CREATOR; switcher glyphs §C (sprout/bolt/briefcase), Time Arc appicon — только favicon |
|
||
| Lens + strip | board Today/Upcoming rail only | **Front#39 + controls IA:** lens Обзор/На сегодня/Заявки в **шапке strip** (underline tabs / mobile sheet); view Месяц/Неделя/День рядом с периодом; owner schedule actions отдельным рядом; localStorage only; soft-default по mood |
|
||
| Week view headers | — | **Front#40:** одна строка day-headers (без дубля `WeekDayColumn`); scroll `.eh-cal-week-scroll` (mobile ~390) |
|
||
| Favicon set | 3 отдельных favicon файла на борде | mood appicon через `applyMood` |
|
||
| Desktop nav | phone bottom tabs на борде | desktop: **одна строка** chrome — logo + mood \| nav (Календарь / Найти / Записи / Ещё) \| nickname + logout; bottom nav — mobile |
|
||
| Header identity | — | nickname primary (не raw email); email только в `title` tooltip |
|
||
| Bookings past/expired | — | `expired` бейдж + Cancel скрыт; empty-state с CTA Discover / календари; soft list time |
|
||
| Agenda empty copy | — | personal «Нет событий»; commercial «Нет слотов» |
|
||
| More invites | пункт меню | скрыт при pending=0; badge счётчика при pending > 0 |
|
||
| D9 guest specialist schedule | — | **модель B (Front#35):** roster карточек → тап → фильтр слотов по `event.specialist_id`; «Все слоты студии»; book без specialist в body; **не** chip-filter |
|
||
| Confirmed на personal | — | Front-only overlay confirmed чужих commercial на default personal; title `событие · студия · спец`; клик → `/c/:foreignCalId/e/:eventId` |
|
||
| SpecialistsPanel density | — | mobile: имя/теги сверху, actions снизу full-width (Front#33/#35) |
|
||
| Stage | полный smoke на stage | **done** 2026-07-27: Login×3 / Calendar×3 + agenda / Discover / CONTROL commercial + Confirm·Decline / More moods |
|
||
| Домены calentiq.* | — | публичный stage: `stage.calentiq.com` / `admin.stage.calentiq.com` (канон STAGE-BROWSER.md) |
|
||
|
||
IA без sidebar / без Creator mood — совпадает с non-goals (проверено на stage).
|
||
|
||
### Visual pass ×3 moods (local + stage)
|
||
|
||
**Checked (vite preview + Playwright shots + stage HTTPS):** Login §D, Calendar grid+agenda, Discover media, CONTROL slot/bookings (Confirm/Decline на event card), More mood cards — FLOW / MOMENTUM / CONTROL.
|
||
|
||
**Polish in this pass:** agenda copy/casing/counts + time-first rows; CONTROL steel rail emphasis; neutral Discover cover in mock (не flow-appicon во всех moods).
|
||
|
||
**Front#31 (2026-07-27):** desktop one-row chrome (logo|nav|logout); header nickname; bookings `expired` + soft list time + empty CTA; agenda personal vs commercial empty copy; Discover cover photo/fallback; More invites badge.
|
||
|
||
**Front#35 (2026-07-28, SHA `57cfcf3`):** D9 модель B (guest roster → schedule filter); confirmed foreign overlay на personal; SpecialistsPanel mobile density; F6 EventActionCard past+pending → expired / no Cancel, Book скрыт на past.
|
||
|
||
**Front#39 (2026-07-28, SHA `c2cb754` / `d38a927`):** Mood chip убран из Ещё; Lens Обзор/Сегодня/Записи + strip над сеткой во всех 3 moods; mobile sheets + strip collapsed; mood→DB, lens→localStorage; без flip / CREATOR. (Placement chip уточнён в Front#40.) **Controls IA (2026-07-29):** lens перенесён в шапку strip (labels: Обзор / На сегодня / Заявки); view рядом с периодом; owner schedule actions отдельным рядом.
|
||
|
||
**Front#40 (2026-07-28, SHA mood `7c092d1` / week `db11c41`):** Mood chip в AppShell рядом с BrandWordmark (**не** в calendar toolbar Month/Week/Day); 3 moods; `PATCH preferences.mood`; без дубля в Ещё. Week view: одна строка day-headers + `.eh-cal-week-scroll` для mobile ~390.
|
||
|
||
**Front#45 (2026-07-29):** Mobile mood chrome — chip icon-only (без truncate label); полный BrandWordmark CalenTIQ на mobile; sheet icon+label+tagline; `aria-label` на chip. Switcher glyphs по board §C (sprout/bolt/briefcase), не Time Arc appicon.
|
||
|
||
**Remaining intentional:** no pixel-perfect phone chrome; Discover без photo-hero grid (cover via `image_url` when API returns it; broken URL → wash+initials); §E specialist schedule card vs panel — не pixel-perfect board mocks (follow-up). Product flow D9 B — documented; board pixel mock — Future.
|
||
|
||
### Bookings inbox + More invites (locked 2026-07-27)
|
||
|
||
Продуктовые решения (не deviation — канон):
|
||
|
||
1. **Event card Confirm/Decline** остаётся обязательным (quick approve на слоте).
|
||
2. **`/bookings`** — grouped inbox, не только participant:
|
||
- **Группа A — К подтверждению:** pending bookings, где пользователь calendar **owner** или **assigned specialist** (`event.specialist_id` = user). Confirm/Decline те же, что на `EventActionCard`.
|
||
- **Группа B — Мои записи:** participant bookings (upcoming/past + Cancel) как раньше.
|
||
- Пустые группы скрывать (`count=0`).
|
||
- Опционально подпись owner vs specialist внутри A; иначе одна секция «К подтверждению».
|
||
3. **`specialist_invite` в More:** скрывать пункт меню, если **0 pending** входящих; при
|
||
pending > 0 — **badge** со счётчиком. Deep-link `/invites?token=` работает. Исходящие
|
||
invite остаются в `SpecialistsPanel`.
|
||
4. **Не** класть строки `specialist_invite` в `/bookings`.
|
||
5. **Past-pending / `expired`:** Back#60 помечает past-pending → `expired` и исключает из
|
||
`booking-requests`; Confirm/Decline → `409`. UI: бейдж «истекла», Cancel скрыт
|
||
(Bookings + EventActionCard); defensive map past+pending → expired badge.
|
||
Front#35 F6: на past Book скрыт; past+pending на карточке → expired label.
|
||
|
||
API: `GET /v1/user/booking-requests` (Back) + существующий `PUT /v1/bookings/:id`
|
||
(`409` на expired / full).
|
||
|
||
### Guest specialist schedule + confirmed overlay (locked Front#35)
|
||
|
||
1. **D9 модель B (guest на commercial):** roster активных специалистов (карточки) →
|
||
тап → сетка только со слотами выбранного `event.specialist_id`; CTA «Все слоты
|
||
студии» сбрасывает фильтр. **Не** chip-filter на shared grid. Book body без
|
||
specialist. Owner `SpecialistsPanel` (invite/CRUD) не менять этим флоу.
|
||
2. **Confirmed на personal (Front-only):** `GET /v1/user/bookings` (confirmed) +
|
||
догрузка events/calendars → overlay на **default personal** grid; title
|
||
`event · studio · specialist`; клик → `/c/:foreignCalId/e/:eventId`. Back без
|
||
изменений.
|
||
3. **SpecialistsPanel density (mobile):** имя/теги сверху, actions снизу full-width.
|
||
|
||
### Mood + Lens (locked Front#39 / placement Front#40)
|
||
|
||
1. **Mood** = визуальная атмосфера (`html[data-mood]`, FLOW/MOMENTUM/CONTROL). Primary UX —
|
||
chip → sheet в **AppShell** рядом с BrandWordmark (Front#40); compact на auth.
|
||
**Нет** в `/more`; **не** в toolbar Month/Week/Day. Persist: `preferences.mood`
|
||
через `PATCH /v1/user/me`. Без flip; без CREATOR. Front#45: mobile chip icon-only;
|
||
полный CalenTIQ wordmark; desktop — полный label; sheet — §C glyph + label + tagline.
|
||
Glyphs: FLOW sprout, MOMENTUM bolt, CONTROL briefcase (не Time Arc appicon).
|
||
2. **Lens** = отдельный контентный режим (`overview` / `today` / `bookings`), не mood и не
|
||
view month/week/day. UI: Обзор / На сегодня / Заявки. Переключатель — в шапке strip
|
||
(underline/text tabs на desktop; chip → sheet на mobile), **не** рядом с ViewMode.
|
||
Soft-default при смене mood, если lens не pinned: FLOW→overview, MOMENTUM→today,
|
||
CONTROL→bookings.
|
||
3. **Strip** над сеткой (не на HTML-архиве месяца): Front-only derive — free gaps /
|
||
события сегодня / upcoming bookings. Desktop раскрыт по умолчанию; mobile свёрнут
|
||
(tap раскрывает). Сетка всегда видна. Workspace toolbar: контекст (селектор) /
|
||
виджет (период + view) / owner schedule actions (отдельный ряд).
|
||
4. **Persistence:** mood → DB; language → `user.language`; lens → `localStorage`
|
||
(`eh.calendar.lens` + pinned). Без нового Back API.
|
||
5. **Week view (Front#40):** одна строка day-headers (без дубля `WeekDayColumn`);
|
||
горизонтальный скролл `.eh-cal-week-scroll` (mobile ~390).
|
||
|
||
### Follow-ups (вне этого fix-pass или частично)
|
||
|
||
| Тема | Статус |
|
||
|------|--------|
|
||
| Discover `image_url` в search serialization | Back отдаёт поле; upload API **нет** — только URL field / seed; Front#31: photo vs fallback media classes + onError fallback |
|
||
| Stage Popular clutter (e2e calendars) | filter notes: см. `EventHubSpec/STAGE-POPULAR-CLEANUP.md`; не трогать реальные smoke данные без фильтра по e2e-паттернам |
|
||
| §E specialist schedule card vs panel | deviation: EventActionCard + SpecialistsPanel; pixel mock — Future; **product D9 B** — done Front#35 |
|
||
| Desktop one-row chrome | **done** Front#31; mood chip у logo — Front#40 (`7c092d1`) |
|
||
| D9 B + confirmed personal overlay | **done** Front#35 (`57cfcf3`) |
|
||
| Mood chip + Lens strip | **done** Front#39 (`c2cb754` / `d38a927`); chip → AppShell Front#40; mobile icon-only Front#45 |
|
||
| Week view single header + scroll | **done** Front#40 (`db11c41`) |
|
||
|
||
## Mood concept = product surface
|
||
|
||
Mood — не переименование `calm|energetic|business` и не смена primary hex.
|
||
|
||
Каждый mood — **отдельная атмосфера продукта** при той же IA:
|
||
|
||
| Mood | Ощущение | Chrome / surfaces | Discover / booking feel |
|
||
|------|----------|-------------------|-------------------------|
|
||
| **FLOW** (`calm`) | спокойствие, баланс | soft sage panels, light wash, soft chips | мягкие карточки, спокойный CTA |
|
||
| **MOMENTUM** (`energetic`) | энергия, скорость | ink `#111820`, coral `#FF6A3D`, denser chips | тёмный discover, яркий CTA |
|
||
| **CONTROL** (`business`) | бизнес, доступность | steel `#324A5F`, cool neutrals | коммерческие карточки слот/специалист/CTA |
|
||
|
||
Референс на борде: секции **B Mood Overview**, **C Mood Switcher**, **D Core Screens**, **NEW Discover**, **E Booking / Commercial**.
|
||
|
||
Switcher — **branded cards** (иконка + короткий tagline), не plain list/tabs:
|
||
|
||
- FLOW — *Find balance*
|
||
- MOMENTUM — *Get more done*
|
||
- CONTROL — *Grow the business*
|
||
|
||
Опционально: mood-aware favicon из [`boards/calentiq-icon-system-final.png`](boards/calentiq-icon-system-final.png) / `mood-icons/`.
|
||
|
||
Токены сейчас узкие ([`tokens/colors.json`](tokens/colors.json)); для parity нужны surfaces, gradients, chip/event styles, chrome — не только primary.
|
||
|
||
---
|
||
|
||
## Workstreams (mood-first)
|
||
|
||
Порядок важен: сначала атмосфера и токены, затем экраны поверх них.
|
||
|
||
### 1. Mood system / atmosphere — **P0 / first** ✅
|
||
|
||
CSS-токены и chrome на mood beyond primary hex: surfaces, gradients, event chip styles; switcher как branded cards (icon + tagline); опционально mood favicon.
|
||
|
||
**Acceptance**
|
||
|
||
- [x] Per-mood token set: surface / wash / chip / border / CTA (не только primary)
|
||
- [x] Mood switcher = 3 branded cards с иконкой и tagline с борда
|
||
- [x] Смена mood меняет атмосферу chrome (не только accent button)
|
||
- [x] API keys остаются `calm|energetic|business`
|
||
- [x] Опционально: favicon следует активному mood
|
||
|
||
**Design:** board §B, §C, §F; `mood-icons/`; `tokens/`
|
||
**Done:** EventHubFront#25 — `index.css` mood tokens + `MoodSwitcher` cards + favicon via `applyMood`.
|
||
|
||
### 2. Calendar mood-chrome — **P0** ✅
|
||
|
||
Та же сетка/IA; soft panels (FLOW), denser chips (MOMENTUM), mood-tinted cells (CONTROL) — как на борде §B / §D Calendar.
|
||
|
||
**Acceptance**
|
||
|
||
- [x] Month/week выглядят различно по mood при той же навигации
|
||
- [x] Event chips / cells тонированы mood-токенами
|
||
- [x] Нет sidebar / смены layout ради «красоты»
|
||
|
||
**Design:** board §B Mood Overview, §D Calendar
|
||
**Done:** EventHubFront#26 — `--cal-*` tokens + `.eh-cal` / `.eh-chip` в `CalendarWidget`; IA без изменений.
|
||
**Follow-up:** month grid §B/D — FLOW sage cell wash + chip limit 2; MOMENTUM denser/hotter chips limit 5; CONTROL steel cells + sharper chips limit 3; split time/title chips.
|
||
|
||
### 3. Discover mood variants — **P1** ✅
|
||
|
||
Визуальная дифференциация FLOW vs MOMENTUM vs CONTROL: soft cards + CTA; соответствие борду (NEW Discover / §D Discover), не as-is скринам.
|
||
|
||
**Acceptance**
|
||
|
||
- [x] Discover в трёх moods визуально различим (фон, карточки, CTA)
|
||
- [x] Soft card + CTA pattern с борда (не плоский as-is list-only)
|
||
- [x] IA и фильтры без смены модели; только presentation
|
||
|
||
**Design:** board NEW Discover, §D Discover; as-is refs: `eventhub-discover-{flow,momentum,control}.png`
|
||
**Done:** EventHubFront#27 — `--disc-*` + `.eh-discover-card` / `.eh-discover-cta`; list → card grid.
|
||
**Follow-up:** media hierarchy — `.eh-discover-media` with per-mood size/radius/washes (FLOW air / MOMENTUM energy / CONTROL steel), optional cover via `image_url`, display title + soft-card rhythm.
|
||
|
||
### 4. CONTROL booking surfaces — **P1** ✅
|
||
|
||
Коммерческие карточки: слот, специалист, CTA — только Control-specific (§E).
|
||
|
||
**Acceptance**
|
||
|
||
- [x] Slot card + specialist card + primary CTA в CONTROL
|
||
- [x] Specialists остаются внутри Control (не 4-й mood)
|
||
- [x] FLOW/MOMENTUM не получают Control commercial chrome
|
||
|
||
**Design:** board §E Booking / Commercial
|
||
**Done:** EventHubFront#28 — `.eh-book-slot` / `.eh-book-specialist` / `.eh-book-request`; steel chrome только под `data-mood=business`.
|
||
**Follow-up:** §E polish — `--book-*` tokens; CONTROL steel left-rail + sharper radii; slot duration/available label; specialist/request avatars; mood-token CTA/Decline.
|
||
|
||
### 5. Polish + stage smoke — **P2** ✅
|
||
|
||
Мелкие расхождения с бордом, wordmark/lockup consistency, stage smoke трёх moods.
|
||
|
||
**Acceptance**
|
||
|
||
- [x] Mock smoke: calendar → discover → bookings в 3 moods (+ IA без sidebar)
|
||
- [x] Нет регрессий IA (top + bottom nav) — покрыто mock e2e
|
||
- [x] Известные отклонения от борда зафиксированы в UI-PARITY (Known deviations)
|
||
- [x] Visual pass ×3 moods (local preview / Playwright shots) — Login / Calendar / Discover / CONTROL booking
|
||
- [x] Stage smoke на живом стенде — UI `0.2.29` (`79dadfb21f98`) @ `https://stage.calentiq.com` (2026-07-27)
|
||
|
||
**Done:** EventHubFront#29 — `e2e/tests/mood-parity-smoke.spec.ts`, brand meta, CONTROL tagline polish.
|
||
**Follow-up:** visual pass polish — agenda Предстоящие + counts/time-first; CONTROL steel rail; mock Discover cover neutral. Stage: seed commercial + slots + pending booking для §E Confirm/Decline.
|
||
|
||
## Non-goals
|
||
|
||
- Left sidebar / смена IA
|
||
- 4-й Creator mood / AI-assistant home
|
||
- Rename API keys (`calm|energetic|business` остаются)
|
||
- Покупка доменов / DNS cutover
|
||
- Админский UI (`design/admin/`) — не трогать Front-бордами
|
||
- Полный pixel-perfect каждого пикселя борда (направление + mood atmosphere)
|
||
|
||
---
|
||
|
||
## Mapping → issues
|
||
|
||
| # | Workstream | Issue |
|
||
|---|------------|-------|
|
||
| — | Story (родитель) | [Spec#11](https://git.sabilin.com/EventHub/EventHubSpec/issues/11) |
|
||
| 1 | Mood system / atmosphere | [Front#25](https://git.sabilin.com/EventHub/EventHubFront/issues/25) |
|
||
| 2 | Calendar mood-chrome | [Front#26](https://git.sabilin.com/EventHub/EventHubFront/issues/26) |
|
||
| 3 | Discover mood variants | [Front#27](https://git.sabilin.com/EventHub/EventHubFront/issues/27) |
|
||
| 4 | CONTROL booking surfaces | [Front#28](https://git.sabilin.com/EventHub/EventHubFront/issues/28) |
|
||
| 5 | Polish + stage smoke | [Front#29](https://git.sabilin.com/EventHub/EventHubFront/issues/29) |
|
||
| — | P1/P2 UX polish + expired + desktop chrome | [Front#31](https://git.sabilin.com/EventHub/EventHubFront/issues/31) |
|
||
| — | Past-pending → `expired` | [Back#60](https://git.sabilin.com/EventHub/EventHubBack/issues/60) |
|
||
| — | P2: D9 B + confirmed personal + density/F6 | [Front#35](https://git.sabilin.com/EventHub/EventHubFront/issues/35) |
|
||
| — | Mood chip + Lens strip (workspace) | [Front#39](https://git.sabilin.com/EventHub/EventHubFront/issues/39) |
|
||
| — | Mood chip → AppShell + week scroll | [Front#40](https://git.sabilin.com/EventHub/EventHubFront/issues/40) |
|
||
| — | Mood chip icon-only mobile + mark-only logo | [Front#45](https://git.sabilin.com/EventHub/EventHubFront/issues/45) |
|
||
|
||
Эпик: [Spec#10](https://git.sabilin.com/EventHub/EventHubSpec/issues/10).
|
||
|
||
---
|
||
|
||
## Suggested start
|
||
|
||
Кодить с **Task 1 (Mood system / atmosphere)**: без токенов и switcher-as-cards остальные экраны будут «перекраской primary», а не mood product surface.
|