diff --git a/docs/pos-design.md b/docs/pos-design.md new file mode 100644 index 0000000..01eed8c --- /dev/null +++ b/docs/pos-design.md @@ -0,0 +1,50 @@ +# Касса food-market — дизайн-система (светлая тема) + +Подход: чисто, светло, крупно, ничего лишнего (как Square POS / Loyverse / Poster). +Всё строится на токенах из одного места — `Styles/Tokens.axaml` (ResourceDictionary). +Тёмная тема — те же токены, другой набор значений (опция в настройках, не по умолчанию). + +## Палитра (токены) +| Токен | Светлая | Назначение | +|---|---|---| +| `PosBg` | #F4F6F5 | фон приложения | +| `PosCard` | #FFFFFF | карточки, полосы, модальные | +| `PosBorder` | #E3E8E6 | рамки, разделители | +| `PosText` | #0F1F17 | основной текст | +| `PosтатText2` / `PosTextMuted` | #5F6F68 | вторичный текст | +| `PosBrand` | #16A34A | бренд/главное действие (зелёный Food Market) | +| `PosBrandHover` | #15803D | hover | +| `PosBrandPressed` | #166534 | pressed | +| `PosDanger` | #DC2626 | опасное (Очистить/Удалить) — только контур | +| `PosWarn` | #D97706 | предупреждение (смена закрыта, нет связи) — янтарный | +| `PosBrandSoft` | #DCFCE7 | мягкий зелёный фон (чипы, успех) | +| `PosWarnSoft` | #FEF3C7 | мягкий янтарный фон | + +Контраст текста к фону ≥ WCAG AA (PosText на PosCard/PosBg — ~14:1; PosTextMuted — ~5:1). + +## Типографика (Inter) +- ИТОГО: 44–56 pt, Bold. +- Суммы строк: 18–20 pt, SemiBold, **tabular** (моноширинные цифры — колонки не прыгают). +- Названия товаров: 17–18 pt. +- Служебное/подписи: 13–14 pt, PosTextMuted. +- Моноширинные цифры: `` → FontFeatures "tnum=1" / FontFamily с tabular. + +## Форма и ритм +- Скругления: карточки/кнопки 12–14, чипы 999 (капсула). +- Тени: мягкие у карточек (BoxShadow 0 1 3 #00000014, 0 4 12 #00000010). +- Сетка отступов: шаг 8 px (8/12/16/24). +- Кнопки: высота ≥ 48 px (сенсор ≥ 44). Главная — заливка PosBrand; вторичные — + контур PosBorder на белом; опасная — контур PosDanger (без заливки). + +## Компоненты (классы стилей) +- `Button.primary` — зелёная заливка, белый текст, крупная. +- `Button.ghost` — белая, контур PosBorder, текст PosText (вторичные действия). +- `Button.danger` — белая, контур PosDanger, текст PosDanger (Очистить/Удалить). +- `Button.key` — клавиша цифровой клавиатуры/степпера. +- `Border.card` — белая карточка со скруглением и тенью. +- `Border.chip` / `Border.chip.ok` / `.warn` — капсулы статуса. +- `TextBox.search` — поле поиска/скана с иконкой. + +## Тёмная тема (опция) +Те же имена токенов, тёмные значения (PosBg #0F1713, PosCard #15201B, PosText #E8EFEA…), +переключается через `RequestedThemeVariant` + подмену словаря. По умолчанию — светлая. diff --git a/docs/pos-screenshots/01-login-1366x768.png b/docs/pos-screenshots/01-login-1366x768.png index 47d1d1a..c3904ae 100644 Binary files a/docs/pos-screenshots/01-login-1366x768.png and b/docs/pos-screenshots/01-login-1366x768.png differ diff --git a/docs/pos-screenshots/01-login-1920x1080.png b/docs/pos-screenshots/01-login-1920x1080.png index b48d57d..573a038 100644 Binary files a/docs/pos-screenshots/01-login-1920x1080.png and b/docs/pos-screenshots/01-login-1920x1080.png differ diff --git a/docs/pos-screenshots/01b-login-pin-1366x768.png b/docs/pos-screenshots/01b-login-pin-1366x768.png new file mode 100644 index 0000000..facd783 Binary files /dev/null and b/docs/pos-screenshots/01b-login-pin-1366x768.png differ diff --git a/docs/pos-screenshots/01b-login-pin-1920x1080.png b/docs/pos-screenshots/01b-login-pin-1920x1080.png new file mode 100644 index 0000000..caafa93 Binary files /dev/null and b/docs/pos-screenshots/01b-login-pin-1920x1080.png differ diff --git a/docs/pos-screenshots/02-shift-open-1366x768.png b/docs/pos-screenshots/02-shift-open-1366x768.png index 0800870..43cce32 100644 Binary files a/docs/pos-screenshots/02-shift-open-1366x768.png and b/docs/pos-screenshots/02-shift-open-1366x768.png differ diff --git a/docs/pos-screenshots/02-shift-open-1920x1080.png b/docs/pos-screenshots/02-shift-open-1920x1080.png index 985f414..123ada4 100644 Binary files a/docs/pos-screenshots/02-shift-open-1920x1080.png and b/docs/pos-screenshots/02-shift-open-1920x1080.png differ diff --git a/docs/pos-screenshots/03-sale-empty-1366x768.png b/docs/pos-screenshots/03-sale-empty-1366x768.png index 64ab705..0e56d19 100644 Binary files a/docs/pos-screenshots/03-sale-empty-1366x768.png and b/docs/pos-screenshots/03-sale-empty-1366x768.png differ diff --git a/docs/pos-screenshots/03-sale-empty-1920x1080.png b/docs/pos-screenshots/03-sale-empty-1920x1080.png index 998492e..e1c9a81 100644 Binary files a/docs/pos-screenshots/03-sale-empty-1920x1080.png and b/docs/pos-screenshots/03-sale-empty-1920x1080.png differ diff --git a/docs/pos-screenshots/04-sale-items-1366x768.png b/docs/pos-screenshots/04-sale-items-1366x768.png index 141a989..ab53ed6 100644 Binary files a/docs/pos-screenshots/04-sale-items-1366x768.png and b/docs/pos-screenshots/04-sale-items-1366x768.png differ diff --git a/docs/pos-screenshots/04-sale-items-1920x1080.png b/docs/pos-screenshots/04-sale-items-1920x1080.png index d7adf6d..a0b7657 100644 Binary files a/docs/pos-screenshots/04-sale-items-1920x1080.png and b/docs/pos-screenshots/04-sale-items-1920x1080.png differ diff --git a/docs/pos-screenshots/05-payment-cash-1366x768.png b/docs/pos-screenshots/05-payment-cash-1366x768.png index 27ef21f..200e553 100644 Binary files a/docs/pos-screenshots/05-payment-cash-1366x768.png and b/docs/pos-screenshots/05-payment-cash-1366x768.png differ diff --git a/docs/pos-screenshots/05-payment-cash-1920x1080.png b/docs/pos-screenshots/05-payment-cash-1920x1080.png index 46a6054..d5deaaf 100644 Binary files a/docs/pos-screenshots/05-payment-cash-1920x1080.png and b/docs/pos-screenshots/05-payment-cash-1920x1080.png differ diff --git a/docs/pos-screenshots/06-payment-mixed-1366x768.png b/docs/pos-screenshots/06-payment-mixed-1366x768.png index ed7b882..b3d23bf 100644 Binary files a/docs/pos-screenshots/06-payment-mixed-1366x768.png and b/docs/pos-screenshots/06-payment-mixed-1366x768.png differ diff --git a/docs/pos-screenshots/06-payment-mixed-1920x1080.png b/docs/pos-screenshots/06-payment-mixed-1920x1080.png index baa3502..92efb7c 100644 Binary files a/docs/pos-screenshots/06-payment-mixed-1920x1080.png and b/docs/pos-screenshots/06-payment-mixed-1920x1080.png differ diff --git a/docs/pos-screenshots/07-return-1366x768.png b/docs/pos-screenshots/07-return-1366x768.png index e2b1b7b..018d5e3 100644 Binary files a/docs/pos-screenshots/07-return-1366x768.png and b/docs/pos-screenshots/07-return-1366x768.png differ diff --git a/docs/pos-screenshots/07-return-1920x1080.png b/docs/pos-screenshots/07-return-1920x1080.png index cf262ab..0986c36 100644 Binary files a/docs/pos-screenshots/07-return-1920x1080.png and b/docs/pos-screenshots/07-return-1920x1080.png differ diff --git a/docs/pos-screenshots/08-shift-z-1366x768.png b/docs/pos-screenshots/08-shift-z-1366x768.png index 0099a9c..13804b0 100644 Binary files a/docs/pos-screenshots/08-shift-z-1366x768.png and b/docs/pos-screenshots/08-shift-z-1366x768.png differ diff --git a/docs/pos-screenshots/08-shift-z-1920x1080.png b/docs/pos-screenshots/08-shift-z-1920x1080.png index a2d15a8..4e37de9 100644 Binary files a/docs/pos-screenshots/08-shift-z-1920x1080.png and b/docs/pos-screenshots/08-shift-z-1920x1080.png differ diff --git a/docs/pos-screenshots/09-shell-offline-1366x768.png b/docs/pos-screenshots/09-shell-offline-1366x768.png index 9dcbc22..a5c35ef 100644 Binary files a/docs/pos-screenshots/09-shell-offline-1366x768.png and b/docs/pos-screenshots/09-shell-offline-1366x768.png differ diff --git a/docs/pos-screenshots/09-shell-offline-1920x1080.png b/docs/pos-screenshots/09-shell-offline-1920x1080.png index d8670f2..317ed6a 100644 Binary files a/docs/pos-screenshots/09-shell-offline-1920x1080.png and b/docs/pos-screenshots/09-shell-offline-1920x1080.png differ diff --git a/docs/pos-screenshots/10-shell-online-1366x768.png b/docs/pos-screenshots/10-shell-online-1366x768.png index db7d823..5d26866 100644 Binary files a/docs/pos-screenshots/10-shell-online-1366x768.png and b/docs/pos-screenshots/10-shell-online-1366x768.png differ diff --git a/docs/pos-screenshots/10-shell-online-1920x1080.png b/docs/pos-screenshots/10-shell-online-1920x1080.png index 7b982b7..44fa745 100644 Binary files a/docs/pos-screenshots/10-shell-online-1920x1080.png and b/docs/pos-screenshots/10-shell-online-1920x1080.png differ diff --git a/docs/pos-screenshots/before/01-login-1366x768.png b/docs/pos-screenshots/before/01-login-1366x768.png new file mode 100644 index 0000000..49406ef Binary files /dev/null and b/docs/pos-screenshots/before/01-login-1366x768.png differ diff --git a/docs/pos-screenshots/before/01-login-1920x1080.png b/docs/pos-screenshots/before/01-login-1920x1080.png new file mode 100644 index 0000000..8c70c27 Binary files /dev/null and b/docs/pos-screenshots/before/01-login-1920x1080.png differ diff --git a/docs/pos-screenshots/before/01b-login-pin-1366x768.png b/docs/pos-screenshots/before/01b-login-pin-1366x768.png new file mode 100644 index 0000000..64ca6f3 Binary files /dev/null and b/docs/pos-screenshots/before/01b-login-pin-1366x768.png differ diff --git a/docs/pos-screenshots/before/01b-login-pin-1920x1080.png b/docs/pos-screenshots/before/01b-login-pin-1920x1080.png new file mode 100644 index 0000000..9c7db5f Binary files /dev/null and b/docs/pos-screenshots/before/01b-login-pin-1920x1080.png differ diff --git a/docs/pos-screenshots/before/02-shift-open-1366x768.png b/docs/pos-screenshots/before/02-shift-open-1366x768.png new file mode 100644 index 0000000..edcf878 Binary files /dev/null and b/docs/pos-screenshots/before/02-shift-open-1366x768.png differ diff --git a/docs/pos-screenshots/before/02-shift-open-1920x1080.png b/docs/pos-screenshots/before/02-shift-open-1920x1080.png new file mode 100644 index 0000000..c828b32 Binary files /dev/null and b/docs/pos-screenshots/before/02-shift-open-1920x1080.png differ diff --git a/docs/pos-screenshots/before/03-sale-empty-1366x768.png b/docs/pos-screenshots/before/03-sale-empty-1366x768.png new file mode 100644 index 0000000..10786b4 Binary files /dev/null and b/docs/pos-screenshots/before/03-sale-empty-1366x768.png differ diff --git a/docs/pos-screenshots/before/03-sale-empty-1920x1080.png b/docs/pos-screenshots/before/03-sale-empty-1920x1080.png new file mode 100644 index 0000000..952b988 Binary files /dev/null and b/docs/pos-screenshots/before/03-sale-empty-1920x1080.png differ diff --git a/docs/pos-screenshots/before/04-sale-items-1366x768.png b/docs/pos-screenshots/before/04-sale-items-1366x768.png new file mode 100644 index 0000000..89661c2 Binary files /dev/null and b/docs/pos-screenshots/before/04-sale-items-1366x768.png differ diff --git a/docs/pos-screenshots/before/04-sale-items-1920x1080.png b/docs/pos-screenshots/before/04-sale-items-1920x1080.png new file mode 100644 index 0000000..7c9b7b0 Binary files /dev/null and b/docs/pos-screenshots/before/04-sale-items-1920x1080.png differ diff --git a/docs/pos-screenshots/before/05-payment-cash-1366x768.png b/docs/pos-screenshots/before/05-payment-cash-1366x768.png new file mode 100644 index 0000000..efdb0cf Binary files /dev/null and b/docs/pos-screenshots/before/05-payment-cash-1366x768.png differ diff --git a/docs/pos-screenshots/before/05-payment-cash-1920x1080.png b/docs/pos-screenshots/before/05-payment-cash-1920x1080.png new file mode 100644 index 0000000..009b024 Binary files /dev/null and b/docs/pos-screenshots/before/05-payment-cash-1920x1080.png differ diff --git a/docs/pos-screenshots/before/06-payment-mixed-1366x768.png b/docs/pos-screenshots/before/06-payment-mixed-1366x768.png new file mode 100644 index 0000000..3c6fc0e Binary files /dev/null and b/docs/pos-screenshots/before/06-payment-mixed-1366x768.png differ diff --git a/docs/pos-screenshots/before/06-payment-mixed-1920x1080.png b/docs/pos-screenshots/before/06-payment-mixed-1920x1080.png new file mode 100644 index 0000000..bf50748 Binary files /dev/null and b/docs/pos-screenshots/before/06-payment-mixed-1920x1080.png differ diff --git a/docs/pos-screenshots/before/07-return-1366x768.png b/docs/pos-screenshots/before/07-return-1366x768.png new file mode 100644 index 0000000..0c20313 Binary files /dev/null and b/docs/pos-screenshots/before/07-return-1366x768.png differ diff --git a/docs/pos-screenshots/before/07-return-1920x1080.png b/docs/pos-screenshots/before/07-return-1920x1080.png new file mode 100644 index 0000000..1d7b37c Binary files /dev/null and b/docs/pos-screenshots/before/07-return-1920x1080.png differ diff --git a/docs/pos-screenshots/before/08-shift-z-1366x768.png b/docs/pos-screenshots/before/08-shift-z-1366x768.png new file mode 100644 index 0000000..e86713f Binary files /dev/null and b/docs/pos-screenshots/before/08-shift-z-1366x768.png differ diff --git a/docs/pos-screenshots/before/08-shift-z-1920x1080.png b/docs/pos-screenshots/before/08-shift-z-1920x1080.png new file mode 100644 index 0000000..d4e5c24 Binary files /dev/null and b/docs/pos-screenshots/before/08-shift-z-1920x1080.png differ diff --git a/docs/pos-screenshots/before/09-shell-offline-1366x768.png b/docs/pos-screenshots/before/09-shell-offline-1366x768.png new file mode 100644 index 0000000..4f9e5be Binary files /dev/null and b/docs/pos-screenshots/before/09-shell-offline-1366x768.png differ diff --git a/docs/pos-screenshots/before/09-shell-offline-1920x1080.png b/docs/pos-screenshots/before/09-shell-offline-1920x1080.png new file mode 100644 index 0000000..ed6b214 Binary files /dev/null and b/docs/pos-screenshots/before/09-shell-offline-1920x1080.png differ diff --git a/docs/pos-screenshots/before/10-shell-online-1366x768.png b/docs/pos-screenshots/before/10-shell-online-1366x768.png new file mode 100644 index 0000000..867817b Binary files /dev/null and b/docs/pos-screenshots/before/10-shell-online-1366x768.png differ diff --git a/docs/pos-screenshots/before/10-shell-online-1920x1080.png b/docs/pos-screenshots/before/10-shell-online-1920x1080.png new file mode 100644 index 0000000..4c19f09 Binary files /dev/null and b/docs/pos-screenshots/before/10-shell-online-1920x1080.png differ diff --git a/docs/pos-screenshots/index.html b/docs/pos-screenshots/index.html index 7db3df4..c82e919 100644 --- a/docs/pos-screenshots/index.html +++ b/docs/pos-screenshots/index.html @@ -1 +1 @@ -Касса food-market — скриншоты

Касса food-market — скриншоты процессов

рендер headless (Avalonia/Skia, Linux) — 1920×1080 и 1366×768. Кадров: 22
Вход кассира (адрес сервера, логин, пароль) (1920x1080)
Вход кассира (адрес сервера, логин, пароль) (1366x768)
Быстрый вход по PIN (зарегистрированное устройство) (1920x1080)
Быстрый вход по PIN (зарегистрированное устройство) (1366x768)
Смена: Z-отчёт/состояние смены (1920x1080)
Смена: Z-отчёт/состояние смены (1366x768)
Продажа: пустой чек, ожидание сканирования (1920x1080)
Продажа: пустой чек, ожидание сканирования (1366x768)
Продажа: чек с товарами (вкл. весовой) (1920x1080)
Продажа: чек с товарами (вкл. весовой) (1366x768)
Оплата наличными со сдачей (1920x1080)
Оплата наличными со сдачей (1366x768)
Оплата смешанная (нал+карта) (1920x1080)
Оплата смешанная (нал+карта) (1366x768)
Возврат по чеку (выбор позиций) (1920x1080)
Возврат по чеку (выбор позиций) (1366x768)
Z-отчёт при закрытии (должно/факт/разница) (1920x1080)
Z-отчёт при закрытии (должно/факт/разница) (1366x768)
Статус-бар: нет связи, чеки в очереди (1920x1080)
Статус-бар: нет связи, чеки в очереди (1366x768)
Статус-бар: на связи, очередь пуста (1920x1080)
Статус-бар: на связи, очередь пуста (1366x768)

Windows 11 — реальное окно

Снято на Windows 11 (VM, software-рендер — у VM нет GPU; консоль 1280×800). Подтверждает нативный рендер: кириллица, формат чисел «3 362 ₸», кнопки без обрезки. Высокое разрешение 1366/1920 — в headless-кадрах выше (тот же движок Avalonia/Skia/Inter).
Windows 11 — экран продажи (реальное окно)
Windows 11 — экран продажи (реальное окно)
\ No newline at end of file +Касса food-market — скриншоты

Касса food-market — скриншоты процессов

Светлая тема (Avalonia/Skia, headless, Linux) — 1920×1080 и 1366×768. Кадров: 22

Стало (светлая тема)

Вход кассира (адрес сервера, логин, пароль) (1920x1080)
Вход кассира (адрес сервера, логин, пароль) (1366x768)
Быстрый вход по PIN (зарегистрированное устройство) (1920x1080)
Быстрый вход по PIN (зарегистрированное устройство) (1366x768)
Смена: Z-отчёт/состояние смены (1920x1080)
Смена: Z-отчёт/состояние смены (1366x768)
Продажа: пустой чек, ожидание сканирования (1920x1080)
Продажа: пустой чек, ожидание сканирования (1366x768)
Продажа: чек с товарами (вкл. весовой) (1920x1080)
Продажа: чек с товарами (вкл. весовой) (1366x768)
Оплата наличными со сдачей (1920x1080)
Оплата наличными со сдачей (1366x768)
Оплата смешанная (нал+карта) (1920x1080)
Оплата смешанная (нал+карта) (1366x768)
Возврат по чеку (выбор позиций) (1920x1080)
Возврат по чеку (выбор позиций) (1366x768)
Z-отчёт при закрытии (должно/факт/разница) (1920x1080)
Z-отчёт при закрытии (должно/факт/разница) (1366x768)
Статус-бар: нет связи, чеки в очереди (1920x1080)
Статус-бар: нет связи, чеки в очереди (1366x768)
Статус-бар: на связи, очередь пуста (1920x1080)
Статус-бар: на связи, очередь пуста (1366x768)

Было (тёмная тема)

для сравнения — прежний мрачный интерфейс
01-login-1366x768
01-login-1920x1080
01b-login-pin-1366x768
01b-login-pin-1920x1080
02-shift-open-1366x768
02-shift-open-1920x1080
03-sale-empty-1366x768
03-sale-empty-1920x1080
04-sale-items-1366x768
04-sale-items-1920x1080
05-payment-cash-1366x768
05-payment-cash-1920x1080
06-payment-mixed-1366x768
06-payment-mixed-1920x1080
07-return-1366x768
07-return-1920x1080
08-shift-z-1366x768
08-shift-z-1920x1080
09-shell-offline-1366x768
09-shell-offline-1920x1080
10-shell-online-1366x768
10-shell-online-1920x1080

Windows 11 — реальное окно

Снято на Windows 11 (VM, software-рендер — у VM нет GPU; консоль 1280×800). Подтверждает нативный рендер: кириллица, формат чисел «3 362 ₸», кнопки без обрезки. Высокое разрешение 1366/1920 — в headless-кадрах выше (тот же движок Avalonia/Skia/Inter).
Windows 11 — экран продажи (реальное окно)
\ No newline at end of file diff --git a/docs/pos-ui-progress.md b/docs/pos-ui-progress.md new file mode 100644 index 0000000..9bad38c --- /dev/null +++ b/docs/pos-ui-progress.md @@ -0,0 +1,39 @@ +# Новый внешний вид кассы — прогресс + +Задача владельца (08.10.2026): «визуально выглядит ужасно, фон мрачный — сделай +интерфейс более стильным, светлым, удобным». Светлая тема по умолчанию, +ориентиры Square/Loyverse/Poster. Скорость не ухудшать. + +## Замеры скорости (до/после) +| Метрика | До (dark) | После (light) | +|---|---|---| +| Холодный старт (процесс→логика), Linux | 146 мс | 149 мс (в пределах шума) | +| Поиск по штрихкоду | 13,9 мс | 11,2 мс | +| Поиск по имени на 30 000 | 41,9 мс | 33,2 мс | + +Скорость не ухудшилась (светлая тема — только ресурсы/стили, логика та же). + +## План +1. [x] Токены светлой темы в `Styles/Tokens.axaml` (ThemeDictionaries Light/Dark) + docs/pos-design.md. +2. [x] Светлая тема по умолчанию (`RequestedThemeVariant=Light`); тёмная — те же токены (вариант Dark). +3. [x] Экран продажи: белая верхняя полоса (лого/точка/кассир/чипы смены+связи), + поиск со скан-иконкой, корзина-карточки со степпером [−]N[+] и удалением, + белая карточка чека с крупным зелёным ИТОГО и «Оплатить · F12», вторичные + кнопки-контуры, пустая корзина-заглушка, капсулы горячих клавиш. +4. [x] Оплата (светлое модальное): сегменты Нал/Карта/Смешанная, быстрые суммы + (без сдачи/1000/2000/5000/10000/20000), цифровая клавиатура, крупная «Сдача». +5. [x] Остальные экраны в стиле: вход (логин + PIN-пад), регистрация/выбор точки, + смена/Z-отчёт (разница цветом), возврат (степперы). Нет связи — чип в шапке. +6. [ ] Избранные товары: сервер (флаг/порядок у товара) + миграция + плитки UI. +7. [x] Удобство: кнопки ≥48px, клавиши крупные; фокус в поле скана; адаптив 1366/1920. +8. [~] Скриншоты «Было/Стало» 1920×1080 + 1366×768 (галерея с разделами); реальное окно Windows 11 — в конце. +9. [x] --uitest OK; unit 43 зелёные; скорость не хуже. Smoke Linux/Windows — в конце. +10. [~] Коммиты в main; push (по ходу). + +Осталось: избранные товары (п.6), тёмная тема как переключатель в настройках, +реальное окно Windows 11, smoke Win/Linux, итоговый push. + +НЕ трогать: прод, shared-postgres, global.json, gateway nginx, sklad, другие VM. + +## Журнал +- 08.10 — старт; сохранены «до»-скриншоты (22), замерен baseline; планы зафиксированы. diff --git a/src/food-market.pos/App.axaml b/src/food-market.pos/App.axaml index 73d0160..687cef5 100644 --- a/src/food-market.pos/App.axaml +++ b/src/food-market.pos/App.axaml @@ -2,47 +2,19 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:foodmarket.Pos" x:Class="foodmarket.Pos.App" - RequestedThemeVariant="Dark"> + RequestedThemeVariant="Light"> + + + + + + + - - - - - - - - + diff --git a/src/food-market.pos/Styles/PosStyles.axaml b/src/food-market.pos/Styles/PosStyles.axaml new file mode 100644 index 0000000..f98b637 --- /dev/null +++ b/src/food-market.pos/Styles/PosStyles.axaml @@ -0,0 +1,152 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/food-market.pos/Styles/Tokens.axaml b/src/food-market.pos/Styles/Tokens.axaml new file mode 100644 index 0000000..f85d281 --- /dev/null +++ b/src/food-market.pos/Styles/Tokens.axaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/food-market.pos/Tooling/ScreenshotRunner.cs b/src/food-market.pos/Tooling/ScreenshotRunner.cs index 7fef0f2..43db87a 100644 --- a/src/food-market.pos/Tooling/ScreenshotRunner.cs +++ b/src/food-market.pos/Tooling/ScreenshotRunner.cs @@ -90,11 +90,32 @@ private static void WriteGallery(string dir, List<(string file, string caption)> ".grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(420px,1fr));gap:16px;padding:20px}" + "figure{margin:0;background:#1e293b;border:1px solid #334155;border-radius:10px;overflow:hidden}" + "img{width:100%;display:block;background:#000;cursor:zoom-in}figcaption{padding:8px 10px;color:#cbd5e1;font-size:13px}"); - sb.Append($"

Касса food-market — скриншоты процессов

рендер headless (Avalonia/Skia, Linux) — 1920×1080 и 1366×768. Кадров: {shots.Count}
"); + sb.Append($"

Касса food-market — скриншоты процессов

Светлая тема (Avalonia/Skia, headless, Linux) — 1920×1080 и 1366×768. Кадров: {shots.Count}
"); + sb.Append("

Стало (светлая тема)

"); + sb.Append("
"); foreach (var (file, caption) in shots) sb.Append($"
{System.Net.WebUtility.HtmlEncode(caption)}
"); sb.Append("
"); + // Раздел «Было» — прежняя тёмная тема (если сохранена в before/). + var beforeDir = Path.Combine(dir, "before"); + if (Directory.Exists(beforeDir)) + { + var befs = Directory.GetFiles(beforeDir, "*.png").OrderBy(f => f).ToList(); + if (befs.Count > 0) + { + sb.Append("

Было (тёмная тема)

" + + "
для сравнения — прежний мрачный интерфейс
"); + sb.Append("
"); + foreach (var b in befs) + { + var rel = "before/" + Path.GetFileName(b); + sb.Append($"
{System.Net.WebUtility.HtmlEncode(Path.GetFileNameWithoutExtension(b))}
"); + } + sb.Append("
"); + } + } + // Раздел «Windows 11» — реальные скриншоты окна на Windows (если есть). var winDir = Path.Combine(dir, "windows"); if (Directory.Exists(winDir)) diff --git a/src/food-market.pos/ViewModels/ViewModels.cs b/src/food-market.pos/ViewModels/ViewModels.cs index 8907674..936a046 100644 --- a/src/food-market.pos/ViewModels/ViewModels.cs +++ b/src/food-market.pos/ViewModels/ViewModels.cs @@ -24,19 +24,24 @@ public partial class MainWindowViewModel : ViewModelBase [ObservableProperty] private object? _currentPage; [ObservableProperty] private string _cashierName = "—"; [ObservableProperty] private string _shiftNumber = "смена не открыта"; + [ObservableProperty] private bool _isShiftOpen; + [ObservableProperty] private string _pointName = "Магазин"; [ObservableProperty] private bool _isOnline = true; [ObservableProperty] private int _queueCount; [ObservableProperty] private PaymentViewModel? _payment; [ObservableProperty] private bool _isPaymentOpen; [ObservableProperty] private string? _updateMessage; - public string NetBadge => IsOnline ? "● на связи" : "○ нет связи"; - public string QueueBadge => QueueCount > 0 ? $"{QueueCount} чек(ов) в очереди" : "очередь пуста"; + public string NetBadge => IsOnline ? "На связи" : "Нет связи"; + public string ShiftBadge => IsShiftOpen ? $"Смена {ShiftNumber}" : "Смена закрыта"; + public string QueueBadge => QueueCount > 0 ? $"· {QueueCount} в очереди" : ""; partial void OnIsOnlineChanged(bool value) { OnPropertyChanged(nameof(NetBadge)); } partial void OnQueueCountChanged(int value) { OnPropertyChanged(nameof(QueueBadge)); } + partial void OnIsShiftOpenChanged(bool value) => OnPropertyChanged(nameof(ShiftBadge)); + partial void OnShiftNumberChanged(string value) => OnPropertyChanged(nameof(ShiftBadge)); /// Конструктор для дизайнера/скриншотов (демо-данные). - public MainWindowViewModel() { CurrentPage = SaleViewModel.Sample(); CashierName = "Пётр Кассиров"; ShiftNumber = "С-2026-000001"; } + public MainWindowViewModel() { CurrentPage = SaleViewModel.Sample(); CashierName = "Пётр Кассиров"; ShiftNumber = "С-2026-000001"; IsShiftOpen = true; PointName = "Магазин №1 · ул. Абая 10"; } public MainWindowViewModel(AppServices svc) { _svc = svc; if (svc.Session is not null) StartSession(); else ShowLogin(); } @@ -86,7 +91,7 @@ private static string LocalVersion() private void RefreshStatus() { if (_svc is not null) QueueCount = _svc.Store.PendingCount(); } [RelayCommand] private void ShowSale() { CurrentPage = _sale ??= (_svc is null ? SaleViewModel.Sample() : new SaleViewModel(_svc) { PaymentRequested = OpenPayment, SaleCommitted = _ => RefreshStatus() }); } - [RelayCommand] private void ShowShift() => CurrentPage = _svc is null ? ShiftViewModel.Sample() : new ShiftViewModel(_svc) { OnShiftChanged = s => { ShiftNumber = s ?? "смена не открыта"; } }; + [RelayCommand] private void ShowShift() => CurrentPage = _svc is null ? ShiftViewModel.Sample() : new ShiftViewModel(_svc) { OnShiftChanged = s => { ShiftNumber = s ?? "смена не открыта"; IsShiftOpen = s is not null; } }; [RelayCommand] private void ShowReturn() => CurrentPage = _svc is null ? ReturnViewModel.Sample() : new ReturnViewModel(_svc); private void OpenPayment(PaymentViewModel pvm) @@ -369,6 +374,10 @@ public partial class SaleViewModel : ViewModelBase [ObservableProperty] private decimal _total; [ObservableProperty] private int _itemCount; [ObservableProperty] private SaleLineVm? _selectedLine; + public bool IsCartEmpty => ItemCount == 0; + public bool HasAnyDiscount => Discount > 0m; + partial void OnItemCountChanged(int value) => OnPropertyChanged(nameof(IsCartEmpty)); + partial void OnDiscountChanged(decimal value) => OnPropertyChanged(nameof(HasAnyDiscount)); /// Поднять модальную оплату (обрабатывает оболочка). public Action? PaymentRequested; @@ -433,6 +442,17 @@ public void SetLineQuantity(SaleLineVm line, decimal qty) Recalc(); } + [RelayCommand] private void IncLine(SaleLineVm line) { if (line.Model is { } m) SetLineQuantity(line, m.Quantity + 1m); } + [RelayCommand] private void DecLine(SaleLineVm line) { if (line.Model is { } m) SetLineQuantity(line, m.Quantity - 1m); } + [RelayCommand] + private void RemoveLine(SaleLineVm line) + { + if (line.Model is { } m) _cart.Remove(m); + Lines.Remove(line); + if (ReferenceEquals(SelectedLine, line)) SelectedLine = Lines.FirstOrDefault(); + Recalc(); + } + public void SetCartDiscount(decimal amount) { _cart.SetCartDiscount(amount); Recalc(); Message = $"Скидка на чек: {amount:N0} ₸"; } [RelayCommand] @@ -524,16 +544,35 @@ public partial class PaymentViewModel : ViewModelBase public decimal Change => PaymentMath.Compute(Total, PaidCash, PaidCard).Change; public decimal Shortfall => PaymentMath.Compute(Total, PaidCash, PaidCard).Shortfall; public bool Sufficient => PaymentMath.Compute(Total, PaidCash, PaidCard).Sufficient; + public bool IsCash => Method == "Наличные"; + public bool IsCard => Method == "Карта"; + public bool IsMixed => Method == "Смешанная"; partial void OnPaidCashChanged(decimal value) => RaisePay(); partial void OnPaidCardChanged(decimal value) => RaisePay(); partial void OnTotalChanged(decimal value) => RaisePay(); + partial void OnMethodChanged(string value) { OnPropertyChanged(nameof(IsCash)); OnPropertyChanged(nameof(IsCard)); OnPropertyChanged(nameof(IsMixed)); } private void RaisePay() { OnPropertyChanged(nameof(Change)); OnPropertyChanged(nameof(Shortfall)); OnPropertyChanged(nameof(Sufficient)); } /// Вызывается при подтверждении оплаты (cash, card, change). public Func? OnConfirm; public Action? OnCancel; - [RelayCommand] private void ExactCash() { PaidCash = Total; PaidCard = 0m; Method = "Наличные"; } + [RelayCommand] private void ExactCash() { PaidCash = Total; PaidCard = 0m; } + [RelayCommand] private void SelectCash() { Method = "Наличные"; PaidCard = 0m; } + [RelayCommand] private void SelectCard() { Method = "Карта"; PaidCard = Total; PaidCash = 0m; } + [RelayCommand] private void SelectMixed() { Method = "Смешанная"; } + + /// Быстрая сумма наличных: «Без сдачи» (ровно) или номинал. + [RelayCommand] private void QuickCash(string amount) + { + if (amount == "exact") { PaidCash = Total; return; } + if (decimal.TryParse(amount, out var a)) PaidCash = a; + } + + // Экранная цифровая клавиатура для наличных (целые тенге). + [RelayCommand] private void KeyDigit(string d) { if (int.TryParse(d, out var n)) PaidCash = PaidCash * 10m + n; } + [RelayCommand] private void KeyBack() { PaidCash = Math.Floor(PaidCash / 10m); } + [RelayCommand] private void KeyClear() { PaidCash = 0m; } [RelayCommand] private async Task Confirm() @@ -544,8 +583,8 @@ private async Task Confirm() [RelayCommand] private void Cancel() => OnCancel?.Invoke(); - public static PaymentViewModel SampleCash() => new() { Total = 3365m, PaidCash = 5000m, Method = "Наличные" }; - public static PaymentViewModel SampleMixed() => new() { Total = 3365m, PaidCash = 1365m, PaidCard = 2000m, Method = "Смешанная" }; + public static PaymentViewModel SampleCash() => new() { Total = 3362m, PaidCash = 5000m, Method = "Наличные" }; + public static PaymentViewModel SampleMixed() => new() { Total = 3362m, PaidCash = 1362m, PaidCard = 2000m, Method = "Смешанная" }; } /// Смена: открыть (размен) / закрыть (факт → должно/факт/разница), @@ -568,9 +607,12 @@ public partial class ShiftViewModel : ViewModelBase public decimal ExpectedCash => ShiftMath.ExpectedCash(OpeningFloat, SalesCash, ReturnsCash, DrawerIn, DrawerOut); public decimal Difference => ShiftMath.CashDifference(ActualCash, ExpectedCash); + public bool DiffSurplus => Difference > 0m; // излишек + public bool DiffShortage => Difference < 0m; // недостача + public string DiffLabel => Difference == 0m ? "Сходится" : Difference > 0m ? "Излишек" : "Недостача"; partial void OnOpeningFloatChanged(decimal value) => RaiseCalc(); partial void OnActualCashChanged(decimal value) => RaiseCalc(); - private void RaiseCalc() { OnPropertyChanged(nameof(ExpectedCash)); OnPropertyChanged(nameof(Difference)); } + private void RaiseCalc() { OnPropertyChanged(nameof(ExpectedCash)); OnPropertyChanged(nameof(Difference)); OnPropertyChanged(nameof(DiffSurplus)); OnPropertyChanged(nameof(DiffShortage)); OnPropertyChanged(nameof(DiffLabel)); } /// Сообщить оболочке новый номер смены (или null — закрыта). public Action? OnShiftChanged; diff --git a/src/food-market.pos/Views/LoginView.axaml b/src/food-market.pos/Views/LoginView.axaml index c79798d..f614cb5 100644 --- a/src/food-market.pos/Views/LoginView.axaml +++ b/src/food-market.pos/Views/LoginView.axaml @@ -3,63 +3,65 @@ xmlns:vm="clr-namespace:foodmarket.Pos.ViewModels" x:Class="foodmarket.Pos.Views.LoginView" x:DataType="vm:LoginViewModel"> - - - - - - - - - - + + + + + + - - - + + + + + + + + + + + + + + + + + - + - + - - - - - - - + + + + + + + - - - - - - - - - - + +