AAYMA
RU
Войти

Apex Match

Веб-приложение подбирает до трёх подрядчиков для мероприятия по городу, категории, дате, формату, бюджету, языку и длительности и объясняет, почему…

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

О проекте

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

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

Суть

Веб-приложение подбирает до трёх подрядчиков для мероприятия по городу, категории, дате, формату, бюджету, языку и длительности и объясняет, почему подходит каждый и почему отсеяны остальные.

Как устроено

Каталог из 66 профилей в 17 категориях (catalog.csv) вместе с фактами из описаний (facts.json с хешем исходного текста) импортируется в PostgreSQL транзакционно. Go-бэкенд нормализует запрос, берёт профили с совпадающими городом и категорией и проверяет ограничения по порядку: формат, бюджет, язык, длительность, занятость. Подходящие профили сортируются по price_from_kzt и id, возвращаются первые три. Объяснения собираются из шаблонов и проверенных фактов без LLM, для каждого отсеянного кандидата указана причина. Есть альтернативы при пустом результате и локализация RU/KK/EN.

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

  • deterministic filter funnel
  • constraint checking
  • template explanations with verified facts
  • exclusion diagnostics
  • no-match alternatives

Особенности

Задеплоено на testrr.shop, есть админ-панель с импортом CSV и журналом аудита. Факты для объяснений привязаны к хешу описания, поэтому устаревший факт не проходит импорт. Результат детерминирован: один и тот же запрос даёт один и тот же порядок, а воронка отсева видна пользователю. Судя по раннему коммиту, команда сначала изучала кейс 8 (ассистент совещаний).

Стек

Go · net/http · pgx · PostgreSQL · React · TypeScript · Vite · Zod · Vitest · Docker Compose · Nginx · systemd


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

README

README.md

Apex Match — Event Vendor Matching

English | Русский

Deployment: English · Русский

Apex Match is a web application built by Apex-AI for HackAlem AI. It helps event organizers find up to three suitable vendors based on city, category, date, event format, budget, language, and working duration. Each result includes a starting price and an explanation of why the profile matches.

Live website: testrr.shop · API reference data: catalog · API status: health

This overview reflects the project as of September 23, 2026. The public frontend and Go backend are deployed and connected through the live API. The baseline catalog contains 66 profiles across 17 categories, with calendar data covering September 23–December 31, 2026.

Contents

Purpose and features

Event organizers need to compare their requirements against information spread across vendor profiles. Apex Match makes that selection reproducible and explains the outcome.

After completing the form and running a search, users receive:

  • Up to three catalog cards with starting prices, working-hour limits, and explanations.
  • The total number of eligible profiles before the three-card limit is applied.
  • Reasons for excluding other candidates: event format, budget, language, duration, or availability.
  • Distinct messages when a city has no vendors in the selected category and when existing vendors do not meet the requirements.
  • Labels identifying synthetic profiles and values filled in during dataset preparation.
  • Field-level validation messages, plus separate loading, technical-error, and retry states.

The interface includes five quick scenarios. They populate the form; the user then starts the search with «Найти подрядчиков» (Find vendors). Each request covers one category and one vendor; the budget is not distributed across all services for an event.

How matching works

  1. The backend validates JSON, required fields, types, and the supported date window.
  2. It selects profiles whose normalized city and category match exactly. Normalization handles Unicode, case, and extra whitespace.
  3. It checks constraints in this order: event format → budget → language → duration → availability.
  4. It sorts eligible profiles by price_from_kzt ASC, then id ASC, and returns the first three.
  5. It builds explanations from the request conditions, structured data, and verified excerpts from profile descriptions.

When a profile fails several checks, the public diagnostics count it at the first failed step. Conditions are never relaxed automatically, and ineligible profiles are not added to fill three cards. The same catalog version and normalized request produce the same results in the same order.

A price equal to the budget and a duration equal to the working-hour limit are allowed. If language or duration is omitted, the corresponding check is skipped. max_hours: null means the working-hour limit does not apply.

Data and explanations

The source dataset is stored in backend/data/catalog.csv. It contains 66 anonymized profiles, including 13 synthetic profiles already present in the supplied data.

AttributeValue
GeographyAlmaty, Astana, and «Зарубежье» (Abroad), a source-dataset grouping
Categories17, including hosts, photographers, videographers, venues, florists, and others
Event formatsWedding, toi, corporate event, conference, anniversary, birthday
LanguagesRussian, Kazakh, English
CurrencyKazakhstani tenge, KZT
Calendar window2026-09-23 through 2026-12-31, inclusive
Explanation facts66 profile features and 2 conditions requiring confirmation

backend/data/catalog.meta.json defines the calendar window. backend/data/facts.json links statements to a profile ID, a quotation, and a hash of the source description. If a description changes, outdated facts fail import validation.

The current implementation does not make online LLM calls. Explanations are assembled from templates and prepared facts. Model API keys, training, embeddings, and a vector database are not required. Verifying that a fact matches a description is not an independent verification of a vendor's advertising claim.

The starting price applies to the event, is not multiplied by hours, and is not a final quote. A date missing from the busy-date list means only that it is not marked busy in the dataset; it does not confirm real availability or a booking.

Technology and architecture

ComponentTechnologies
FrontendReact 19, TypeScript, Vite, CSS
API response validationZod
Frontend testsVitest, Testing Library, jsdom
BackendGo 1.25+, net/http, pgx/v5
Admin panelSeparate Go module, embedded HTML/CSS/JavaScript, bcrypt, PostgreSQL sessions
StoragePostgreSQL 16+; local Compose uses PostgreSQL 16
Backend testsGo testing, race detector, PostgreSQL integration
Local infrastructureDocker Compose
ProductionUbuntu, Nginx, HTTPS, systemd, PostgreSQL
Browser → Nginx / HTTPS → React frontend
                     ├─ /api/* → Go matching API → PostgreSQL
                     └─ /admin/* → Go admin service → same PostgreSQL

CSV + metadata + facts → catalog CLI → validation → migrations / import → PostgreSQL

The frontend sends requests and displays backend responses; it does not independently filter or reorder vendors. The API reads a consistent catalog snapshot from PostgreSQL and verifies its integrity. Import validates the entire dataset before replacing the catalog in a single transaction. A failed import preserves the previous snapshot.

The catalog is small, so there is no separate Redis instance, queue, or persistent cache. The public interface uses built-in form options. The metadata endpoint is available, but the frontend does not yet load those options dynamically.

Repository structure

.
├── README.md                        # project overview in English
├── README.ru.md                     # project overview in Russian
├── TECH_SPEC.md                      # original requirements and acceptance criteria
├── ARCHITECTURE.md                   # architecture and solution contract
├── admin_panel/                    # authenticated catalog management, CSV preview, audit log
├── backend/
│   ├── cmd/server/                  # HTTP server
│   ├── cmd/catalog/                 # catalog validation, migrations, and import
│   ├── internal/                    # models, matching, HTTP, PostgreSQL, configuration
│   ├── data/                        # CSV, calendar metadata, facts
│   ├── examples/                    # request and response examples
│   ├── scripts/smoke.sh             # HTTP smoke checks
│   ├── compose.yaml                 # local database, initialization, and API
│   ├── Dockerfile
│   ├── Makefile
│   ├── ENDPOINT.MD                  # full HTTP contract
│   ├── TESTING.md                   # backend testing
│   └── README.md
└── frontend/
    ├── src/api/                     # HTTP/mock adapters, contracts, and schemas
    ├── src/app/                     # application configuration
    ├── src/features/recommendations/ # form, cards, states, and tests
    ├── src/shared/                  # shared components and formatting
    ├── src/styles/                  # styles
    ├── .env.example
    ├── .env.production              # live API on the same origin
    ├── package.json
    └── README.md

The repository also includes a separate admin panel at testrr.shop/admin/. It supports authenticated catalog search, manual creation and editing, deletion, CSV preview and import, export, and an audit log. It shares PostgreSQL with the public API, so saved changes are reflected in subsequent searches. Setup and API details are documented in the admin panel directory.

Local quick start

You need Git, Docker with Compose v2, and Node.js 24+ with npm. Go 1.25+ is required to run or test the backend outside Docker. Access to the private GitHub repository is required.

1. Get the project

git clone https://github.com/BAITC-Hacks/hack-1ad72463-apex-ai.git
cd hack-1ad72463-apex-ai

2. Start the backend and PostgreSQL

From the repository root:

cd backend
docker compose up --build -d
curl --fail http://localhost:8080/readyz
sh scripts/smoke.sh

Compose starts the database, applies migrations and imports the catalog through a one-off init service, then starts the API. The API is available at http://localhost:8080, and PostgreSQL at 127.0.0.1:54329. Database files are persisted in backend/.tmp/postgres-compose.

3. Start the frontend

In another terminal, from the repository root:

cd frontend
npm ci
cat > .env.local <<'ENV'
VITE_API_MODE=http
VITE_API_BASE_URL=http://localhost:8080
ENV
npm run dev -- --host 127.0.0.1 --port 5173 --strictPort

Open localhost:5173. The backend configuration allows the http://localhost:5173 origin, so use that exact browser address. In this mode, the interface calls the local API.

Standalone demo without a backend

Set VITE_API_MODE=mock in frontend/.env.local and restart Vite. The interface displays a DEMO / MOCK API label. Mock mode uses prepared scenarios, does not perform a real catalog search, and does not replace integration testing with PostgreSQL.

Run the backend with Go

From backend, with Go installed and Docker available:

docker compose up -d db
cp .env.example .env
set -a
. ./.env
set +a
make deps
make bootstrap
make run

This replaces running the API through Compose. If the Compose API already occupies port 8080, run docker compose stop api first. The application does not load .env automatically, so export the variables as shown above.

To stop Compose, run docker compose down from backend. Database files are retained.

Admin panel

Open testrr.shop/admin/ to manage the shared catalog. Access requires an administrator account. The panel supports manual creation, full-record editing, deletion, CSV preview and import, CSV export, a blank template, and the latest 50 audit events. Vendor IDs are immutable; deleting the last profile is blocked.

Local setup and first login

First initialize the backend catalog using the quick-start instructions above. In another terminal, from the repository root:

cd admin_panel
cp .env.example .env
set -a
. ./.env
set +a
make build
bin/admin init
bin/admin serve

The supplied configuration uses the same local database as the backend. Open 127.0.0.1:18081/admin/; the exact origin must match ADMIN_ORIGIN. The admin service is not included in the backend Compose file. Keep the backend and admin_panel directories next to each other because the Go module uses replace ../backend.

init creates admin tables and the admin account without replacing the catalog. It prints a random temporary password once. There is no shared default password. Repeating init preserves an existing account. On first login, change the temporary password, then sign in again. Password changes revoke all sessions; sessions otherwise expire after eight hours. Account creation and role management are not exposed in the UI.

Catalog changes and CSV

Download the template or export from the panel to obtain the 13-column CSV format. Use UTF-8, comma-separated columns, and | inside list fields, such as русский|английский. The upload limit is 5 MiB per multipart request and 5,000 records per file. Manual and CSV input use the same catalog validation rules.

Preview the file before applying it. By default, only new IDs may be imported; any existing ID rejects the entire import. Selecting update existing records allows those profiles to be replaced in full. Profiles absent from the file are retained. Preview is a validation step, not a reservation: a concurrent catalog change requires a new preview.

Changes use a catalog revision (ETag / If-Match) to prevent overwriting another administrator's work. A successful transaction saves the catalog and audit event together. New matching requests see committed changes without restarting the public API. Editing a description removes its outdated explanation facts; new facts are not generated automatically. Changes live in PostgreSQL and do not rewrite repository CSV files.

The public frontend still uses built-in city/category options. Adding a new city or category in the panel updates API metadata but does not automatically add an option to that form. The three-result limit and price/ID sorting remain unchanged.

See the admin guide, admin API, test guide, and deployment guide.

Configuration

Backend

VariablePurpose
DATABASE_URLPostgreSQL DSN; required for the server, migrations, and import
HTTP_ADDRHTTP server address; defaults to :8080
CORS_ORIGINSComma-separated allowed origins; locally http://localhost:3000,http://localhost:5173
CATALOG_CSVCatalog file for the CLI; defaults to data/catalog.csv
CATALOG_METACalendar metadata; defaults to data/catalog.meta.json
CATALOG_FACTSFacts file; - disables additional facts during import
TEST_DATABASE_URLSeparate connection for integration tests

Example: backend/.env.example. The password in the local Compose configuration is for development only.

Admin service

VariablePurpose
DATABASE_URLSame database as the matching API
ADMIN_ADDRListen address, default 127.0.0.1:18081
ADMIN_ORIGINExact browser origin without a path; default https://testrr.shop
ADMIN_INSECURE_HTTPtrue only for local loopback HTTP; production uses secure cookies
ADMIN_TRUST_PROXYTrust Nginx X-Real-IP only when the service and peer use loopback
ADMIN_INITIAL_PASSWORDOptional initial password for init; omit to generate one

Frontend

VariablePurpose
VITE_API_MODEhttp for the live API; mock for standalone fixtures
VITE_API_BASE_URLBackend root URL or a URL ending in /api

Production configuration: VITE_API_MODE=http, VITE_API_BASE_URL=/api. Requests go to POST /api/recommendations on the same domain.

Vite variables are embedded at build time. Rebuild the frontend after changing the API address. Before a production build, remove local overrides from .env.local or explicitly set the production values in the environment. VITE_* variables are visible in the browser and must not contain secrets.

HTTP API

MethodBackend pathPurpose
POST/api/recommendationsFind up to three suitable vendors
GET/api/catalog/metaReference data, versions, and calendar window
GET/healthzHTTP process liveness
GET/readyzDatabase availability and catalog integrity
GET/metricsHTTP counters and latency metrics in Prometheus format

In production, Nginx also exposes GET /api as an alias for /api/catalog/meta and GET /api/health as a readiness check mapped to /readyz. The internal /healthz, /readyz, and /metrics paths are not directly proxied to the public Internet.

Example request to the deployed service. Keep the Russian catalog values shown below: translating the documentation does not change the API's accepted values.

curl --fail-with-body https://testrr.shop/api/recommendations \
  -H 'Content-Type: application/json' \
  -d '{
    "city": "Алматы",
    "date": "2026-11-14",
    "event_format": "корпоратив",
    "category": "Ведущий",
    "budget_kzt": 1000000,
    "duration_hours": 6,
    "language": "русский"
  }'

Required fields: city, date, event_format, category, and budget_kzt. Language and duration may be omitted or set to null. The response contains status, message, results, diagnostics, and metadata.

OutcomeHTTPMeaning
MATCHES_FOUND200Eligible profiles were found
NO_CATALOG200No profiles exist in the selected city and category
NO_MATCH200Profiles exist, but all were excluded by the conditions
VALIDATION_ERROR422Request field validation failed
CATALOG_UNAVAILABLE503The database or catalog is not ready

Business outcomes and errors use different response structures. See backend/ENDPOINT.MD for the full contract, additional error codes, and examples.

Demo scenarios

Baseline request: Almaty, host, corporate event, 2026-11-14, budget 1,000,000 ₸, Russian, 6 hours.

ScenarioChange from the baselineExpected result with the original catalog
Popular requestNone4 eligible profiles; returns HK-44923, HK-29829, HK-27222
Busy dateDate 2026-12-191 card: HK-35215
Rare categoryFlorist, wedding, budget 300,000 ₸1 card: HK-90001, a synthetic profile
No matchesBudget 100,000 ₸NO_MATCH
No categoryAstana, decoratorNO_CATALOG

These expectations apply to the original dataset version. Results may change when the catalog is updated.

Testing

Frontend, from frontend:

npm ci
npm run test:run
npm run build

Tests cover the form, result cards, distinct empty states, synthetic-profile labels, starting prices, correct handling of max_hours: null, and 422/503 errors. The build also checks TypeScript.

Backend, from backend:

make test
make check
make build
make benchmark

Integration tests require a real PostgreSQL instance and TEST_DATABASE_URL:

export TEST_DATABASE_URL='postgres://hackalem:[email protected]:54329/hackalem?sslmode=disable'
make test-integration

Integration tests create a unique schema, verify migrations, import, rollback, concurrent reads, catalog corruption, and database failures, then remove that test schema. PostgreSQL checks in the general test run are skipped when TEST_DATABASE_URL is not set.

During deployment on September 23, 2026, all 8 frontend tests, the production build, HTTP checks for five business scenarios, and browser checks against the live API passed. These are results from a specific run, not a continuous CI status. See TESTING.md for backend details.

Admin tests run separately from the backend module. From admin_panel, with TEST_DATABASE_URL pointing to a test database, run make test check. Without it, database integration tests are skipped. See admin_panel/TESTING.md for coverage and a manual verification procedure.

Deployment and operations

The live website is testrr.shop. Nginx serves the static frontend build and proxies /api/* to the Go service at 127.0.0.1:18080. PostgreSQL and the application port are not exposed to the Internet. HTTPS uses a Let's Encrypt certificate with automatic renewal; HTTP and www redirect to the canonical HTTPS address.

ComponentCurrent location
Frontend/opt/hackalem/frontend/current, a symlink to a release directory
Backend/opt/hackalem/backend/current
Backend servicehackalem-backend.service
Backend environment/etc/hackalem/backend.env
Admin release / service/opt/hackalem/admin_panel/current / hackalem-admin.service
Admin environment / port/etc/hackalem/admin.env / 127.0.0.1:18081
Website configuration/etc/nginx/sites-available/testrr.shop
Production PostgreSQL18.6; database hackalem

Build the production frontend from frontend:

npm ci
VITE_API_MODE=http VITE_API_BASE_URL=/api npm run build

To update the frontend, upload the contents of frontend/dist into a new release directory and switch the current symlink atomically. Preserve the Nginx /admin/ proxy, API routes, SPA fallback to index.html, HTTPS settings, and ACME configuration. index.html uses no-cache; hashed files under /assets/ use long-lived caching. Retain previous releases and configuration backups for rollback.

Update the catalog through local Compose, from backend:

docker compose build
docker compose run --rm init
docker compose up -d api

The catalog check|migrate|import|bootstrap CLI validates and loads files. CLI import replaces the entire catalog rather than adding a single record. The admin panel offers a separate incremental CSV workflow with a preview: existing IDs are updated only when explicitly selected, and records absent from the uploaded file are retained. Back up the database before a production update. Direct table edits can break integrity checks; use the supported import workflow.

Check the production API:

curl --fail https://testrr.shop/api/health
curl --fail https://testrr.shop/api/catalog/meta

On the server, use systemctl status hackalem-backend hackalem-admin nginx and journalctl -u hackalem-backend. The backend writes JSON logs with request IDs, status codes, duration, catalog versions, and matching outcomes. Process metrics reset on restart.

Limitations and future work

The current MVP does not handle bookings, payments, messages to vendors, or verification of their actual availability. The public matching API does not require authentication. Catalog CRUD and CSV uploads are handled by the separate authenticated admin panel, not by the public matching API.

Only dates within the source calendar window are supported. There is no free-text search, semantic ranking, reviews, quality scoring, automatic budget expansion, service-bundle selection, or calendar synchronization. Price sorting is a transparent MVP rule, not a measure of professional quality.

Future work includes extending the admin panel, loading form options dynamically, updating the calendar, adding typed constraints, and evaluating relevance against labeled scenarios. Semantic ranking can be introduced separately among profiles that already satisfy all mandatory constraints.

Documentation

The detailed documents linked below are currently in Russian.

Authors

  • Sanzhar Serikbayev (Серикбаев Санжар) — Fullstack developer
  • Alina Kumarova (Құмарова Алина) — Analyst / QA tester
  • Viktor Babanov (Бабанов Виктор) — Frontend developer
Звёзды
⭐ 0
Форки
0
Язык
Go
Последний push
в прошлом месяце
Коммиты
30
Авторы
4
Файлы
108
Ветки
8

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

Zerodemokrg 18Your Name 7alina08-12 4Zerodemokrg 1

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

  • 2026-09-23 17:56docs: add detailed English and Russian deployment and recovery guidesZerodemokrg
  • 2026-09-23 17:54Add project short descriptionalina08-12
  • 2026-09-23 17:46Merge backend alternatives and RU/KK/EN response localizationZerodemokrg
  • 2026-09-23 17:46Merge main into backend branch and preserve both documentation updatesZerodemokrg
  • 2026-09-23 17:43docs(backend): isolate localization documentationZerodemokrg
  • 2026-09-23 17:43feat(frontend): add explainability funnel and localizationYour Name
  • 2026-09-23 17:42feat(backend): localize recommendation responsesZerodemokrg
  • 2026-09-23 17:40feat(frontend): add explainability funnel and localizationYour Name
Все коммиты (30)
  • 2026-09-23 17:35Merge main into backend alternatives branchZerodemokrg
  • 2026-09-23 17:33docs: document admin workflows, API, architecture, testing and deploymentZerodemokrg
  • 2026-09-23 17:22feat(frontend): add actionable no-match alternativesYour Name
  • 2026-09-23 17:19feat(frontend): add actionable no-match alternativesYour Name
  • 2026-09-23 17:18feat(backend): add actionable no-match alternativesZerodemokrg
  • 2026-09-23 17:18fix: use half-hour increments for admin duration inputZerodemokrg
  • 2026-09-23 17:14docs: make English README default and add Russian translationZerodemokrg
  • 2026-09-23 17:09feat: add authenticated catalog admin panel with CSV preview and transactional moderationZerodemokrg
  • 2026-09-23 16:58docs: add complete Apex Match project overview and setup guideZerodemokrg
  • 2026-09-23 16:44feat(frontend): add public contractor matching appYour Name
  • 2026-09-23 16:38Update README.mdZerodemokrg
  • 2026-09-23 16:37docs: add project authors to root READMEZerodemokrg
  • 2026-09-23 16:28feat(frontend): build contractor recommendation experienceYour Name
  • 2026-09-23 16:11Implement Go and PostgreSQL contractor recommendation backendZerodemokrg
  • 2026-09-23 16:05docs: define contractor matching MVP and delivery roadmapYour Name
  • 2026-09-23 15:59Merge pull request #2 from BAITC-Hacks/tech_specZerodemokrg
  • 2026-09-23 15:58Update Go and PostgreSQL specificationsalina08-12
  • 2026-09-23 15:40Merge pull request #1 from BAITC-Hacks/tech_specZerodemokrg
  • 2026-09-23 15:39Merge remote-tracking branch 'origin/main' into tech_specalina08-12
  • 2026-09-23 15:32Add architecture and technical specificationalina08-12
  • 2026-09-23 15:12docs: add bilingual meeting assistant research and implementation planZerodemokrg
  • 2026-09-23 13:23Update README.mdZerodemokrg
Структура репозитория (108 файлов)
ARCHITECTURE.md
DEPLOY.MD
DEPLOY.ru.MD
README.md
README.ru.md
SHORT_DESCRIPTION.MD
TECH_SPEC.md
admin_panel/.env.example
admin_panel/.gitignore
admin_panel/ENDPOINT.MD
admin_panel/Makefile
admin_panel/README.md
admin_panel/TESTING.md
admin_panel/cmd/admin/main.go
admin_panel/deploy/README.md
admin_panel/deploy/admin.env.example
admin_panel/deploy/hackalem-admin.conf
admin_panel/deploy/hackalem-admin.service
admin_panel/go.mod
admin_panel/go.sum
admin_panel/internal/app/auth.go
admin_panel/internal/app/server.go
admin_panel/internal/app/server_test.go
admin_panel/internal/app/web/app.js
admin_panel/internal/app/web/index.html
admin_panel/internal/app/web/style.css
backend/.dockerignore
backend/.env.example
backend/.gitignore
backend/Dockerfile
backend/ENDPOINT.MD
backend/Makefile
backend/README.md
backend/TESTING.md
backend/catalogadmin/service.go
backend/cmd/catalog/main.go
backend/cmd/server/main.go
backend/compose.yaml
backend/data/catalog.csv
backend/data/catalog.meta.json
backend/data/facts.json
backend/examples/recommendation-request.json
backend/examples/recommendation-response.json
backend/go.mod
backend/go.sum
backend/internal/catalog/loader.go
backend/internal/catalog/loader_test.go
backend/internal/config/config.go
backend/internal/domain/alternatives.go
backend/internal/domain/model.go
backend/internal/httpapi/alternatives_test.go
backend/internal/httpapi/i18n_test.go
backend/internal/httpapi/request.go
backend/internal/httpapi/server.go
backend/internal/httpapi/server_test.go
backend/internal/i18n/i18n.go
backend/internal/i18n/i18n_test.go
backend/internal/matching/alternatives.go
backend/internal/matching/alternatives_test.go
backend/internal/matching/i18n_test.go
backend/internal/matching/service.go
backend/internal/matching/service_test.go
backend/internal/matching/text.go
backend/internal/postgres/migrations/001_catalog.sql
backend/internal/postgres/store.go
backend/internal/postgres/store_integration_test.go
backend/scripts/smoke.sh
frontend/.env.example
frontend/.env.production
frontend/.gitignore
frontend/README.md
frontend/index.html
frontend/package-lock.json
frontend/package.json
frontend/src/api/contracts.ts
frontend/src/api/errors.ts
frontend/src/api/httpRecommendationGateway.test.ts
frontend/src/api/httpRecommendationGateway.ts
frontend/src/api/mockRecommendationGateway.ts
frontend/src/api/recommendationGateway.ts
frontend/src/api/schemas.ts
frontend/src/app/App.tsx
frontend/src/app/config.ts
frontend/src/features/recommendations/AlternativeSuggestions.tsx
frontend/src/features/recommendations/ContractorCard.tsx
frontend/src/features/recommendations/DemoPresets.tsx
frontend/src/features/recommendations/DiagnosticsPanel.test.tsx
frontend/src/features/recommendations/DiagnosticsPanel.tsx
frontend/src/features/recommendations/EmptyState.tsx
frontend/src/features/recommendations/ErrorState.tsx
frontend/src/features/recommendations/LoadingState.tsx
frontend/src/features/recommendations/RecommendationForm.tsx
frontend/src/features/recommendations/RecommendationPage.test.tsx
frontend/src/features/recommendations/RecommendationPage.tsx
frontend/src/features/recommendations/ResultsPanel.tsx
frontend/src/i18n/LocaleContext.test.tsx
frontend/src/i18n/LocaleContext.tsx
frontend/src/i18n/format.ts
frontend/src/i18n/translations.ts
frontend/src/main.tsx
frontend/src/shared/ui/Field.tsx
frontend/src/styles/globals.css
frontend/src/test/setup.ts
frontend/src/vite-env.d.ts
frontend/tsconfig.app.json
frontend/tsconfig.json
frontend/tsconfig.node.json
frontend/vite.config.ts
Ветки (8)

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

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

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