SPI.SKI: web-apps, окна, карточки, кэш и стили
Самостоятельная карта приложения без запуска реального клиента. Каждый экран объясняет один слой системы: от входа и маршрутов до партнерского кабинета, серверной связи и визуальных режимов.
Общая карта презентации: слои проекта и быстрый zoom
Это обзорная карта всех листов. Выбирайте слой, меняйте масштаб и проваливайтесь в нужную карточку.
Большая карта проекта: окна, кэш, API и база как связанные уровни
Один экран показывает, откуда приходят данные, где они живут в клиенте, куда уходят запросы и какие таблицы получают результат.
Как стартует приложение и где живут окна
Главная цепочка: bootstrap, провайдеры, runtime, инициализация данных, router и глобальные controls.
Окна приложения: где лежат структуры и чем они запрашиваются
Это не список экранов, а карта связей: маршрут открывает компонент, компонент читает cache/hook, cache вызывает endpoint, ответ возвращается в UI.
| Окно | Входные переменные | Где хранится | Что выходит наружу |
|---|---|---|---|
EventsPage |
start_param, filters, active id, search |
EventsCache, AppProfileCache.lastPath |
EventCard, buy/share buttons, load more |
MyTicketsPage |
userId, status, page, limit |
UserTiketsCache, localStorage |
ticket list, QR state, active badge |
PartnerEventsPage |
role, dateMode, hiddenOnly, sortOrder | PartnerRoutingCache, FilterButtonsCache |
EventsControls, detail/stat view |
PartnerChannelsPage |
role, channel mode, sortOrder | FilterButtonsCache.partnerChannels |
Channels, connect/edit dialogs |
Главная карточка: внешний свайп, внутренний свайп и отключенный 3D
Текущий production path отделен от экспериментального 3D-контура, который есть в коде, но выключен.
Объект события: внутренняя структура, карточка и выходные переменные
Главная карточка строится не из одной картинки. Это связка ssEvent, временных tmp-данных, параметров кнопок и вложенных медиа.
| Структура | Вход | Преобразование | Выход |
|---|---|---|---|
ssEvent |
Events.events[] из GET /events |
EventsCache.setActiveEvent(event) |
activeEvent для карточки и actions |
EventPayetParams |
activeEvent + ticket type quotas |
геттеры showBuy, showShare, genFromReq |
кнопки покупки/списков и массив PayReqItem[] |
MediaSlider |
event.images[], active context, visibility |
left/center/right позиция, lazy video, keyboard arrows | текущий media frame без внешнего SwiperJS |
useSwiperScrollManager |
slide key, active index, scroll element | восстановление scrollTop, gesture isolation |
горизонтальный свайп не ломает вертикальный scroll |
Покупка, share и платеж: как активное событие отправляет данные
Здесь показан путь от выбора карточки до реальных endpoint-ов, таблиц БД и обратного обновления билетов.
EventsSwiper.onIndexChange
EventsCache.setActiveEvent
EventPayetParams.setEvent
showBuy/showShare/genFromReq
CustomAnimatedAction
buy dialog, promo code, share helper
dataManager.buyTicket
POST /payments/buy
payments, tickets
external payment link or free ticket
clearTiket, loadUserTickets
navigate to /my-tickets
| Buy path | Структура запроса | Результат |
|---|---|---|
PayReq |
eventId, userId, items[], tag, promoCode |
PayRes: link, ttl, expired или созданный билет |
PayReqItem[] |
ticket_type_id, ticketCount, free |
строки в tickets, квоты в ticket_types |
check_buy |
eventId, userId |
подтверждение платежа, обновление tickets |
| Share path | Структура запроса | Результат |
|---|---|---|
RefReq |
eventId, force_new, tag, fromStory |
share message id / referral link |
TelegramApi |
shareMessage или shareToStory |
публикация в Telegram runtime |
| DB | share_msg_ids, opened_codes |
привязка user -> event -> tag/source |
Партнерский кабинет: mini-router, фильтры, списки и модалки
Визуально это dashboard, но внутри он связан кэшами состояния, виртуальными списками и общими компонентами.
Organizer
Promoter
Партнерский кабинет: mini-router, фильтры, списки и модалки
Партнерские страницы связаны двумя cache-структурами. URL открывает окно, а конкретный вид, tab и выбранный event живут внутри cache.
| Партнерская структура | Поля | Кто читает | Куда ведет |
|---|---|---|---|
PartnerRoutingState |
mainTab, eventsTab, eventsView, eventsEventId |
PartnerEventsPage, App.tsx filters |
main/list/detail/editor transition |
FilterButtonsState.partnerEvents |
organizer/promoter: dateMode, hiddenOnly, sortOrder |
EventsControls, FilterMainButtonsBase |
OrganizatorStatsReq для /stats/stats |
FilterButtonsState.partnerChannels |
organizer: mode, sortOrder; promoter: sortOrder |
PartnerChannelsPage, Channels |
/channels/channels-* endpoint group |
EventSavePayload |
event, ticketTypes, promotion, media[] | useEventEditor, EventEditor |
events, ticket_types, promo_ticket_types, media files |
Связь с сервером: кэш, дедупликация, API и обратное обновление UI
Данные идут через единый слой кэшей, а UI обновляется через подписчиков `CacheEntry`.
Связи базы данных: какие таблицы поддерживают основные объекты
Это укрупненная ER-карта по рабочему контуру приложения: пользователи, события, билеты, платежи, партнерские заявки и реферальные открытия.
| Бизнес-объект | Основная таблица | Связанные таблицы | Кто запрашивает |
|---|---|---|---|
| Пользователь | users |
partners, tickets, payments, share_msg_ids |
/users/profile, /users, auth middleware |
| Событие | events |
ticket_types, promo_ticket_types, tickets, tags |
/events, /events/save, /stats/stats |
| Покупка | payments |
tickets, ticket_types, users |
/payments/buy, /payments/check_buy |
| Промо/реферал | share_msg_ids |
opened_codes, tags, tickets |
/referal, partner stats, share flows |
Стили: DOM-атрибуты, design-mode, market-mode и платформы
Визуальный режим управляется не пропсами компонентов, а атрибутами на `html` и CSS-переменными.
Sources
SCSS
Runtime
Как читать связи: объект, вход, хранение, запрос, выход
Каждая новая схема устроена одинаково: слева пользовательское окно или объект, в центре состояние/cache, справа endpoint, серверная структура или таблица БД.
Route / Window
Показывает, какое окно открывается и какой компонент является владельцем первого состояния.
Пример:/events -> EventsPage.
State / Cache
Показывает, где данные лежат в памяти, localStorage или IndexedDB и кто подписан на изменения.
Пример:EventsCache.activeEventVariable.
Request / Response
Показывает, какую структуру отправляет UI и какую структуру получает обратно через ApiResponse<T>.
EventsReq -> Events.
DB Relation
Показывает таблицы, FK, логические связи массивов и где эти связи проявляются в интерфейсе.
Пример:tickets.event_id -> events.id.
| Что смотреть | Где в презентации | Что дает для разработки |
|---|---|---|
| Как окно получает данные | Окна и хранение, Данные и сервер | Понятно, какой cache/endpoint менять при изменении экрана. |
| Как устроена карточка события | Карточки и свайпы, Event object, Buy/share flow | Видно, где активное событие, где медиа, где кнопки и где покупка. |
| Как работает партнерка | Партнерский экран, Partner relations | Видно, почему URL не описывает весь экран без PartnerRoutingCache. |
| Какие таблицы связаны | База данных | Видно, какие серверные запросы затрагивают users/events/tickets/payments/referal. |