AAYMA
RU
Войти

Event Match

Flutter-приложение с Node.js-сервером для подбора до трёх event-подрядчиков: жёсткие ограничения, детерминированный скоринг, объяснения на…

Доведённый продукт
Команда «aipunks» 21💬 0 комментариевс 23 сентября 2026 г.

О проекте

Команда: aipunks
Кейс HackAlem.ai: Креативные индустрии — Firebird
Стадия: Доведённый продукт

Задача кейса: «#79-lite»: подобрать до 3 подрядчиков для мероприятия и объяснить выбор

Суть

Flutter-приложение с Node.js-сервером для подбора до трёх event-подрядчиков: жёсткие ограничения, детерминированный скоринг, объяснения на проверенных фактах, кнопки ослабления условий, плюс кабинеты, модерация, переписка и GPT-помощник.

Как устроено

Каталог из 66 исходных и 434 синтетических профилей (всего 500) загружается в SQLite. Ядро на Dart сначала применяет жёсткие фильтры (формат, язык, часы, занятость по календарю, бюджет), затем считает скор с весами: бюджет 0.30, форматы 0.20, совпадения описания 0.20, языки 0.15, часы 0.15; порядок — score↓, цена↑, id↑. GPT через OpenAI Responses API только выбирает порядок из заранее проверенных explanation_options. Ответы кэшируются по hash каталога; при сбое AI остаётся локальная выдача. Если вариантов мало, до трёх кнопок ослабляют по одному параметру.

Ключевые решения

  • hard-constraint filtering
  • weighted deterministic scoring
  • constraint relaxation suggestions
  • grounded explanations
  • AI response cache

Особенности

GPT не сочиняет причины: ему разрешено выбрать только точный вариант из explanation_options, и сервер с клиентом это проверяют. Три отдельных исхода: подобрали, категории нет, кандидаты не прошли условия.

Стек

Flutter · Dart · Node.js · SQLite · GitHub Actions

Модели

OpenAI Responses API (GPT)


Проект создан за 5 часов на финале хакатона HackAlem.ai (23 сентября 2026, Астана). Код — BAITC-Hacks/hack-d2c4660e-aipunks.

README

README.md

Event Match · aipunks

Подбор event-подрядчиков в Казахстане (#79-lite): до трёх рекомендаций, проверенная доступность, контрастные факты и конкретные изменения условий, если вариантов мало.

Стек: Flutter 3.44.1 / Dart 3.12.1, Node.js 24.16+, SQLite, OpenAI Responses API. Firebase не используется при запуске. Локальный подбор работает без сервера и интернета; AI-редактор — дополнительный слой.

Запуск

Сначала зависимости Flutter — они нужны и общему Dart-ядру сервера:

cd apps/event_match
flutter pub get
cd ../api
npm ci

Создайте apps/api/.env по .env.example, задайте OPENAI_API_KEY=... только в этом файле. Ключ не передаётся во Flutter. Затем:

npm start

Сервер запускается на 127.0.0.1:8787, автоматически импортирует 500 профилей в apps/api/data/event-match.sqlite и создаёт первого администратора, если в базе ещё нет админа.

По умолчанию логин — [email protected]. Случайный пароль сохраняется в локальный файл apps/api/data/event-match.sqlite.admin-credentials.json, исключённый из Git. Свои данные можно задать до первого запуска через ADMIN_EMAIL, ADMIN_NAME и ADMIN_PASSWORD в apps/api/.env. Повторный запуск не меняет существующие аккаунты и пароли.

Скрипт создания админа находится в репозитории: apps/api/src/admin-create.mjs. Его можно запустить отдельно командой npm run admin:create из apps/api, без запуска API и Flutter. Подробнее — первый администратор.

В другом терминале из корня репозитория:

cd apps/event_match
flutter run -d chrome --web-port=5173

После изменения pubspec.yaml, добавления фото или шрифтов полностью остановите старый flutter run клавишей q и запустите его заново. Hot reload может оставить старый набор ресурсов: тогда существующий assets/images/event-table.jpg возвращает 404, а шрифты заменяются системными. Фото включено в pubspec.yaml; копировать его в web/ или подключать через внешний URL не нужно.

Конфигурация Chrome в VS Code использует 5173. В loopback-режиме без ALLOWED_ORIGINS разрешены произвольные локальные dev-порты Chrome; явно заданный список ограничивает их. Если сервер не запущен, приложение загружает встроенный JSONL и показывает локальные объяснения.

Android-эмулятор по умолчанию использует http://10.0.2.2:8787. Для физического телефона нужен адрес компьютера в общей сети, настройка HOST, локальный токен и разрешение брандмауэра — инструкция. Локальный HTTP разрешён только в debug Android; для release нужен HTTPS. iOS в этой конфигурации не проверялся.

Что реализовано

  • Кабинеты клиента/подрядчика, админка и план события перенесены из новых веток и подключены к SQLite.
  • ИИ-помощник с уточнениями-кнопками и переписка с опубликованными подрядчиками — в правых панелях.
  • Регистрация, модерация публикаций, календари, права доступа и личные данные — через локальный API.
  • Запуск кабинетов, выдача первого администратора и ограничения — инструкция интеграции.
  • Все жёсткие ограничения, включая календарь площадок и max_hours: null.
  • Полный набор нарушений; основная причина: формат → язык → часы → занятость → бюджет.
  • Детерминированный скоринг: бюджет 0.30, число форматов 0.20, совпадения описания 0.20, языки 0.15, часы 0.15; поправки на происхождение данных.
  • Порядок: score ↓, цена ↑, id ↑. Score — соответствие продуктовой эвристике, не рейтинг качества.
  • Индивидуальный факт + соответствие бюджету; общие условия в сводке. Почти одинаковые описания не объявляются разными преимуществами.
  • До трёх кнопок ослабления, каждая меняет ровно один параметр. Число вариантов пересчитывается.
  • Три исхода: подобрали / категории нет / кандидаты не прошли условия.
  • SQLite-каталог и постоянный кэш AI; hash каталога и версия алгоритма.
  • Переключатель GPT/локальные факты, источник текста в карточке, вклад фич в раскрытых деталях.
  • При сбое AI, несовпадении версий или отсутствии ключа — локальная выдача без изменения порядка.

В подборке показаны 1–2 предложения: подтверждённое условие/цитата профиля и стартовая цена относительно лимита с оговоркой об итоговой стоимости. GPT выбирает порядок двух проверенных предложений; сервер и клиент принимают только точный вариант из explanation_options. Это ограниченный выбор формулировки, а не свободное сочинение причин. Без GPT остаются те же проверенные факты. В каталоге GPT по-прежнему генерирует сводку услуг: заголовок «Об услугах» не обещает соответствия заказу. В подборке заголовок «Почему в подборке», неизвестное вынесено в «Что уточнить». Источник GPT отмечается только после принятого ответа модели. Правила и исследования.

Если профили не имеют подтверждённых отличий, карточки честно сообщают об этом. Абсолютная неповторяемость объяснений для таких данных не заявляется. Прежнее ядро учитывает пожелания лексически. Новый помощник разбирает пожелания и отрицания GPT, проверяет признаки по цитатам и явно отмечает неподтверждённые требования; это не гарантия полного смыслового понимания.

Демо на расширенном каталоге

Все запросы — свадьба, без языка/часов, если не указано иное.

СценарийУсловияОжидаемый результат
Плотный пулАлматы, Ведущий, 06.10.2026, 1 000 000 ₸Из 16 прошедших: Кики → Эмилия → Лунный Ветер
Соседняя датаТо же, 05.10.2026Из 13 прошедших: Эмилия → Лунный Ветер → Лазурный Ветер; исключения по занятости в сводке
Редкая категорияАлматы, Флорист, 10.10.2026, 1 000 000 ₸Тони Тони Чоппер; предложение 09.10 с двумя вариантами
Никто не проходитАлматы, Ведущий, 26.12.2026, 1 ₸Нет результата; повышение бюджета до 650 000 ₸ даёт один вариант
Нет категорииЗарубежье, Флорист, 10.10.2026, 1 000 000 ₸Отдельный исход и предложения других городов
Честная эквивалентностьАлматы, Лайв-бэнд, 23.09.2026, 2 000 000 ₸Два близких профиля отмечены как не имеющие уникального преимущества

Пересчёт без сборки приложения: dart run tool/audit_catalog.dart из apps/event_match.

Проверки без сборок Web/APK

# apps/event_match
flutter analyze
flutter test

# apps/api
npm test

Серверные тесты используют подменный GPT, не тратят API-бюджет. Явный живой тест при работающем сервере: node --env-file=.env src/smoke.mjs. Он делает одну генерацию при промахе кэша и повторяет только успешный ответ для проверки кэша.

Данные и устройство

Исходные data/catalog.csv и снимок data/catalog.original.jsonl содержат 66 профилей организаторов (13 синтетических). Рабочий JSONL содержит 500 профилей: исходные 66 без изменений и 434 новых с ID DEMO-* и synthetic: true. Всего синтетических — 447. В карточках новые записи отмечены как «Демонстрационный профиль · добавлен нами»; их цены, услуги и календари вымышлены.

Из корня: node scripts/seed_catalog.mjs воспроизводит тот же каталог без сети. Из apps/api: npm run db:seed повторно генерирует каталог и атомарно импортирует его в SQLite; npm run catalog:audit проверяет уникальность. После изменения каталога перезапустите работающий API и перезагрузите приложение: оба держат снимок в памяти. Для восстановления исходного снимка из CSV: python scripts/import_catalog.py data/catalog.csv data/catalog.original.jsonl, затем повторите засеивание.

Редкие категории сохранены по три профиля. Новые календари занимают 30–50% дней осенью и 70–80% в декабре; декабрьские выходные новых профилей заняты. Подробные результаты и границы проверки уникальности — в отчёте.

Звёзды
⭐ 0
Форки
0
Язык
Dart
Последний push
в прошлом месяце
Коммиты
29
Авторы
3
Файлы
321
Ветки
11

Авторы коммитов

Danildos 15dev-dmitrii-g 12jlokerov 2

История коммитов

  • 2026-09-23 17:59feat: update localization and remove account language picker [skip ci]Danildos
  • 2026-09-23 17:52feat: enable language switching across application [skip ci]Danildos
  • 2026-09-23 17:52Merge integrated admin and explanations into main [skip ci]Danildos
  • 2026-09-23 17:51fix: integrate comparison tests and localized panel labels [skip ci]Danildos
  • 2026-09-23 17:49Merge feat/bootstrap-admin-account preserving account types [skip ci]Danildos
  • 2026-09-23 17:48Merge codex/match-explanations with inline comparison [skip ci]Danildos
  • 2026-09-23 17:42chore: include authorized hackathon demo API configuration [skip ci]Danildos
  • 2026-09-23 17:42ayeDanildos
Все коммиты (29)
  • 2026-09-23 17:40feat: bootstrap initial admin on API startupjlokerov
  • 2026-09-23 17:36feat: ground match explanations in verified request factsdev-dmitrii-g
  • 2026-09-23 17:22ui: simplify hero action and strengthen palette accentsDanildos
  • 2026-09-23 17:10feat: integrate local accounts, messaging and GPT assistant [skip ci]Danildos
  • 2026-09-23 16:46feat(assistant): integrate live matching into catalog and event workflowsdev-dmitrii-g
  • 2026-09-23 16:42fix(planning): preserve event drafts and save edits without losing contextdev-dmitrii-g
  • 2026-09-23 16:40fix(accounts): prevent stale calendar saves and allow moderator revocationdev-dmitrii-g
  • 2026-09-23 16:19docs(communication): record isolated release verificationdev-dmitrii-g
  • 2026-09-23 16:19docs(communication): document delivered inquiry and support workflowsdev-dmitrii-g
  • 2026-09-23 16:18feat(communication): add private inquiries, messaging, and administrator supportdev-dmitrii-g
  • 2026-09-23 16:04chore(preview): add non-destructive local account and event fixturesdev-dmitrii-g
  • 2026-09-23 15:57feat: add favorites folders and alternative date searchDanildos
  • 2026-09-23 15:55docs: record verification of integrated account and planning flowsdev-dmitrii-g
  • 2026-09-23 15:55feat(assistant): add conversational matching with validated Firebase backenddev-dmitrii-g
  • 2026-09-23 15:54feat(planning): add saved event plans with team and budget comparisondev-dmitrii-g
  • 2026-09-23 15:53feat(accounts): add authenticated workspaces and moderated live catalogdev-dmitrii-g
  • 2026-09-23 15:39feat: redesign Event Match for desktop and mobilejlokerov
  • 2026-09-23 15:32test: cover AI summaries and document responsive cards [skip ci]Danildos
  • 2026-09-23 15:28feat: add SQLite API and seed 500 contractor profilesDanildos
  • 2026-09-23 14:27feat: refresh adaptive UI and configure Firebase apps [skip ci]Danildos
  • 2026-09-23 14:05baseDanildos
Структура репозитория (321 файлов)
.agents/skills/git-advanced-workflows/SKILL.md
.agents/skills/git-advanced-workflows/references/details.md
.agents/skills/ui-ux-pro-max/SKILL.md
.agents/skills/ui-ux-pro-max/data/app-interface.csv
.agents/skills/ui-ux-pro-max/data/catalog-summary.json
.agents/skills/ui-ux-pro-max/data/charts.csv
.agents/skills/ui-ux-pro-max/data/colors.csv
.agents/skills/ui-ux-pro-max/data/data-provenance.json
.agents/skills/ui-ux-pro-max/data/google-font-licenses.json
.agents/skills/ui-ux-pro-max/data/google-fonts.csv
.agents/skills/ui-ux-pro-max/data/icons.csv
.agents/skills/ui-ux-pro-max/data/landing.csv
.agents/skills/ui-ux-pro-max/data/motion.csv
.agents/skills/ui-ux-pro-max/data/phosphor-icons-upstream.json
.agents/skills/ui-ux-pro-max/data/products.csv
.agents/skills/ui-ux-pro-max/data/react-performance.csv
.agents/skills/ui-ux-pro-max/data/stacks/angular.csv
.agents/skills/ui-ux-pro-max/data/stacks/astro.csv
.agents/skills/ui-ux-pro-max/data/stacks/avalonia.csv
.agents/skills/ui-ux-pro-max/data/stacks/flutter.csv
.agents/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv
.agents/skills/ui-ux-pro-max/data/stacks/javafx.csv
.agents/skills/ui-ux-pro-max/data/stacks/jetpack-compose.csv
.agents/skills/ui-ux-pro-max/data/stacks/laravel.csv
.agents/skills/ui-ux-pro-max/data/stacks/nextjs.csv
.agents/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv
.agents/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv
.agents/skills/ui-ux-pro-max/data/stacks/react-native.csv
.agents/skills/ui-ux-pro-max/data/stacks/react.csv
.agents/skills/ui-ux-pro-max/data/stacks/shadcn.csv
.agents/skills/ui-ux-pro-max/data/stacks/svelte.csv
.agents/skills/ui-ux-pro-max/data/stacks/swiftui.csv
.agents/skills/ui-ux-pro-max/data/stacks/threejs.csv
.agents/skills/ui-ux-pro-max/data/stacks/uno.csv
.agents/skills/ui-ux-pro-max/data/stacks/uwp.csv
.agents/skills/ui-ux-pro-max/data/stacks/vue.csv
.agents/skills/ui-ux-pro-max/data/stacks/winui.csv
.agents/skills/ui-ux-pro-max/data/stacks/wpf.csv
.agents/skills/ui-ux-pro-max/data/styles.csv
.agents/skills/ui-ux-pro-max/data/typography.csv
.agents/skills/ui-ux-pro-max/data/ui-reasoning.csv
.agents/skills/ui-ux-pro-max/data/ux-guidelines.csv
.agents/skills/ui-ux-pro-max/references/pro-rules.md
.agents/skills/ui-ux-pro-max/references/quick-reference.md
.agents/skills/ui-ux-pro-max/scripts/core.py
.agents/skills/ui-ux-pro-max/scripts/design_system.py
.agents/skills/ui-ux-pro-max/scripts/reasoning_contract.py
.agents/skills/ui-ux-pro-max/scripts/search.py
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-api.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-catalog.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-existing.csv
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-metadata.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/google-overrides.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/icons-curated.csv
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-core.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-package.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-react-exports.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/catalogs/phosphor-react-package.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-baseline.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-cases.json
.agents/skills/ui-ux-pro-max/scripts/tests/fixtures/relevance-thresholds.json
.agents/skills/ui-ux-pro-max/scripts/tests/test_catalog_refresh.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_catalog_summary_line_endings.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_core.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_core_data_quality.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_data_contracts.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_design_system_mode.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_design_system_stack.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_native_desktop_stack_freshness.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_relevance_evaluator.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_skill_script_paths.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_style_taxonomy.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_text_layout_resilience.py
.agents/skills/ui-ux-pro-max/scripts/tests/test_web_stack_freshness.py
.agents/skills/ui-ux-pro-max/scripts/validate_data.py
.firebaserc
.github/workflows/flutter.yml
.gitignore
README.md
apps/api/.env
apps/api/.env.example
apps/api/data/assistant_catalog.json
apps/api/data/catalog.json
apps/api/package-lock.json
apps/api/package.json
apps/api/src/admin-create.mjs
apps/api/src/admin-grant.mjs
apps/api/src/assistant-smoke.mjs
apps/api/src/assistant/actions.mjs
apps/api/src/assistant/catalog.mjs
apps/api/src/assistant/dialogue.mjs
apps/api/src/assistant/engine.mjs
apps/api/src/assistant/openai.mjs
apps/api/src/assistant/runtime.mjs
apps/api/src/assistant/service.mjs
apps/api/src/assistant/types.mjs
apps/api/src/assistant/validation.mjs
apps/api/src/bootstrap-admin.mjs
apps/api/src/database.mjs
apps/api/src/explanations.mjs
apps/api/src/import.mjs
apps/api/src/server.mjs
apps/api/src/smoke.mjs
apps/api/src/worker.mjs
apps/api/src/workspace.mjs
apps/api/test/assistant_core.test.mjs
apps/api/test/assistant_provider.test.mjs
apps/api/test/assistant_runtime.test.mjs
apps/api/test/assistant_service.test.mjs
apps/api/test/backend.test.mjs
apps/api/test/bootstrap-admin.test.mjs
apps/api/test/helpers/assistant_cache.mjs
apps/api/test/http.test.mjs
apps/api/test/seed.test.mjs
apps/api/test/workspace.test.mjs
apps/event_match/.gitignore
apps/event_match/.metadata
apps/event_match/README.md
apps/event_match/analysis_options.yaml
apps/event_match/android/.gitignore
apps/event_match/android/app/build.gradle.kts
apps/event_match/android/app/src/debug/AndroidManifest.xml
apps/event_match/android/app/src/main/AndroidManifest.xml
apps/event_match/android/app/src/main/kotlin/com/example/event_match/MainActivity.kt
apps/event_match/android/app/src/main/res/drawable-v21/launch_background.xml
apps/event_match/android/app/src/main/res/drawable/launch_background.xml
apps/event_match/android/app/src/main/res/mipmap-hdpi/ic_launcher.png
apps/event_match/android/app/src/main/res/mipmap-mdpi/ic_launcher.png
apps/event_match/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
apps/event_match/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
apps/event_match/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
apps/event_match/android/app/src/main/res/values-night/styles.xml
apps/event_match/android/app/src/main/res/values/styles.xml
apps/event_match/android/app/src/profile/AndroidManifest.xml
apps/event_match/android/build.gradle.kts
apps/event_match/android/gradle.properties
apps/event_match/android/gradle/wrapper/gradle-wrapper.properties
apps/event_match/android/settings.gradle.kts
apps/event_match/assets/data/catalog.jsonl
apps/event_match/assets/data/demo.jsonl
apps/event_match/assets/fonts/CormorantGaramond-Italic.ttf
apps/event_match/assets/fonts/CormorantGaramond-OFL.txt
apps/event_match/assets/fonts/Manrope-OFL.txt
apps/event_match/assets/fonts/Manrope.ttf
apps/event_match/assets/fonts/NotoSans-OFL.txt
apps/event_match/assets/fonts/NotoSans.ttf
apps/event_match/assets/images/event-table.jpg
apps/event_match/ios/.gitignore
apps/event_match/ios/Flutter/AppFrameworkInfo.plist
apps/event_match/ios/Flutter/Debug.xcconfig
apps/event_match/ios/Flutter/Release.xcconfig
apps/event_match/ios/Runner.xcodeproj/project.pbxproj
apps/event_match/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
apps/event_match/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
apps/event_match/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
apps/event_match/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
apps/event_match/ios/Runner.xcworkspace/contents.xcworkspacedata
apps/event_match/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
apps/event_match/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
apps/event_match/ios/Runner/AppDelegate.swift
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/AppIcon.appiconset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
apps/event_match/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png
apps/event_match/ios/Runner/Assets.xcassets/LaunchImage.imageset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/LaunchImage.imageset/[email protected]
apps/event_match/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
apps/event_match/ios/Runner/Base.lproj/LaunchScreen.storyboard
apps/event_match/ios/Runner/Base.lproj/Main.storyboard
apps/event_match/ios/Runner/Info.plist
apps/event_match/ios/Runner/Runner-Bridging-Header.h
apps/event_match/ios/Runner/SceneDelegate.swift
apps/event_match/ios/RunnerTests/RunnerTests.swift
apps/event_match/lib/app/account_shell.dart
apps/event_match/lib/app/app.dart
apps/event_match/lib/app/app_theme.dart
apps/event_match/lib/app/communication_scope.dart
apps/event_match/lib/app/design_tokens.dart
apps/event_match/lib/app/firebase_bootstrap.dart
apps/event_match/lib/core/local_api.dart
apps/event_match/lib/features/assistant/data/api_assistant_service.dart
apps/event_match/lib/features/assistant/data/basic_assistant_service.dart
apps/event_match/lib/features/assistant/data/firebase_assistant_service.dart
apps/event_match/lib/features/assistant/domain/assistant_models.dart
apps/event_match/lib/features/assistant/domain/assistant_service.dart
apps/event_match/lib/features/assistant/presentation/assistant_controller.dart
apps/event_match/lib/features/assistant/presentation/assistant_host.dart
apps/event_match/lib/features/assistant/presentation/assistant_screen.dart
apps/event_match/lib/features/assistant/presentation/widgets/assistant_recommendations.dart
apps/event_match/lib/features/auth/data/firebase_auth_gateway.dart
apps/event_match/lib/features/auth/data/local_auth_gateway.dart
apps/event_match/lib/features/auth/domain/auth_gateway.dart
apps/event_match/lib/features/auth/presentation/auth_pages.dart
apps/event_match/lib/features/auth/presentation/session_controller.dart
apps/event_match/lib/features/auth/presentation/settings_page.dart
apps/event_match/lib/features/matching/data/api_catalog_repository.dart
apps/event_match/lib/features/matching/data/api_recommendation_service.dart
apps/event_match/lib/features/matching/data/catalog_repository.dart
apps/event_match/lib/features/matching/data/favorites_repository.dart
apps/event_match/lib/features/matching/data/local_recommendation_service.dart
apps/event_match/lib/features/matching/domain/alternative_dates.dart
apps/event_match/lib/features/matching/domain/catalog_version.dart
apps/event_match/lib/features/matching/domain/explanation_policy.dart
apps/event_match/lib/features/matching/domain/favorites.dart
apps/event_match/lib/features/matching/domain/matching_engine.dart
apps/event_match/lib/features/matching/domain/models.dart
apps/event_match/lib/features/matching/domain/normalization.dart
apps/event_match/lib/features/matching/domain/recommendation_service.dart
apps/event_match/lib/features/matching/presentation/favorites_controller.dart
apps/event_match/lib/features/matching/presentation/favorites_page.dart
apps/event_match/lib/features/matching/presentation/matching_controller.dart
apps/event_match/lib/features/matching/presentation/matching_screen.dart
apps/event_match/lib/features/matching/presentation/selection_presentation.dart
apps/event_match/lib/features/matching/presentation/widgets/ai_explanation.dart
apps/event_match/lib/features/matching/presentation/widgets/alternative_dates_strip.dart
apps/event_match/lib/features/matching/presentation/widgets/catalog_hero.dart
apps/event_match/lib/features/matching/presentation/widgets/contractor_card.dart
apps/event_match/lib/features/matching/presentation/widgets/contractor_details.dart
apps/event_match/lib/features/matching/presentation/widgets/equal_card_grid.dart
apps/event_match/lib/features/matching/presentation/widgets/favorite_folder_picker.dart
apps/event_match/lib/features/matching/presentation/widgets/order_filters.dart
apps/event_match/lib/features/matching/presentation/widgets/recommendation_comparison.dart
apps/event_match/lib/features/matching/presentation/widgets/selection_overview.dart
apps/event_match/lib/features/matching/presentation/widgets/side_panel.dart
apps/event_match/lib/features/messages/messages_panel.dart
apps/event_match/lib/features/planning/data/firestore_event_plan_repository.dart
apps/event_match/lib/features/planning/domain/event_plan.dart
apps/event_match/lib/features/planning/domain/event_plan_engine.dart
apps/event_match/lib/features/planning/domain/event_plan_repository.dart
apps/event_match/lib/features/planning/presentation/event_plan_page.dart
apps/event_match/lib/features/workspace/data/firestore_workspace_repository.dart
apps/event_match/lib/features/workspace/data/local_workspace_repository.dart
apps/event_match/lib/features/workspace/data/workspace_catalog_repository.dart
apps/event_match/lib/features/workspace/domain/workspace_models.dart
apps/event_match/lib/features/workspace/domain/workspace_repository.dart
apps/event_match/lib/features/workspace/presentation/admin_page.dart
apps/event_match/lib/features/workspace/presentation/catalog_page.dart
apps/event_match/lib/features/workspace/presentation/client_page.dart
apps/event_match/lib/features/workspace/presentation/contractor_page.dart
apps/event_match/lib/features/workspace/presentation/workspace_widgets.dart
apps/event_match/lib/firebase_options.dart
apps/event_match/lib/l10n/app_localizations.dart
apps/event_match/lib/l10n/messages.dart
apps/event_match/lib/l10n/messages.json
apps/event_match/lib/main.dart
apps/event_match/pubspec.lock
apps/event_match/pubspec.yaml
apps/event_match/test/advanced_filters_test.dart
apps/event_match/test/ai_explanation_test.dart
apps/event_match/test/alternative_dates_test.dart
apps/event_match/test/api_service_test.dart
apps/event_match/test/assistant_test.dart
apps/event_match/test/assistant_transport_test.dart
apps/event_match/test/assistant_widget_test.dart
apps/event_match/test/auth_session_test.dart
apps/event_match/test/auth_widget_test.dart
apps/event_match/test/catalog_layout_regression_test.dart
apps/event_match/test/catalog_test.dart
apps/event_match/test/client_workspace_test.dart
apps/event_match/test/communication_preview_test.dart
apps/event_match/test/communications_test.dart
apps/event_match/test/contractor_details_test.dart
apps/event_match/test/controller_test.dart
apps/event_match/test/design_preview_test.dart
apps/event_match/test/event_plan_navigation_test.dart
apps/event_match/test/event_plan_test.dart
apps/event_match/test/event_plan_widget_test.dart
apps/event_match/test/explanation_policy_test.dart
apps/event_match/test/favorites_flow_test.dart
apps/event_match/test/favorites_panel_test.dart
apps/event_match/test/favorites_test.dart
apps/event_match/test/favorites_widgets_test.dart
apps/event_match/test/matching_test.dart
apps/event_match/test/pipeline_test.dart
apps/event_match/test/provider_admin_test.dart
apps/event_match/test/selection_comparison_test.dart
apps/event_match/test/selection_handoff_test.dart
apps/event_match/test/widget_test.dart
apps/event_match/test/workspace_domain_test.dart
apps/event_match/tool/audit_catalog.dart
apps/event_match/tool/matching_worker.dart
apps/event_match/web/favicon.png
apps/event_match/web/icons/Icon-192.png
apps/event_match/web/icons/Icon-512.png
apps/event_match/web/icons/Icon-maskable-192.png
apps/event_match/web/icons/Icon-maskable-512.png
apps/event_match/web/index.html
apps/event_match/web/manifest.json
data/catalog.csv
data/catalog.original.jsonl
design-system/event-match/MASTER.md
docs/architecture.md
docs/catalog-seeding.md
docs/design-references.md
docs/development.md
docs/favorites-and-dates.md
docs/feature-integration.md
docs/firebase.md
docs/local-backend.md
docs/match-explanations.md
docs/pipeline.md
docs/product-ideas.md
docs/selection-comparison.md
scripts/audit_catalog.mjs
scripts/import_catalog.py
scripts/seed_catalog.mjs
skills-lock.json
Ветки (11)

Обсуждение 0 комментариев

Войдите, чтобы комментировать

Пока нет комментариев — будьте первым.