Демо-проект
Панель диспетчера в телефоне: Графин
Заказы, водители и просрочка в кармане диспетчера; две правки чужого экрана сделаны в двух состояниях, до и после.
разработка мобильного приложения · Flutter · Dart · Android · iOS

Задача
«Графин» - служба доставки питьевой воды и обслуживания кулеров: бутыли 19 литров, помпы, возвратная тара, окна доставки. Демо-проект: компания, водители и заказы вымышлены, задача типовая. Диспетчер не всегда сидит за монитором - он отходит к складу, к машинам, к телефону в коридоре, и всё это время смена продолжается. Мобильная панель нужна ровно для этих минут: посмотреть, что горит, и передать заказ другому водителю, не возвращаясь к столу.
Второе назначение проекта - показать не готовое приложение, а работу над чужим кодом. Заказчик на бирже чаще приходит не за «сделайте с нуля», а с фразой «приложение есть, доработайте экран». Поэтому два экрана сделаны в двух состояниях: до правки и после.
Решение
Flutter, семь экранов: смена, заказы, водители, карточка заказа, карточка водителя, полная лента событий и «О приложении». Тема только тёмная - так в брифе, светлой у этого демо нет.
- Правка «список не показывает, что горит». В состоянии «до» просроченный заказ ничем не помечен: № 1031 стоит седьмым в плоском списке и подписан «В пути» тем же приглушённым серым, что «Доставлен» у соседних строк, - на первом экране он читается как обычная строка. Два других просроченных стоят 9-м и 12-м и до первого экрана вообще не доходят. В состоянии «после» просроченные подняты в секцию с липким заголовком, у строк заказов, которые ещё в работе, появился обратный отсчёт до конца окна доставки, статус получил цвет, а просроченная строка - красную полосу слева. Под заголовком - лента из пяти чипов-фильтров с количествами (все 24, новые 5, в пути 9, просрочены 3, доставлены 7); в ширину экрана она не помещается и прокручивается вбок.
- Правка «пустой экран ничего не объясняет». Фильтр «Просрочены», когда просрочек нет, показывал голый фон. Стало: нарисованная галочка в круге, заголовок «Просрочек нет», строка «Все 24 заказа идут в срок» и кнопка «Показать все заказы».
- Оба состояния живут в одном дереве кода и выбираются переменной сборки:
--dart-define=DEMO=k11-before. Веток git и папок «before/after» нет - любой кадр переснимается одной командой, и «до» не устаревает, пока правится «после». - Просрочка - не статус, а вычисляемый признак: срок вышел, а заказ ещё в работе - назначен, забран или в пути. Отдельным статусом заказ оказался бы одновременно «в пути» и «просрочен»: все три просроченных в демо как раз «в пути».
- Действия диспетчера работают, а не нарисованы: заказ передаётся другому водителю через шторку выбора и отмечается доставленным, таймлайн из пяти шагов дописывается временем.
Детали, которые легко не заметить
- Данные детерминированы: «сейчас» - константа 25 августа 2026, 15:14, ни
Random, ниDateTime.now()в данных нет. Поэтому «просрочен на 14 минут» и «-00:14» - результат вычитания, а не записанная строка, и кадр переснимается один в один хоть через полгода. - Действия не портят исходные данные: списки неизменяемы, обновление собирает новый заказ. Отдельный тест проверяет, что после отметки доставленным прежний объект остался нетронутым.
- Русские окончания считаются, а не подставляются: «на 1 минуту», «на 2 минуты», «на 14 минут» - одна функция на три формы.
- Неизвестный пресет не даёт приложению открыться «как получится»: вместо панели показывается экран ошибки со списком допустимых значений. Сборка при этом проходит -
String.fromEnvironmentпринимает любую строку, проверка живёт в рантайме, и на неё есть тест. - В данных нет ни одного телефона и ни одной улицы с домом: у заказа показаны зона, район и этаж. Демонстрационная природа заявлена прямо - строка внизу экрана смены и отдельный экран «О приложении».
- Шрифты лежат в репозитории, пакет
google_fontsне подключён намеренно: он тянет файлы по сети, и в кадр может попасть подменный шрифт. - Съёмка автоматизирована скриптом: статус-бар приводится к нейтральному виду (9:41, без оператора), кадр снимается только через
simctlиadb. Кадры Android дополнительно проверяются на сигнатуру png, завершающий чанк и минимальный размер -adb exec-outумеет молча обрезать файл. - Расхождение внутри брифа оставлено видимым, а не замазано: подпись плитки «из них 12 закрыты» не сходится с числами чипов, из которых следует 10. Обе цифры и их происхождение записаны в README, решать владельцу.
Что осталось
Галерея кадров для этой страницы не собрана: есть только исходники съёмки, двенадцать необработанных кадров с iOS и Android. Пар «до и после» на странице пока нет. Кода это не касается: все пять пресетов сняты на обеих платформах, то есть обе сборки собираются и запускаются.
Скриншоты




