Compare commits

...

2 commits

Author SHA1 Message Date
nns 93e26dc8df docs(site): отчёт и скриншоты Круга 3 (касса «скоро» единообразно, «₸» без переноса)
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker Public / Build + push Public (test + latest) (push) Waiting to run
Docker Public / Deploy :test → test.food-market.kz (push) Blocked by required conditions
Проверка на test.food-market.kz: касса подаётся одинаково честно (скачивание
«скоро») на главной/about как на /pos; «₸» не переносится в тарифах (1280 и 390).
Автопроверка 5/5. Реквизиты не трогал.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 22:23:11 +05:00
nns a25b940aaa fix(site): касса «скоро» единообразно (главная/about) + «₸» не переносится в тарифах
Круг 3 (финальный прогон этапа 1):
- Касса для Windows и Linux подаётся одинаково честно везде: приложение для
  скачивания — «скоро» (как на /pos, /status, /kb/pos-setup). Правки на главной
  (карточка «Продажи и касса») и /about («Что уже работает»).
- /pricing и конструктор «Бизнес»: сумма и знак «₸»/«₸/мес» не разрываются
  (whitespace-nowrap + неразрывные пробелы) — «10 000 ₸», «14 000 ₸», «5 000 ₸/мес»
  держатся в одну строку на 1280 и на мобильной.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-10-11 22:21:03 +05:00
9 changed files with 66 additions and 4 deletions

View file

@ -184,3 +184,27 @@ net8.0` (не `net8.0-windows`) + Avalonia (кроссплатформенный
`API-токен`, `ОКП`, `Kaspi Magazin`, `Wildberries`, `Ozon`, `TLS 1.3`, `API-токен`, `ОКП`, `Kaspi Magazin`, `Wildberries`, `Ozon`, `TLS 1.3`,
`100 000`, `триал`, `SIN EXCEPCION`. Обложка `/blog/quick-start` = `100 000`, `триал`, `SIN EXCEPCION`. Обложка `/blog/quick-start` =
`/screenshots/catalog.webp` (скриншот продукта, без чужого фото). `/screenshots/catalog.webp` (скриншот продукта, без чужого фото).
---
## Круг 3 (финальный прогон этапа 1, 11.10 — Chrome/Win11 VM)
Две мелкие правки, деплой только на тест (`test.food-market.kz`, commit `a25b940`,
статус `OK`; образ отката `test-pre-site-fixes-3` создан до деплоя).
1. **Касса подаётся единообразно честно.** Раньше /status, /pos, /kb/pos-setup
писали «скоро», а главная и /about — как готовую. Привёл к одному виду: касса
для Windows и Linux, **приложение для скачивания — «скоро»** (как на /pos).
- главная — карточка «Продажи и касса»: «…для Windows и Linux, работает без
интернета. Приложение для скачивания — скоро.»
- /about, «Что уже работает»: «Касса … для Windows и Linux, работает без
интернета (приложение для скачивания — скоро).»
Проверено живым grep и скриншотами (главная/ about) на 1280 и 390.
2. **Знак «₸» не переносится в тарифах.** `whitespace-nowrap` + неразрывные
пробелы: «10 000 ₸» / «14 000 ₸» (конструктор «Бизнес»), «5 000 ₸/мес» («Старт»),
CTA «… 10 000 ₸/мес». Проверка: высота строки цены конструктора 36px (одна
строка) на 1280 и 390 — не разрывается.
Скриншоты: `k3-pricing-1280.png`, `k3-pricing-390.png`, `k3-about-1280.png`.
Автопроверка (Playwright): 5/5. Юридические реквизиты не трогал (отложены до
продакшна). Прод-сайт не трогал.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 199 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View file

@ -54,7 +54,7 @@ export default function BusinessTariffBuilder() {
<p className="text-xs text-slate-500 mt-0.5">База 10 000 ₸ + ваши параметры</p> <p className="text-xs text-slate-500 mt-0.5">База 10 000 ₸ + ваши параметры</p>
</div> </div>
<div className="text-right"> <div className="text-right">
<div className="text-3xl font-extrabold">{fmt.format(total)} ₸</div> <div className="text-3xl font-extrabold whitespace-nowrap">{fmt.format(total)}&nbsp;₸</div>
<div className="text-xs text-slate-500">в месяц</div> <div className="text-xs text-slate-500">в месяц</div>
</div> </div>
</div> </div>

View file

@ -17,7 +17,7 @@ import BaseLayout from '@/layouts/BaseLayout.astro'
<h2>Что уже работает</h2> <h2>Что уже работает</h2>
<ul> <ul>
<li>Каталог товаров: группы, штрихкоды, цены, остатки.</li> <li>Каталог товаров: группы, штрихкоды, цены, остатки.</li>
<li>Касса с торговыми весами — для Windows и Linux, работает без интернета.</li> <li>Касса с торговыми весами для Windows и Linux, работает без интернета (приложение для скачивания — скоро).</li>
<li>Склад: приёмки, инвентаризация, списание, оприходование, перемещение.</li> <li>Склад: приёмки, инвентаризация, списание, оприходование, перемещение.</li>
<li>Отчёты по продажам, остаткам и прибыли.</li> <li>Отчёты по продажам, остаткам и прибыли.</li>
<li>Перенос каталога из файлов Excel/CSV.</li> <li>Перенос каталога из файлов Excel/CSV.</li>

View file

@ -4,7 +4,7 @@ import FAQ from '@/components/FAQ.tsx'
const modules = [ const modules = [
{ icon: '📦', title: 'Товары и каталог', text: 'Группы, штрихкоды, цены, остатки. Перенос каталога из файла (Excel/CSV).' }, { icon: '📦', title: 'Товары и каталог', text: 'Группы, штрихкоды, цены, остатки. Перенос каталога из файла (Excel/CSV).' },
{ icon: '💳', title: 'Продажи и касса', text: 'Касса с весами, сканером и печатью чека. Работает на Windows и Linux, в том числе без интернета.' }, { icon: '💳', title: 'Продажи и касса', text: 'Касса с весами, сканером и печатью чека для Windows и Linux, работает без интернета. Приложение для скачивания — скоро.' },
{ icon: '🏬', title: 'Склад и приёмки', text: 'Несколько складов, приёмка со сканером, инвентаризация, списание, оприходование, перемещение.' }, { icon: '🏬', title: 'Склад и приёмки', text: 'Несколько складов, приёмка со сканером, инвентаризация, списание, оприходование, перемещение.' },
{ icon: '🚚', title: 'Закупки и себестоимость', text: 'Приёмки от поставщиков. Себестоимость считается автоматически по приёмкам.' }, { icon: '🚚', title: 'Закупки и себестоимость', text: 'Приёмки от поставщиков. Себестоимость считается автоматически по приёмкам.' },
{ icon: '👥', title: 'Контрагенты и скидки', text: 'База поставщиков и покупателей, скидки, акции.' }, { icon: '👥', title: 'Контрагенты и скидки', text: 'База поставщиков и покупателей, скидки, акции.' },

View file

@ -15,7 +15,7 @@ import BusinessTariffBuilder from '@/components/BusinessTariffBuilder.tsx'
<div class="grid lg:grid-cols-3 gap-5 mt-10"> <div class="grid lg:grid-cols-3 gap-5 mt-10">
<div class="rounded-xl border border-slate-200 p-6 bg-white"> <div class="rounded-xl border border-slate-200 p-6 bg-white">
<h2 class="font-bold text-lg">Старт</h2> <h2 class="font-bold text-lg">Старт</h2>
<p class="text-3xl font-bold mt-2">5 000 ₸<span class="text-sm font-normal text-slate-500">/мес</span></p> <p class="text-3xl font-bold mt-2 whitespace-nowrap">5&nbsp;000&nbsp;₸<span class="text-sm font-normal text-slate-500">/мес</span></p>
<p class="text-xs text-slate-500 mt-1">90 дней бесплатно, без карты</p> <p class="text-xs text-slate-500 mt-1">90 дней бесплатно, без карты</p>
<ul class="text-sm space-y-1.5 mt-5 text-slate-700"> <ul class="text-sm space-y-1.5 mt-5 text-slate-700">
<li>✓ 1 магазин · 1 касса · 1 склад</li> <li>✓ 1 магазин · 1 касса · 1 склад</li>

View file

@ -0,0 +1,38 @@
import { chromium } from '@playwright/test'
import { mkdirSync } from 'node:fs'
import { resolve } from 'node:path'
const BASE = process.env.SITE_URL ?? 'https://test.food-market.kz'
const OUT = resolve('/home/nns/food-market', 'docs/site-fixes-2026-10-11')
mkdirSync(OUT, { recursive: true })
const results = []
const ok = (n, c, d = '') => { results.push({ n, c: !!c, d }); console.log(`${c ? '✓' : '✗'} ${n} ${d}`) }
const b = await chromium.launch({ args: ['--ignore-certificate-errors'] })
for (const [w, h, tag] of [[1280, 900, '1280'], [390, 844, '390']]) {
const ctx = await b.newContext({ viewport: { width: w, height: h }, deviceScaleFactor: 2, ignoreHTTPSErrors: true, isMobile: w < 500, hasTouch: w < 500 })
const p = await ctx.newPage()
// pricing — конструктор, «₸» не переносится
await p.goto(`${BASE}/pricing`, { waitUntil: 'networkidle' }); await p.waitForTimeout(1200)
// «₸» в большой сумме и «5 000 ₸/мес» в одной строке (проверяем перенос по высоте строки)
const priceBox = await p.locator('#configurator .font-extrabold').first().boundingBox().catch(() => null)
ok(`pricing@${tag}: цена конструктора в одну строку`, priceBox && priceBox.height < 60, priceBox ? `h=${Math.round(priceBox.height)}` : 'нет')
await p.locator('#configurator').scrollIntoViewIfNeeded().catch(() => {})
await p.screenshot({ path: resolve(OUT, `k3-pricing-${tag}.png`) })
// главная — касса «скоро»
await p.goto(`${BASE}/`, { waitUntil: 'networkidle' }); await p.waitForTimeout(600)
const homeTxt = await p.locator('body').innerText()
ok(`главная@${tag}: касса «скачивание — скоро»`, /скачивани[ея].{0,3}—.{0,3}скоро/i.test(homeTxt))
await ctx.close()
}
// about — касса «скоро» (один раз)
{
const ctx = await b.newContext({ viewport: { width: 1280, height: 900 }, deviceScaleFactor: 2, ignoreHTTPSErrors: true })
const p = await ctx.newPage()
await p.goto(`${BASE}/about`, { waitUntil: 'networkidle' }); await p.waitForTimeout(500)
const t = await p.locator('body').innerText()
ok('about: касса «скачивание — скоро»', /приложение для скачивания.{0,3}—.{0,3}скоро/i.test(t))
await p.screenshot({ path: resolve(OUT, 'k3-about-1280.png'), fullPage: true })
await ctx.close()
}
await b.close()
console.log(`\n[site-verify-3] ${results.filter(r => r.c).length}/${results.length} passed → ${OUT}`)