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
Новый пакет 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>
73 lines
5.2 KiB
Plaintext
73 lines
5.2 KiB
Plaintext
---
|
||
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-токен МойСклада. 5–10 минут — и магазин уже работает в 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>
|