food-market/src/food-market.public/src/pages/migration-from-moysklad.astro
nns a4cbb06bb3
Some checks are pending
CI / POS (WPF, Windows) (push) Waiting to run
CI / Backend (.NET 8) (push) Successful in 48s
CI / Web (React + Vite) (push) Successful in 38s
Docker API / Build + push API (push) Successful in 50s
Docker Web / Build + push Web (push) Successful in 40s
Docker API / Deploy API on stage (push) Successful in 18s
Docker Web / Deploy Web on stage (push) Successful in 11s
feat(public): Phase 6 — публичный маркетинговый сайт food-market.public на Astro
Новый пакет src/food-market.public/ — отдельный фронт для маркетинга и
самостоятельной регистрации магазинов-клиентов в SaaS Food Market.
Существующая админка food-market.web НЕ затронута.

Стек: Astro 4 + React 19 islands + Tailwind v3 (палитра идентична
food-market.web — единый бренд), TypeScript 6, content collections для
юр.документов. Static-сайт через nginx, gzip + immutable cache на assets.

Карта страниц (23):
- /                            — главная (Hero + 3 выгоды + скриншот +
                                   6 вертикалей + 6 модулей + Касса +
                                   Интеграции + 3 тарифа + соцпруф +
                                   FAQ + финальный CTA)
- /features                    — модули по сценариям
- /pricing                     — тарифы + интерактивный конструктор
                                   «Бизнес» (per-unit: 10000 база +
                                   2000/магазин + 500/касса + 500/склад,
                                   слайдеры, передача params в /signup)
- /pos                         — УТП лендинг кассы для Windows + весов
- /migration-from-moysklad     — УТП лендинг миграции с МойСклад
                                   (сравнительная таблица + 3 шага)
- /integrations                — список интеграций
- /for-grocery|pharmacy|cafe|alcohol|clothing|household — 6 вертикалей
                                   с уникальными фишками (весовой,
                                   серии/сроки, модификаторы и комбо,
                                   акцизные марки, размерные сетки,
                                   гарантийные сроки)
- /signup                      — регистрация (React-island форма)
- /about /contacts /kb /blog /status /changelog — компания + ресурсы
- /legal/{offer,privacy,consent,requisites} — реальные юр.документы
                                   из /tmp/legal/ как Astro content
                                   collection (markdown с frontmatter,
                                   динамический [slug].astro template,
                                   720px max-width, line-height 1.7,
                                   prose-legal стили)
- /sitemap.xml                 — ручной генератор (sitemap-плагин
                                   конфликтует с Astro 4.16, заменён
                                   на простой APIRoute)

React-острова (3):
- BusinessTariffBuilder — слайдеры + расчёт total + ссылка на signup
- SignupForm — email/password/orgName/phone/plan + валидация + agree
- FAQ — accordion 7 вопросов

API: новый POST /api/auth/signup создаёт Organization + AppUser
(Identity Admin role) + Owner Employee + полный bootstrap через
DevDataSeeder.SeedTenantReferencesAsync (units, price-types, store,
cassa, 6 ролей). Токены НЕ выпускает — фронт сразу делает обычный
/connect/token (password grant) и получает access/refresh без
дублирования OpenIddict-логики. На signup-форме — auth-bridge:
токены передаются через URL fragment в админку
APP_URL/auth-bridge#access=...&refresh=...&welcome=1, AuthBridgePage
кладёт в localStorage и редиректит на /?welcome=signup.

URL-домены через env-переменные (юзер ещё выбирает финальный):
- PUBLIC_SITE_URL — canonical/OG/sitemap (default https://food-market.kz)
- PUBLIC_APP_URL — admin/API endpoint (default https://food-market.zat.kz)
Nginx-конфиг для деплоя сайта — заготовка-template в
deploy/nginx/food-market-public.conf.template, не применён —
ждёт решения по домену.

Dockerfile multi-stage (node:20-alpine build → nginx:1.27 runtime),
build-args PUBLIC_SITE_URL/PUBLIC_APP_URL, deploy/nginx.conf gzip +
immutable cache + try_files для pretty URLs.

SEO: OG-теги, twitter-card, canonical, JSON-LD SoftwareApplication
схема, robots.txt → sitemap-index, lang=ru-KZ.

Admin-side: /auth-bridge route в food-market.web — принимает токены
из URL fragment, кладёт в localStorage (fm.access_token / fm.refresh_token),
редиректит на /. Fragment чтобы access_token не попадал в Referer.

23 страницы билдятся без ошибок. Контейнер собирается. Деплой на
конкретный домен — отдельным шагом после решения юзера.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 19:11:34 +05:00

73 lines
5.2 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
import BaseLayout from '@/layouts/BaseLayout.astro'
const compare = [
{ row: 'Цена за базовый тариф', moy: 'от 4 900 ₽ ≈ 30 000 ₸', us: '5 000 ₸' },
{ row: 'Касса с весами Масса-К', moy: '— (отдельный модуль)', us: '✓ из коробки' },
{ row: 'CRM и лояльность', moy: '+ доплата', us: '✓ включено' },
{ row: 'Финансовый учёт', moy: '+ доплата', us: '✓ включено' },
{ row: 'Скорость интерфейса', moy: '~3 сек загрузка', us: '<1 сек' },
{ row: 'Поддержка KZ-локализации', moy: 'базовая', us: 'полная (тенге, ОКЕИ, ОФД РК)' },
{ row: 'Триал', moy: '14 дней', us: '90 дней без карты' },
]
---
<BaseLayout title="Переход с МойСклада" description="Перенос товаров, штрихкодов, контрагентов и остатков из МойСклада в Food Market за один клик.">
<section class="bg-gradient-to-br from-brand-light/40 via-white to-white">
<div class="max-w-4xl mx-auto px-4 sm:px-6 py-14">
<h1 class="text-4xl font-extrabold">Переходите с МойСклада<br/>за один клик</h1>
<p class="mt-4 text-lg text-slate-600">Импорт товаров, групп, контрагентов, остатков и штрихкодов через ваш существующий API-токен МойСклада. 510 минут — и магазин уже работает в Food Market.</p>
<a href="/signup?plan=start" class="inline-block mt-7 px-5 py-3 bg-brand text-white font-semibold rounded-md hover:bg-brand-hover">Начать миграцию</a>
</div>
</section>
<section class="max-w-5xl mx-auto px-4 sm:px-6 py-14">
<h2 class="text-3xl font-bold text-center mb-8">МойСклад vs Food Market</h2>
<div class="overflow-x-auto rounded-xl border border-slate-200 bg-white">
<table class="w-full text-sm">
<thead class="bg-slate-50">
<tr>
<th class="text-left px-4 py-3 font-semibold">Параметр</th>
<th class="text-left px-4 py-3 font-semibold">МойСклад</th>
<th class="text-left px-4 py-3 font-semibold text-brand">Food Market</th>
</tr>
</thead>
<tbody class="divide-y divide-slate-100">
{compare.map((c) => (
<tr>
<td class="px-4 py-3 font-medium">{c.row}</td>
<td class="px-4 py-3 text-slate-600">{c.moy}</td>
<td class="px-4 py-3 text-slate-900 font-medium">{c.us}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
<section class="bg-slate-50 py-14">
<div class="max-w-4xl mx-auto px-4 sm:px-6">
<h2 class="text-3xl font-bold text-center mb-2">Что переносится</h2>
<p class="text-center text-slate-500 mb-8">Один токен — все данные.</p>
<div class="grid sm:grid-cols-2 gap-3 text-sm">
{['Товары и услуги','Группы и категории','Штрихкоды и артикулы','Цены (розничные + оптовые)','Контрагенты (поставщики и клиенты)','Остатки по складам','Единицы измерения','Атрибуты товаров'].map((x) => (
<div class="bg-white rounded-md border border-slate-200 px-4 py-3">✓ {x}</div>
))}
</div>
</div>
</section>
<section class="max-w-3xl mx-auto px-4 sm:px-6 py-14">
<h2 class="text-3xl font-bold text-center mb-10">3 шага до запуска</h2>
<ol class="space-y-6">
<li class="flex gap-4"><div class="flex-shrink-0 w-10 h-10 rounded-full bg-brand text-white font-bold flex items-center justify-center">1</div>
<div><h3 class="font-semibold">Зарегистрируйтесь в Food Market</h3><p class="text-sm text-slate-600 mt-1">Создайте аккаунт за минуту. 90 дней триал без банковской карты.</p></div></li>
<li class="flex gap-4"><div class="flex-shrink-0 w-10 h-10 rounded-full bg-brand text-white font-bold flex items-center justify-center">2</div>
<div><h3 class="font-semibold">Подключите токен МойСклада</h3><p class="text-sm text-slate-600 mt-1">Настройки → Интеграции → МойСклад → ваш API-токен. Кнопка «Импортировать».</p></div></li>
<li class="flex gap-4"><div class="flex-shrink-0 w-10 h-10 rounded-full bg-brand text-white font-bold flex items-center justify-center">3</div>
<div><h3 class="font-semibold">Откройте кассу и работайте</h3><p class="text-sm text-slate-600 mt-1">Скачайте установщик кассы для Windows, подключите весы и сканер. Магазин запущен.</p></div></li>
</ol>
<div class="text-center mt-10">
<a href="/signup?plan=start" class="px-5 py-3 bg-brand text-white font-semibold rounded-md hover:bg-brand-hover">Начать миграцию</a>
</div>
</section>
</BaseLayout>