- New OnboardingView module (public/js/views/onboarding.js):
• Reads /onboarding/slides.json (designer schema with inline SVG icons,
per-slide cta_primary/cta_skip labels) — falls back to 3 emoji slides
if the JSON is unavailable.
• Renders a Telegram-style dark overlay inside #mobile-frame with a
220px floating SVG icon, title, body, dot indicator (expandable
active dot), primary CTA, and a ghost Skip button.
• Prev/Next via primary CTA; dot click jumps to slide; arrow keys and
horizontal swipe also navigate.
• Haptic feedback via TG_APP on slide change + finish.
• markDone() writes buhapp.onboarded='1' to localStorage so the flow
never repeats. isDone()/reset() exposed for QA.
- App integration (public/js/app.js):
• New App.maybeOnboard() helper — awaited after every successful auth
path: Telegram login, restored session, email login, email register,
and consent accept. Skips silently if already onboarded.
- UI assets (public/onboarding/):
• slides.json with 3 designer slides (Map / Chat / Review).
• Inline-SVG icons for map, chat, and review (icon-*.svg kept for
designer reference, preview.html too).
- Styles (public/css/app.css): new .onboarding-* dark-theme rules.
- Index (public/index.html): loads onboarding.js before app.js.
36 lines
16 KiB
JSON
36 lines
16 KiB
JSON
{
|
||
"version": 1,
|
||
"brand": {
|
||
"primary": "#FF6B35",
|
||
"bg_dark": "#1C1C1E"
|
||
},
|
||
"slides": [
|
||
{
|
||
"id": "map",
|
||
"order": 1,
|
||
"title": "Найди компанию рядом",
|
||
"body": "Открой карту — увидишь, кто из BuhApp находится поблизости. Геолокация работает прямо в Telegram, без отдельных приложений.",
|
||
"cta_primary": "Показать на карте",
|
||
"cta_skip": "Пропустить",
|
||
"icon_svg_inline": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 240 240\" width=\"240\" height=\"240\" role=\"img\" aria-label=\"Карта с геолокацией\">\n <defs>\n <!-- Градиент фона карточки -->\n <linearGradient id=\"mapBg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FF8A5C\"/>\n <stop offset=\"100%\" stop-color=\"#FF6B35\"/>\n </linearGradient>\n <!-- Тень под пин-маркером -->\n <radialGradient id=\"pinShadow\" cx=\"0.5\" cy=\"0.5\" r=\"0.5\">\n <stop offset=\"0%\" stop-color=\"#000\" stop-opacity=\"0.35\"/>\n <stop offset=\"70%\" stop-color=\"#000\" stop-opacity=\"0.08\"/>\n <stop offset=\"100%\" stop-color=\"#000\" stop-opacity=\"0\"/>\n </radialGradient>\n <!-- Свечение вокруг пина -->\n <radialGradient id=\"pinGlow\" cx=\"0.5\" cy=\"0.5\" r=\"0.5\">\n <stop offset=\"0%\" stop-color=\"#FF6B35\" stop-opacity=\"0.45\"/>\n <stop offset=\"100%\" stop-color=\"#FF6B35\" stop-opacity=\"0\"/>\n </radialGradient>\n <!-- Мягкий блик на \"карте\" -->\n <linearGradient id=\"mapSheen\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\" stop-opacity=\"0.18\"/>\n <stop offset=\"100%\" stop-color=\"#FFFFFF\" stop-opacity=\"0\"/>\n </linearGradient>\n </defs>\n\n <!-- Внешний круг-подложка (бренд) -->\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#mapBg)\"/>\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#mapSheen)\"/>\n\n <!-- Декоративные точки вокруг -->\n <circle cx=\"46\" cy=\"62\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.45\"/>\n <circle cx=\"196\" cy=\"58\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.55\"/>\n <circle cx=\"58\" cy=\"188\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"200\" cy=\"184\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.4\"/>\n <circle cx=\"34\" cy=\"124\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"210\" cy=\"130\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n\n <!-- \"Карта\" — белая карточка со скруглёнными краями -->\n <g transform=\"translate(36 44)\">\n <rect x=\"0\" y=\"0\" width=\"168\" height=\"152\" rx=\"20\" ry=\"20\" fill=\"#FFFFFF\"/>\n <!-- Сетка улиц (приглушённая) -->\n <g stroke=\"#FFE2D3\" stroke-width=\"2\" stroke-linecap=\"round\">\n <line x1=\"0\" y1=\"32\" x2=\"168\" y2=\"32\"/>\n <line x1=\"0\" y1=\"62\" x2=\"168\" y2=\"62\"/>\n <line x1=\"0\" y1=\"96\" x2=\"168\" y2=\"96\"/>\n <line x1=\"0\" y1=\"126\" x2=\"168\" y2=\"126\"/>\n <line x1=\"40\" y1=\"0\" x2=\"40\" y2=\"152\"/>\n <line x1=\"84\" y1=\"0\" x2=\"84\" y2=\"152\"/>\n <line x1=\"128\" y1=\"0\" x2=\"128\" y2=\"152\"/>\n </g>\n <!-- Главная дорога — оранжевая -->\n <path d=\"M0 78 Q 60 70 84 80 T 168 76\" stroke=\"#FFB58A\" stroke-width=\"6\" fill=\"none\" stroke-linecap=\"round\"/>\n <!-- Река/парк -->\n <path d=\"M0 110 Q 40 100 70 112 T 168 108\" stroke=\"#FFD8C2\" stroke-width=\"8\" fill=\"none\" stroke-linecap=\"round\" opacity=\"0.7\"/>\n <!-- Маленькие здания -->\n <rect x=\"14\" y=\"14\" width=\"14\" height=\"10\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"50\" y=\"42\" width=\"16\" height=\"12\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"100\" y=\"16\" width=\"12\" height=\"9\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"138\" y=\"42\" width=\"18\" height=\"12\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"14\" y=\"130\" width=\"14\" height=\"12\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"100\" y=\"132\" width=\"14\" height=\"10\" rx=\"2\" fill=\"#F5F5F7\"/>\n <rect x=\"140\" y=\"128\" width=\"16\" height=\"14\" rx=\"2\" fill=\"#F5F5F7\"/>\n </g>\n\n <!-- Свечение вокруг пина -->\n <circle cx=\"120\" cy=\"118\" r=\"58\" fill=\"url(#pinGlow)\"/>\n\n <!-- Тень под пином -->\n <ellipse cx=\"120\" cy=\"186\" rx=\"14\" ry=\"4\" fill=\"url(#pinShadow)\"/>\n\n <!-- Пин-маркер (большой, по центру) -->\n <g transform=\"translate(120 118)\">\n <!-- Внешняя капля -->\n <path d=\"M0 -42 C 16 -42 24 -28 24 -16 C 24 -2 12 12 0 28 C -12 12 -24 -2 -24 -16 C -24 -28 -16 -42 0 -42 Z\"\n fill=\"#1C1C1E\"/>\n <!-- Внутренний круг -->\n <circle cx=\"0\" cy=\"-16\" r=\"11\" fill=\"#FF6B35\"/>\n <!-- Белая точка по центру -->\n <circle cx=\"0\" cy=\"-16\" r=\"4\" fill=\"#FFFFFF\"/>\n </g>\n\n <!-- Маленькие \"компании рядом\" — аватары-пины -->\n <g transform=\"translate(64 156)\">\n <circle cx=\"0\" cy=\"0\" r=\"14\" fill=\"#1C1C1E\"/>\n <circle cx=\"0\" cy=\"0\" r=\"11\" fill=\"#FFD8C2\"/>\n <circle cx=\"0\" cy=\"-2\" r=\"3.5\" fill=\"#1C1C1E\"/>\n <path d=\"M-7 7 Q 0 1 7 7 L 7 9 L -7 9 Z\" fill=\"#1C1C1E\"/>\n </g>\n <g transform=\"translate(176 154)\">\n <circle cx=\"0\" cy=\"0\" r=\"14\" fill=\"#1C1C1E\"/>\n <circle cx=\"0\" cy=\"0\" r=\"11\" fill=\"#FFFFFF\"/>\n <circle cx=\"0\" cy=\"-2\" r=\"3.5\" fill=\"#FF6B35\"/>\n <path d=\"M-7 7 Q 0 1 7 7 L 7 9 L -7 9 Z\" fill=\"#FF6B35\"/>\n </g>\n\n <!-- Радиус-дуга \"рядом\" -->\n <path d=\"M 64 156 A 60 60 0 0 1 176 154\" stroke=\"#FFFFFF\" stroke-width=\"2\" stroke-dasharray=\"3 4\" fill=\"none\" opacity=\"0.55\"/>\n</svg>\n"
|
||
},
|
||
{
|
||
"id": "chat",
|
||
"order": 2,
|
||
"title": "Напиши первым",
|
||
"body": "В чате можно задать вопрос, договориться о встрече или обменяться контактами. Сообщения доходят мгновенно — как в обычном мессенджере.",
|
||
"cta_primary": "Открыть чаты",
|
||
"cta_skip": "Пропустить",
|
||
"icon_svg_inline": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 240 240\" width=\"240\" height=\"240\" role=\"img\" aria-label=\"Чат с сообщениями\">\n <defs>\n <linearGradient id=\"chatBg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FF8A5C\"/>\n <stop offset=\"100%\" stop-color=\"#FF6B35\"/>\n </linearGradient>\n <linearGradient id=\"bubbleMine\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\"/>\n <stop offset=\"100%\" stop-color=\"#F5F5F7\"/>\n </linearGradient>\n <linearGradient id=\"bubbleSheen\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\" stop-opacity=\"0.25\"/>\n <stop offset=\"100%\" stop-color=\"#FFFFFF\" stop-opacity=\"0\"/>\n </linearGradient>\n <linearGradient id=\"circleSheen\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\" stop-opacity=\"0.18\"/>\n <stop offset=\"100%\" stop-color=\"#FFFFFF\" stop-opacity=\"0\"/>\n </linearGradient>\n </defs>\n\n <!-- Внешний круг -->\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#chatBg)\"/>\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#circleSheen)\"/>\n\n <!-- Декор — точки -->\n <circle cx=\"40\" cy=\"58\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.45\"/>\n <circle cx=\"200\" cy=\"60\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.55\"/>\n <circle cx=\"36\" cy=\"180\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"206\" cy=\"182\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.4\"/>\n <circle cx=\"208\" cy=\"118\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"32\" cy=\"120\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n\n <!-- Третий пузырь (ответ собеседника, сверху, тёмный) -->\n <g transform=\"translate(40 50)\">\n <path d=\"M14 0 L 92 0 Q 106 0 106 14 L 106 38 Q 106 52 92 52 L 28 52 L 14 64 L 18 52 Q 14 52 14 38 Z\"\n fill=\"#1C1C1E\"/>\n <!-- Строки текста -->\n <rect x=\"24\" y=\"14\" width=\"62\" height=\"6\" rx=\"3\" fill=\"#FFFFFF\" opacity=\"0.85\"/>\n <rect x=\"24\" y=\"26\" width=\"46\" height=\"6\" rx=\"3\" fill=\"#FFFFFF\" opacity=\"0.55\"/>\n <!-- Хвостик-таймстамп -->\n <circle cx=\"96\" cy=\"46\" r=\"3\" fill=\"#FF6B35\"/>\n </g>\n\n <!-- Второй пузырь (ответ собеседника, ниже) -->\n <g transform=\"translate(40 124)\">\n <path d=\"M14 0 L 100 0 Q 114 0 114 14 L 114 32 Q 114 46 100 46 L 26 46 L 14 58 L 18 46 Q 14 46 14 32 Z\"\n fill=\"#1C1C1E\"/>\n <rect x=\"24\" y=\"14\" width=\"68\" height=\"6\" rx=\"3\" fill=\"#FFFFFF\" opacity=\"0.85\"/>\n <rect x=\"24\" y=\"26\" width=\"38\" height=\"6\" rx=\"3\" fill=\"#FFFFFF\" opacity=\"0.55\"/>\n </g>\n\n <!-- Первый пузырь (наш, справа, белый, крупный) -->\n <g transform=\"translate(112 60)\">\n <path d=\"M92 0 L 14 0 Q 0 0 0 14 L 0 42 Q 0 56 14 56 L 78 56 L 92 70 L 88 56 Q 92 56 92 42 Z\"\n fill=\"url(#bubbleMine)\"/>\n <path d=\"M92 0 L 14 0 Q 0 0 0 14 L 0 42 Q 0 56 14 56 L 78 56 L 92 70 L 88 56 Q 92 56 92 42 Z\"\n fill=\"url(#bubbleSheen)\"/>\n <!-- Строки текста -->\n <rect x=\"14\" y=\"14\" width=\"64\" height=\"6\" rx=\"3\" fill=\"#1C1C1E\" opacity=\"0.85\"/>\n <rect x=\"14\" y=\"26\" width=\"48\" height=\"6\" rx=\"3\" fill=\"#1C1C1E\" opacity=\"0.55\"/>\n <!-- Статус \"прочитано\" — две галочки оранжевые -->\n <g transform=\"translate(72 38)\">\n <path d=\"M0 4 L 4 8 L 12 0\" stroke=\"#FF6B35\" stroke-width=\"2.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n <path d=\"M6 4 L 10 8 L 18 0\" stroke=\"#FF6B35\" stroke-width=\"2.5\" fill=\"none\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </g>\n </g>\n\n <!-- Маленький индикатор \"набирает...\" -->\n <g transform=\"translate(54 196)\">\n <circle cx=\"0\" cy=\"0\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.9\"/>\n <circle cx=\"12\" cy=\"0\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.6\"/>\n <circle cx=\"24\" cy=\"0\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.35\"/>\n </g>\n</svg>\n"
|
||
},
|
||
{
|
||
"id": "review",
|
||
"order": 3,
|
||
"title": "Оставь отзыв",
|
||
"body": "Поставь от 1 до 5 звёзд и напиши, что понравилось. Твои отзывы помогают другим выбрать надёжную компанию.",
|
||
"cta_primary": "Готово",
|
||
"cta_skip": "Позже",
|
||
"icon_svg_inline": "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 240 240\" width=\"240\" height=\"240\" role=\"img\" aria-label=\"Отзыв со звёздами\">\n <defs>\n <linearGradient id=\"revBg\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FF8A5C\"/>\n <stop offset=\"100%\" stop-color=\"#FF6B35\"/>\n </linearGradient>\n <linearGradient id=\"starFill\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFE9D6\"/>\n <stop offset=\"100%\" stop-color=\"#FFCB9C\"/>\n </linearGradient>\n <linearGradient id=\"starFillOrange\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\"/>\n <stop offset=\"100%\" stop-color=\"#FFF1E6\"/>\n </linearGradient>\n <linearGradient id=\"cardSheen\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"0%\" stop-color=\"#FFFFFF\" stop-opacity=\"0.18\"/>\n <stop offset=\"100%\" stop-color=\"#FFFFFF\" stop-opacity=\"0\"/>\n </linearGradient>\n </defs>\n\n <!-- Внешний круг -->\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#revBg)\"/>\n <circle cx=\"120\" cy=\"120\" r=\"112\" fill=\"url(#cardSheen)\"/>\n\n <!-- Декор — точки -->\n <circle cx=\"44\" cy=\"56\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.45\"/>\n <circle cx=\"198\" cy=\"58\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.55\"/>\n <circle cx=\"36\" cy=\"186\" r=\"3\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"204\" cy=\"184\" r=\"4\" fill=\"#FFFFFF\" opacity=\"0.4\"/>\n <circle cx=\"32\" cy=\"120\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n <circle cx=\"210\" cy=\"120\" r=\"2.5\" fill=\"#FFFFFF\" opacity=\"0.5\"/>\n\n <!-- Звёзды (центральная композиция) -->\n <!-- Звезда — пятиконечная, выровненная по центру -->\n <g transform=\"translate(120 102)\">\n <!-- Большая звезда по центру -->\n <g transform=\"translate(0 -38) scale(1.45)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"url(#starFill)\" stroke=\"#1C1C1E\" stroke-width=\"2.2\" stroke-linejoin=\"round\"/>\n </g>\n <!-- Левая -->\n <g transform=\"translate(-44 -30) scale(1.1)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"url(#starFill)\" stroke=\"#1C1C1E\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </g>\n <!-- Правая -->\n <g transform=\"translate(44 -30) scale(1.1)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"url(#starFill)\" stroke=\"#1C1C1E\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </g>\n <!-- Левая нижняя -->\n <g transform=\"translate(-22 4) scale(0.95)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"url(#starFill)\" stroke=\"#1C1C1E\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </g>\n <!-- Правая нижняя -->\n <g transform=\"translate(22 4) scale(0.95)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"url(#starFill)\" stroke=\"#1C1C1E\" stroke-width=\"2\" stroke-linejoin=\"round\"/>\n </g>\n </g>\n\n <!-- Карточка отзыва внизу -->\n <g transform=\"translate(40 140)\">\n <!-- Тень -->\n <rect x=\"2\" y=\"3\" width=\"160\" height=\"62\" rx=\"14\" fill=\"#000\" opacity=\"0.18\"/>\n <!-- Тело карточки -->\n <rect x=\"0\" y=\"0\" width=\"160\" height=\"62\" rx=\"14\" fill=\"#FFFFFF\"/>\n <!-- Аватар -->\n <circle cx=\"18\" cy=\"20\" r=\"12\" fill=\"#FF6B35\"/>\n <circle cx=\"18\" cy=\"17\" r=\"4\" fill=\"#FFFFFF\"/>\n <path d=\"M10 28 Q 18 22 26 28 L 26 32 L 10 32 Z\" fill=\"#FFFFFF\"/>\n <!-- Имя -->\n <rect x=\"36\" y=\"13\" width=\"68\" height=\"6\" rx=\"3\" fill=\"#1C1C1E\" opacity=\"0.85\"/>\n <!-- Строки отзыва -->\n <rect x=\"12\" y=\"42\" width=\"136\" height=\"5\" rx=\"2.5\" fill=\"#1C1C1E\" opacity=\"0.35\"/>\n <rect x=\"12\" y=\"51\" width=\"96\" height=\"5\" rx=\"2.5\" fill=\"#1C1C1E\" opacity=\"0.35\"/>\n <!-- Маленькая звёздочка справа сверху -->\n <g transform=\"translate(140 12) scale(0.45)\">\n <path d=\"M0 -16 L 4.7 -4.9 L 16.8 -3.1 L 7.6 4.7 L 10.4 16.6 L 0 10.4 L -10.4 16.6 L -7.6 4.7 L -16.8 -3.1 L -4.7 -4.9 Z\"\n fill=\"#FF6B35\"/>\n </g>\n </g>\n</svg>\n"
|
||
}
|
||
]
|
||
} |