diff --git a/DEPLOY_GUIDE.md b/DEPLOY_GUIDE.md deleted file mode 100644 index dbd29d6..0000000 --- a/DEPLOY_GUIDE.md +++ /dev/null @@ -1,106 +0,0 @@ -# Mnemo Cards Deployment Guide - -This guide describes how to deploy the Mnemo Cards project (Backend + Web App) using the CI/CD scripts. - -## Overview - -The deployment strategy is designed to optimize resource usage: -- **Backend**: Built directly on the server (saves bandwidth, ensures environment compatibility). -- **Web App**: Built on the client (your machine), then static files are transferred to the server (saves server RAM). - -## Prerequisites - -1. **SSH Access**: You must have SSH access to the server `147.45.152.129` as `root`. - - Ensure your public SSH key is added to `~/.ssh/authorized_keys` on the server. - - You can verify access by running: `ssh root@147.45.152.129` - -2. **Flutter Installed**: You need Flutter installed on your local machine to build the web app. - -3. **Rsync**: Ensure `rsync` is installed on your local machine (usually pre-installed on macOS/Linux). - -## Project Structure - -- `deploy_all.sh`: Master script to trigger deployments. -- `mnemo_cards_web_v2/deploy.sh`: Script to build and deploy the web app. -- `tools/deploy/backend/deploy_remote.sh`: Script to trigger the backend build on the server. -- `tools/deploy/web-app/config.sh`: Configuration for web deployment (server IP, paths, ports). - -## Forgejo CI/CD Setup - -The project includes a workflow `.forgejo/workflows/deploy.yaml` to automate deployment via Forgejo Actions. - -### Why SSH? -Even though Forgejo runs on the same server, the Actions runner usually executes jobs inside isolated Docker containers (like `ubuntu-latest`). To modify files or restart services on the **host** machine (the server itself), the runner needs to "break out" of the container. We use SSH for this because it's secure and standard. - -### Secrets Configuration -To enable the workflow, go to your repository on Forgejo: **Settings -> Actions -> Secrets** and add the following: - -| Secret Name | Value | Description | -|-------------|-------|-------------| -| `SSH_HOST` | `147.45.152.129` | The public IP of your server. | -| `SSH_USER` | `root` | The user to log in as (must have permissions to restart services). | -| `SSH_KEY` | *(Your Private Key)* | The content of your private SSH key (e.g., `~/.ssh/id_rsa`). | - -> **Tip**: You can generate a new key pair specifically for CI/CD if you prefer not to use your personal one: -> `ssh-keygen -t ed25519 -C "ci-cd"` -> Then add the public key to `~/.ssh/authorized_keys` on the server. - -### Runner Installation (Reference) -The Forgejo runner (`act_runner`) has been installed on the server to execute the workflows. -- **Service**: `act_runner.service` -- **User**: `root` (required for Docker/SSH access) -- **Config**: Registered with tag `ubuntu-latest` to match the workflow. - -If you ever need to restart it: -```bash -systemctl restart act_runner -``` - -## How to Deploy - -### Option 1: Via Forgejo UI (Recommended) -1. Go to your repository in Forgejo. -2. Click on the **Actions** tab. -3. Select **Deploy Mnemo Cards** from the left sidebar. -4. Click the **Run workflow** button (dropdown). -5. Select the branch (usually `master`) and click **Run workflow**. - -### Option 2: Via Command Line (Manual) -If you want to run scripts manually without Forgejo Actions: - -#### Full Deployment (Backend + Web) - -To deploy both the backend and the web application, run: - -```bash -./deploy_all.sh -``` - -### 2. Web Only Deployment - -If you only made changes to the frontend: - -```bash -./deploy_all.sh --web-only -``` - -### 3. Backend Only Deployment - -If you only made changes to the backend: - -```bash -./deploy_all.sh --backend-only -``` - -## Troubleshooting - -- **Permission Denied (SSH)**: Check your SSH keys. Ensure you can login to `root@147.45.152.129` without a password prompt (using keys). -- **Build Failed (Web)**: Run `flutter doctor` to ensure your local environment is correct. Try running `flutter build web --release` manually in `mnemo_cards_web_v2` to see detailed errors. -- **Backend Not Restarting**: SSH into the server and check logs: `journalctl -u mnemo_cards_server -f`. -- **Port Conflicts**: The web app is configured to talk to the API on standard HTTPS port `443` via `https://api.mnemo-cards.online`. nginx handles SSL termination and proxies to backend on port `8081`. - -## Configuration - -To change server IP, ports, or paths, edit: -- `tools/deploy/web-app/config.sh` -- `tools/deploy/backend/deploy_remote.sh` diff --git a/mnemo_cards_backend/lib/api/v2/authorize_v2.dart b/mnemo_cards_backend/lib/api/v2/authorize_v2.dart index 1f6af19..7eee4d8 100644 --- a/mnemo_cards_backend/lib/api/v2/authorize_v2.dart +++ b/mnemo_cards_backend/lib/api/v2/authorize_v2.dart @@ -6,6 +6,8 @@ const _publicAuthPaths = { '/auth/oauth/google', '/auth/oauth/telegram', '/auth/telegram/generate-code', // Bot endpoint for generating codes + '/auth/telegram/web-code', // Web app endpoint for creating auth codes + '/auth/telegram/claim-code', // Bot endpoint for claiming web codes '/auth/refresh', '/tests', '/test', @@ -46,6 +48,11 @@ Middleware authorizeV2(UserManager userManager, JwtService jwtService) { // Auth endpoints in public list are accessible without token return await innerHandler(request); } + // Check for dynamic auth paths (e.g., /auth/telegram/code-status/) + if (normalizedPath.startsWith('/auth/telegram/code-status/')) { + // Code status endpoint is public (used before authentication) + return await innerHandler(request); + } } final isStrictAuthPath = diff --git a/mnemo_cards_web_v2/API_V2_MIGRATION.md b/mnemo_cards_web_v2/API_V2_MIGRATION.md deleted file mode 100644 index 441132c..0000000 --- a/mnemo_cards_web_v2/API_V2_MIGRATION.md +++ /dev/null @@ -1,87 +0,0 @@ -# API v2 Migration Guide - -## Status: In Progress - -The web app is being migrated to use API v2 exclusively. API v2 provides: -- Standard OAuth2/JWT Bearer token authentication -- RESTful endpoint patterns -- Better error handling with standard HTTP status codes -- Token refresh mechanism - -## Backend Implementation Status - -### ✅ Completed -- [x] Created `AuthApiV2` with OAuth2 endpoints -- [x] Created `JwtService` for token generation/verification -- [x] Created `authorizeV2` middleware for Bearer token auth -- [x] Created `PacksApiV2` basic structure -- [x] Mounted v2 APIs at `/api/v2` path -- [x] Separated v1 and v2 authorization middleware - -### ⚠️ Needs Completion -- [ ] Fix JwtService HMAC-SHA256 implementation (use proper crypto library) -- [ ] Complete PacksApiV2 endpoints implementation -- [ ] Implement TestsApiV2 -- [ ] Implement GamesApiV2 -- [ ] Implement PurchasesApiV2 -- [ ] Implement SubscriptionsApiV2 -- [ ] Implement PromocodesApiV2 -- [ ] Add comprehensive error responses -- [ ] Add API documentation (OpenAPI/Swagger) - -## Web App Implementation Status - -### ✅ Completed -- [x] Created `ApiConfigV2` with all v2 endpoints -- [x] Created `HttpRepositoryV2` with Bearer token auth -- [x] Updated `StorageModule` to use HttpRepositoryV2 -- [x] Updated `AuthService` to use HttpRepositoryV2 -- [x] Updated dependency injection to use v2 - -### ⚠️ Needs Completion -- [x] Update `GamesManager` to use HttpRepositoryV2 -- [x] Update `TestManager` to use HttpRepositoryV2 -- [ ] Update `StatisticsService` to use HttpRepositoryV2 -- [x] Update `SubscriptionService` to use HttpRepositoryV2 -- [x] Update `PromocodeService` to use HttpRepositoryV2 -- [ ] Update `PackProgressService` to use HttpRepositoryV2 -- [ ] Write unit tests for HttpRepositoryV2 -- [ ] Update integration tests - -## Backend Endpoints - -### Authentication (`/api/v2/auth`) -- `POST /api/v2/auth/oauth/google` - Google OAuth -- `POST /api/v2/auth/refresh` - Refresh access token -- `GET /api/v2/auth/me` - Get current user -- `POST /api/v2/auth/logout` - Logout - -### Packs (`/api/v2/packs`) -- `GET /api/v2/packs` - List packs (with pagination) -- `GET /api/v2/packs/{packId}` - Get pack details -- `GET /api/v2/packs/{packId}/cards` - Get pack cards -- `GET /api/v2/packs/{packId}/cards/{cardId}/image` - Get card image -- `GET /api/v2/packs/{packId}/tests` - Get pack tests - -### Tests (`/api/v2/tests`) -- `GET /api/v2/tests/{testId}` - Get test -- `POST /api/v2/tests/{testId}/results` - Submit results -- `GET /api/v2/tests/{testId}/history` - Get attempt history - -## Migration Steps - -1. **Backend**: Complete JWT implementation and all v2 endpoints -2. **Web App**: Update all services to use HttpRepositoryV2 -3. **Testing**: Write comprehensive tests for v2 endpoints -4. **Deployment**: Deploy backend v2 endpoints -5. **Verification**: Test end-to-end with web app -6. **Deprecation**: Mark v1 APIs as deprecated (keep for mobile app) - -## Next Steps - -1. Fix JWT service to use proper crypto library -2. Complete backend v2 endpoint implementations -3. Update web app services to use HttpRepositoryV2 methods -4. Write tests -5. Deploy and verify - diff --git a/mnemo_cards_web_v2/CHAT_PLAN.md b/mnemo_cards_web_v2/CHAT_PLAN.md deleted file mode 100644 index 03a7a05..0000000 --- a/mnemo_cards_web_v2/CHAT_PLAN.md +++ /dev/null @@ -1,318 +0,0 @@ -# План реализации чата в mnemo_cards_web_v2 - -## 📋 Обзор - -Добавление функциональности чата для общения пользователя с LLM через сервер. Поддержка текста и аудио сообщений (включая голосовые). - -**Дата создания:** November 8, 2025 -**Приоритет:** HIGH -**Оценка времени:** 60-80 часов -**Архитектура:** Clean Architecture, yx_scope/yx_state - ---- - -## 🎯 Цели проекта - -1. **Чат с LLM** - Общение пользователя с ИИ через сервер -2. **Поддержка медиа** - Текст и аудио (включая голосовые сообщения) -3. **Чистая архитектура** - Соблюдение паттернов проекта -4. **Адаптивный UI** - Работа на всех устройствах -5. **Реактивное состояние** - State management через yx_state - ---- - -## 📁 Архитектурный обзор - -### Clean Architecture слои: -``` -├── domain/ -│ ├── models/ # ChatMessage, AudioMessage, ChatSession -│ ├── services/ # ChatService, AudioService -│ └── state/ # ChatStateManager -├── presentation/ -│ ├── pages/ # ChatPage -│ └── widgets/ # MessageBubble, AudioPlayer, etc. -└── di/ - └── user_scope/ - └── modules/ # ChatModule -``` - ---- - -## 📋 Детальный план реализации - -### Фаза 1: Инфраструктура и модели данных (12-16 часов) - -#### 1.1 Модели данных (4-6 часов) -- **ChatMessage** - Базовое сообщение чата -- **AudioMessage** - Аудио сообщение с метаданными -- **ChatSession** - Сессия чата -- **ChatParticipant** - Участник (пользователь/ассистент) -- **MessageStatus** - Статусы сообщений (отправлено, доставлено, ошибка) - -#### 1.2 HTTP интеграция (4-6 часов) -- Расширение `HttpRepositoryV2` методами чата: - - `POST /api/v2/chat/messages` - Отправка текстового сообщения - - `POST /api/v2/chat/audio` - Отправка аудио сообщения - - `GET /api/v2/chat/messages/{sessionId}` - Получение истории - - `POST /api/v2/chat/sessions` - Создание сессии -- Обработка ошибок и таймаутов - -#### 1.3 State management (4-4 часов) -- **ChatStateManager** - Управление состоянием чата -- Состояния: loading, loaded, error -- Реактивные обновления сообщений -- Управление активной сессией - -### Фаза 2: Сервисы и бизнес-логика (16-20 часов) - -#### 2.1 ChatService (6-8 часов) -- Отправка текстовых сообщений -- Получение ответов от LLM -- Управление сессиями чата -- Кэширование сообщений -- Обработка ошибок сети - -#### 2.2 AudioService (6-8 часов) -- Запись аудио через Web Audio API -- Воспроизведение аудио сообщений -- Конвертация форматов (WebM/WAV → подходящий для сервера) -- Управление микрофоном (разрешения, состояние) -- Обработка голосовых команд - -#### 2.3 DI интеграция (4-4 часов) -- **ChatModule** - Модуль для UserScope -- Регистрация сервисов в контейнере -- Зависимости: HttpRepositoryV2, AudioService - -### Фаза 3: UI компоненты (20-24 часов) - -#### 3.1 Базовые компоненты чата (8-10 часов) -- **MessageBubble** - Пузырь сообщения (текст/аудио) -- **MessageList** - Список сообщений с виртуализацией -- **ChatInput** - Поле ввода с прикреплением файлов -- **AudioRecorder** - Кнопка записи голосовых сообщений -- **AudioPlayer** - Воспроизведение аудио сообщений - -#### 3.2 ChatPage (8-10 часов) -- Основная страница чата -- AppBar с информацией о сессии -- Сообщения + input внизу -- Обработка состояний загрузки/ошибок -- Адаптивный layout (мобильный/десктоп) - -#### 3.3 Навигация и роутинг (4-4 часов) -- Добавление маршрута `/chat` в AppRouter -- Кнопка чата в bottom navigation или sidebar -- Переход к чату из других страниц - -### Фаза 4: Аудио функциональность (8-12 часов) - -#### 4.1 Запись аудио (4-6 часов) -- Web Audio API интеграция -- MediaRecorder для захвата -- Визуализация уровня звука -- Обработка разрешений микрофона -- Отправка на сервер - -#### 4.2 Воспроизведение аудио (4-6 часов) -- HTML5 Audio для воспроизведения -- Кастомные контролы (play/pause/progress) -- Обработка ошибок загрузки -- Кэширование аудио файлов - -### Фаза 5: Интеграция и полировка (8-12 часов) - -#### 5.1 Backend endpoints (4-6 часов) -- Реализация серверных эндпоинтов -- Интеграция с LLM API -- Обработка аудио файлов -- Хранение истории чата - -#### 5.2 Тестирование и QA (4-6 часов) -- Unit тесты для всех сервисов -- Widget тесты для UI компонентов -- Интеграционные тесты -- Тестирование аудио функциональности -- Кросс-браузерная совместимость - ---- - -## 🔧 Технические решения - -### Аудио обработка -```dart -// Web Audio API для записи -final stream = await navigator.mediaDevices.getUserMedia({'audio': true}); -final recorder = MediaRecorder(stream); - -// Конвертация для отправки -final audioBlob = await recorder.stop(); -final audioFile = File.fromRawPath(audioBlob); -``` - -### State management -```dart -@freezed -class ChatState with _$ChatState { - const factory ChatState.loading() = ChatStateLoading; - const factory ChatState.loaded({ - required List messages, - required ChatSession session, - }) = ChatStateLoaded; - const factory ChatState.error(String message) = ChatStateError; -} -``` - -### HTTP интеграция -```dart -// Отправка сообщения -final response = await _httpRepository.sendMessage( - sessionId: session.id, - content: message.text, - type: MessageType.text, -); - -// Получение ответа -final llmResponse = ChatMessage.fromJson(response.data); -``` - ---- - -## 📱 UI/UX требования - -### Адаптивный дизайн -- **Мобильный**: Полноэкранный чат, клавиатура поверх -- **Десктоп**: Sidebar или отдельное окно -- **Планшет**: Оптимизированный layout - -### Аудио UX -- Визуальная обратная связь при записи -- Волновая форма для аудио сообщений -- Длительность и размер файла -- Возможность отмены записи - -### Сообщения -- Разные стили для пользователя/ассистента -- Статусы доставки -- Тайминги сообщений -- Поддержка markdown в ответах LLM - ---- - -## 🧪 Тестирование - -### Unit тесты -- ChatService: отправка/получение сообщений -- AudioService: запись/воспроизведение -- ChatStateManager: state transitions -- Модели: сериализация/десериализация - -### Widget тесты -- MessageBubble: рендеринг разных типов -- ChatInput: ввод текста и аудио -- MessageList: виртуализация и скролл - -### Интеграционные тесты -- Полный флоу отправки сообщения -- Аудио запись и отправка -- Обработка ошибок сети - ---- - -## 🚀 Roadmap реализации - -### Неделя 1-2: Фаза 1 (Инфраструктура) -- День 1-2: Модели данных -- День 3-4: HTTP интеграция -- День 5: State management -- День 6-7: DI и модули - -### Неделя 3-4: Фаза 2 (Сервисы) -- День 8-10: ChatService -- День 11-13: AudioService -- День 14: Интеграция сервисов - -### Неделя 5-6: Фаза 3 (UI) -- День 15-18: UI компоненты -- День 19-21: ChatPage -- День 22: Навигация - -### Неделя 7-8: Фаза 4-5 (Аудио + Полировка) -- День 23-25: Аудио функциональность -- День 26-28: Backend интеграция -- День 29-30: Тестирование -- День 31-32: Финальная полировка - ---- - -## 📊 Критерии приемки - -### Функциональные требования -- ✅ Отправка текстовых сообщений -- ✅ Получение ответов от LLM -- ✅ Запись голосовых сообщений -- ✅ Воспроизведение аудио ответов -- ✅ История сообщений сохраняется -- ✅ Обработка ошибок сети - -### Нефункциональные требования -- ✅ Адаптивный дизайн (мобильный/десктоп) -- ✅ Производительность (виртуализация списка) -- ✅ Доступность (WCAG 2.1 AA) -- ✅ Безопасность (HTTPS, валидация данных) - -### Качество кода -- ✅ 80%+ тестового покрытия -- ✅ Соблюдение clean architecture -- ✅ Type-safe код (freezed) -- ✅ Документация всех публичных API - ---- - -## 🔄 Зависимости и риски - -### Внешние зависимости -- **Backend API**: Эндпоинты чата должны быть готовы -- **LLM интеграция**: Доступ к модели ИИ -- **Web Audio API**: Поддержка в целевых браузерах - -### Технические риски -- **Аудио совместимость**: Разные браузеры поддерживают разные кодеки -- **Производительность**: Большие аудио файлы -- **Сетевая надежность**: Обработка обрывов соединения - -### МитIGATION стратегии -- Progressive enhancement для аудио -- Offline-first подход для сообщений -- Graceful degradation при ошибках - ---- - -## 📈 Метрики успеха - -### Технические метрики -- **Время ответа**: <2s для текстовых сообщений -- **Аудио качество**: 128kbps минимум -- **Test coverage**: >80% -- **Bundle size**: <500KB дополнительно - -### Пользовательские метрики -- **Сообщения/сессия**: Среднее количество сообщений -- **Время сессии**: Среднее время использования чата -- **Аудио использование**: Процент голосовых сообщений - ---- - -## 📋 Следующие шаги - -1. **Создать todo-список** для фазы 1 -2. **Начать с моделей данных** (ChatMessage, AudioMessage) -3. **Реализовать HTTP интеграцию** в HttpRepositoryV2 -4. **Создать ChatStateManager** с базовым состоянием -5. **Написать unit тесты** для первых компонентов - ---- - -**Статус плана:** ✅ Готов к реализации -**Следующий шаг:** Создание todo-списка и начало фазы 1 diff --git a/mnemo_cards_web_v2/CORS_FIX.md b/mnemo_cards_web_v2/CORS_FIX.md deleted file mode 100644 index abda6af..0000000 --- a/mnemo_cards_web_v2/CORS_FIX.md +++ /dev/null @@ -1,137 +0,0 @@ -# Решение CORS Error - -## Что такое CORS? - -CORS (Cross-Origin Resource Sharing) - это механизм безопасности браузера, который блокирует запросы между разными доменами/портами. - -## Проблема - -При разработке: -- **Frontend** (Flutter Web) работает на `http://localhost:xxxxx` (случайный порт) -- **Backend** работает на `http://localhost:8000` -- Браузер блокирует запросы между этими портами - -## Решение - -### 1. ✅ Backend настроен (исправлено 19 окт 2025) - -В файле `mnemo_cards_backend/lib/api/mnemo_shelf.dart` добавлена правильная CORS конфигурация: - -```dart -final corsConfig = { - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS', - 'Access-Control-Allow-Headers': 'Origin, Content-Type, Accept, Authorization, user_token, request_token, app_version', - 'Access-Control-Expose-Headers': 'Authorization', - 'Access-Control-Max-Age': '86400', -}; -``` - -**⚠️ ВАЖНО:** CORS middleware должен быть **ПЕРВЫМ** в pipeline, иначе preflight запросы (OPTIONS) будут блокироваться авторизацией: - -```dart -final handler = Pipeline() - .addMiddleware(corsHeaders(headers: corsConfig)) // ← CORS ПЕРВЫМ! - .addMiddleware(logRequests(logger: logger('app'))) - .addMiddleware(appAuthorize(getIt.get())) - .addHandler(rootRouter); -``` - -Это позволяет: -- ✅ Принимать запросы с любого origin (`*`) -- ✅ Разрешает все необходимые HTTP методы -- ✅ Разрешает кастомные заголовки (`user_token`, `request_token`, `app_version`) -- ✅ Разрешает читать заголовок `Authorization` в ответе -- ✅ OPTIONS запросы обрабатываются до проверки авторизации - -### 2. 🚀 Запуск Backend - -Используйте скрипт для запуска backend в режиме разработки: - -```bash -cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_backend -./run_dev.sh -``` - -Backend будет доступен на `http://localhost:8000` - -### 3. 🌐 Запуск Frontend - -В отдельном терминале запустите веб-версию: - -```bash -cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_web_v2 -flutter run -d chrome -``` - -### 4. ✔️ Проверка - -После запуска обоих сервисов: -1. Откройте DevTools в Chrome (F12) -2. Перейдите на вкладку Network -3. Проверьте что запросы к `/packs/previews`, `/games` и т.д. успешны -4. В заголовках ответа должны быть CORS заголовки - -## Альтернативные решения (если не помогло) - -### Вариант 1: Отключить web security в Chrome (только для разработки!) - -```bash -# macOS -open -n -a "Google Chrome" --args --user-data-dir="/tmp/chrome_dev_session" --disable-web-security - -# Linux -google-chrome --disable-web-security --user-data-dir="/tmp/chrome_dev_session" -``` - -⚠️ **Внимание**: Это небезопасно! Используйте только для разработки. - -### Вариант 2: Использовать Flutter с --web-port - -Запускайте Flutter на фиксированном порту: - -```bash -flutter run -d chrome --web-port=8080 -``` - -### Вариант 3: Production CORS (для деплоя) - -Для production версии: - -1. **Backend** уже настроен с правильными CORS настройками ✅ -2. **Frontend** использует `https://api.mnemo-cards.online` (nginx:443) ✅ -3. **Nginx** настроен без конфликтующих COEP/COOP headers ✅ - -Текущая конфигурация позволяет: -- ✅ Запросы с `mnemo-cards.online` на `https://api.mnemo-cards.online` -- ✅ Все необходимые HTTP методы и headers -- ✅ Preflight OPTIONS запросы - -## Диагностика - -Если CORS ошибка все еще возникает: - -1. **Проверьте что backend запущен**: - ```bash - curl http://localhost:8000/games - ``` - -2. **Проверьте CORS заголовки**: - ```bash - curl -H "Origin: http://localhost:8080" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose http://localhost:8000/games - ``` - -3. **Посмотрите логи backend** - там будут видны все входящие запросы - -4. **Проверьте что ApiConfig использует правильный URL**: - ```dart - // В lib/domain/config/api_config.dart - static const String baseUrl = 'http://localhost:8000'; - ``` - -## Полезные ссылки - -- [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) -- [shelf_cors_headers package](https://pub.dev/packages/shelf_cors_headers) -- [Flutter Web: CORS](https://docs.flutter.dev/platform-integration/web/building#handling-cors-errors-only-applicable-to-web) - diff --git a/mnemo_cards_web_v2/DESIGN_ADAPTATION_PLAN.md b/mnemo_cards_web_v2/DESIGN_ADAPTATION_PLAN.md deleted file mode 100644 index 4ac3454..0000000 --- a/mnemo_cards_web_v2/DESIGN_ADAPTATION_PLAN.md +++ /dev/null @@ -1,601 +0,0 @@ -# План адаптации дизайна веб-приложения mnemo_cards_web_v2 - -**Цель**: Адаптировать дизайн веб-приложения `mnemo_cards_web_v2`, чтобы он был визуально похож на мобильное приложение `mnemo_cards`. - -**Дата создания**: 19 октября 2025 -**Статус**: План - ---- - -## 📊 Анализ текущего состояния - -### Мобильное приложение (mnemo_cards) -**Ключевые особенности дизайна:** - -1. **Цветовая схема**: - - Черно-белая основа (black/white primary) - - Кастомные акцентные цвета: peach, golden, green - - Специальные цвета: progressBlue, menuBlue, backgroundBlue, borderGray - - Использует MaterialColor для создания палитр - -2. **Типографика**: - - Шрифт: `Nunito` - - Все тексты жирные: `FontWeight.w700` для всех стилей - - Использует flutter_screenutil для адаптивных размеров - -3. **Карточки паков**: - - Горизонтальная компоновка (Row) - - Изображение слева (квадратное, равно высоте карточки) - - Информация справа (title, subtitle, количество карточек) - - Граница с цветом пака (`border: Border.all(color: pack.color)`) - - Скругленные углы (12.0) - - Прозрачный фон карточки - - Высота: ~110.h - -4. **UI компоненты**: - - RefreshIndicator с кастомным цветом - - Простые границы и минималистичный дизайн - - Иконки из webp файлов - - Loading состояния с изображениями (cerdo/luna) - -5. **Профиль**: - - UserStatistics виджет со списком слов - - Прогресс-бары для каждого слова - - SimpleTile компоненты с Divider'ами - - Золотой цвет для выученных слов - -### Веб-приложение (mnemo_cards_web_v2) -**Текущий дизайн:** - -1. **Цветовая схема**: - - Material 3 с синим seedColor - - Стандартная палитра Material - - Отсутствуют кастомные акцентные цвета - -2. **Типографика**: - - Шрифт: `Nunito` ✅ - - Стандартные весы шрифтов Material - -3. **Карточки паков**: - - Вертикальная компоновка (Column) - - Изображение сверху (AspectRatio 16:9) - - Информация снизу - - Стандартные Material Card с elevation - - Hero анимация ✅ - -4. **UI компоненты**: - - Material 3 компоненты - - Shimmer loading states ✅ - - Современный responsive дизайн ✅ - -5. **Профиль**: - - Продвинутый дизайн со статистикой - - StatsCard компоненты - - SimpleChart для графиков - - Settings card с темной темой - ---- - -## 🎯 Этапы адаптации - -### Этап 1: Обновление цветовой схемы и темизации - -**Приоритет**: 🔴 Высокий -**Время**: 2-3 часа -**Сложность**: Средняя - -#### Задачи: - -1. **Создать файл с цветовыми константами** (`lib/presentation/theme/app_colors.dart`): - ```dart - // Точные цвета из мобильного приложения - const Color peach = Color(0xffffc994); - const Color golden = Color(0xffffea00); - const Color green = Color(0xff3d5309); - const Color greenAccent = Color(0xff688d11); - const Color black = Color(0xff000000); - const Color white = Color(0xffffffff); - const Color progressBlue = Color(0xff8CCBFF); - const Color menuBlue = Color(0xff99C4E9); - const Color backgroundBlue = Color(0xFFf0f0f0); - const Color testBlue = Color(0xffD0EAFF); - const Color borderGray = Color(0xffABABAB); - ``` - -2. **Обновить `app_theme.dart`**: - - Изменить ColorScheme на черно-белую основу - - Светлая тема: - - primary: MaterialColor(0xFF000000, colorMap) - - surface: white - - onSurface: black - - secondary: green - - Темная тема: - - primary: MaterialColor(0xFFFFFFFF, whiteColorMap) - - surface: black - - onSurface: white - - secondary: lightBlue - -3. **Обновить TextTheme**: - - Установить `FontWeight.w700` для всех стилей текста - - Сохранить Nunito шрифт - -4. **Обновить компонентные темы**: - - AppBarTheme: иконки с primary цветом - - CardTheme: скругление 12.0, минимальная elevation - - ButtonTheme: жирные тексты - -**Файлы для изменения**: -- ✏️ `lib/presentation/theme/app_theme.dart` -- ➕ `lib/presentation/theme/app_colors.dart` - ---- - -### Этап 2: Адаптация карточек паков (PackCard) - -**Приоритет**: 🔴 Высокий -**Время**: 3-4 часа -**Сложность**: Высокая - -#### Задачи: - -1. **Изменить компоновку PackCard на горизонтальную**: - - Изменить Column на Row - - Левая часть: квадратное изображение (height = width) - - Правая часть: информация о паке - -2. **Обновить стиль карточки**: - - Удалить elevation из Card - - Добавить Border.all с цветом пака - - Сделать фон прозрачным или белым - - Скругление: 12.0 - -3. **Добавить парсинг цвета пака**: - - Использовать `pack.color?.asColor` из мобильного приложения - - Создать extension для ColorDto - -4. **Обновить информацию в карточке**: - - Жирный большой заголовок - - Subtitle светлее - - Иконка карточек с количеством - - Индикатор загрузки (опционально) - -5. **Адаптировать высоту**: - - Фиксированная высота ~110-120px - - Квадратное изображение слева - -**Файлы для изменения**: -- ✏️ `lib/presentation/widgets/pack_card.dart` -- ➕ `lib/utils/color_extension.dart` (для парсинга цветов) - -**Визуальный пример**: -``` -┌─────────────────────────────────────────┐ -│ ┌─────┐ │ -│ │ │ Pack Title (bold, large) │ -│ │ IMG │ Pack Subtitle (light) │ -│ │ │ 🃏 42 cards │ -│ └─────┘ │ -└─────────────────────────────────────────┘ -``` - ---- - -### Этап 3: Адаптация HomePage (список паков) - -**Приоритет**: 🟡 Средний -**Время**: 2 часа -**Сложность**: Низкая - -#### Задачи: - -1. **Изменить layout с GridView на ListView**: - - Вертикальный список карточек - - Padding: 8.0 - -2. **Обновить RefreshIndicator**: - - Кастомные цвета (использовать цвет первого пака или primary) - - displacement: 20 - -3. **Обновить Loading состояние**: - - Опционально: добавить изображение (cerdo/luna) вместо shimmer - - Или оставить shimmer, но адаптировать под горизонтальную карточку - -4. **Обновить Search bar**: - - Сделать более минималистичным - - Убрать излишнюю стилизацию - -**Файлы для изменения**: -- ✏️ `lib/presentation/pages/home/home_page.dart` -- ✏️ `lib/presentation/widgets/loading/pack_card_shimmer.dart` - ---- - -### Этап 4: Адаптация GamesPage и GameCard - -**Приоритет**: 🟡 Средний -**Время**: 2-3 часа -**Сложность**: Средняя - -#### Задачи: - -1. **Обновить GameCard под стиль мобильного**: - - Возможно также сделать горизонтальную компоновку - - Или оставить вертикальную, но обновить стили - - Добавить границы с цветом игры - - Использовать кастомные цвета - -2. **Обновить GamesPage**: - - Изменить layout (Grid или List в зависимости от выбора) - - Обновить RefreshIndicator - - Адаптировать Loading состояния - -3. **Обновить shimmer для GameCard** - -**Файлы для изменения**: -- ✏️ `lib/presentation/widgets/game_card.dart` -- ✏️ `lib/presentation/pages/games/games_page.dart` -- ✏️ `lib/presentation/widgets/loading/game_card_shimmer.dart` - ---- - -### Этап 5: Адаптация ProfilePage - -**Приоритет**: 🟢 Низкий -**Время**: 3-4 часа -**Сложность**: Средняя - -#### Задачи: - -1. **Упростить дизайн профиля**: - - Убрать или упростить статистические карточки - - Добавить UserStatistics компонент (или его аналог) - - Использовать SimpleTile стиль с Divider'ами - -2. **Обновить статистику**: - - Показывать список изученных слов с прогрессом - - Использовать HorizontalProgressWidget - - Золотой цвет для выученных слов - -3. **Обновить Settings секцию**: - - Более простой стиль с dividers - - Минималистичные иконки - -4. **Обновить logout кнопку**: - - Более простой стиль - -**Файлы для изменения**: -- ✏️ `lib/presentation/pages/profile/profile_page.dart` -- ✏️ `lib/presentation/widgets/stats_card.dart` (упростить или удалить) -- ➕ `lib/presentation/widgets/simple_tile.dart` (создать) -- ➕ `lib/presentation/widgets/horizontal_progress.dart` (создать) - ---- - -### Этап 6: Адаптация PackDetailsPage - -**Приоритет**: 🟢 Низкий -**Время**: 2 часа -**Сложность**: Низкая - -#### Задачи: - -1. **Упростить дизайн деталей пака**: - - Убрать излишнюю стилизацию - - Использовать границы вместо elevation - - Адаптировать под минималистичный стиль - -2. **Обновить список карточек**: - - Более простой стиль ListTile - - Границы вместо карточек - -**Файлы для изменения**: -- ✏️ `lib/presentation/pages/pack_details/pack_details_page.dart` - ---- - -### Этап 7: Адаптация общих компонентов - -**Приоритет**: 🟡 Средний -**Время**: 2-3 часа -**Сложность**: Низкая - -#### Задачи: - -1. **Обновить MainShell** (нижняя навигация): - - Адаптировать стили под новую тему - - Проверить цвета иконок - -2. **Обновить AuthPage**: - - Упростить дизайн кнопок - - Использовать новую цветовую схему - -3. **Обновить ErrorView и LoadingView**: - - Адаптировать под новую тему - - Опционально: добавить кастомные изображения для ошибок - -4. **Создать общие утилиты**: - - ColorExtension для парсинга ColorDto - - Дополнительные helper'ы - -**Файлы для изменения**: -- ✏️ `lib/presentation/widgets/main_shell.dart` -- ✏️ `lib/presentation/pages/auth/auth_page.dart` -- ✏️ `lib/presentation/widgets/error_view.dart` -- ✏️ `lib/presentation/widgets/loading_view.dart` -- ➕ `lib/utils/color_extension.dart` - ---- - -### Этап 8: Адаптация для responsive дизайна - -**Приоритет**: 🟢 Низкий -**Время**: 2-3 часа -**Сложность**: Средняя - -#### Задачи: - -1. **Обновить Responsive утилиты**: - - Адаптировать под новые размеры карточек - - Убедиться, что горизонтальные карточки хорошо смотрятся на разных экранах - -2. **Тестирование на разных разрешениях**: - - Mobile (узкий экран) - - Tablet (средний экран) - - Desktop (широкий экран) - -3. **Адаптация максимальной ширины контента**: - - Убедиться, что карточки не слишком широкие на больших экранах - -**Файлы для изменения**: -- ✏️ `lib/utils/responsive.dart` -- ✏️ Все страницы с использованием responsive логики - ---- - -### Этап 9: Финальная полировка и тестирование - -**Приоритет**: 🔴 Высокий -**Время**: 2-3 часа -**Сложность**: Низкая - -#### Задачи: - -1. **Проверка консистентности**: - - Все цвета соответствуют мобильному приложению - - Все шрифты жирные где нужно - - Все границы используют правильные цвета - -2. **Темная тема**: - - Проверить, что темная тема работает корректно - - Адаптировать все компоненты под темную тему - -3. **Accessibility**: - - Проверить контрастность цветов - - Обновить Semantics labels если нужно - -4. **Тестирование**: - - Визуальное тестирование всех экранов - - Проверка анимаций и переходов - - Unit тесты для новых компонентов - -5. **Документация**: - - Обновить README с информацией о дизайне - - Создать DESIGN_GUIDE.md с примерами компонентов - -**Файлы для проверки**: -- Все обновленные файлы -- Тесты - ---- - -## 📁 Структура новых файлов - -``` -lib/ -├── presentation/ -│ ├── theme/ -│ │ ├── app_theme.dart ✏️ Обновить -│ │ └── app_colors.dart ➕ Создать -│ ├── widgets/ -│ │ ├── pack_card.dart ✏️ Полностью переделать -│ │ ├── game_card.dart ✏️ Обновить -│ │ ├── simple_tile.dart ➕ Создать -│ │ ├── horizontal_progress.dart ➕ Создать -│ │ └── loading/ -│ │ ├── pack_card_shimmer.dart ✏️ Обновить под горизонтальную карточку -│ │ └── game_card_shimmer.dart ✏️ Обновить -│ └── pages/ -│ ├── home/ -│ │ └── home_page.dart ✏️ Изменить layout -│ ├── games/ -│ │ └── games_page.dart ✏️ Обновить стили -│ ├── profile/ -│ │ └── profile_page.dart ✏️ Упростить дизайн -│ └── pack_details/ -│ └── pack_details_page.dart ✏️ Упростить -├── utils/ -│ └── color_extension.dart ➕ Создать -└── assets/ ➕ Опционально - └── images/ - ├── cerdo.webp ➕ Копировать из мобильного - └── luna.webp ➕ Копировать из мобильного -``` - ---- - -## 🎨 Ключевые изменения дизайна - -### До и После: - -#### 1. Цветовая схема -**До**: Material 3 синяя палитра -**После**: Черно-белая основа с акцентными цветами (golden, green, peach) - -#### 2. Карточки паков -**До**: Вертикальные карточки с изображением 16:9 сверху -**После**: Горизонтальные карточки с квадратным изображением слева и границей цвета пака - -#### 3. Типографика -**До**: Стандартные веса шрифтов Material -**После**: Все тексты жирные (FontWeight.w700) - -#### 4. UI компоненты -**До**: Material 3 elevation, стандартные карточки -**После**: Минималистичный дизайн с границами, без elevation - -#### 5. Профиль -**До**: Продвинутая статистика с графиками и карточками -**После**: Простой список слов с прогрессом, SimpleTile компоненты - ---- - -## ⚠️ Важные замечания - -1. **Сохранить функциональность**: - - Все существующие функции должны работать - - Hero анимации сохранить - - RefreshIndicator сохранить - -2. **Responsive дизайн**: - - Убедиться, что горизонтальные карточки хорошо смотрятся на всех экранах - - На очень узких экранах возможно нужно адаптировать размеры - -3. **Тестирование**: - - Обновить тесты для новых компонентов - - Проверить, что старые тесты проходят - -4. **Темная тема**: - - Особое внимание к темной теме - - Проверить контрастность - -5. **Assets**: - - Возможно понадобится скопировать иконки из мобильного приложения - - Добавить cerdo.webp и luna.webp для loading состояний - ---- - -## 📊 Приоритизация этапов - -### Критический путь (начать с этого): -1. **Этап 1**: Цветовая схема и темизация -2. **Этап 2**: Адаптация PackCard (самое заметное изменение) -3. **Этап 3**: Адаптация HomePage - -### Средний приоритет: -4. **Этап 4**: GamesPage и GameCard -5. **Этап 7**: Общие компоненты -6. **Этап 5**: ProfilePage - -### Низкий приоритет (можно отложить): -7. **Этап 6**: PackDetailsPage -8. **Этап 8**: Responsive адаптация -9. **Этап 9**: Финальная полировка - ---- - -## 🚀 Порядок выполнения - -### День 1 (4-5 часов): -- Этап 1: Цветовая схема (2-3 часа) -- Этап 2: PackCard начать (2 часа) - -### День 2 (4-5 часов): -- Этап 2: PackCard завершить (2 часа) -- Этап 3: HomePage (2 часа) -- Тестирование (1 час) - -### День 3 (4-5 часов): -- Этап 4: GamesPage (2-3 часа) -- Этап 7: Общие компоненты (2 часа) - -### День 4 (3-4 часа): -- Этап 5: ProfilePage (3 часа) -- Этап 6: PackDetailsPage (1 час) - -### День 5 (2-3 часа): -- Этап 8: Responsive (2 часа) -- Этап 9: Финальная полировка (1 час) - -**Общее время**: 17-22 часа работы - ---- - -## 📝 Чек-лист выполнения - -### Этап 1: Цветовая схема -- [ ] Создан app_colors.dart с константами -- [ ] Обновлен app_theme.dart (светлая тема) -- [ ] Обновлен app_theme.dart (темная тема) -- [ ] Все тексты жирные (FontWeight.w700) -- [ ] Проверено на обоих темах - -### Этап 2: PackCard -- [ ] Изменена компоновка на горизонтальную -- [ ] Добавлена граница с цветом пака -- [ ] Создан ColorExtension для парсинга -- [ ] Обновлена информация в карточке -- [ ] Hero анимация работает - -### Этап 3: HomePage -- [ ] Изменен GridView на ListView -- [ ] Обновлен RefreshIndicator -- [ ] Обновлен PackCardShimmer -- [ ] Проверена прокрутка и загрузка - -### Этап 4: GamesPage -- [ ] Обновлен GameCard -- [ ] Обновлен GamesPage layout -- [ ] Обновлен GameCardShimmer -- [ ] Проверена функциональность - -### Этап 5: ProfilePage -- [ ] Упрощен дизайн -- [ ] Создан SimpleTile компонент -- [ ] Создан HorizontalProgress (опционально) -- [ ] Обновлена статистика - -### Этап 6: PackDetailsPage -- [ ] Упрощен дизайн -- [ ] Обновлен список карточек -- [ ] Проверена функциональность - -### Этап 7: Общие компоненты -- [ ] Обновлен MainShell -- [ ] Обновлен AuthPage -- [ ] Обновлены ErrorView/LoadingView -- [ ] Созданы утилиты - -### Этап 8: Responsive -- [ ] Проверено на mobile -- [ ] Проверено на tablet -- [ ] Проверено на desktop -- [ ] Адаптированы размеры - -### Этап 9: Финальная полировка -- [ ] Проверена консистентность -- [ ] Проверена темная тема -- [ ] Проверена accessibility -- [ ] Все тесты проходят -- [ ] Обновлена документация - ---- - -## 🎯 Ожидаемый результат - -После выполнения всех этапов веб-приложение `mnemo_cards_web_v2` будет визуально похоже на мобильное приложение `mnemo_cards`: - -- ✅ Идентичная цветовая схема (черно-белая с акцентами) -- ✅ Жирные шрифты Nunito -- ✅ Горизонтальные карточки паков с границами -- ✅ Минималистичный дизайн без лишних elevation -- ✅ Упрощенный профиль со статистикой -- ✅ Консистентный UI на всех экранах -- ✅ Работающая темная тема -- ✅ Сохраненная функциональность (авторизация, навигация, загрузка данных) - ---- - -**Автор плана**: AI Assistant -**Дата**: 19 октября 2025 -**Версия**: 1.0 - diff --git a/mnemo_cards_web_v2/DESIGN_ADAPTATION_PROGRESS.md b/mnemo_cards_web_v2/DESIGN_ADAPTATION_PROGRESS.md deleted file mode 100644 index 8ff3924..0000000 --- a/mnemo_cards_web_v2/DESIGN_ADAPTATION_PROGRESS.md +++ /dev/null @@ -1,233 +0,0 @@ -# Прогресс адаптации дизайна - -**Дата**: 19 октября 2025 -**Статус**: В процессе - ---- - -## ✅ Выполнено - -### 🎨 Этап 1: Цветовая схема и темизация (ЗАВЕРШЕНО) - -**Создано:** -- ✅ `lib/presentation/theme/app_colors.dart` - цветовые константы из мобильного приложения - - Peach, golden, green, progressBlue, borderGray и др. - - MaterialColor палитры для черного и белого - -**Обновлено:** -- ✅ `lib/presentation/theme/app_theme.dart` - - Черно-белая ColorScheme (вместо синей Material 3) - - Все тексты жирные (FontWeight.w700) - - Минимальная elevation (1) - - Светлая и темная темы - -**Результаты:** -- Приложение использует черно-белую основу с акцентными цветами -- Все тексты жирные, как в мобильном приложении -- Минималистичный дизайн - ---- - -### 📦 Этап 2: Адаптация карточек паков (ЗАВЕРШЕНО) - -**Создано:** -- ✅ `lib/utils/color_extension.dart` - extension для парсинга String? цветов -- ✅ `lib/presentation/widgets/pack_card_vertical.dart` - вертикальная карточка для плитки -- ✅ `lib/presentation/widgets/loading/pack_card_vertical_shimmer.dart` - shimmer для вертикальных карточек - -**Обновлено:** -- ✅ `lib/presentation/widgets/pack_card.dart` - - Горизонтальная компоновка (изображение слева, текст справа) - - Граница с цветом пака - - Отображение base64 изображений - - Фиксированная высота 110px - -- ✅ `lib/presentation/widgets/loading/pack_card_shimmer.dart` - - Адаптирован под горизонтальную карточку - -**Результаты:** -- Горизонтальные карточки для мобильного вида -- Вертикальные карточки для desktop вида (плитка) -- Изображения паков отображаются из base64 -- Сохранена стилистика с цветными границами - ---- - -### 🏠 Этап 3: Адаптация HomePage (ЗАВЕРШЕНО) - -**Обновлено:** -- ✅ `lib/presentation/pages/home/home_page.dart` - - Адаптивный layout: - - **Мобильный (< 600px)**: ListView с горизонтальными карточками - - **Desktop/Tablet (≥ 600px)**: GridView с вертикальными карточками - - BouncingScrollPhysics для плавной прокрутки - - RefreshIndicator с displacement: 20 - - Shimmer loading адаптируется под размер экрана - -**Результаты:** -- HomePage автоматически адаптируется под размер экрана -- На широких экранах - красивая плитка (3-4 колонки) -- На узких экранах - компактный список - ---- - -### 📄 Этап 4: Адаптация PackDetailsPage (ЗАВЕРШЕНО) - -**Обновлено:** -- ✅ `lib/presentation/pages/pack_details/pack_details_page.dart` - - Custom header в стиле мобильного приложения: - - Кнопка "к темам" для возврата - - Большой заголовок (36px, жирный) - - Подзаголовок (20px, легкий) - - Секция с карточками: - - Сетка карточек 100x100px - - Фоновый цвет пака (0.1 opacity) - - Expand/collapse функциональность - - Кнопки управления: - - Expand/Collapse (стрелка вверх/вниз) - - Shuffle (перемешать) - - Favorite (избранное) - - Разделители с цветом пака - - Удалён стандартный AppBar - -**Создано:** -- ✅ `_ControlButton` - виджет кнопки управления - - Размер: 110x60 - - Граница с borderGray - - Иконка 29px - -**Результаты:** -- PackDetailsPage соответствует стилю мобильного приложения -- Все элементы на своих местах -- Работает expand/collapse карточек - ---- - -## 📊 Статистика - -### Созданные файлы (6): -1. `lib/presentation/theme/app_colors.dart` -2. `lib/utils/color_extension.dart` -3. `lib/presentation/widgets/pack_card_vertical.dart` -4. `lib/presentation/widgets/loading/pack_card_vertical_shimmer.dart` -5. `DESIGN_ADAPTATION_PLAN.md` -6. `DESIGN_ADAPTATION_PROGRESS.md` (этот файл) - -### Обновленные файлы (8): -1. `lib/presentation/theme/app_theme.dart` -2. `lib/presentation/widgets/pack_card.dart` -3. `lib/presentation/widgets/loading/pack_card_shimmer.dart` -4. `lib/presentation/pages/home/home_page.dart` -5. `lib/presentation/pages/pack_details/pack_details_page.dart` -6. `lib/domain/config/api_config.dart` (appVersion 1.1.0) -7. `test/presentation/theme/app_theme_test.dart` - -### Тесты: -- ✅ **117 тестов - все проходят** -- ✅ Нет линтер ошибок - ---- - -## 🎯 Ключевые достижения - -### 1. Цветовая схема -- ✅ Черно-белая основа вместо синей -- ✅ Все акцентные цвета из мобильного приложения -- ✅ Темная и светлая темы работают - -### 2. Типографика -- ✅ Все тексты жирные (FontWeight.w700) -- ✅ Шрифт Nunito сохранен -- ✅ Правильные размеры (36px для заголовков, 20px для подзаголовков) - -### 3. Карточки паков -- ✅ Горизонтальный layout для мобильных -- ✅ Вертикальный layout для desktop -- ✅ Границы с цветом пака -- ✅ Base64 изображения отображаются - -### 4. Адаптивность -- ✅ Автоматическое переключение ListView/GridView -- ✅ 3-4 колонки на широких экранах -- ✅ Правильные пропорции карточек (childAspectRatio: 0.7) - -### 5. PackDetailsPage -- ✅ Custom header как в мобильном -- ✅ Сетка карточек с expand/collapse -- ✅ Кнопки управления (expand, shuffle, favorite) -- ✅ Разделители с цветом пака - ---- - -## 📈 Прогресс по плану - -| Этап | Описание | Статус | -|------|----------|--------| -| 1 | Цветовая схема и темизация | ✅ 100% | -| 2 | Адаптация PackCard | ✅ 100% | -| 3 | Адаптация HomePage | ✅ 100% | -| 4 | PackDetailsPage | ✅ 100% | -| 5 | GamesPage | ⏳ 0% | -| 6 | ProfilePage | ⏳ 0% | -| 7 | Общие компоненты | ⏳ 0% | -| 8 | Responsive адаптация | ✅ 50% (HomePage готов) | -| 9 | Финальная полировка | ⏳ 0% | - -**Общий прогресс: ~45%** (4 из 9 этапов) - ---- - -## 🔜 Следующие шаги - -### Приоритет 1 (Критический): -- [ ] Адаптация GamesPage (Этап 5) - - Обновить GameCard под стиль мобильного - - Адаптивный layout (список/плитка) - - Обновить shimmer loading - -### Приоритет 2 (Высокий): -- [ ] Адаптация ProfilePage (Этап 6) - - Упростить дизайн - - Добавить компоненты SimpleTile - - Обновить статистику - -### Приоритет 3 (Средний): -- [ ] Общие компоненты (Этап 7) - - MainShell - - AuthPage - - ErrorView/LoadingView - -### Приоритет 4 (Низкий): -- [ ] Финальная полировка (Этап 9) - - Проверка консистентности - - Темная тема - - Accessibility - - Документация - ---- - -## 💡 Технические заметки - -### Реализованные паттерны: -1. **Адаптивные карточки**: Два виджета (PackCard + PackCardVertical) для разных layout'ов -2. **Responsive utility**: Использование `Responsive.isMobile()` для переключения -3. **Color extension**: Extension на String? для парсинга цветов -4. **Expand/Collapse**: Простое state management с `setState` - -### Размеры и пропорции: -- Горизонтальная карточка: высота 110px -- Вертикальная карточка: childAspectRatio 0.7 (ширина/высота) -- Карточка пака в сетке: 100x100px -- Кнопки управления: 110x60px - -### Цвета: -- Primary: Black (light) / White (dark) -- Secondary: Green (#3d5309) -- Border: BorderGray (#ABABAB) -- Pack color: Из pack.color field - ---- - -**Последнее обновление**: 19 октября 2025 -**Все тесты**: ✅ 117/117 проходят - diff --git a/mnemo_cards_web_v2/DEV_SETUP.md b/mnemo_cards_web_v2/DEV_SETUP.md deleted file mode 100644 index 6b28a2d..0000000 --- a/mnemo_cards_web_v2/DEV_SETUP.md +++ /dev/null @@ -1,208 +0,0 @@ -# 🚀 Быстрый старт для разработки - -## Предварительные требования - -- ✅ Flutter SDK установлен -- ✅ Dart SDK установлен -- ✅ Chrome браузер - -## 📋 Пошаговая инструкция - -### 1️⃣ Запустите Backend - -Откройте **первый терминал** и запустите backend сервер: - -```bash -cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_backend -./run_dev.sh -``` - -Вы должны увидеть: -``` -Starting Mnemo Cards Backend in development mode... -Backend will be available at http://localhost:8000 - -Server listening on http://0.0.0.0:8000 -``` - -✅ Backend работает на `http://localhost:8000` - -### 2️⃣ Запустите Frontend - -Откройте **второй терминал** и запустите web приложение: - -```bash -cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_web_v2 -flutter run -d chrome -``` - -Flutter автоматически откроет Chrome и приложение будет доступно на случайном порту. - -### 3️⃣ Проверка работы - -1. Приложение должно загрузиться без CORS ошибок -2. Откройте DevTools (F12) → Network -3. Проверьте запросы к backend (должны быть успешными) -4. Пройдите авторизацию через Google - -## 🔧 Если возникли проблемы - -### CORS Error - -Если вы видите CORS ошибку в консоли: - -``` -Access to XMLHttpRequest at 'http://localhost:8000/...' from origin '...' has been blocked by CORS policy -``` - -**Решение:** -1. Убедитесь что backend запущен -2. Перезапустите backend (может потребоваться после изменений) -3. Очистите кэш браузера (Ctrl+Shift+Delete) -4. Перезагрузите страницу (Ctrl+R) - -Подробнее см. [CORS_FIX.md](CORS_FIX.md) - -### Connection Refused - -Если запросы не проходят: - -```bash -# Проверьте что backend работает -curl http://localhost:8000/games -``` - -Должен вернуть JSON с играми. - -### Backend не запускается - -```bash -# Убедитесь что порт 8000 свободен -lsof -ti:8000 - -# Если порт занят, убейте процесс -kill -9 $(lsof -ti:8000) - -# Или используйте другой порт -cd mnemo_cards_backend -dart run lib/main.dart -a 0.0.0.0 -p 8001 --isar isar --workdir $(pwd) -``` - -И обновите `ApiConfig.baseUrl` на `http://localhost:8001` - -## 📝 Конфигурация - -### API URL - -Конфигурация находится в `lib/domain/config/api_config.dart`: - -```dart -static String get baseUrl => const String.fromEnvironment( - 'API_BASE_URL', - defaultValue: 'http://localhost:8000', // Для разработки -); -``` - -Для production используйте environment variable: - -```bash -flutter run -d chrome --dart-define=API_BASE_URL=https://your-domain.com -``` - -### Telegram Bot Deep Link - -Для работы веб-инициированного входа через Telegram можно переопределить имя бота: - -```bash -flutter run -d chrome \ - --dart-define=API_BASE_URL=http://localhost:8000 \ - --dart-define=TELEGRAM_BOT_USERNAME=mnemo_cards_bot -``` - -По умолчанию используется `mnemo_cards_bot`. -Deep-link генерируется через `https://t.me/?start=login_`. - -### CORS настройки - -CORS настроен в `mnemo_cards_backend/lib/api/mnemo_shelf.dart`: - -```dart -final corsConfig = { - 'Access-Control-Allow-Origin': '*', // Для разработки - разрешены все origins - 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS', - 'Access-Control-Allow-Headers': '...', -}; -``` - -⚠️ Для production замените `'*'` на конкретный домен! - -## 🏗️ Структура проекта - -``` -mnemo_cards_web_v2/ -├── lib/ -│ ├── di/ # Dependency Injection (yx_scope) -│ ├── domain/ # Business logic, services, state -│ ├── presentation/ # UI, pages, widgets -│ └── main.dart # Entry point -├── test/ # Unit & integration tests -├── web/ # Web-specific files -└── pubspec.yaml # Dependencies -``` - -## 🧪 Тестирование - -Запуск всех тестов: - -```bash -flutter test -``` - -Запуск конкретного теста: - -```bash -flutter test test/domain/services/http_repository_test.dart -``` - -## 🔍 Отладка - -### Flutter DevTools - -```bash -flutter run -d chrome --observatory-port=9999 -``` - -Затем откройте: http://localhost:9999/ - -### Backend логи - -Backend выводит все запросы в консоль: -``` -[app] GET /games -[app] POST /user/create -``` - -### Network Inspector - -1. Откройте DevTools (F12) -2. Вкладка Network -3. Фильтр: XHR -4. Смотрите Headers и Response для каждого запроса - -## 📚 Дополнительные ресурсы - -- [CORS_FIX.md](CORS_FIX.md) - Подробное решение CORS проблем -- [API_INTEGRATION_TEMP.md](API_INTEGRATION_TEMP.md) - Документация по API -- [PLAN.md](PLAN.md) - План разработки и архитектура - -## 🎯 Горячие клавиши - -- `r` - Hot reload (без перезапуска) -- `R` - Hot restart (полный перезапуск) -- `h` - Помощь -- `q` - Выход - ---- - -**Удачной разработки! 🚀** - diff --git a/mnemo_cards_web_v2/FUTURE_PLANS.md b/mnemo_cards_web_v2/FUTURE_PLANS.md deleted file mode 100644 index 372bfa7..0000000 --- a/mnemo_cards_web_v2/FUTURE_PLANS.md +++ /dev/null @@ -1,117 +0,0 @@ -Отличный вопрос! Давайте проанализирую план и предложу улучшения: - -[1 tool called] - -Проанализировав план, вижу несколько важных аспектов, которые стоит добавить или уточнить: - -## 🔍 Что можно доработать в плане: - -### 1. **🚨 Обработка ошибок и граничные случаи** -- Что делать, если Firebase не инициализируется? -- Обработка протухших токенов (401 ошибки) -- Fallback при недоступности backend -- Retry логика для сетевых запросов -- Graceful degradation для гостей - -### 2. **🎮 WebView Bridge для игр (критично!)** -План упоминает интеграцию с играми поверхностно, но в проекте есть сложная система `payloads_shared` и `bridge_core`. Нужно детализировать: -- Как подключать payloads из `../games/packages/payloads_shared` -- JavaScript bridge настройка -- Обработка событий от игр -- Передача результатов игры в профиль - -### 3. **💾 Кеширование данных** -- Кеш изображений карточек (CachedNetworkImage?) -- Кеш списка тем (чтобы работало при плохом интернете) -- Стратегия инвалидации кеша -- IndexedDB для web? - -### 4. **🔄 Миграция данных гостя** -Важный сценарий не описан: -- Пользователь зашел как гость, прошел несколько тестов -- Потом авторизовался через Google -- Как сохранить прогресс гостя? - -### 5. **🏗️ Environment конфигурация** -- dev/staging/prod окружения -- Разные Firebase проекты -- Feature flags через Remote Config -- API endpoints по окружениям - -### 6. **🔒 Безопасность (Web специфика)** -- Где хранить токены (SecureStorage в web =?) -- CORS настройки для API -- CSP (Content Security Policy) -- Защита от XSS -- Валидация данных от backend - -### 7. **📱 Адаптивность (детализация)** -План упоминает, но нужны детали: -- Breakpoints: mobile (<600px), tablet (600-1200px), desktop (>1200px) -- Разные layouts для разных размеров -- Responsive Bottom Navigation vs Side Navigation -- Touch vs Mouse взаимодействие - -### 8. **🧪 Тестирование** -Отсутствует секция: -- Unit тесты для State Managers -- Тестирование Scopes (yx_scope имеет test utils) -- Widget тесты -- Integration тесты -- Mock'и для Firebase и Dio - -### 9. **📊 Аналитика (детализация событий)** -Какие события логировать: -- `page_view` - просмотр страниц -- `login` - авторизация (с типом) -- `pack_opened` - открытие темы -- `test_started` / `test_completed` - тесты -- `game_started` / `game_completed` - игры -- `card_favorited` - добавление в избранное - -### 10. **🚀 CI/CD и деплой** -- GitHub Actions / другой CI? -- Автоматическая сборка при push -- Firebase Hosting / другой хостинг? -- Versioning и changelog - -### 11. **🔗 Deep Links и Share** -- Обработка `/pack/:id` из URL -- Share карточки / темы -- UTM параметры для аналитики -- Open Graph meta tags для соцсетей - -### 12. **⚡ Производительность** -- Lazy loading списков (pagination) -- Code splitting для роутов -- Tree shaking -- Минимизация bundle size -- Web Workers для тяжелых операций? - -### 13. **🎨 UI/UX детали** -- Loading states (shimmer) -- Empty states (нет тем, нет игр) -- Error states (красиво показывать ошибки) -- Animations и transitions -- Скелетоны для загрузки - -### 14. **📝 Логирование и мониторинг** -- Centralized logger -- Log levels (debug, info, warning, error) -- Firebase Crashlytics для web -- Performance monitoring -- User feedback механизм - -### 15. **🌐 SEO (для web важно!)** -- Meta tags (title, description) -- Open Graph для social media -- Structured data (JSON-LD) -- Sitemap generation -- robots.txt - -### 16. **♿ Accessibility** -- Semantic HTML -- ARIA labels -- Keyboard navigation -- Screen reader support -- Focus management diff --git a/mnemo_cards_web_v2/FUTURE_TASKS_PLAN.md b/mnemo_cards_web_v2/FUTURE_TASKS_PLAN.md deleted file mode 100644 index ae3524e..0000000 --- a/mnemo_cards_web_v2/FUTURE_TASKS_PLAN.md +++ /dev/null @@ -1,686 +0,0 @@ -# Future Tasks Plan - mnemo_cards_web_v2 - -**Created:** October 28, 2025 -**Status:** Active Development -**Current Phase:** API v2 Implementation & Feature Completion - ---- - -## 📋 Overview - -This document outlines the comprehensive plan for completing the mnemo_cards_web_v2 project. Tasks are organized by priority and dependency. - ---- - -## 🎯 Phase 1: Complete API v2 Backend Implementation - -**Priority:** HIGH -**Estimated Time:** 8-12 hours -**Dependencies:** None - -### 1.1 Fix JWT Service Implementation -**Status:** 🔴 Critical -**Time:** 2-3 hours - -**Tasks:** -- [ ] Replace placeholder HMAC-SHA256 with proper crypto library - - Use `crypto` package: `package:crypto/crypto.dart` - - Implement proper HMAC-SHA256 signing - - Add secret key management (environment variable or secure storage) -- [ ] Test JWT token generation and verification -- [ ] Add token expiration handling -- [ ] Implement refresh token blacklist storage (Isar model or in-memory cache) -- [ ] Add comprehensive error handling - -**Acceptance Criteria:** -- JWT tokens are properly signed with HMAC-SHA256 -- Token verification works correctly -- Token expiration is enforced -- Refresh tokens can be invalidated - -**Files to Modify:** -- `mnemo_cards_backend/lib/api/v2/jwt_service.dart` - ---- - -### 1.2 Complete Authentication API v2 -**Status:** 🟡 In Progress -**Time:** 2-3 hours - -**Tasks:** -- [ ] Verify Google OAuth flow works end-to-end -- [ ] Add Telegram authentication endpoint (future) -- [ ] Test token refresh mechanism -- [ ] Add rate limiting for auth endpoints -- [ ] Add comprehensive error responses -- [ ] Write integration tests - -**Acceptance Criteria:** -- Google OAuth flow works completely -- Token refresh works when access token expires -- Proper error messages for all failure scenarios -- Tests cover all auth flows - -**Files to Modify:** -- `mnemo_cards_backend/lib/api/v2/auth_api_v2.dart` - ---- - -### 1.3 Implement Packs API v2 -**Status:** 🟡 Partial -**Time:** 3-4 hours - -**Tasks:** -- [ ] Complete `GET /api/v2/packs` with proper pagination - - Query params: `?page=1&limit=20&search=term&language=lang` - - Return paginated response: `{ items: [], total: 0, page: 1, limit: 20 }` -- [ ] Implement `GET /api/v2/packs/{packId}` - - Return full pack details - - Include user's purchase status if authenticated -- [ ] Implement `GET /api/v2/packs/{packId}/cards` - - Return all cards in pack - - Support pagination if needed -- [ ] Implement `GET /api/v2/packs/{packId}/cards/{cardId}/image` - - Return card image (reuse existing v1 logic) -- [ ] Implement `GET /api/v2/packs/{packId}/tests` - - Return tests for pack -- [ ] Add filtering and search capabilities -- [ ] Write comprehensive tests - -**Acceptance Criteria:** -- All pack endpoints work correctly -- Pagination works properly -- Search and filtering work -- Tests cover all endpoints - -**Files to Modify:** -- `mnemo_cards_backend/lib/api/v2/packs_api_v2.dart` - ---- - -### 1.4 Implement Tests API v2 -**Status:** ⬜ Not Started -**Time:** 2-3 hours - -**Tasks:** -- [ ] Implement `GET /api/v2/tests/{testId}` - - Return test details -- [ ] Implement `POST /api/v2/tests/{testId}/results` - - Accept test results - - Validate results - - Save to database -- [ ] Implement `GET /api/v2/tests/{testId}/history` - - Return user's test attempt history - - Support pagination -- [ ] Write tests - -**Acceptance Criteria:** -- All test endpoints work correctly -- Results are properly saved -- History is correctly retrieved -- Tests cover all endpoints - -**Files to Create:** -- `mnemo_cards_backend/lib/api/v2/tests_api_v2.dart` - ---- - -### 1.5 Implement Games API v2 -**Status:** ⬜ Not Started -**Time:** 1-2 hours - -**Tasks:** -- [ ] Implement `GET /api/v2/games` - - Return all available games - - Include game metadata -- [ ] Implement `GET /api/v2/games/{gameId}/assets` - - Return game assets URL/info -- [ ] Write tests - -**Acceptance Criteria:** -- Games list endpoint works -- Game assets endpoint works -- Tests cover endpoints - -**Files to Create:** -- `mnemo_cards_backend/lib/api/v2/games_api_v2.dart` - ---- - -### 1.6 Implement Purchases API v2 -**Status:** ⬜ Not Started -**Time:** 4-5 hours - -**Tasks:** -- [ ] Implement `POST /api/v2/purchases/packs/{packId}` - - Create purchase intent - - Return purchase info -- [ ] Implement `GET /api/v2/purchases/packs/{packId}/status` - - Check if pack is purchased -- [ ] Implement `POST /api/v2/purchases/payments` - - Create payment (YooKassa integration) - - Return payment URL/redirect -- [ ] Implement `GET /api/v2/purchases/payments/{paymentId}/verify` - - Verify payment status - - Update user purchases on success -- [ ] Write tests - -**Acceptance Criteria:** -- Purchase flow works end-to-end -- Payment integration works -- Payment verification works -- User purchases are updated correctly - -**Files to Create:** -- `mnemo_cards_backend/lib/api/v2/purchases_api_v2.dart` - ---- - -### 1.7 Implement Subscriptions API v2 -**Status:** ⬜ Not Started -**Time:** 3-4 hours - -**Tasks:** -- [ ] Implement `GET /api/v2/subscriptions/plans` - - Return available subscription plans -- [ ] Implement `POST /api/v2/subscriptions` - - Create subscription (delegate to existing logic) -- [ ] Implement `GET /api/v2/subscriptions/me` - - Get current user's subscription -- [ ] Implement `DELETE /api/v2/subscriptions/me` - - Cancel subscription -- [ ] Write tests - -**Acceptance Criteria:** -- All subscription endpoints work -- Subscription creation works -- Cancellation works -- Tests cover all endpoints - -**Files to Create:** -- `mnemo_cards_backend/lib/api/v2/subscriptions_api_v2.dart` - ---- - -### 1.8 Implement Promocodes API v2 -**Status:** ⬜ Not Started -**Time:** 1-2 hours - -**Tasks:** -- [ ] Implement `GET /api/v2/promocodes` - - Return available promocodes (if public) - - Query params: `?active=true` -- [ ] Implement `POST /api/v2/promocodes/{code}/apply` - - Apply promocode - - Validate code - - Apply discount/benefit -- [ ] Write tests - -**Acceptance Criteria:** -- Promocode listing works -- Promocode application works -- Discounts are applied correctly -- Tests cover endpoints - -**Files to Create:** -- `mnemo_cards_backend/lib/api/v2/promocodes_api_v2.dart` - ---- - -### 1.9 Update Backend Routing -**Status:** 🟡 Partial -**Time:** 1 hour - -**Tasks:** -- [ ] Mount all v2 APIs in `mnemo_shelf.dart` -- [ ] Verify v2 routes don't conflict with v1 -- [ ] Test all v2 endpoints are accessible -- [ ] Add OpenAPI documentation for v2 endpoints - -**Acceptance Criteria:** -- All v2 APIs are mounted correctly -- No route conflicts -- All endpoints accessible - -**Files to Modify:** -- `mnemo_cards_backend/lib/api/mnemo_shelf.dart` - ---- - -## 🎯 Phase 2: Migrate Web App to Use API v2 - -**Priority:** HIGH -**Estimated Time:** 6-8 hours -**Dependencies:** Phase 1 (at least backend auth must be working) - -### 2.1 Complete HttpRepositoryV2 Implementation -**Status:** 🟡 Partial -**Time:** 2-3 hours - -**Tasks:** -- [ ] Add missing methods to `HttpRepositoryV2`: - - Purchase methods (`createPackPurchase`, `verifyPayment`, etc.) - - Subscription methods (`getSubscriptionPlans`, `purchaseSubscription`, `cancelSubscription`) - - Promocode methods (`getPromocodes`, `applyPromocode`) - - User methods (`updateUserSettings`, `getUserPurchases`, `getUserStatistics`) -- [ ] Ensure all methods match API v2 endpoints -- [ ] Add proper error handling -- [ ] Write unit tests - -**Acceptance Criteria:** -- All v2 API endpoints are accessible via HttpRepositoryV2 -- Error handling is consistent -- Tests cover all methods - -**Files to Modify:** -- `mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart` - ---- - -### 2.2 Migrate PackManager to Use v2 -**Status:** ⬜ Not Started -**Time:** 1-2 hours - -**Tasks:** -- [ ] Update `PackManager` to use `HttpRepositoryV2` instead of `HttpRepository` -- [ ] Update method calls to use v2 endpoints -- [ ] Update error handling -- [ ] Write/update tests - -**Acceptance Criteria:** -- PackManager uses v2 API -- All pack operations work -- Tests pass - -**Files to Modify:** -- `mnemo_cards_web_v2/lib/domain/services/pack_manager.dart` -- `mnemo_cards_web_v2/test/domain/services/pack_manager_test.dart` - ---- - -### 2.3 Migrate GamesManager to Use v2 -**Status:** 🟡 Partial -**Time:** 1 hour - -**Tasks:** -- [x] Update `GamesManager` to use `HttpRepositoryV2` -- GamesManager uses v2 API -- Games load correctly -- Tests pass - -**Files to Modify:** -- `mnemo_cards_web_v2/lib/domain/services/games_manager.dart` -- `mnemo_cards_web_v2/test/domain/services/games_manager_test.dart` - ---- - -### 2.4 Migrate TestManager to Use v2 -**Status:** 🟡 Partial -**Time:** 1-2 hours - -**Tasks:** -- [x] Update `TestManager` to use `HttpRepositoryV2` -- TestManager uses v2 API -- Tests load and submit correctly -- Tests pass - -**Files to Modify:** -- `mnemo_cards_web_v2/lib/domain/services/test_manager.dart` -- `mnemo_cards_web_v2/test/domain/services/test_manager_test.dart` - ---- - -### 2.5 Migrate Other Services to Use v2 -**Status:** 🟡 Partial -**Time:** 2-3 hours - -**Tasks:** -- [x] Update `SubscriptionService` to use `HttpRepositoryV2` -- [x] Update `PromocodeService` to use `HttpRepositoryV2` -- [ ] Update `StatisticsService` to use v2 (if needed) -- [ ] Update `PackProgressService` to use v2 (if needed) -- [ ] Update tests for all services - -**Acceptance Criteria:** -- All services use v2 API -- All functionality works -- Tests pass - -**Files to Modify:** -- `mnemo_cards_web_v2/lib/domain/services/subscription_service.dart` -- `mnemo_cards_web_v2/lib/domain/services/promocode_service.dart` -- Related test files - ---- - -### 2.6 Remove V1 Dependencies -**Status:** ⬜ Not Started -**Time:** 1 hour - -**Tasks:** -- [ ] Remove deprecated `HttpRepository` from dependency injection -- [ ] Remove deprecated `ApiConfig` usage (or mark clearly deprecated) -- [ ] Update all references to use v2 -- [ ] Clean up unused code - -**Acceptance Criteria:** -- No v1 dependencies remain in web app -- Code is clean -- No deprecation warnings - ---- - -## 🎯 Phase 3: Feature Implementation - -**Priority:** MEDIUM -**Estimated Time:** 12-16 hours -**Dependencies:** Phase 2 complete - -### 3.1 Pack Purchase Flow -**Status:** ⬜ Not Started** -**Time:** 6-8 hours - -**Tasks:** -- [ ] Create `PurchaseService` using `HttpRepositoryV2` -- [ ] Implement purchase flow: - - Check if pack is owned - - Show "Buy Pack" button if not owned - - Create payment via API v2 - - Handle payment redirect - - Verify payment after return - - Update UI to show purchased packs -- [ ] Create purchase UI: - - Purchase confirmation dialog - - Payment redirect handling - - Payment status display -- [ ] Write unit tests -- [ ] Write integration tests - -**Acceptance Criteria:** -- Users can purchase packs -- Payment flow works end-to-end -- UI updates correctly after purchase -- Tests cover purchase flow - -**Files to Create:** -- `mnemo_cards_web_v2/lib/domain/services/purchase_service.dart` -- `lib/presentation/pages/purchase/purchase_page.dart` (if needed) -- `lib/di/user_scope/modules/purchase_module.dart` - -**Files to Modify:** -- `lib/presentation/pages/pack_details/pack_details_page.dart` -- `lib/presentation/widgets/pack_card.dart` - ---- - -### 3.2 Enhanced Subscription Management -**Status:** 🟡 Partial -**Time:** 4-5 hours - -**Tasks:** -- [ ] Create subscription page UI -- [ ] Display subscription plans -- [ ] Implement subscription purchase -- [ ] Implement subscription cancellation -- [ ] Show subscription status on ProfilePage -- [ ] Add subscription benefits UI -- [ ] Write tests - -**Acceptance Criteria:** -- Subscription page works -- Purchase flow works -- Cancellation works -- UI displays subscription status correctly - -**Files to Create:** -- `lib/presentation/pages/subscription/subscription_page.dart` - -**Files to Modify:** -- `lib/presentation/pages/profile/profile_page.dart` -- `lib/domain/services/subscription_service.dart` - ---- - -### 3.3 Promocode UI -**Status:** ⬜ Not Started -**Time:** 2-3 hours - -**Tasks:** -- [ ] Create promocode input widget -- [ ] Add promocode section to ProfilePage or PurchasePage -- [ ] Implement promocode application flow -- [ ] Show promocode benefits/status -- [ ] Handle promocode errors -- [ ] Write tests - -**Acceptance Criteria:** -- Users can enter promocodes -- Promocodes are applied correctly -- Error handling works -- UI feedback is clear - -**Files to Create:** -- `lib/presentation/widgets/promocode_input.dart` - -**Files to Modify:** -- `lib/presentation/pages/profile/profile_page.dart` - ---- - -## 🎯 Phase 4: Quality & Testing - -**Priority:** MEDIUM -**Estimated Time:** 8-10 hours -**Dependencies:** Phase 2-3 complete - -### 4.1 Comprehensive Testing -**Status:** ⬜ Not Started -**Time:** 6-8 hours - -**Tasks:** -- [ ] Write unit tests for all v2 API endpoints (backend) -- [ ] Write unit tests for `HttpRepositoryV2` (web app) -- [ ] Write integration tests for auth flow -- [ ] Write integration tests for pack browsing -- [ ] Write integration tests for purchase flow -- [ ] Write integration tests for subscription flow -- [ ] Ensure test coverage >80% for all new code - -**Acceptance Criteria:** -- All new code has tests -- Test coverage >80% -- All tests pass - ---- - -### 4.2 Fix Remaining Test Failures -**Status:** 🟡 In Progress -**Time:** 1-2 hours - -**Tasks:** -- [ ] Fix `test_page_test.dart` (empty file causing compilation errors) -- [ ] Investigate other failing tests -- [ ] Fix all test failures -- [ ] Ensure all tests pass - -**Acceptance Criteria:** -- All tests pass -- No compilation errors in tests - ---- - -### 4.3 Code Quality Improvements -**Status:** ⬜ Not Started -**Time:** 2-3 hours - -**Tasks:** -- [ ] Run `flutter analyze` and fix all warnings -- [ ] Fix linter errors -- [ ] Improve code documentation -- [ ] Add JSDoc comments to public APIs -- [ ] Refactor any complex code - -**Acceptance Criteria:** -- No linter warnings -- Code is well-documented -- Code follows project patterns - ---- - -## 🎯 Phase 5: Additional Features (Lower Priority) - -**Priority:** LOW -**Estimated Time:** 12-16 hours -**Dependencies:** Phases 1-4 complete - -### 5.1 Vocabulary/Review Page -**Status:** ⬜ Not Started -**Time:** 6-8 hours - -**Tasks:** -- [ ] Create `VocabularyPage` in bottom navigation -- [ ] Fetch all learned cards across packs -- [ ] Implement filtering by pack/language -- [ ] Implement search functionality -- [ ] Create review interface -- [ ] Add export functionality -- [ ] Write tests - -**Files to Create:** -- `lib/presentation/pages/vocabulary/vocabulary_page.dart` -- `lib/domain/services/vocabulary_service.dart` -- `lib/domain/state/vocabulary_state_manager.dart` -- `lib/di/user_scope/modules/vocabulary_module.dart` - ---- - -### 5.2 Settings Page -**Status:** ⬜ Not Started -**Time:** 2-3 hours - -**Tasks:** -- [ ] Create separate `SettingsPage` -- [ ] Move settings from ProfilePage -- [ ] Add theme toggle -- [ ] Add language selection -- [ ] Add sound effects toggle -- [ ] Add notifications settings -- [ ] Implement settings persistence -- [ ] Write tests - -**Files to Create:** -- `lib/presentation/pages/settings/settings_page.dart` -- `lib/domain/state/settings_state_manager.dart` - ---- - -### 5.3 Telegram Authentication (Code-based) -**Status:** 🔴 Blocked -**Time:** 8-10 hours - -**Tasks:** -- [ ] Design auth flow (code generation, validation, timeout) -- [ ] Add backend endpoints: - - `POST /api/v2/auth/telegram/request` - Request auth code - - `POST /api/v2/auth/telegram/verify` - Verify code and return token -- [ ] Update telegram bot with `/auth` command -- [ ] Implement code generation and storage in bot -- [ ] Add `TelegramAuthService` in web app -- [ ] Create `TelegramAuthPage` UI -- [ ] Integrate with existing `AuthService` -- [ ] Add timeout handling (codes expire after 5 min) -- [ ] Write tests - -**Blocker:** Requires backend API endpoints and telegram bot modifications - ---- - -## 🎯 Phase 6: Documentation & Deployment - -**Priority:** LOW -**Estimated Time:** 4-6 hours -**Dependencies:** Phases 1-4 complete - -### 6.1 API Documentation -**Tasks:** -- [ ] Generate OpenAPI/Swagger documentation for v2 -- [ ] Document all v2 endpoints -- [ ] Add request/response examples -- [ ] Document authentication flow -- [ ] Create API migration guide - ---- - -### 6.2 Deployment Preparation -**Tasks:** -- [ ] Update production API URLs -- [ ] Configure CORS for production -- [ ] Set up JWT secret key management -- [ ] Test deployment to staging -- [ ] Create deployment checklist - ---- - -## 📊 Priority Matrix - -### 🔴 High Priority (Complete First) -1. Fix JWT Service crypto implementation -2. Complete backend auth API v2 -3. Migrate web app services to use v2 -4. Implement pack purchase flow - -### 🟡 Medium Priority (Complete Next) -1. Complete remaining backend v2 endpoints -2. Implement subscription management UI -3. Comprehensive testing -4. Fix test failures - -### 🟢 Low Priority (Complete When Time Allows) -1. Vocabulary/Review page -2. Settings page -3. Telegram authentication -4. API documentation -5. Deployment preparation - ---- - -## 📈 Estimated Timeline - -**Phase 1 (Backend v2):** 8-12 hours -**Phase 2 (Web Migration):** 6-8 hours -**Phase 3 (Features):** 12-16 hours -**Phase 4 (Quality):** 8-10 hours -**Phase 5 (Additional Features):** 12-16 hours (optional) -**Phase 6 (Documentation):** 4-6 hours (optional) - -**Total Core Work (Phases 1-4):** ~34-46 hours -**Total Including Optional:** ~50-68 hours - ---- - -## 🎯 Success Criteria - -The project will be considered complete when: - -1. ✅ API v2 is fully implemented on backend -2. ✅ Web app uses API v2 exclusively -3. ✅ All core features work (auth, packs, tests, purchases, subscriptions) -4. ✅ Test coverage >80% -5. ✅ All tests pass -6. ✅ No critical bugs -7. ✅ Code follows project patterns and conventions - ---- - -## 📝 Notes - -- **Backward Compatibility:** V1 APIs should remain functional for mobile app -- **Testing:** Write tests as features are implemented, not after -- **Documentation:** Update PROGRESS.md and TODO.md after each major task -- **Code Quality:** Follow clean architecture, yx_scope, yx_state patterns -- **Web Only:** Remember this is a web app - no mobile/macOS features needed - ---- - -**Last Updated:** October 28, 2025 - diff --git a/mnemo_cards_web_v2/GAME_TESTS_IMPLEMENTATION_PLAN.md b/mnemo_cards_web_v2/GAME_TESTS_IMPLEMENTATION_PLAN.md deleted file mode 100644 index a5bd5f4..0000000 --- a/mnemo_cards_web_v2/GAME_TESTS_IMPLEMENTATION_PLAN.md +++ /dev/null @@ -1,208 +0,0 @@ -# План реализации игровых тестов в mnemo_cards_web_v2 - -## Анализ текущей архитектуры - -### mnemo_cards (референс) -- **Архитектура**: Bloc + Service Locator (GetIt) -- **Типы вопросов**: - - `SimpleTestQuestionBody`: выбор одного варианта из нескольких кнопок - - `InputButtonsTestQuestionBody`: ввод слова по буквам с кнопками -- **Управление состоянием**: `TestManager` (Cubit) + `ActiveTestHolder` (Bloc) -- **Хранение состояния**: `TestQuestionState` (с подклассами) -- **UI**: PageView с вопросами, прогресс, результаты - -### mnemo_cards_web_v2 (текущая) -- **Архитектура**: Чистая архитектура с yx_scope/yx_state -- **Модули**: `TestsModule`, `TestsStateManager` (StateManager) -- **Текущая реализация**: базовый `TestPage` без полноценной игровой механики - -## Цели реализации - -1. **Простые тесты**: начать с выбора 1 варианта из нескольких (аналог SimpleTest) -2. **Архитектура**: придерживаться yx_state/yx_scope, не копировать код mnemo_cards -3. **Прогрессивная разработка**: от простого к сложному - -## Фазы реализации - -### Фаза 1: Базовая инфраструктура для игровых тестов - -#### 1.1 Расширение модели данных -- Создать `domain/models/game_question.dart` -- Определить `GameQuestion` с типами: `multipleChoice`, `inputLetters` -- Добавить `GameQuestionState` для отслеживания прогресса - -#### 1.2 Game Session Manager -- Создать `domain/services/game_session_manager.dart` -- Управление активной игровой сессией -- Отслеживание ответов, времени, прогресса -- Автоматический переход к следующему вопросу - -#### 1.3 Game State Manager -- Расширить `domain/state/tests_state_manager.dart` -- Добавить состояния: `playing`, `questionCompleted`, `sessionCompleted` -- Управление игровым потоком - -#### 1.4 Базовые UI компоненты -- `presentation/widgets/game/question_display.dart` - отображение вопроса -- `presentation/widgets/game/answer_options.dart` - варианты ответов -- `presentation/widgets/game/progress_indicator.dart` - прогресс - -### Фаза 2: Простые тесты с выбором ответа - -#### 2.1 Модель данных для Multiple Choice -```dart -class MultipleChoiceQuestion extends GameQuestion { - final String question; - final String? image; - final String? audio; - final List options; - final String correctAnswer; - final String word; // связанное слово для статистики -} -``` - -#### 2.2 Game Session для Multiple Choice -- Управление выбором ответа -- Валидация правильности -- Автоматический переход через 300мс при правильном ответе -- Визуальная обратная связь (зеленый/красный) - -#### 2.3 UI компоненты -- `MultipleChoiceWidget` - основной виджет вопроса -- Анимации выбора ответа -- Звуковые эффекты (опционально) - -### Фаза 3: Расширенные возможности - -#### 3.1 Статистика и аналитика -- Отправка результатов в `statistics_service.dart` -- Трекинг правильных/неправильных ответов -- Время ответа на вопрос - -#### 3.2 Игровые улучшения -- Таймер на вопрос (опционально) -- Подсказки -- Пропуск вопросов - -#### 3.3 UX улучшения -- Анимации переходов -- Звуковое сопровождение -- Темная тема адаптация - -### Фаза 4: Сложные типы вопросов - -#### 4.1 Input Letters (ввод по буквам) -- Аналог `InputButtonsTestQuestionBody` -- Кнопки с буквами -- Валидация введенного слова - -#### 4.2 Match Questions (соответствие) -- Связывание элементов -- Drag & Drop - -#### 4.3 Matrix Questions (матрица) -- Более сложные комбинации - -## Технические решения - -### Архитектура состояний -``` -GameSessionState -├── sessionNotStarted -├── questionInProgress -│ ├── currentQuestion: GameQuestion -│ ├── selectedAnswer: String? -│ ├── timeElapsed: Duration -│ └── isCorrect: bool? -├── questionCompleted -│ ├── correct: bool -│ └── nextQuestionDelay: Duration -└── sessionCompleted - ├── results: GameResults - └── statistics: TestStatisticsDto -``` - -### Навигация вопросов -- Использовать `PageView` для swipe навигации -- Блокировать swipe назад после ответа -- Автоматический переход вперед при правильном ответе - -### Управление ресурсами -- Preload изображений и аудио -- Кэширование через `image_cache_service.dart` -- Освобождение ресурсов при завершении сессии - -## Порядок реализации - -### Шаг 1: Базовая инфраструктура ✅ -1. Создать модели данных -2. Реализовать GameSessionManager -3. Расширить TestsStateManager -4. Создать базовые UI компоненты - -### Шаг 2: Multiple Choice тесты 🔄 -1. Создать MultipleChoiceQuestion модель -2. Реализовать логику выбора ответа -3. Создать UI компоненты -4. Интегрировать с существующим TestPage - -### Шаг 3: Статистика и аналитика -1. Интеграция со StatisticsService -2. Отправка результатов -3. Сохранение прогресса - -### Шаг 4: UX улучшения -1. Анимации -2. Звуки -3. Темная тема - -### Шаг 5: Дополнительные типы вопросов -1. Input Letters -2. Match questions -3. Matrix questions - -## Критерии готовности - -### Функциональные требования -- ✅ Загрузка тестов из API -- ✅ Отображение вопросов с текстом/изображениями/аудио -- ✅ Выбор ответа из нескольких вариантов -- ✅ Визуальная обратная связь -- ✅ Автоматический переход к следующему вопросу -- ✅ Показ результатов по завершении -- ✅ Отправка статистики на бэкенд - -### Нефункциональные требования -- ⚡ Быстрая загрузка и навигация -- 🎯 Адаптивный UI для разных экранов -- ♿ Доступность (accessibility) -- 🎨 Соответствие дизайну приложения - -## Риски и mitigation - -### Риск 1: Сложность интеграции с существующей архитектурой -**Mitigation**: Начать с малого, постепенно расширять - -### Риск 2: Производительность при большом количестве вопросов -**Mitigation**: Ленивая загрузка, preload ближайших вопросов - -### Риск 3: UX несоответствия с мобильной версией -**Mitigation**: Регулярные проверки с дизайнерами, usability testing - -## Следующие шаги - -1. **Немедленно**: Создать модели данных и базовую инфраструктуру -2. **Краткосрочные**: Реализовать Multiple Choice тесты -3. **Среднесрочные**: Добавить статистику и улучшения UX -4. **Долгосрочные**: Расширить на другие типы вопросов - -## Тестирование - -- Unit тесты для всех сервисов и менеджеров -- Widget тесты для UI компонентов -- Integration тесты для полного игрового потока -- E2E тесты с реальными данными - ---- - -*План составлен на основе анализа mnemo_cards и архитектуры mnemo_cards_web_v2. Реализация будет вестись итеративно с постоянным тестированием.* diff --git a/mnemo_cards_web_v2/PLAN.md b/mnemo_cards_web_v2/PLAN.md deleted file mode 100644 index 59b65e3..0000000 --- a/mnemo_cards_web_v2/PLAN.md +++ /dev/null @@ -1,780 +0,0 @@ -# План разработки mnemo_cards_web_v2 - -## 📋 Описание проекта - -Flutter web приложение для изучения языков с использованием **yx_scope** и **yx_state** для управления зависимостями и состоянием. - -### Основные функции: -- 📚 Изучение языков через карточки и темы -- 🎮 Мини-игры для запоминания -- 👤 Профиль пользователя со статистикой -- 🔐 Авторизация через Google и Telegram -- 👻 Гостевой режим (без авторизации) - ---- - -## 🏗️ Архитектура (yx_scope) - -### Иерархия скоупов: - -``` -AppScope (корневой, всегда существует) - ├── AuthModule (модуль авторизации) - ├── RouterModule (модуль навигации) - ├── AnalyticsModule (модуль аналитики) - └── UserScope (дочерний скоуп, создается при входе) - ├── PacksModule (модуль тем/карточек) - ├── GamesModule (модуль игр) - └── ProfileModule (модуль профиля) -``` - -### Детальное описание скоупов: - -#### **AppScope** -*Жизненный цикл: весь запуск приложения* - -**Зависимости:** -- `Dio` - HTTP клиент -- `GoRouter` - роутинг приложения -- `FirebaseApp` - Firebase инстанс -- `FirebaseAnalytics` - аналитика -- `SharedPreferences` - локальное хранилище -- `UserScopeHolder` - холдер для UserScope -- `AuthService` - сервис авторизации (работает с Firebase Auth, Google Sign-In, Telegram) -- `RemoteConfigService` - Remote Config -- `ThemeStateManager` - управление темой (yx_state) - -**Интерфейс:** -```dart -abstract class AppScope implements Scope { - GoRouter get router; - FirebaseAnalytics get analytics; - AuthService get authService; - UserScopeHolder get userScopeHolder; - ThemeStateManager get themeManager; - SharedPreferences get sharedPreferences; -} -``` - -**Модули:** -- `AuthModule` - Google/Telegram авторизация -- `RouterModule` - настройка роутинга -- `AnalyticsModule` - Firebase Analytics, Crashlytics -- `StorageModule` - SharedPreferences, SecureStorage - ---- - -#### **UserScope** -*Жизненный цикл: от входа пользователя до выхода (или с начала для гостя)* - -**Зависимости:** -- `UserStateManager` - состояние пользователя (yx_state) -- `HttpRepositoryV2` - API запросы с токеном пользователя -- `PackManager` - управление темами/карточками -- `GamesManager` - управление играми -- `FavoriteCardsManager` - избранные карточки -- `TestStateManager` - состояние тестов -- `StatisticsService` - статистика пользователя - -**Интерфейс:** -```dart -abstract class UserScope implements Scope { - UserStateManager get userStateManager; - PackManager get packManager; - GamesManager get gamesManager; - StatisticsService get statisticsService; -} - -// Интерфейс для родителя (AppScope должен его реализовать) -abstract class UserScopeParent implements Scope { - GoRouter get router; - FirebaseAnalytics get analytics; - AuthService get authService; - SharedPreferences get sharedPreferences; -} -``` - -**Модули:** -- `PacksModule` - работа с темами и карточками -- `GamesModule` - загрузка и запуск игр -- `ProfileModule` - статистика, настройки профиля - -**Типы пользователей:** -- **Гость** - `UserScope` создается без авторизации, `UserDto` = null -- **Авторизованный** - `UserScope` с `UserDto` после логина - ---- - -## 🎨 UI Структура (3 вкладки) - -### 1. **Темы (HomePage)** -- Список доступных тем (`CardPackDto`) -- Карточки тем с превью -- Переход к просмотру карточек темы -- Фильтры и поиск - -### 2. **Игры (GamesPage)** -- Список доступных игр (`GameDto`) -- Кнопки запуска игр -- Интеграция с WebView играми -- Прогресс по играм - -### 3. **Профиль (ProfilePage)** -- Статистика изучения -- Кнопка входа/выхода -- Настройки (тема, звук, etc) -- Промокоды и подписка - ---- - -## 📦 State Management (yx_state) - -### State Managers: - -#### 1. **ThemeStateManager** (в AppScope) -```dart -class ThemeState { - final ThemeMode mode; - const ThemeState(this.mode); -} - -class ThemeStateManager extends StateManager { - ThemeStateManager(SharedPreferences prefs) - : super(ThemeState(_loadFromPrefs(prefs))); - - void toggleTheme() => handle((emit) async { - final newMode = state.mode == ThemeMode.light - ? ThemeMode.dark - : ThemeMode.light; - emit(ThemeState(newMode)); - await _saveToPrefs(newMode); - }); -} -``` - -#### 2. **UserStateManager** (в UserScope) -```dart -@freezed -class UserState with _$UserState { - const factory UserState.guest() = _Guest; - const factory UserState.authenticated({ - required UserDto user, - }) = _Authenticated; - const factory UserState.loading() = _Loading; -} - -class UserStateManager extends StateManager { - UserStateManager() : super(const UserState.guest()); - - void setUser(UserDto user) => handle((emit) async { - emit(UserState.authenticated(user: user)); - }); - - void logout() => handle((emit) async { - emit(const UserState.guest()); - }); -} -``` - -#### 3. **PacksStateManager** (в UserScope) -```dart -@freezed -class PacksState with _$PacksState { - const factory PacksState.loading() = _Loading; - const factory PacksState.loaded(List packs) = _Loaded; - const factory PacksState.error(String message) = _Error; -} - -class PacksStateManager extends StateManager { - final HttpRepositoryV2 _repository; - - PacksStateManager(this._repository) - : super(const PacksState.loading()); - - Future loadPacks() => handle((emit) async { - emit(const PacksState.loading()); - try { - final packs = await _repository.getPacks(); - emit(PacksState.loaded(packs)); - } catch (e) { - emit(PacksState.error(e.toString())); - } - }); -} -``` - -#### 4. **GamesStateManager** (в UserScope) -```dart -@freezed -class GamesState with _$GamesState { - const factory GamesState.loading() = _Loading; - const factory GamesState.loaded(List games) = _Loaded; - const factory GamesState.error(String message) = _Error; -} -``` - ---- - -## 🔐 Авторизация - -### Процесс авторизации: - -#### **Гостевой режим:** -```dart -// При запуске приложения -void main() async { - final appScopeHolder = AppScopeHolder(); - await appScopeHolder.create(); - - // Создаем UserScope для гостя сразу - final appScope = appScopeHolder.scope!; - await appScope.userScopeHolder.create(); - - runApp(App(appScopeHolder: appScopeHolder)); -} -``` - -#### **Google авторизация:** -```dart -class AuthService { - final GoogleSignIn _googleSignIn; - final HttpRepositoryV2 _repository; - - Future loginWithGoogle() async { - final account = await _googleSignIn.signIn(); - final auth = await account.authentication; - - // Отправляем токен на backend - final (user, token) = await _repository.createOrGetUser( - auth.idToken!, - ExternalIdType.google, - account.email, - account.displayName, - ); - - return user; - } -} -``` - -#### **Telegram авторизация:** -```dart -class AuthService { - Future loginWithTelegram(TelegramWebAppData data) async { - final (user, token) = await _repository.createOrGetUser( - data.user.id.toString(), - ExternalIdType.telegram, - 'no-email-tg', - data.user.username, - ); - - return user; - } -} -``` - -### Переключение между гостем и авторизованным: -```dart -// В AuthPage после успешной авторизации -final user = await authService.loginWithGoogle(); -userScopeHolder.scope!.userStateManager.setUser(user); - -// При выходе -await userStateManager.logout(); -// UserScope НЕ удаляется, просто переходит в guest режим -``` - ---- - -## 🚦 Навигация (go_router) - -### Структура роутов: - -```dart -final router = GoRouter( - initialLocation: '/home', - routes: [ - ShellRoute( - builder: (context, state, child) => MainShell(child: child), - routes: [ - GoRoute( - path: '/home', - builder: (context, state) => const HomePage(), - ), - GoRoute( - path: '/games', - builder: (context, state) => const GamesPage(), - ), - GoRoute( - path: '/profile', - builder: (context, state) => const ProfilePage(), - ), - ], - ), - GoRoute( - path: '/auth', - builder: (context, state) => const AuthPage(), - ), - GoRoute( - path: '/pack/:id', - builder: (context, state) => PackDetailsPage( - packId: state.pathParameters['id']!, - ), - ), - GoRoute( - path: '/test/:packId', - builder: (context, state) => TestPage( - packId: state.pathParameters['packId']!, - ), - ), - ], -); -``` - -### MainShell - Bottom Navigation: -```dart -class MainShell extends StatelessWidget { - final Widget child; - - @override - Widget build(BuildContext context) { - return Scaffold( - body: child, - bottomNavigationBar: BottomNavigationBar( - items: [ - BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Темы'), - BottomNavigationBarItem(icon: Icon(Icons.games), label: 'Игры'), - BottomNavigationBarItem(icon: Icon(Icons.person), label: 'Профиль'), - ], - onTap: (index) { - switch (index) { - case 0: context.go('/home'); - case 1: context.go('/games'); - case 2: context.go('/profile'); - } - }, - ), - ); - } -} -``` - ---- - -## 📚 Зависимости (pubspec.yaml) - -### Обновленный pubspec.yaml: - -```yaml -dependencies: - flutter: - sdk: flutter - - # YX Framework - yx_scope: ^1.1.2 - yx_scope_flutter: ^1.1.2 - yx_state: ^1.0.0 - yx_state_flutter: ^1.0.0 - - # Общие пакеты проекта - mnemo_cards_common: - path: ../mnemo_cards_common - mnemo_cards_frontend_common: - path: ../mnemo_cards_frontend_common - - # Роутинг - go_router: ^14.2.0 - - # HTTP - dio: ^5.3.3 - - # State Management helpers - rxdart: ^0.28.0 - - # Firebase - firebase_core: ^3.3.0 - firebase_auth: ^5.3.1 - firebase_analytics: ^11.2.1 - firebase_crashlytics: ^4.0.4 - firebase_remote_config: ^5.4.7 - - # Авторизация - google_sign_in: ^6.2.1 - # telegram_web_app: ^0.3.1 (если нужно) - - # Code Generation - freezed_annotation: ^2.4.1 - json_annotation: ^4.7.0 - - # Storage - shared_preferences: ^2.2.3 - flutter_secure_storage: ^9.2.2 - - # UI - flutter_screenutil: ^5.9.0 - shimmer: ^3.0.0 - auto_size_text: ^3.0.0 - fl_chart: ^0.68.0 - - # Utils - universal_image: ^1.0.10 - url_launcher: ^6.2.6 - package_info_plus: ^8.0.0 - -dev_dependencies: - flutter_test: - sdk: flutter - - # Code Generation - build_runner: ^2.4.13 - freezed: ^2.4.5 - json_serializable: ^6.8.0 - - # Linting - flutter_lints: ^6.0.0 - yx_scope_linter: ^1.1.0 - custom_lint: ^0.5.3 -``` - ---- - -## 📁 Структура проекта - -``` -lib/ -├── main.dart # Точка входа -├── app.dart # Главный виджет приложения -│ -├── di/ # Dependency Injection (yx_scope) -│ ├── app_scope/ -│ │ ├── app_scope_container.dart # Контейнер AppScope -│ │ ├── app_scope_holder.dart # Холдер AppScope -│ │ ├── app_scope.dart # Интерфейс AppScope -│ │ └── modules/ -│ │ ├── auth_module.dart # Модуль авторизации -│ │ ├── router_module.dart # Модуль роутинга -│ │ ├── analytics_module.dart # Модуль аналитики -│ │ └── storage_module.dart # Модуль хранилища -│ │ -│ └── user_scope/ -│ ├── user_scope_container.dart # Контейнер UserScope -│ ├── user_scope_holder.dart # Холдер UserScope -│ ├── user_scope.dart # Интерфейс UserScope -│ └── modules/ -│ ├── packs_module.dart # Модуль тем/карточек -│ ├── games_module.dart # Модуль игр -│ └── profile_module.dart # Модуль профиля -│ -├── domain/ # Бизнес-логика -│ ├── models/ # Модели (из mnemo_cards_common) -│ ├── services/ -│ │ ├── auth_service.dart # Сервис авторизации -│ │ ├── http_repository_v2.dart # HTTP клиент (Bearer OAuth2) -│ │ ├── pack_manager.dart # Менеджер тем -│ │ ├── games_manager.dart # Менеджер игр -│ │ └── statistics_service.dart # Сервис статистики -│ │ -│ └── state/ # State Managers (yx_state) -│ ├── theme_state_manager.dart -│ ├── user_state_manager.dart -│ ├── packs_state_manager.dart -│ └── games_state_manager.dart -│ -├── presentation/ # UI слой -│ ├── router/ -│ │ └── app_router.dart # Конфигурация go_router -│ │ -│ ├── pages/ -│ │ ├── home/ -│ │ │ ├── home_page.dart # Страница "Темы" -│ │ │ └── widgets/ -│ │ │ -│ │ ├── games/ -│ │ │ ├── games_page.dart # Страница "Игры" -│ │ │ └── widgets/ -│ │ │ -│ │ ├── profile/ -│ │ │ ├── profile_page.dart # Страница "Профиль" -│ │ │ └── widgets/ -│ │ │ -│ │ ├── auth/ -│ │ │ └── auth_page.dart # Страница авторизации -│ │ │ -│ │ ├── pack_details/ -│ │ │ └── pack_details_page.dart # Детали темы -│ │ │ -│ │ └── test/ -│ │ └── test_page.dart # Страница теста -│ │ -│ ├── widgets/ # Общие виджеты -│ │ ├── app_bar.dart -│ │ ├── bottom_nav_bar.dart -│ │ ├── pack_card.dart -│ │ ├── game_card.dart -│ │ └── statistics_chart.dart -│ │ -│ └── theme/ -│ └── app_theme.dart # Темы приложения -│ -└── utils/ # Утилиты - ├── logger.dart - ├── extensions.dart - └── constants.dart -``` - ---- - -## 🔄 Жизненный цикл приложения - -### 1. Запуск приложения: - -```dart -void main() async { - WidgetsFlutterBinding.ensureInitialized(); - - // Инициализация Firebase - await Firebase.initializeApp(); - - // Создание AppScope - final appScopeHolder = AppScopeHolder(); - await appScopeHolder.create(); - - // Создание UserScope для гостя - final appScope = appScopeHolder.scope!; - await appScope.userScopeHolder.create(); - - runApp(App(appScopeHolder: appScopeHolder)); -} -``` - -### 2. Структура App виджета: - -```dart -class App extends StatelessWidget { - final AppScopeHolder appScopeHolder; - - const App({required this.appScopeHolder, super.key}); - - @override - Widget build(BuildContext context) { - return ScopeProvider( - holder: appScopeHolder, - child: ScopeBuilder.withPlaceholder( - builder: (context, appScope) { - // Вложенный ScopeProvider для UserScope - return ScopeProvider( - holder: appScope.userScopeHolder, - child: ScopeBuilder.withPlaceholder( - builder: (context, userScope) { - return StateManagerBuilder( - stateManager: appScope.themeManager, - builder: (context, themeState) { - return MaterialApp.router( - routerConfig: appScope.router, - theme: AppTheme.light, - darkTheme: AppTheme.dark, - themeMode: themeState.mode, - ); - }, - ); - }, - placeholder: const Center( - child: CircularProgressIndicator(), - ), - ), - ); - }, - placeholder: const Center( - child: CircularProgressIndicator(), - ), - ), - ); - } -} -``` - -### 3. Авторизация: - -```dart -// В AuthPage -class AuthPage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return ScopeBuilder( - builder: (context, appScope) { - return ScopeBuilder( - builder: (context, userScope) { - return Column( - children: [ - ElevatedButton( - onPressed: () async { - // Логин через Google - final user = await appScope.authService - .loginWithGoogle(); - - // Обновляем состояние пользователя - userScope.userStateManager.setUser(user); - - // Роутер автоматически перенаправит на home - context.go('/home'); - }, - child: Text('Войти через Google'), - ), - ElevatedButton( - onPressed: () async { - // Логин через Telegram - final user = await appScope.authService - .loginWithTelegram(); - userScope.userStateManager.setUser(user); - context.go('/home'); - }, - child: Text('Войти через Telegram'), - ), - TextButton( - onPressed: () { - // Войти как гость (UserScope уже создан) - context.go('/home'); - }, - child: Text('Продолжить как гость'), - ), - ], - ); - }, - ); - }, - ); - } -} -``` - -### 4. Использование в страницах: - -```dart -// HomePage -class HomePage extends StatelessWidget { - @override - Widget build(BuildContext context) { - return ScopeBuilder( - builder: (context, userScope) { - return StateManagerBuilder( - stateManager: userScope.packsStateManager, - builder: (context, state) { - return state.when( - loading: () => CircularProgressIndicator(), - loaded: (packs) => ListView.builder( - itemCount: packs.length, - itemBuilder: (context, index) { - return PackCard(pack: packs[index]); - }, - ), - error: (message) => Text('Error: $message'), - ); - }, - ); - }, - ); - } -} -``` - ---- - -## 🎯 Этапы разработки - -### **Этап 1: Основа (1-2 дня)** -- [x] Создать структуру проекта -- [ ] Настроить pubspec.yaml с зависимостями -- [ ] Создать AppScope (контейнер, холдер, интерфейс) -- [ ] Создать UserScope (контейнер, холдер, интерфейс) -- [ ] Настроить Firebase -- [ ] Реализовать ThemeStateManager -- [ ] Настроить go_router с базовыми роутами -- [ ] Создать главный App виджет с ScopeProvider'ами - -### **Этап 2: Авторизация (1-2 дня)** -- [ ] Реализовать AuthService (Google, Telegram) -- [ ] Создать UserStateManager -- [ ] Реализовать HttpRepositoryV2 с токенами -- [ ] Создать AuthPage -- [ ] Реализовать гостевой режим -- [ ] Настроить роутинг для auth/guest - -### **Этап 3: Темы (2-3 дня)** -- [ ] Создать PacksModule в UserScope -- [ ] Реализовать PacksStateManager -- [ ] Создать PackManager -- [ ] Реализовать HomePage с списком тем -- [ ] Создать PackDetailsPage -- [ ] Реализовать TestPage -- [ ] Добавить избранное - -### **Этап 4: Игры (1-2 дня)** -- [ ] Создать GamesModule в UserScope -- [ ] Реализовать GamesStateManager -- [ ] Создать GamesManager -- [ ] Реализовать GamesPage -- [ ] Интегрировать WebView для игр - -### **Этап 5: Профиль (1-2 дня)** -- [ ] Создать ProfileModule в UserScope -- [ ] Реализовать StatisticsService -- [ ] Создать ProfilePage -- [ ] Добавить графики статистики (fl_chart) -- [ ] Реализовать настройки -- [ ] Добавить промокоды и подписку - -### **Этап 6: Полировка (1-2 дня)** -- [ ] Добавить анимации и переходы -- [ ] Оптимизировать производительность -- [ ] Добавить обработку ошибок -- [ ] Добавить loading states -- [ ] Протестировать все flow'ы -- [ ] Адаптивная верстка для разных экранов - -### **Этап 7: Тестирование и деплой (1 день)** -- [ ] Тестирование авторизации -- [ ] Тестирование всех страниц -- [ ] Проверка работы с backend -- [ ] Build для production -- [ ] Деплой на хостинг - ---- - -## 📝 Примечания - -### Преимущества yx_scope: -- ✅ Compile-safe доступ к зависимостям -- ✅ Четкий жизненный цикл скоупов -- ✅ Отсутствие Service Locator паттерна -- ✅ Простая иерархия и изоляция -- ✅ Flutter-friendly интеграция - -### Преимущества yx_state: -- ✅ Простой и понятный API -- ✅ Встроенная обработка ошибок -- ✅ Интеграция с Flutter виджетами -- ✅ Поддержка rxdart transformers - -### Важные моменты: -- UserScope создается сразу при запуске (для гостя) -- UserScope НЕ удаляется при logout, только меняется состояние -- AuthService находится в AppScope (доступен всегда) -- HttpRepositoryV2 в UserScope получает токен из AuthService -- Все State Managers используют freezed для типобезопасности - ---- - -## 🔗 Ссылки на документацию - -- [yx_scope](../packages/yx/city-services-pub/yx_scope/packages/yx_scope/README.md) -- [yx_scope_flutter](../packages/yx/city-services-pub/yx_scope/packages/yx_scope_flutter/README.md) -- [yx_state](../packages/yx/city-services-pub/yx_state/packages/yx_state/README.md) -- [go_router](https://pub.dev/packages/go_router) -- [freezed](https://pub.dev/packages/freezed) - ---- - -**Общая оценка времени разработки: 8-14 дней** - -Готов к началу разработки! 🚀 - diff --git a/mnemo_cards_web_v2/PROGRESS.md b/mnemo_cards_web_v2/PROGRESS.md deleted file mode 100644 index 492ffc4..0000000 --- a/mnemo_cards_web_v2/PROGRESS.md +++ /dev/null @@ -1,2246 +0,0 @@ -# Progress Report - mnemo_cards_web_v2 - -## 📊 Project Status: API v2 Implementation Phase - -**Last Updated:** November 8, 2025 -**Current Phase:** API v2 Implementation & Migration -**Overall Progress:** ~90% (Core features complete, Tasks system fully implemented, API v2 Phase 1.6 complete) - ---- - -## 🔧 Recent Updates (November 8, 2025) - -### Purchase Page Fix - JSON Deserialization Issue ✅ COMPLETED -**Date:** November 8, 2025 -**Status:** Fixed - Purchase page now loads correctly -**Time Spent:** 2 hours - -**Issue:** Purchase page (`/purchase/5`) was not loading due to JSON deserialization problems with `CardPackBuyDto` and `Item` objects. - -**Root Cause:** -- `CardPackBuyDto` constructor incorrectly marked nullable fields as `required` -- `_buildItem` method used `item.toString()` which doesn't work for polymorphic `Item` subclasses -- `Item.fromJson` factory method properly creates `TextItem` and `SpacerItem` instances, but UI wasn't handling them correctly - -**Solution:** -- Fixed `CardPackBuyDto` constructor to properly handle nullable fields (items, color, version, price, store IDs) -- Implemented proper type-safe rendering in `_buildItem` method with switch statement for `ItemType` -- Added specific handling for `TextItem` (title/subtitle), `SpacerItem` (height), and `ButtonItem` -- Added proper spacing and icons for different item types - -**Technical Details:** -- JSON contains items array with types: "spacer", "text", "spacer" -- TextItem has title/subtitle fields for rich content display -- SpacerItem uses height property for vertical spacing -- All items properly deserialize through `Item.fromJson` factory - -**Result:** Purchase page now correctly displays pack information, preview cards, and properly formatted "what's included" section. - ---- - -### Tasks System Implementation - PHASE 1 COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Phase 1 Complete - Models, State Management, and UI Components -**Time Spent:** 8 hours - -**Goal:** Реализовать механику заданий для mnemo_cards_web_v2 - систему заданий, которые пользователь выполняет как в приложении, так и в реальном мире. - -**Completed in Phase 1:** -- ✅ Created comprehensive task data models (Task, TaskProgress, TaskReward, enums) -- ✅ Implemented TasksRepository with mock data for development -- ✅ Created TasksStateManager with full state management using yx_state -- ✅ Added TasksModule to UserScope with proper dependency injection -- ✅ Built TaskCard widget with rewards display and action buttons -- ✅ Implemented TasksPage with filtering, tabs, and search functionality -- ✅ Added navigation route `/tasks` and updated bottom navigation -- ✅ Updated MainShell to include "Задания" tab -- ✅ Integrated with existing yx_scope/yx_state architecture - -**Features Implemented:** -- Task types: app-internal, external, social -- Task difficulties: easy, medium, hard -- Task statuses: available, in-progress, completed, expired, failed -- Reward system: XP, coins, achievements -- UI: Cards, filters, tabs, confirmation dialogs -- Navigation: Bottom nav integration, route handling -- State management: Reactive updates, error handling, loading states - -**Files Created:** -- `lib/domain/models/task_models.dart` - Task data models -- `lib/domain/services/tasks_repository.dart` - Tasks data access -- `lib/domain/state/tasks_state_manager.dart` - Tasks state management -- `lib/di/user_scope/modules/tasks_module.dart` - DI module -- `lib/presentation/widgets/task_card.dart` - Task card widget -- `lib/presentation/pages/tasks/tasks_page.dart` - Tasks page -- 8+ unit tests for all components - -**Next Phase:** Phase 3 - Advanced Features (task creation, admin panel) - ---- - -### Tasks System Phase 2 - Backend Integration - COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Complete - Real API integration with fallback to mock data -**Time Spent:** 4 hours - -**Goal:** Интегрировать систему заданий с реальным API бэкенда вместо моковых данных. - -**Completed in Phase 2:** -- ✅ Added tasks API endpoints to ApiConfigV2 (/api/v2/tasks, /tasks/{id}, /tasks/{id}/complete, etc.) -- ✅ Implemented HttpRepositoryV2 methods for all task operations (getTasks, getTask, startTask, completeTask, getUserTaskProgress) -- ✅ Updated TasksRepository to use real API with intelligent fallback (API → Cache → Mock) -- ✅ Added comprehensive caching system for offline functionality -- ✅ Integrated HttpRepositoryV2 into TasksModule dependency injection -- ✅ Added proper error handling with network fallbacks -- ✅ Maintained backward compatibility with existing mock data - -**API Endpoints Implemented:** -- `GET /api/v2/tasks` - Get tasks with filtering (status, type, difficulty, tag, limit, offset) -- `GET /api/v2/tasks/{taskId}` - Get specific task details -- `POST /api/v2/tasks/{taskId}/start` - Mark task as in progress -- `POST /api/v2/tasks/{taskId}/complete` - Complete task with proof URL/notes -- `GET /api/v2/users/me/tasks/progress` - Get user task progress and statistics - -**Features Added:** -- **Intelligent Fallback System**: API first → Cache fallback → Mock data as last resort -- **Offline Support**: Tasks cached locally for offline viewing -- **User Authentication**: All API calls use Bearer token authentication -- **Error Resilience**: Graceful degradation when backend is unavailable -- **Progress Tracking**: Real-time sync of user progress with backend - -**Architecture Improvements:** -- **Clean API Integration**: HttpRepositoryV2 provides clean abstraction over Dio -- **Dependency Injection**: Proper wiring of HttpRepositoryV2 into TasksModule -- **Caching Strategy**: SharedPreferences-based caching for performance -- **Logging**: Comprehensive logging for debugging and monitoring - -**Files Modified:** -- `lib/domain/config/api_config_v2.dart` - Added task endpoints -- `lib/domain/services/http_repository_v2.dart` - Added task API methods -- `lib/domain/services/tasks_repository.dart` - Real API integration with caching -- `lib/di/user_scope/modules/tasks_module.dart` - Added HttpRepositoryV2 dependency - -**Testing:** All existing tests pass, system gracefully handles API unavailability. - -**Next Phase:** Phase 3 - Advanced Features (task creation, admin panel, analytics) - ---- - -### Pack Purchase Page Implementation - COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Complete - Purchase flow with YooKassa integration -**Time Spent:** 5 hours - -**Goal:** Implement a complete purchase flow for card packs with YooKassa payment integration, following clean architecture and existing patterns. - -**Completed Tasks:** -- ✅ Created `PurchaseState` with freezed (initial, loading, loaded, error, purchasing, completed) -- ✅ Implemented `PurchaseStateManager` using yx_state pattern -- ✅ Added `getPackBuy()` method to `PurchasesService` -- ✅ Created `PurchasePage` with pack preview, features, and payment integration -- ✅ Created `PurchaseModule` for DI -- ✅ Added purchase route `/purchase/:packId` to router -- ✅ Wrote 12 comprehensive unit tests for `PurchaseStateManager` -- ✅ Fixed `pack_card_vertical.dart` syntax error -- ✅ Updated TODO.md with completion status - -**Architecture:** -- State management with yx_state pattern -- Clean separation: state manager → service → repository -- Proper error handling and logging -- Freezed unions for type-safe states -- DI module for testability - -**Features:** -- Load pack purchase info from `/api/v2/packs/{packId}/buy` -- Display pack preview with cards and features -- Create YooKassa payment via `/api/v2/purchases/packs/{packId}` -- Open payment URL in browser -- Verify payment after user returns -- Show success/error feedback - -**Files Created:** -- `lib/domain/state/purchase_state_manager.dart` (198 lines) -- `lib/di/user_scope/modules/purchase_module.dart` (20 lines) -- `lib/presentation/pages/purchase/purchase_page.dart` (530 lines) -- `test/domain/state/purchase_state_manager_test.dart` (392 lines) - -**Files Modified:** -- `lib/domain/services/purchases_service.dart` - Added getPackBuy method -- `lib/di/user_scope/user_scope.dart` - Added PurchaseModule -- `lib/di/user_scope/user_scope_container.dart` - Wired purchase module -- `lib/presentation/router/app_router.dart` - Added /purchase/:packId route -- `TODO.md` - Marked BI-2 as complete - -**Usage:** -```dart -// Navigate to purchase page -context.push('/purchase/${packId}'); -``` - -**Next Steps:** -- Add purchase button to PackDetailsPage ✅ COMPLETED -- Show purchase status on pack cards -- Handle purchased pack access -- Add analytics events for purchase flow -- Test Adsgram integration with real block ID -- Update backend ads endpoints if needed - ---- - -### Pack Purchase Status Check Implementation ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** Complete - Pack purchase status verification and redirect logic -**Time Spent:** 2 hours - -**Goal:** Modify PackDetailsPage to check pack purchase status on load and redirect to purchase page if pack is not purchased, instead of showing pack details. - -**Completed Tasks:** -- ✅ Updated PackDetailsPage to use `GetCardPackResponse` instead of `CardPackDto` -- ✅ Added purchase status check in `_loadPack()` method -- ✅ Implemented automatic redirect to `/purchase/:packId` for unpurchased packs -- ✅ Maintained proper loading and error states -- ✅ Updated all methods to handle `CardPackDto` type casting -- ✅ Verified app compiles successfully with new logic - -**Architecture Changes:** -- **Type System:** Changed from direct `CardPackDto` to `GetCardPackResponse` union type -- **API Integration:** Leverages existing `GetCardPackResponseType.buy` vs `GetCardPackResponseType.dto` distinction -- **Navigation Flow:** Seamless redirect prevents showing details for unpurchased packs -- **Error Handling:** Preserved existing error handling patterns -- **State Management:** Clean separation between purchased and unpurchased pack handling - -**Technical Implementation:** -- **Response Type Checking:** `packResponse.responseType == GetCardPackResponseType.buy` -- **Automatic Redirect:** `context.push('/purchase/${widget.packId}');` for unpurchased packs -- **Type Safety:** Proper `as CardPackDto` casting after purchase verification -- **Backward Compatibility:** All existing functionality preserved for purchased packs - -**Files Modified:** -- `lib/presentation/pages/pack_details/pack_details_page.dart` - Core logic update (1019 lines) - -**Integration Points:** -- Works with existing PurchasePage route (`/purchase/:packId`) -- Compatible with AdsRewardButton and purchase button logic -- Maintains existing pack loading, progress, and test functionality -- No changes required to router or other components - -**User Experience:** -- **Unpurchased Packs:** Direct redirect to purchase page (no details shown) -- **Purchased Packs:** Full pack details page with all features -- **Error States:** Proper error handling for network issues -- **Loading States:** Smooth loading experience maintained - ---- - -### Ads Reward Unlock UI Implementation - COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Complete - Ads reward functionality with UI integration -**Time Spent:** 4 hours - -**Goal:** Implement complete UI for unlocking packs by watching rewarded ads, with Adsgram SDK integration. - -**Completed Tasks:** -- ✅ Created `AdsRewardButton` widget with state management -- ✅ Integrated AdsRewardStateManager with proper state handling -- ✅ Added Adsgram SDK dependency and configuration -- ✅ Created responsive button with loading/success/error states -- ✅ Integrated button into PackDetailsPage alongside purchase button -- ✅ Added Adsgram configuration to ApiConfigV2 -- ✅ Implemented development simulation for testing -- ✅ Added proper error handling and user feedback -- ✅ Wrote basic widget tests for AdsRewardButton - -**Architecture:** -- State management with AdsRewardStateManager (freezed states) -- Clean integration with existing scope and DI -- Adsgram SDK integration with fallback for development -- Responsive UI with proper loading and error states -- Analytics integration for reward claims - -**Features:** -- **AdsRewardButton** shows different states: - - Initial loading: Spinner while checking availability - - Not available: Hidden if no ad offer - - Ready: "Watch Ad to Unlock" with pack info - - Claiming: Processing reward - - Success: "Unlocked!" confirmation - - Error: Retry option with error message -- **Adsgram Integration**: Real rewarded ads with JavaScript interop -- **JS Callbacks**: Bidirectional communication between Dart and JavaScript -- **Block ID**: Configured with 16505 as requested -- **User Feedback**: SnackBar messages and visual state changes - -**Files Created:** -- `lib/presentation/widgets/ads_reward_button.dart` (210 lines) -- `lib/utils/adsgram_stub.dart` (77 lines - now real JS interop) -- `lib/domain/config/api_config_v2.dart` (ads config section) -- `test/presentation/widgets/ads_reward_button_test.dart` (80 lines) - -**Files Modified:** -- `lib/presentation/pages/pack_details/pack_details_page.dart` (added AdsRewardButton) -- `pubspec.yaml` (added js, http dependencies) -- `web/foos.js` (enhanced with callback system) -- `lib/presentation/pages/auth/auth_page.dart` (updated showAd method) -- `mnemo_cards_backend/lib/api/v2/ads_api_v2.dart` (added reward callback endpoint) -- `TODO.md` (marked BI-2A as complete) -- `PROGRESS.md` (this entry) - -**Backend Integration:** -- Added `GET /api/v2/adsgram/reward?userId={userId}` endpoint -- Integrated with existing AdsApiV2 -- Added OpenAPI documentation - -**JavaScript Integration:** -- Enhanced `web/foos.js` with callback system -- Bidirectional communication: Dart ↔ JavaScript -- `setRewardCallback()` and `setErrorCallback()` functions -- `showAd()` and `showAdWithBlockId()` functions -- Real Adsgram SDK integration with block ID 16505 - -**Integration Points:** -```dart -// In PackDetailsPage -Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Row( - children: [ - Expanded( - child: AdsRewardButton( - packId: widget.packId, - onSuccess: () => _refreshPackData(), - ), - ), - const SizedBox(width: 12), - Expanded(child: _buildPurchaseButton()), - ], - ), -) -``` - -**Configuration:** -```dart -// Adsgram settings -static String get adsgramBlockId => '16505'; -static const int adsgramRewardAmount = 1; -static String adsgramRewardUrl(String userId) => - '$baseUrl/adsgram/reward?userId=$userId'; - -// Development simulation -static const bool showAdsInDevelopment = false; -``` - -**Testing:** -- Basic widget rendering tests -- State management integration -- Development simulation works correctly -- Error handling and retry functionality - -**Next Steps:** -- ✅ **Adsgram Block ID configured**: 16505 -- ✅ **Reward URL implemented**: /adsgram/reward?userId=[userId] -- Test with production Adsgram ads when SDK becomes available -- Add more comprehensive analytics for ad impressions/completions -- Monitor ad completion rates and user engagement -- Consider A/B testing different ad placements and messaging - ---- - -### Game Tests Implementation Plan - PLANNING COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Planning Complete, Ready to Start Implementation - -**Goal:** Реализовать систему игровых тестов в mnemo_cards_web_v2, начиная с простых тестов с выбором 1 варианта из нескольких, с соблюдением архитектуры yx_scope/yx_state. - -**Planning Deliverables:** -- ✅ Created `GAME_TESTS_IMPLEMENTATION_PLAN.md` - comprehensive 5-phase implementation plan -- ✅ Analyzed mnemo_cards test system architecture -- ✅ Designed web-compatible test flow with clean architecture -- ✅ Planned progressive implementation from simple to complex - -**Key Features Planned:** -- Game session management with state tracking -- Multiple choice questions with visual feedback -- Statistics integration and results submission -- Responsive UI with animations and theming -- Support for advanced question types (input letters, matching) - -**Architecture:** -- Frontend: New GameSessionManager, GameStateManager, UI components -- Integration: Extended TestsModule, new question models -- Testing: Comprehensive unit tests for all components -- Progressive: Start with multiple choice, expand to complex types - -**Next Phase:** Phase 3 - Statistics & Analytics (results submission) - -### Game Tests Phase 4 - UX Improvements ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** ✅ Complete - Sound effects, animations, and enhanced user experience - -**Completed Features:** - -#### 1. Sound System Implementation ✅ -- ✅ **GameSoundService**: Centralized audio management service -- ✅ **Multiple Sound Types**: Correct, wrong, transition, start, complete, button tap, celebration -- ✅ **Enable/Disable Control**: User preference for sound on/off -- ✅ **Async Sound Playback**: Non-blocking audio operations -- ✅ **Resource Management**: Proper initialization and disposal - -#### 2. Advanced Answer Button Animations ✅ -- ✅ **Scale Animation**: Subtle scaling effect when buttons are selected -- ✅ **Color Transitions**: Smooth color changes for correct/incorrect feedback -- ✅ **Shadow Effects**: Elevation and glow effects for visual feedback -- ✅ **Text Animation**: Font size and weight changes with AnimatedDefaultTextStyle -- ✅ **Elastic Bounce**: Spring-like animation for correct answers using Curves.elasticOut -- ✅ **Ripple Effects**: Enhanced splash animations on tap - -#### 3. Game Page Transition Animations ✅ -- ✅ **AnimatedSwitcher**: Smooth transitions between different question types -- ✅ **Fade + Slide**: Combined fade and slide animations for question changes -- ✅ **Staggered Timing**: Different animation curves for in/out transitions -- ✅ **Unique Keys**: Proper AnimatedSwitcher keys for state management - -#### 4. Results Screen Animations ✅ -- ✅ **Score Circle Animation**: Scale and glow animation for final score display -- ✅ **Number Counter**: Animated percentage counting from 0 to final score -- ✅ **Delayed Reveals**: Staggered appearance of UI elements -- ✅ **Color Transitions**: Dynamic color changes based on performance -- ✅ **Shadow Effects**: Performance-based glow effects - -#### 5. Enhanced Visual Feedback ✅ -- ✅ **Material Design**: Proper elevation, shadows, and surface colors -- ✅ **Accessibility**: Better contrast and readable text sizes -- ✅ **Performance Indicators**: Visual cues for loading states and transitions -- ✅ **Responsive Scaling**: Animations adapt to different screen sizes - -#### 6. Sound Integration Throughout App ✅ -- ✅ **Game Start**: Sound when entering game mode -- ✅ **Answer Feedback**: Immediate audio response to correct/wrong answers -- ✅ **Question Transitions**: Audio cues for moving between questions -- ✅ **Game Completion**: Celebration sound for finishing tests -- ✅ **Button Interactions**: Subtle sounds for UI interactions - -#### 7. Dark Theme Compatibility ✅ -- ✅ **Dynamic Colors**: Theme-aware color selection for all animations -- ✅ **Opacity Adjustments**: Proper alpha values for dark/light themes -- ✅ **Contrast Preservation**: Maintained readability in both themes -- ✅ **Shadow Adaptation**: Theme-appropriate shadow colors and intensities - -**Technical Highlights:** -- **Performance Optimized**: Efficient animation controllers and resource management -- **Theme Aware**: Automatic adaptation to light/dark theme changes -- **Accessible**: Animations respect user accessibility preferences -- **Scalable**: Easy to add new sound effects and animation patterns -- **Non-Blocking**: All audio operations are async and don't freeze UI - -**Files Created/Modified:** -- `lib/domain/services/game_sound_service.dart` ✅ (NEW) -- `lib/presentation/widgets/game/answer_options.dart` ✅ (ENHANCED) -- `lib/presentation/pages/game/game_page.dart` ✅ (ENHANCED) -- `lib/domain/state/tests_state_manager.dart` ✅ (SOUND INTEGRATION) -- `lib/di/user_scope/modules/tests_module.dart` ✅ (SOUND SERVICE) -- `test/domain/services/game_sound_service_test.dart` ✅ (NEW) - -**Animation Types Implemented:** -1. **Scale Transformations** - Button selection feedback -2. **Color Transitions** - Answer correctness indication -3. **Shadow/Glow Effects** - Performance celebration -4. **Text Animations** - Font size/weight changes -5. **Fade + Slide** - Question transitions -6. **Elastic Bounce** - Success feedback -7. **Number Counters** - Score reveal animations - -**Sound Effects Added:** -- ✅ Correct answer sound -- ✅ Wrong answer sound -- ✅ Question transition sound -- ✅ Game start sound -- ✅ Game completion sound -- ✅ Button tap sound -- ✅ Celebration sound - ---- - -### PackTip Support Implementation ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** Complete - PackTip support added to PackCard and PackCardVertical widgets -**Time Spent:** 5 hours - -**Goal:** Implement support for CardPackPreviewDto.tip field to display small icons or badges in corners or right side of pack cards, adapting PackTip functionality from mobile app to web version for both horizontal and vertical card layouts. - -**Completed Features:** - -#### 1. PackTipExt Extension Creation ✅ -- ✅ Created `PackTipExt` extension for `PackTip` class with `build()` method -- ✅ Implemented support for all PackTipType variants: - - `PackTipType.asset` - Display asset images with theming - - `PackTipType.base64` - Decode and display base64 images - - `PackTipType.text` - Display text labels - - `PackTipType.unknown` - Safe fallback handling -- ✅ Adapted from mobile implementation with web-specific optimizations -- ✅ Error handling for corrupted base64 data - -#### 2. PackCard PackTip Integration ✅ -- ✅ Added `_buildPackTip()` method to PackCard widget -- ✅ Implemented support for all PackTipPosition values: - - `PackTipPosition.topRight` - Badge in top-right corner - - `PackTipPosition.bottomRight` - Badge in bottom-right corner - - `PackTipPosition.fullRight` - Full-width right side display - - `PackTipPosition.unknown` - Safe fallback -- ✅ Stack-based layout with Positioned widgets for overlay placement -- ✅ Proper theming with pack color integration and opacity adjustments - -#### 3. PackCardVertical PackTip Integration ✅ -- ✅ Added `_buildPackTip()` method to PackCardVertical widget -- ✅ Adapted positioning logic for vertical card layout (fullRight as bottom banner) -- ✅ Implemented support for all PackTipPosition values in vertical context -- ✅ Refactored PackCardVertical layout to use Stack for tip overlays - -#### 4. Layout Architecture Updates ✅ -- ✅ Refactored both PackCard and PackCardVertical to use Stack widget for tip overlays -- ✅ Maintained existing horizontal (PackCard) and vertical (PackCardVertical) card layouts -- ✅ Positioned tips correctly relative to card boundaries for both orientations -- ✅ Responsive sizing based on card dimensions - -#### 5. UI/UX Features ✅ -- ✅ **fullRight Position**: Tip occupies right side for horizontal cards, bottom banner for vertical cards -- ✅ **Corner Positions**: Small badges in card corners with proper border radius for both layouts -- ✅ **Visual Consistency**: Matches mobile app PackTip appearance across all card types -- ✅ **Theme Integration**: Respects app theme colors and opacity levels -- ✅ **Performance**: Efficient rendering with minimal rebuilds - -#### 6. Code Quality & Testing ✅ -- ✅ Type-safe implementation with proper null checking -- ✅ Clean separation of concerns with dedicated extension -- ✅ Comprehensive error handling and fallbacks -- ✅ Linter-clean code with proper documentation -- ✅ Build verification - app compiles successfully - -**Technical Details:** -- **Architecture:** Extension pattern for PackTip rendering, Stack-based overlay system -- **Compatibility:** Adapts mobile PackTip system to web Flutter constraints -- **Performance:** Lightweight implementation with efficient image handling -- **Extensibility:** Easy to add new tip types following existing patterns - -**Files Created/Modified:** -- `lib/utils/pack_tip_extension.dart` ✅ (NEW - PackTipExt extension) -- `lib/presentation/widgets/pack_card.dart` ✅ (ENHANCED - PackTip support) -- `lib/presentation/widgets/pack_card_vertical.dart` ✅ (ENHANCED - PackTip support) - -**Integration Points:** -- CardPackPreviewDto.tip field consumption -- Pack color theming integration -- Existing PackCard and PackCardVertical layout preservation -- Stack-based overlay positioning for both horizontal and vertical cards - -**Next Steps:** -- Test with real PackTip data from backend -- Monitor performance with multiple tips displayed -- Consider animation enhancements for tip appearance - ---- - -### Game Tests Phase 5 - Advanced Question Types ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** ✅ Complete - Input Letters, Match, and Matrix question types implemented - -**Completed Features:** - -#### 1. Input Letters Questions ✅ -- ✅ **InputLettersWidget**: Interactive template filling with visual feedback -- ✅ **Template Display**: Shows blanks and filled letters with animations -- ✅ **Real-time Updates**: Letters appear in template as user types -- ✅ **Validation**: Case-insensitive answer checking -- ✅ **Auto-submit**: Clears input after submission for next attempt - -#### 2. Match Questions - Ready for Backend ✅ -- ✅ **MatchWidget**: Two-column interface for connecting items -- ✅ **Interactive Selection**: Tap-to-select mechanism for creating pairs -- ✅ **Visual Feedback**: Connected items highlighted with checkmarks -- ✅ **Connection Display**: Shows current pairings below columns -- ✅ **Validation Logic**: Ready for when backend supports Match questions -- ⏳ **Backend Integration**: Waiting for InputButtonsTestQuestionBody structure - -#### 3. Matrix Questions - Ready for Backend ✅ -- ✅ **MatrixWidget**: Table/grid interface for filling values -- ✅ **Dynamic Grid**: Headers and cells generated from question data -- ✅ **Cell Input**: Individual text fields for each matrix cell -- ✅ **Validation Logic**: Ready for when backend supports Matrix questions -- ⏳ **Backend Integration**: Waiting for MatrixTestQuestionBody structure - -#### 4. Game Session Manager Updates ✅ -- ✅ **Input Letters Validation**: Template-based answer checking -- ✅ **Flexible Answer Types**: Support for strings, maps, and lists -- ✅ **Extensible Validation**: Easy to add Match/Matrix validation when ready - -#### 5. State Management Extensions ✅ -- ✅ **Question Type Conversion**: Extended `_convertTestToGameQuestions` -- ✅ **Input Letters Detection**: SimpleTestQuestionBody with template support -- ✅ **Match/Matrix Placeholders**: Ready for future backend support -- ✅ **Backward Compatibility**: Existing multiple choice still works - -#### 6. UI Integration ✅ -- ✅ **GamePage Support**: All question types integrated via `question.when()` -- ✅ **Responsive Design**: Widgets adapt to screen size -- ✅ **Consistent Styling**: Material Design with proper theming -- ✅ **Accessibility**: Proper focus management and keyboard support -- ✅ **Graceful Degradation**: Placeholder messages for unsupported types - -#### 7. Comprehensive Testing ✅ -- ✅ **InputLettersWidget Tests**: Template display, input handling, submission -- ✅ **MatchWidget Tests**: Selection, connection creation, validation -- ✅ **MatrixWidget Tests**: Grid display, cell filling, submission -- ✅ **Integration Coverage**: All user interactions and edge cases - -**Technical Highlights:** -- **Type-Safe Architecture**: Union types ensure compile-time safety -- **Scalable Design**: Easy to add more question types in the future -- **Performance Optimized**: Efficient state updates and rendering -- **User Experience**: Intuitive interfaces with clear feedback -- **Forward Compatible**: Ready for backend enhancements - -**Files Created/Modified:** -- `lib/presentation/widgets/game/input_letters_widget.dart` ✅ (NEW) -- `lib/presentation/widgets/game/match_widget.dart` ✅ (NEW) -- `lib/presentation/widgets/game/matrix_widget.dart` ✅ (NEW) -- `lib/domain/services/game_session_manager.dart` ✅ (EXTENDED) -- `lib/domain/state/tests_state_manager.dart` ✅ (EXTENDED) -- `lib/presentation/pages/game/game_page.dart` ✅ (EXTENDED) -- `test/presentation/widgets/game/input_letters_widget_test.dart` ✅ (NEW) -- `test/presentation/widgets/game/match_widget_test.dart` ✅ (NEW) -- `test/presentation/widgets/game/matrix_widget_test.dart` ✅ (NEW) - -**Question Types Status:** -1. **Multiple Choice** (Phase 2) ✅ **FULLY IMPLEMENTED** -2. **Input Letters** (Phase 5) ✅ **FULLY IMPLEMENTED** -3. **Match** (Phase 5) ✅ **UI READY - WAITING FOR BACKEND** -4. **Matrix** (Phase 5) ✅ **UI READY - WAITING FOR BACKEND** - -**Next Steps for Match/Matrix:** -- Add MatrixTestQuestionBody to mnemo_cards_common -- Implement proper Match question structure in backend -- Enable Match/Matrix question conversion in TestsStateManager -- Test end-to-end Match/Matrix game flow - ---- - -### Game Tests Phase 2 - Multiple Choice Tests ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** ✅ Complete - Full game flow with Multiple Choice questions - -**Completed Features:** - -#### 1. Game Page & Navigation ✅ -- ✅ Created `GamePage` with complete game session flow -- ✅ Added `/game/:testId` route to app router -- ✅ Modified `TestPage` to include "Play Interactive Game" button -- ✅ Integrated navigation between traditional tests and games - -#### 2. Game Flow Implementation ✅ -- ✅ **Preparing State**: Shows game info and start button -- ✅ **Active Game State**: Displays current question with options -- ✅ **Answer Feedback**: Visual feedback for correct/incorrect answers -- ✅ **Navigation**: Previous/Next buttons with proper state handling -- ✅ **Auto-advance**: Automatic progression after correct answers -- ✅ **Completion State**: Results screen with score and statistics - -#### 3. UI Components Integration ✅ -- ✅ **QuestionDisplay**: Shows question text, images, and audio -- ✅ **AnswerOptions**: Interactive multiple choice buttons with animations -- ✅ **GameProgressIndicator**: Progress bar, score, and time tracking -- ✅ **Responsive Design**: Adapts to mobile/tablet/desktop layouts -- ✅ **Material Design**: Consistent theming and animations - -#### 4. State Management Integration ✅ -- ✅ Connected `TestsStateManager` game session states to UI -- ✅ Real-time state updates using `StateBuilder` -- ✅ Proper error handling and loading states -- ✅ Session lifecycle management (start, progress, complete, reset) - -#### 5. Game Logic ✅ -- ✅ Question progression with state validation -- ✅ Answer submission and validation -- ✅ Score calculation and statistics tracking -- ✅ Session completion and results aggregation -- ✅ Exit confirmation and session reset functionality - -#### 6. Testing & Quality Assurance ✅ -- ✅ `GamePage` widget tests with state scenarios -- ✅ Integration tests for game flow -- ✅ UI component tests for all game widgets -- ✅ State management tests for game sessions -- ✅ Comprehensive test coverage for new functionality - -**Technical Highlights:** -- **Seamless Integration**: GamePage works alongside existing TestPage -- **State-Driven UI**: All UI updates react to state changes automatically -- **User Experience**: Intuitive game flow with clear feedback -- **Performance**: Efficient state updates and memory management -- **Extensibility**: Architecture ready for additional question types - -**Files Created/Modified:** -- `lib/presentation/pages/game/game_page.dart` ✅ (New) -- `lib/presentation/pages/test/test_page.dart` ✅ (Modified - added game button) -- `lib/presentation/router/app_router.dart` ✅ (Modified - added game route) -- `test/presentation/pages/game/game_page_test.dart` ✅ (New) -- `test/presentation/widgets/game/*_test.dart` ✅ (New test files) - ---- - -### Game Tests Phase 1 - Basic Infrastructure ✅ COMPLETE -**Date:** November 8, 2025 -**Status:** ✅ Complete - All components implemented and tested - -**Completed Features:** - -#### 1. Data Models ✅ -- ✅ Created `GameQuestion` union type with support for multiple choice, input letters, match, and matrix questions -- ✅ Implemented `MultipleChoiceQuestion`, `InputLettersQuestion`, `MatchQuestion`, `MatrixQuestion` models -- ✅ Added `QuestionResult` and `GameSessionResult` for tracking answers and session data -- ✅ Generated freezed code for all models - -#### 2. GameSessionManager Service ✅ -- ✅ Created `GameSessionManager` for managing active game sessions -- ✅ Implemented session lifecycle (start, submit answers, complete, reset) -- ✅ Added answer validation for different question types -- ✅ Integrated time tracking and statistics calculation -- ✅ Proper state management with session reset functionality - -#### 3. TestsStateManager Enhancement ✅ -- ✅ Extended `TestsState` with game session states (`gameSessionPreparing`, `gameSessionActive`, `gameSessionCompleted`) -- ✅ Added `startGameSession()`, `submitAnswer()`, `nextQuestion()`, `completeGameSession()` methods -- ✅ Implemented question navigation and session completion logic -- ✅ Added session statistics and state getters - -#### 4. Dependency Injection ✅ -- ✅ Updated `TestsModule` to include `GameSessionManager` -- ✅ Added proper dependency wiring in `UserScope` -- ✅ Integrated with existing `TestManager` and `TestsStateManager` - -#### 5. UI Components ✅ -- ✅ Created `QuestionDisplay` widget for showing questions with text, images, and audio -- ✅ Built `AnswerOptions` widget for multiple choice interactions with visual feedback -- ✅ Implemented `GameProgressIndicator` with progress bar, statistics, and time tracking -- ✅ Added responsive design and proper theming - -#### 6. Comprehensive Testing ✅ -- ✅ `GameSessionManager` tests (6 tests) - session management, answer validation, statistics -- ✅ `GameQuestion` models tests (7 tests) - all question types and result models -- ✅ `TestsStateManager` tests (mock-based testing) -- ✅ UI widget tests for `QuestionDisplay`, `AnswerOptions`, `GameProgressIndicator` -- ✅ `TestsModule` DI tests -- ✅ All tests passing with proper coverage - -**Technical Highlights:** -- Clean Architecture: Models, Services, State Managers, UI components properly separated -- Yx_scope/yx_state: Full integration with dependency injection and reactive state management -- Freezed: Type-safe immutable models with JSON serialization -- Comprehensive testing: Unit tests for all components with proper mocking -- Responsive UI: Mobile-first design with adaptive layouts -- Error handling: Graceful degradation for missing images, invalid data - -**Files Created/Modified:** -- `lib/domain/models/game_question.dart` ✅ -- `lib/domain/services/game_session_manager.dart` ✅ -- `lib/domain/state/tests_state_manager.dart` ✅ -- `lib/di/user_scope/modules/tests_module.dart` ✅ -- `lib/presentation/widgets/game/question_display.dart` ✅ -- `lib/presentation/widgets/game/answer_options.dart` ✅ -- `lib/presentation/widgets/game/progress_indicator.dart` ✅ -- 8 comprehensive test files ✅ - ---- - - - -### Statistics System Upgrade - PLANNING COMPLETE ✅ -**Date:** November 8, 2025 -**Status:** Planning Complete, Ready to Start Implementation - -**Goal:** Расширить систему сбора и отображения статистики пользователя для создания детализированной страницы профиля с красивым UI и настройками приложения. - -**Planning Deliverables:** -- ✅ Created `STATISTICS_UPGRADE_PLAN.md` - comprehensive 10-section plan -- ✅ Created `STATISTICS_TASKS.md` - frontend task breakdown (93-119 hours) -- ✅ Created `../mnemo_cards_backend/STATISTICS_TASKS.md` - backend tasks (35-47 hours) -- ✅ Updated `TODO.md` with STAT-1 feature entry -- ✅ Updated `workflow_state.md` for both projects -- ✅ Total estimated time: 111-144 hours - -**Key Features Planned:** -- Extended statistics (streaks, study time, accuracy, pack progress) -- Detailed word statistics with difficulty scoring -- Achievement system with 8+ types -- Study session tracking -- Beautiful profile page redesign -- Statistics detail pages (words, packs, achievements) -- Enhanced settings page -- Timeline charts and activity heatmaps -- Animations (counters, confetti, shimmer) - -**Architecture:** -- Backend: New DTOs, StatisticsCalculator, SessionTracker, AchievementManager -- Frontend: Enhanced services, state managers, redesigned UI -- 6 API endpoints for statistics -- fl_chart for all charts -- Comprehensive testing - -**Next Phase:** Backend Phase 1 - Create new DTOs (6-9 hours) - ---- - -### Pack Details Shuffle Animation ✅ COMPLETE -- 🎯 **Added animated shuffle transitions for pack card grid/list:** - - Introduced reusable `ShuffleAnimatedSwitcher` with fade+scale transitions for shuffled/favorites views - - Highlighted shuffle control with `AnimatedRotation` feedback and active styling tied to shuffle state - - Cards now glide into new positions via movement-aware wrappers with dedicated widget/unit coverage - -### Telegram Login Bridge ✅ COMPLETE -- 🎯 **Implemented web-initiated Telegram login codes with 5-minute TTL while keeping legacy `/code` flow:** - - Added backend endpoints for web code creation, bot claims, and status polling (`/auth/telegram/web-code`, `/claim-code`, `/code-status/{code}`) - - Updated Telegram bot to accept `login_` payloads, claim codes automatically when opened from the web, and retain `/code` command fallback - - Extended web UI to generate codes, deep-link to the bot, display real-time status + countdown, and auto-attempt login once the bot confirms the code -- ✅ Added service/unit tests covering new auth service helpers and status model parsing -- 📌 Known issue: existing legacy widget/service tests (24) remain red; tracked separately in test stabilization backlog - -### Chat Module Implementation ✅ MODULARIZATION COMPLETE -- 🎯 **Successfully extracted chat functionality into separate `mnemo_cards_chat` Flutter module:** - - Created independent Flutter package with proper pubspec.yaml and dependencies - - Migrated all chat components: models, services, state management, and tests - - Implemented clean architecture with ChatRepository interface for loose coupling - - Added ChatModule for yx_scope DI integration in main application - - Maintained all existing functionality while improving maintainability -- ✅ **Technical achievements:** - - Created reusable chat module that can be used in multiple projects - - Proper dependency injection with abstract ChatRepository interface - - Simplified ChatStateManager with manual state classes (avoiding freezed complexity) - - All code generation working (freezed, json_serializable) - - Module compiles successfully and integrates cleanly with main project -- 📈 **Benefits achieved:** - - Better separation of concerns and modularity - - Improved testability and maintainability - - Reusable chat functionality across different applications - - Clean API boundaries with ChatRepository abstraction - - Ready for Phase 2 (UI components, audio functionality, backend integration) - -### Ads Reward Flow Planning 🟡 IN PROGRESS -- 🎯 **Outlined plan to port rewarded-ad unlock flow from mobile to web:** - - Analyzed backend `/ads` endpoints and mobile `ProductForAdDeeplink` usage - - Documented required additions for `HttpRepositoryV2`, services, state, and UI - - Selected Adsgram web SDK for rewarded ads wrapper - - Defined analytics, error handling, and retry requirements -- ✅ Created `AdsRewardService`, `AdsRewardStateManager`, and scope module with targeted unit tests -- 📋 Added dedicated task to `tasks.md` for implementation with acceptance criteria -- 📈 Updated roadmap artifacts to reflect ads reward feature priority - -### Purchases Flow Wiring – API v2 ✅ COMPLETE -- 🎯 **Implemented end-to-end purchases client over the new API v2 endpoints:** - - Added `PackPurchaseStatus` and `PaymentVerificationResult` models for pack access checks and post-payment polling - - Extended `HttpRepositoryV2` with `/purchases` helpers (`createPackPurchase`, `getPackPurchaseStatus`, `createPayment`, `verifyPayment`, `getUserPurchases`) - - Introduced `PurchasesService` with dedicated yx_scope module; exposed via `UserScope` for UI integration - - Created focused unit tests ensuring the service delegates correctly to the v2 repository -- 📌 Next UI step: hook pack buy / subscription pages to the new service and surface purchase status in profile - -### API v2 Web Client Migration – Phase 2 ✅ COMPLETE -- 🎯 **Retired legacy v1 HTTP client and finished porting remaining services to API v2:** - - Added reusable `PromocodeDto`, `PromocodeApplyResult`, `SubscriptionPageData`, and `SubscriptionPlanDto` models - - Extended `HttpRepositoryV2` with promocode apply/list helpers and subscription plan/status purchasing endpoints - - Migrated `PromocodeService` and `SubscriptionService` to `HttpRepositoryV2` - - Removed legacy `HttpRepository` + tests, updated DI and state manager tests to rely on the v2 repository -- 📌 Follow-up: wire UI flows to the new endpoints once backend responses are finalized (admin campaign list remains to be surfaced) - -### Card Flipper Responsive Layout ✅ COMPLETE -- 🎯 **Modernized `CardFlipper` UI with desktop/tablet/mobile breakpoints:** - - Introduced compact, medium, and expanded layouts driven by `LayoutBuilder` - - Adjusted progress indicator, card sizing, and controls per breakpoint - - Added optional `stateManagerOverride` to simplify widget testing -- ✅ Created widget tests covering compact, tablet, wide desktop, and tall desktop scenarios -- ✅ Ensured card flip animation sizing adapts without regressions -- ✅ `dart format` + analyzer clean - -### Card Viewer Study Flow ✅ COMPLETE -- 🎯 **Unified card study entry point with fullscreen `CardViewer`:** - - Removed separate “Изучение” CTA; tapping a card launches study mode directly - - Passed display-ordered card lists (respecting shuffle & favorites filters) into viewer - - Ensured viewer opens at tapped index and preserves pack order -- ✅ Added widget tests for initial index, swipe ordering, and flip interaction -- ✅ Simplified controls panel to focus on view, shuffle, favorites actions - -### Pack Details Shuffle Animation ✅ COMPLETE -- 🎯 **Added animated transitions when toggling shuffle/list/favorites modes:** - - Implemented keyed `AnimatedSwitcher` (fade + scale + slide) for grid/list container - - Enhanced shuffle rotation feedback and key generation to reflect state changes -- ✅ Updated widget tests for `ShuffleAnimatedSwitcher` to cover new transition stack -- ✅ Verified controls remain responsive across breakpoints - ---- - -## 🔧 Previous Updates (December 19, 2024) - -### Card Images Fix ✅ COMPLETE -- 🎯 **Fixed card word images not displaying in packs:** - - Updated all frontend widgets to use `ApiConfigV2` instead of deprecated `ApiConfig` - - Fixed image URLs to use correct v2 API format: `/api/v2/packs/{packId}/cards/{cardId}/image` - - Modified backend image endpoint to allow public access for enabled packs - - Added validation to verify pack exists, is enabled, and card belongs to pack - - Updated 4 frontend widgets: PackCardItem, CardFlipper, CardViewer, PackDetailsPage - - Enhanced backend endpoint with better error handling and security checks - - Added comprehensive unit tests (6 new tests covering all scenarios) -- ✅ Images now load correctly without authentication requirements -- ✅ Proper URL generation using API v2 format -- ✅ Public access to images for enabled packs (supports preview in listings) -- ✅ All linter errors fixed - -## 🔧 Previous Updates (October 28, 2025) - -### API v2 Implementation 🔄 IN PROGRESS -- 🎯 **Started API v2 implementation for web app:** - - Created ApiConfigV2 with all v2 RESTful endpoints - - Created HttpRepositoryV2 with OAuth2/JWT Bearer token authentication - - Implemented backend v2 structure: - - AuthApiV2 with Google OAuth endpoint - - JwtService for token generation/verification - - authorizeV2 middleware for Bearer token auth - - PacksApiV2 basic structure - - Mounted v2 APIs at `/api/v2` path in backend - - Migrated AuthService to use HttpRepositoryV2 - - Updated dependency injection to use v2 as primary -- ✅ Foundation complete, remaining work: - - Fix JWT crypto implementation - - Complete all backend v2 endpoints - - Migrate remaining web services to v2 - - Implement purchase/subscription flows -- 📋 Created comprehensive FUTURE_TASKS_PLAN.md with detailed roadmap - -## 🔧 Previous Updates (October 28, 2025) - -### Tests Functionality Verification ✅ -- 🎯 **Complete test functionality verified and tested:** - - TestManager service fully integrated with HttpRepository - - 6 comprehensive unit tests written and passing - - Test flow verified: PackDetailsPage → TestPage - - Test loading, taking, completing, and result display all working - - Statistics submission to backend functional - - Progress tracking during tests operational -- ✅ All test acceptance criteria met -- ✅ Clean code with proper error handling -- ✅ No navigation or state management issues - -### Pack Images Display Feature ✅ -- 🎯 **Complete pack image display functionality implemented:** - - ImageCacheService for caching decoded base64 images - - ImageCacheModule integrated into UserScope - - PackCard widget displays cached pack cover images - - PackDetailsHeader displays cached pack icon images - - Hero animations maintained from list to details - - Graceful fallback to placeholder icons for missing images - - 15 comprehensive unit tests passing -- ✅ Images decoded from base64 (CardPackPreviewDto.imageBase64) -- ✅ Performance optimized with image caching (similar to mobile app) -- ✅ Clean architecture following yx_scope patterns -- ✅ No linter errors introduced - -## 🔧 Previous Updates (December 19, 2024) - -### Favorites Feature Implementation ✅ -- 🎯 **Complete Favorites functionality implemented:** - - FavoritesStateManager with SharedPreferences integration - - FavoritesModule in UserScope - - UI integration in PackDetailsPage with heart icons - - Toggle favorite status for cards - - Local storage persistence - - 12 comprehensive unit tests passing -- ✅ Full UI integration with visual feedback -- ✅ Proper state management with yx_state -- ✅ Clean architecture following project patterns - -### Tests Feature Implementation ✅ -- 🎯 **Complete test-taking functionality implemented:** - - TestManager service for backend communication - - TestsStateManager for state management - - TestsModule in UserScope - - Complete TestPage UI with: - - Test introduction screen - - Question flow with progress tracking - - Answer selection interface - - Results display with scoring - - Navigation between questions - - Support for SimpleTestQuestionBody questions - - Backend statistics submission - - Routing and navigation working -- ✅ Full test-taking flow implemented -- ✅ Progress tracking and result calculation -- ✅ Backend integration for statistics -- ✅ Responsive UI design - -## 🔧 Previous Updates (October 19, 2025) - -### UserScope Lifecycle Fix ✅ -- 🐛 **Fixed UserScope creation logic:** - - UserScope was being created for all users (including guests) - - **Solution:** UserScope now created only for authenticated users - - Auto-login creates UserScope only if user is found - - Auth pages create UserScope only after successful authentication - - Logout properly disposes UserScope -- ✅ Updated App widget to conditionally provide UserScope -- ✅ Added notification system for UserScope changes -- ✅ Created comprehensive test for UserScope lifecycle -- ✅ All linter errors resolved - -### Исправление бесконечной загрузки ✅ -- 🐛 **Fixed infinite loading issue:** - - App was stuck in loading screen after UserScope changes - - **Root cause:** Missing ScopeProvider for UserScope after conditional logic - - **Solution:** Restored conditional ScopeProvider -- ✅ Fixed type casting for ScopeProvider -- ✅ Added proper imports for UserScopeContainer and ScopeStateHolder -- ✅ App now loads correctly for both guest and authenticated users -- ✅ All tests passing (127 tests) - -### CORS Configuration Fix ✅ -- 🐛 **Fixed critical CORS issue in backend:** - - CORS middleware was placed AFTER authorization middleware - - Preflight OPTIONS requests were returning 401 before CORS headers could be added - - **Solution:** Moved `corsHeaders` middleware to be FIRST in pipeline - - Custom headers (`app_version`, `user_token`, `request_token`) now properly allowed -- ✅ Updated CORS_FIX.md with important middleware ordering information -- ✅ Backend needs restart for changes to take effect - -### HTTP Headers Verification & Improvements -- ✅ Verified that headers are not being overwritten anywhere in frontend -- ✅ Improved logging to show all important headers in requests: - - `app_version`: Application version header - - `user_token`: User authentication token - - `request_token`: Request security token -- ✅ Removed unused Dio instance from `StorageModule` -- ✅ Added comprehensive tests for headers (3 new tests): - - Test for app_version header in interceptor - - Test for user_token header when authenticated - - Test for request_token header generation -- ✅ All tests passing (14 tests in HttpRepository suite) - ---- - -## ✅ Stage 1: Foundation (COMPLETED) - -### 🎯 Goals -- Create project structure -- Set up dependency injection with yx_scope -- Implement state management with yx_state -- Configure routing with go_router -- Set up Firebase integration -- Create base UI pages - -### ✨ Completed Features - -#### 1. Project Infrastructure ✅ -- [x] Created folder structure following clean architecture -- [x] Configured `pubspec.yaml` with all dependencies: - - yx_scope & yx_scope_flutter (^1.1.2) - - yx_state & yx_state_flutter (^1.0.0) - - go_router (^14.2.0) - - Firebase packages (core, auth, analytics, crashlytics) - - dio (^5.3.3) for HTTP - - freezed for immutable models - - shared_preferences for local storage -- [x] Set up `analysis_options.yaml` with linting rules -- [x] Configured code generation (freezed, json_serializable) - -#### 2. Dependency Injection (yx_scope) ✅ - -**AppScope (Root Scope)** -- [x] `AppScopeContainer` - Main dependency container -- [x] `AppScopeHolder` - Lifecycle management -- [x] `AppScope` interface - Isolates dependencies -- [x] Modules created: - - `AuthModule` - Authentication services - - `RouterModule` - Navigation setup - - `AnalyticsModule` - Firebase Analytics (placeholder) - - `StorageModule` - SharedPreferences initialization -- [x] Async initialization with `rawAsyncDep` for Firebase and SharedPreferences -- [x] Dependencies provided: - - GoRouter - - FirebaseAnalytics (placeholder) - - AuthService - - UserScopeHolder - - ThemeStateManager - - SharedPreferences - -**UserScope (Child Scope)** -- [x] `UserScopeContainer` - User-specific dependencies -- [x] `UserScopeHolder` - Child scope lifecycle -- [x] `UserScope` and `UserScopeParent` interfaces -- [x] Dependencies provided: - - UserStateManager -- [x] Ready for expansion with: - - PacksModule - - GamesModule - - ProfileModule - -#### 3. State Management (yx_state) ✅ - -**ThemeStateManager** -- [x] Manages app theme (light/dark) -- [x] Persists theme preference to SharedPreferences -- [x] Toggle functionality -- [x] Integrated with MaterialApp - -**UserStateManager** -- [x] Uses freezed for type-safe states: - - `UserState.guest()` - Guest mode - - `UserState.authenticated(user)` - Logged in - - `UserState.loading()` - Auth in progress -- [x] Methods: `setUser()`, `logout()` -- [x] Reactive state updates - -#### 4. Routing (go_router) ✅ -- [x] Created `app_router.dart` with route configuration -- [x] Implemented `MainShell` with bottom navigation (3 tabs) -- [x] Routes defined: - - `/home` - HomePage (Темы) - - `/games` - GamesPage (Игры) - - `/profile` - ProfilePage (Профиль) - - `/auth` - AuthPage (Авторизация) -- [x] ShellRoute for persistent bottom navigation -- [x] Initial location set to `/home` - -#### 5. UI Pages ✅ - -**HomePage** (`/home`) -- [x] Basic scaffold with app bar -- [x] Placeholder for packs list -- [x] Ready for Stage 3 implementation - -**GamesPage** (`/games`) -- [x] Basic scaffold with app bar -- [x] Placeholder for games list -- [x] Ready for Stage 4 implementation - -**ProfilePage** (`/profile`) -- [x] Basic scaffold with app bar -- [x] User state display (guest/authenticated) -- [x] StateBuilder integration -- [x] Navigation to auth page -- [x] Logout functionality (placeholder) - -**AuthPage** (`/auth`) -- [x] Basic scaffold -- [x] Three auth options UI: - - Google Sign-In button - - Telegram Login button - - Continue as Guest button -- [x] Ready for Stage 2 implementation - -**MainShell** -- [x] Bottom navigation bar with 3 items -- [x] Icons and labels -- [x] Navigation logic -- [x] Child widget rendering - -#### 6. Services ✅ - -**AuthService** -- [x] Created with SharedPreferences dependency -- [x] Methods defined (with UnimplementedError): - - `loginWithGoogle()` - - `logout()` -- [x] Ready for Stage 2 implementation - -#### 7. Theme ✅ -- [x] `AppTheme.light` - Light theme -- [x] `AppTheme.dark` - Dark theme -- [x] Material 3 design -- [x] Color scheme: - - Primary: Blue - - Secondary: Orange -- [x] Custom component themes: - - AppBarTheme - - CardTheme - - InputDecorationTheme - -#### 8. Main App ✅ -- [x] `main.dart` - App entry point -- [x] Firebase initialization -- [x] AppScope creation -- [x] UserScope initialization for guest mode -- [x] Error handling for initialization - -**App Widget** -- [x] ScopeProvider for AppScope -- [x] Nested ScopeProvider for UserScope -- [x] StateBuilder for reactive theme -- [x] MaterialApp.router integration -- [x] Loading placeholders - -#### 9. Testing ✅ -**Unit Tests Created:** -- [x] `auth_module_test.dart` - AuthModule tests -- [x] `storage_module_test.dart` - StorageModule tests -- [x] `router_module_test.dart` - RouterModule tests -- [x] `auth_service_test.dart` - AuthService tests -- [x] `theme_state_manager_test.dart` - ThemeStateManager tests -- [x] `user_state_manager_test.dart` - UserStateManager tests -- [x] `user_scope_container_test.dart` - UserScope tests -- [x] `app_router_test.dart` - Router configuration tests -- [x] `app_theme_test.dart` - Theme tests -- [x] `scope_integration_test.dart` - Integration tests - -**Test Coverage:** -- ✅ All modules tested -- ✅ All state managers tested -- ✅ All services tested -- ✅ Router configuration tested -- ✅ Theme configuration tested -- ✅ Scope lifecycle tested -- ✅ Integration tests for scope hierarchy - ---- - -## ✅ Stage 2: Авторизация (COMPLETED) - -### 🎯 Goals -- Backend integration with HTTP client -- Implement authentication with Google and Telegram -- Complete auth flow with token management -- Update UI for login/logout functionality -- Comprehensive testing - -### ✨ Completed Features - -#### 1. Backend Integration ✅ -- [x] Created `ApiConfig` class with environment configuration - - Base URL configuration - - API endpoint paths - - Timeout settings - - App version management -- [x] Configured HTTP communication layer -- [x] Request/response logging -- [x] Ready for production deployment - -#### 2. API Exceptions ✅ -- [x] Created exception hierarchy: - - `ApiException` (base class) - - `NetworkException` (network errors) - - `ServerException` (server errors) - - `UnauthorizedException` (401) - - `ForbiddenException` (403) - - `NotFoundException` (404) - - `ValidationException` (400) -- [x] Proper error messages and status codes -- [x] Stack trace preservation - -#### 3. HttpRepository ✅ -- [x] Created with Dio integration -- [x] Token storage and retrieval (SharedPreferences) -- [x] Request interceptor for auth tokens -- [x] Request token generation for security -- [x] Response/Error interceptors -- [x] Error handling and mapping -- [x] API endpoints implemented: - - `createUser` - User authentication - - `fetchUser` - Get current user - - `getPacksPreviews` - Get all packs - - `getPack` - Get specific pack - - `getGames` - Get available games -- [x] Token management methods: - - `saveToken()` - Persist auth token - - `getToken()` - Retrieve auth token - - `clearToken()` - Remove auth token - - `isAuthenticated()` - Check auth status - -#### 4. AuthService Enhancement ✅ -- [x] Complete Google Sign-In implementation - - Get Google ID token - - Send to backend for validation - - Receive and store user + auth token - - Error handling -- [x] Telegram login (placeholder) -- [x] Logout functionality - - Clear Google session - - Clear auth token - - Update user state -- [x] Auto-login on app start - - Check for saved token - - Fetch user data - - Handle invalid tokens -- [x] Helper methods: - - `getCurrentUser()` - Get user from backend - - `isAuthenticated()` - Check auth status - - `currentGoogleUser` - Google account info - - `isGoogleSignedIn` - Google sign-in status - -#### 5. App Initialization ✅ -- [x] Updated `main.dart` with proper initialization -- [x] Created `_AppInitializer` widget - - Auto-login logic - - Error handling - - Guest mode fallback - - Loading states -- [x] Scope creation order managed correctly - -#### 6. UI Updates ✅ - -**AuthPage** (`/auth`) -- [x] Complete implementation with three options: - - Google Sign-In button - - Telegram Login button (placeholder) - - Continue as Guest button -- [x] Loading states during authentication -- [x] Error display with `SelectableText.rich` -- [x] Button disable during loading -- [x] Proper navigation after login -- [x] User state update after successful auth - -**ProfilePage** (`/profile`) -- [x] Guest mode display - - Information message - - Sign-in button -- [x] Authenticated user display: - - User avatar (initial letter) - - User name and email - - Statistics card (packs, purchases, subscription) - - Logout button -- [x] Loading states -- [x] Logout confirmation -- [x] Error handling with SnackBar - -#### 7. Module Updates ✅ -- [x] Updated `StorageModule`: - - Added Dio dependency - - Added HttpRepository - - Updated documentation -- [x] Updated `AuthModule`: - - Changed from FlutterSecureStorage to HttpRepository - - Updated AuthService constructor - - Maintained GoogleSignIn configuration - -#### 8. Testing ✅ -**New Test Files Created:** -- [x] `api_config_test.dart` - API configuration tests (5 tests) -- [x] `api_exception_test.dart` - Exception hierarchy tests (7 tests) -- [x] `http_repository_test.dart` - HTTP client tests (10 tests) -- [x] `auth_service_test.dart` - Updated for new implementation (9 tests) - -**Test Coverage:** -- ✅ All configuration values tested -- ✅ All exception types tested -- ✅ Token management tested -- ✅ Auth service interface tested -- ✅ Error scenarios covered - ---- - -## ✅ Stage 3: Темы (Packs) (COMPLETED) - -### 🎯 Goals -- Create packs functionality in UserScope -- Load and display card packs from backend -- Implement search functionality -- Create pack details page -- Comprehensive testing - -### ✨ Completed Features - -#### 1. PackManager Service ✅ -- [x] Created `PackManager` service - - `loadPacks()` - Load all packs from backend - - `loadPack(id)` - Load specific pack details - - `searchPacks()` - Search packs by query - - `filterByLanguage()` - Filter by language (ready) -- [x] Error handling and logging -- [x] Integration with HttpRepository - -#### 2. PacksStateManager ✅ -- [x] Created with freezed states: - - `PacksState.loading()` - Loading packs - - `PacksState.loaded(packs, searchQuery)` - Packs loaded - - `PacksState.error(message)` - Error occurred -- [x] Methods: - - `loadPacks()` - Load all packs - - `searchPacks(query)` - Filter by search query - - `reload()` - Force refresh -- [x] Auto-load packs on initialization -- [x] Caching for search functionality - -#### 3. PacksModule ✅ -- [x] Created `PacksModule` in UserScope -- [x] Dependencies provided: - - PackManager - - PacksStateManager -- [x] Auto-loads packs on creation -- [x] Added to UserScopeContainer - -#### 4. UserScope Updates ✅ -- [x] Updated `UserScope` interface: - - Added `packsStateManager` getter -- [x] Updated `UserScopeParent` interface: - - Added `httpRepository` getter -- [x] Updated `UserScopeContainer`: - - Added PacksModule - - Exposed PacksStateManager - - Provide httpRepository from parent -- [x] Updated `AppScopeContainer`: - - Implement httpRepository getter - -#### 5. UI Components ✅ - -**PackCard Widget** -- [x] Card design for pack preview -- [x] Shows pack icon placeholder -- [x] Shows pack title -- [x] Shows pack ID -- [x] Tap navigation to details - -**HomePage** (`/home`) -- [x] Complete implementation with: - - Search bar in app bar - - Grid layout for pack cards - - Pull-to-refresh functionality - - Loading state (spinner) - - Empty state (no packs / no search results) - - Error state with retry button - - Clear search functionality -- [x] StateBuilder integration -- [x] Search triggered on text change -- [x] Responsive grid layout - -**PackDetailsPage** (`/pack/:id`) -- [x] Complete implementation: - - Pack header with icon - - Pack title and subtitle - - Cards count - - List of all cards - - Pull-to-refresh - - Loading state - - Error state with retry - - Empty cards state -- [x] Card list items with front/back text -- [x] Navigation from HomePage - -#### 6. Router Updates ✅ -- [x] Added `/pack/:id` route -- [x] Integrated PackDetailsPage -- [x] Updated imports - -#### 7. Testing ✅ -**New Test Files Created:** -- [x] `pack_manager_test.dart` - PackManager tests (6 tests) -- [x] `packs_state_manager_test.dart` - State manager tests (7 tests) - -**Test Coverage:** -- ✅ PackManager instantiation -- ✅ Search functionality (empty, filters, case-insensitive, subtitle) -- ✅ Filter by language -- ✅ PacksStateManager initialization -- ✅ State manager methods -- ✅ All previous tests still passing - ---- - -## ✅ Stage 4: Игры (Games) (COMPLETED) - -### 🎯 Goals -- Create games functionality in UserScope -- Load and display games from backend -- Implement search functionality -- Create game cards UI -- Comprehensive testing - -### ✨ Completed Features - -#### 1. GamesManager Service ✅ -- [x] Created `GamesManager` service - - `loadGames()` - Load all games from backend - - `loadGame(id, games)` - Find specific game - - `searchGames()` - Search games by query -- [x] Error handling and logging -- [x] Integration with HttpRepository - -#### 2. GamesStateManager ✅ -- [x] Created with freezed states: - - `GamesState.loading()` - Loading games - - `GamesState.loaded(games, searchQuery)` - Games loaded - - `GamesState.error(message)` - Error occurred -- [x] Methods: - - `loadGames()` - Load all games - - `searchGames(query)` - Filter by search query - - `reload()` - Force refresh -- [x] Auto-load games on initialization -- [x] Caching for search functionality - -#### 3. GamesModule ✅ -- [x] Created `GamesModule` in UserScope -- [x] Dependencies provided: - - GamesManager - - GamesStateManager -- [x] Auto-loads games on creation -- [x] Added to UserScopeContainer - -#### 4. UserScope Updates ✅ -- [x] Updated `UserScope` interface: - - Added `gamesStateManager` getter -- [x] Updated `UserScopeContainer`: - - Added GamesModule - - Exposed GamesStateManager - -#### 5. UI Components ✅ - -**GameCard Widget** -- [x] Card design for game preview -- [x] Shows game icon with color -- [x] Shows game title and subtitle -- [x] Color parsing from DTO -- [x] Tap handler (shows coming soon message) - -**GamesPage** (`/games`) -- [x] Complete implementation with: - - Search bar in app bar - - Grid layout for game cards - - Pull-to-refresh functionality - - Loading state (spinner) - - Empty state (no games / no search results) - - Error state with retry button - - Clear search functionality -- [x] StateBuilder integration -- [x] Search triggered on text change -- [x] Responsive grid layout (max 300px width) - -#### 6. Testing ✅ -**New Test Files Created:** -- [x] `games_manager_test.dart` - GamesManager tests (8 tests) -- [x] `games_state_manager_test.dart` - State manager tests (11 tests) - -**Test Coverage:** -- ✅ GamesManager instantiation -- ✅ loadGame method (found and not found) -- ✅ Search functionality (empty, filters, case-insensitive) -- ✅ Search in title, subtitle, and id -- ✅ GamesStateManager initialization -- ✅ State manager methods -- ✅ GamesState variants (loading, loaded, error) -- ✅ when() method functionality - ---- - -## ✅ Stage 6: Полировка (Polish) (COMPLETED) - -### 🎯 Goals -- Improve UI/UX with modern loading states -- Add animations and transitions -- Enhance responsive design -- Improve accessibility -- Fix code quality issues -- Performance optimizations - -### ✨ Completed Features - -#### 1. Shimmer Loading ✅ -- [x] Created `PackCardShimmer` widget - - Matches PackCard layout - - Dark/light theme support - - Smooth shimmer animation -- [x] Created `GameCardShimmer` widget - - Matches GameCard layout - - Theme-aware colors - - Professional loading experience -- [x] Updated HomePage loading state - - Shows 6 shimmer cards instead of spinner - - Much better perceived performance -- [x] Updated GamesPage loading state - - Shows 6 shimmer cards - - Consistent UX across pages - -#### 2. Hero Animations ✅ -- [x] Added Hero animation to PackCard - - Smooth transition from list to details - - Tag: `pack-${pack.id}` -- [x] Added Hero animation to PackDetailsPage - - Matches card animation - - Seamless visual continuity - -#### 3. Code Quality Improvements ✅ -- [x] Fixed super parameter warnings (4 exceptions) - - UnauthorizedException - - ForbiddenException - - NotFoundException - - ValidationException -- [x] Improved BuildContext async handling - - AuthPage: Proper mounted checks - - ProfilePage: Early returns for unmounted -- [x] Added const constructors - - AuthPage MaterialPage - - Reduced warnings from 8 to 3 - -#### 4. Reusable UI Components ✅ -- [x] Created `ErrorView` widget - - Title, message, retry button - - Consistent error display - - Reusable across pages -- [x] Created `LoadingView` widget - - Optional message - - Centered spinner - - Reusable loading state - -#### 5. Responsive Design ✅ -- [x] Created `Responsive` utility class - - isMobile(), isTablet(), isDesktop() - - getMaxWidth() for content constraints - - getGridCrossAxisCount() for grids - - getPagePadding() for consistent spacing -- [x] Created `ResponsiveCenter` widget - - Constrains content width on large screens - - Better readability on desktop - - Ready for use across pages - -#### 6. Accessibility ✅ -- [x] Added Semantics to PackCard - - "Pack: {title}. Tap to view details." - - button: true role - - Screen reader support -- [x] Added Semantics to GameCard - - "Game: {title}. {subtitle}. Tap to play." - - button: true role - - Better a11y experience - ---- - -## ✅ API Integration with Main App (COMPLETED) - -### 🎯 Goal -Enable mnemo_cards_web_v2 to communicate with the same backend as the main mnemo_cards app without backend modifications (temporary solution). - -### ✨ Changes Made - -#### 1. API Configuration ✅ -- Changed baseUrl: `http://localhost:8080` → `http://localhost:8000` - - Matches main app web version - - Production URL: `https://api.mnemo-cards.online` (via nginx on port 443) -- Changed appVersion: `2.0.0` → `1.1.0` - - Required for TokenGenerator compatibility - - Enables proper request token generation - -#### 2. Authentication Headers ✅ -- Changed auth header: `Authorization` → `AppHeaders.userToken` - - Backend expects `user_token` header - - Matches main app implementation -- Fixed token reception: Uses `HttpHeaders.authorizationHeader` - - Backend returns token in standard `Authorization` response header - - Changed from `.first` to `.last` to match main app - -#### 3. Request Body Encoding ✅ -- Improved JSON encoding for Map data -- Proper string conversion for other types -- Matches TokenGenerator requirements - -#### 4. Test Updates ✅ -- Updated ApiConfig tests for new baseUrl and appVersion -- All 113 tests passing ✅ - -### 🔑 Technical Details - -**Request Headers Sent:** -``` -user_token: auth_token // Custom auth header -request_token: sha256_hash // Security token -app_version: 1.1.0 // Version header -``` - -**Token Generation:** -- Uses `TokenGenerator.generateRequestToken()` -- SHA256 hash of: `requestBody_appVersion_userToken_requestPath_salt` -- Version 1.1.0+ required for current salt - -**Auth Flow:** -1. POST `/user/create` with Google ID token -2. Receive auth token in `Authorization` response header -3. Store token in SharedPreferences -4. Send token in `user_token` header for subsequent requests - -### 📊 Impact -- ✅ Full compatibility with main app backend -- ✅ No backend changes required -- ✅ Can authenticate with Google -- ✅ Access to shared user database -- ✅ Access to same card packs and games - -### ⚠️ Temporary Solution -This integration uses the main app's custom authentication scheme. Future versions should migrate to: -- Standard OAuth2/JWT tokens -- Standard `Authorization: Bearer` header -- RESTful API patterns -- API versioning - -See [API_INTEGRATION_TEMP.md](./API_INTEGRATION_TEMP.md) for complete details. - ---- - -## 📈 Compilation Status - -### ✅ Build Status -- **lib/ compilation:** SUCCESS (0 errors) -- **test/ compilation:** SUCCESS (all tests passing) -- **Code generation:** SUCCESS (freezed, json_serializable) -- **Linter:** No critical issues - -### 🧪 Test Results -``` -Total Tests: 83 -Passing: 83 ✅ -Failing: 0 -Coverage: ~90% for Stages 1-3 code -``` - -**Test Categories:** -- Module Tests: 8 tests ✅ -- Service Tests: 19 tests ✅ (Auth + HTTP + Packs) -- State Manager Tests: 21 tests ✅ (Theme + User + Packs) -- Router Tests: 2 tests ✅ -- Theme Tests: 11 tests ✅ -- Integration Tests: 4 tests ✅ -- API Config Tests: 5 tests ✅ -- API Exception Tests: 7 tests ✅ -- HTTP Repository Tests: 10 tests ✅ -- PackManager Tests: 6 tests ✅ -- PacksStateManager Tests: 7 tests ✅ - ---- - -## 📁 Current Project Structure - -``` -lib/ -├── main.dart ✅ -├── app.dart ✅ -├── di/ -│ ├── app_scope/ -│ │ ├── app_scope_container.dart ✅ -│ │ ├── app_scope_holder.dart ✅ -│ │ ├── app_scope.dart ✅ -│ │ └── modules/ -│ │ ├── auth_module.dart ✅ -│ │ ├── router_module.dart ✅ -│ │ ├── analytics_module.dart ✅ -│ │ └── storage_module.dart ✅ -│ └── user_scope/ -│ ├── user_scope_container.dart ✅ -│ ├── user_scope_holder.dart ✅ -│ └── user_scope.dart ✅ -├── domain/ -│ ├── services/ -│ │ └── auth_service.dart ✅ (stub) -│ └── state/ -│ ├── theme_state_manager.dart ✅ -│ └── user_state_manager.dart ✅ -└── presentation/ - ├── router/ - │ └── app_router.dart ✅ - ├── pages/ - │ ├── home/ - │ │ └── home_page.dart ✅ - │ ├── games/ - │ │ └── games_page.dart ✅ - │ ├── profile/ - │ │ └── profile_page.dart ✅ - │ └── auth/ - │ └── auth_page.dart ✅ - ├── widgets/ - │ └── main_shell.dart ✅ - └── theme/ - └── app_theme.dart ✅ - -test/ ✅ -├── di/ -│ ├── app_scope/ -│ │ └── modules/ -│ │ ├── auth_module_test.dart -│ │ ├── storage_module_test.dart -│ │ └── router_module_test.dart -│ └── user_scope/ -│ └── user_scope_container_test.dart -├── domain/ -│ ├── services/ -│ │ └── auth_service_test.dart -│ └── state/ -│ ├── theme_state_manager_test.dart -│ └── user_state_manager_test.dart -├── presentation/ -│ ├── router/ -│ │ └── app_router_test.dart -│ └── theme/ -│ └── app_theme_test.dart -└── integration/ - └── scope_integration_test.dart -``` - ---- - -## 🎓 Key Technical Decisions - -### ✅ Architecture Patterns Used -1. **Clean Architecture** - Separation of concerns (DI, Domain, Presentation) -2. **Dependency Injection** - yx_scope for compile-safe DI -3. **State Management** - yx_state for reactive state -4. **Immutability** - freezed for type-safe immutable models -5. **Declarative Routing** - go_router for navigation - -### ✅ yx_scope Benefits Demonstrated -- ✅ Compile-time safety for dependencies -- ✅ Clear scope lifecycle (create/drop) -- ✅ Hierarchical scopes (App → User) -- ✅ No service locator pattern -- ✅ Easy testing with mock dependencies - -### ✅ yx_state Benefits Demonstrated -- ✅ Simple reactive state management -- ✅ Flutter widget integration (StateBuilder) -- ✅ Immutable states with freezed -- ✅ Clean state update API - ---- - -## 🚀 How to Run - -### Development -```bash -cd mnemo_cards_web_v2 -flutter pub get -flutter run -d chrome -``` - -### Run Tests -```bash -flutter test -``` - -### Code Generation -```bash -flutter pub run build_runner build --delete-conflicting-outputs -``` - ---- - -## ✅ Stage 5: Профиль (Profile Enhancement) (COMPLETED) - -### 🎯 Goals -- Create StatisticsService for user statistics -- Create ProfileModule in UserScope -- Enhance ProfilePage with statistics and settings -- Add theme toggle functionality -- Comprehensive testing - -### ✨ Completed Features - -#### 1. StatisticsService ✅ -- [x] Created `StatisticsService` for calculating user statistics - - `getStatistics(user)` - Get complete user statistics - - Calculates learned words count (based on packs) - - Calculates tests completed (based on purchases and subscription) - - Calculates total study time - - Generates daily progress for last 7 days -- [x] Data structures: - - `UserStatistics` - Complete statistics data - - `DailyProgress` - Daily progress data point -- [x] Equality support for testing -- [x] Error handling and edge cases - -#### 2. ProfileModule ✅ -- [x] Created `ProfileModule` in UserScope -- [x] Dependencies provided: - - StatisticsService -- [x] Added to UserScopeContainer -- [x] Integrated with UserScope interface - -#### 3. UserScope Updates ✅ -- [x] Updated `UserScope` interface: - - Added `statisticsService` getter -- [x] Updated `UserScopeContainer`: - - Added ProfileModule - - Exposed StatisticsService - - Updated documentation - -#### 4. UI Components ✅ - -**StatsCard Widget** -- [x] Displays single statistic in a card -- [x] Shows icon, label, and value -- [x] Customizable color -- [x] Material 3 design - -**SimpleChart Widget** -- [x] Bar chart for daily progress -- [x] Shows last 7 days of activity -- [x] Auto-scaling bars -- [x] Date labels -- [x] No external dependencies (custom implementation) - -**ProfilePage Enhanced** (`/profile`) -- [x] Complete redesign with sections: - - User header with avatar and name - - Premium badge for subscribed users - - Statistics section with 3 cards: - * Learned Words count - * Tests Completed count - * Study Time formatted - - Daily progress chart - - Account info card (packs, purchases) - - Settings card with: - * Dark Mode toggle (working!) - * Language setting (placeholder) - * Sound effects setting (placeholder) - - Logout button -- [x] Responsive layout -- [x] Pull-to-refresh functionality -- [x] Loading states -- [x] Error handling -- [x] Material 3 components - -#### 5. Theme Integration ✅ -- [x] Dark mode toggle working -- [x] Theme persisted to SharedPreferences -- [x] System theme preference support -- [x] Smooth theme transitions -- [x] Updated ProfilePage uses ThemeStateManager - -#### 6. Testing ✅ -**New Test Files Created:** -- [x] `statistics_service_test.dart` - Statistics service tests (10 tests) - -**Test Coverage:** -- ✅ StatisticsService instantiation -- ✅ Statistics calculation with packs -- ✅ Statistics calculation without packs -- ✅ Tests completed with subscription vs without -- ✅ Daily progress generation -- ✅ Non-negative values validation -- ✅ Study time calculation -- ✅ UserStatistics equality -- ✅ DailyProgress equality -- ✅ Date comparison (day-level) - ---- - -## 📈 Compilation Status - -### ✅ Build Status -- **lib/ compilation:** SUCCESS (0 errors) -- **test/ compilation:** SUCCESS (all tests passing) -- **Code generation:** SUCCESS (freezed, json_serializable) -- **Linter:** 8 info-level warnings (unchanged from Stage 4) - -### 🧪 Test Results -``` -Total Tests: 134 -Passing: 134 ✅ -Failing: 0 -Coverage: ~90% for implemented features -``` - -**Test Breakdown:** -- ImageCacheService: 15 tests ✅ -- TestManager: 6 tests ✅ -- Previous tests: 113 tests ✅ - -**Test Categories:** -- Module Tests: 8 tests ✅ -- Service Tests: 29 tests ✅ (Auth + HTTP + Packs + Statistics) -- State Manager Tests: 33 tests ✅ (Theme + User + Packs + Games) -- Router Tests: 2 tests ✅ -- Theme Tests: 11 tests ✅ -- Integration Tests: 4 tests ✅ -- API Config Tests: 5 tests ✅ -- API Exception Tests: 7 tests ✅ -- HTTP Repository Tests: 10 tests ✅ -- PackManager Tests: 6 tests ✅ -- PacksStateManager Tests: 7 tests ✅ -- GamesManager Tests: 9 tests ✅ -- GamesStateManager Tests: 11 tests ✅ -- StatisticsService Tests: 10 tests ✅ - ---- - -## 🔜 Next Steps: Stage 6 - Полировка (Polish) - -### Planned Features -1. **UI Polish** - - [ ] Add shimmer loading states - - [ ] Improve animations and transitions - - [ ] Add page transitions - - [ ] Hero animations for cards - - [ ] Better error boundaries - -2. **Responsive Design** - - [ ] Mobile optimization - - [ ] Tablet breakpoints - - [ ] Desktop layout improvements - -3. **Accessibility** - - [ ] Semantic labels - - [ ] Keyboard navigation - - [ ] Screen reader support - -4. **Performance** - - [ ] Code splitting - - [ ] Image optimization - - [ ] Lazy loading - -**Estimated Time:** 1-2 days -**Dependencies:** None - ---- - -## 📊 Overall Project Status - -| Stage | Name | Status | Progress | -|-------|------|--------|----------| -| 1 | Основа | ✅ Complete | 100% | -| 2 | Авторизация | ✅ Complete | 100% | -| 3 | Темы | ✅ Complete | 100% | -| 4 | Игры | ✅ Complete | 100% | -| 5 | Профиль | ✅ Complete | 100% | -| 6 | Полировка | ✅ Complete | 100% | -| 7 | Деплой | 🔄 Not Started | 0% | - -**Overall Project Completion:** ~85% (6/7 stages) - ---- - -## 📝 Notes - -### Lessons Learned -1. **yx_scope async initialization**: Use `rawAsyncDep` for async dependencies like Firebase -2. **Child scopes**: Don't need separate `ScopeProvider`, use holder directly -3. **StateBuilder**: Simple and effective for reactive UI -4. **freezed states**: Excellent for type-safe state management - -### Known Limitations -1. Firebase Analytics not fully configured (placeholder) -2. AuthService methods throw UnimplementedError (intentional for Stage 1) -3. No real HTTP communication yet (awaiting Stage 2) -4. No error boundaries (planned for Stage 6) - ---- - -## 🔧 Statistics System - Frontend Phase 1 ✅ COMPLETED - -**Date:** November 8, 2025 -**Status:** Phase 1 Complete - HttpRepositoryV2 Statistics Methods -**Time Spent:** 4 hours - -**Goal:** Update HttpRepositoryV2 with comprehensive statistics API methods to support detailed user statistics, pack progress, word analytics, timeline data, session tracking, and achievements. - -**Completed in Phase 1:** - -### API Configuration Updates -- ✅ Added 6 new endpoint constants to `ApiConfigV2`: - - `/users/me/statistics/detailed` - Complete user statistics - - `/users/me/statistics/packs` - Pack progress with filtering - - `/users/me/statistics/words` - Paginated word statistics - - `/users/me/statistics/timeline` - Study activity timeline - - `/users/me/sessions` - Study session recording - - `/users/me/achievements` - Achievement progress - -### HttpRepositoryV2 Methods Implementation -- ✅ **getDetailedStatistics()** - Returns UserDataDto with complete statistics -- ✅ **getPacksStatistics({String? packId})** - Pack progress with optional filtering -- ✅ **getWordsStatistics({params})** - Advanced pagination with sorting/filtering: - - Pagination: `limit`, `offset` (1-100 items) - - Sorting: `difficulty`, `accuracy`, `recent`, `alphabetical` - - Filtering: `packId`, `needsReview` -- ✅ **getTimelineStatistics({String? period, DateTime? from, DateTime? to})** - Timeline data: - - Period aggregation: `day`, `week`, `month`, `year` - - Custom date ranges - - Daily activity mapping -- ✅ **recordStudySession(StudySessionDto)** - Session metadata recording -- ✅ **getAchievements()** - Achievement progress tracking - -### Response DTOs Created -- ✅ **WordsStatisticsResponse** - Paginated word statistics with metadata -- ✅ **TimelineStatisticsResponse** - Timeline data with period information -- ✅ **StudySessionResponse** - Session recording confirmation - -### Error Handling & Validation -- ✅ Proper DioException handling with ApiException rethrow -- ✅ NetworkException and ServerException for different error types -- ✅ Parameter validation (limit clamping, date parsing) -- ✅ Null-safe response parsing - -### Testing Implementation -- ✅ Comprehensive smoke tests (6 tests, all passing) -- ✅ Method signature verification -- ✅ Integration with existing test patterns - -**Technical Details:** -- **Architecture:** Clean separation with dedicated statistics section -- **Error Handling:** Consistent with existing HttpRepositoryV2 patterns -- **Type Safety:** Full type-safe response parsing with custom DTOs -- **Performance:** Efficient query parameter building and response parsing -- **Extensibility:** Easy to add new statistics endpoints following same pattern - -**Next Steps:** -- Phase 3: Build statistics UI widgets and pages -- Phase 4: Integrate into profile/settings pages -- Phase 5: Add animations and polish - ---- - -## 🔧 Statistics System - Frontend Phase 2 ✅ COMPLETED - -**Date:** November 8, 2025 -**Status:** Phase 2 Complete - Statistics Service & State Manager -**Time Spent:** 3 hours - -**Goal:** Create StatisticsService business logic layer and StatisticsStateManager with comprehensive state management for the statistics system. - -**Completed in Phase 2:** - -### StatisticsService Implementation -- ✅ Enhanced existing StatisticsService with HttpRepositoryV2 integration -- ✅ Implemented all 6 API methods (detailed, packs, words, timeline, sessions, achievements) -- ✅ Added proper error handling and response processing -- ✅ Maintained backward compatibility with legacy getStatistics method -- ✅ Integrated with dependency injection system - -### StatisticsStateManager with yx_state -- ✅ Created comprehensive state management with yx_state -- ✅ Implemented state classes (loading, loaded, error states) -- ✅ Added computed properties (currentStreak, totalStudyTime, completedPacksCount, etc.) -- ✅ Implemented async loading methods with error handling -- ✅ Added state refresh and error clearing capabilities -- ✅ Created type-safe state transitions - -### Dependency Injection Integration -- ✅ Created StatisticsModule for clean DI setup -- ✅ Added StatisticsModule to UserScopeContainer -- ✅ Updated UserScope interface with StatisticsService and StatisticsStateManager -- ✅ Proper dependency injection with singleton pattern - -### State Management Features -- ✅ **Loading States:** Proper loading indicators during API calls -- ✅ **Error Handling:** Network and server error management with user-friendly messages -- ✅ **Data Refresh:** Automatic state refresh after session recording -- ✅ **Computed Properties:** Real-time calculations from state data -- ✅ **Selective Updates:** Individual data loading (detailed, packs, words, timeline, achievements) - -### Testing Implementation -- ✅ Comprehensive unit tests for StatisticsService (9 tests passing) -- ✅ Mock-based testing with proper dependency injection -- ✅ Error handling verification -- ✅ Legacy method compatibility testing -- ✅ State manager structure validation - -**Technical Details:** -- **Architecture:** Clean separation between service layer and state management -- **State Management:** yx_state with immutable state classes and async operations -- **Error Recovery:** Graceful error handling with state recovery mechanisms -- **Performance:** Efficient state updates and computed property caching -- **Scalability:** Easy to extend with new statistics features - -**Integration Points:** -- HttpRepositoryV2 for API communication -- UserScope for dependency injection -- yx_state for reactive state management -- Existing app architecture patterns - -**Next Steps:** -- Phase 3: Build statistics UI widgets and pages -- Phase 4: Integrate into profile/settings pages -- Phase 5: Add animations and polish - ---- - ---- - -## 🔧 Statistics System - Frontend Phase 3 ✅ COMPLETED - -**Date:** November 8, 2025 -**Status:** Phase 3 Complete - Statistics UI Widgets & Pages -**Time Spent:** 7 hours - -**Goal:** Create comprehensive statistics UI with beautiful, responsive Material Design widgets for displaying detailed user analytics, progress tracking, and achievement systems. - -**Completed in Phase 3:** - -### StatisticsPage - Main Hub -- ✅ **Tabbed Interface** - 5 comprehensive tabs: Overview, Words, Activity, Achievements, Packs -- ✅ **Navigation Integration** - Added to bottom navigation bar (5th tab) -- ✅ **Route Configuration** - `/statistics` route in GoRouter -- ✅ **Responsive Design** - Material Design with proper theming and spacing -- ✅ **State Management Integration** - Proper yx_state integration with error handling - -### StatisticsOverviewWidget - Dashboard -- ✅ **Key Metrics Cards** - Current streak, study time, completed packs, words learned -- ✅ **Recent Achievements** - Last 7 days unlocks with progress indicators -- ✅ **Activity Summary** - Daily activity overview with charts -- ✅ **Quick Actions** - Refresh and filter buttons -- ✅ **Progress Visualization** - Linear progress bars and completion percentages - -### WordsStatisticsWidget - Word Analytics -- ✅ **Pagination** - Configurable page size (20 items) with navigation controls -- ✅ **Advanced Filtering** - By pack, difficulty needs review status -- ✅ **Sorting Options** - Difficulty, accuracy, recent activity, alphabetical -- ✅ **Word Cards** - Detailed statistics per word (correct/incorrect/skipped) -- ✅ **Difficulty Indicators** - Color-coded difficulty levels (Easy/Medium/Hard) -- ✅ **Review Status** - Visual indicators for words needing attention - -### TimelineWidget - Study Activity Charts -- ✅ **Interactive Charts** - Bar chart showing daily study minutes -- ✅ **Period Filtering** - Week, month, year views with date range options -- ✅ **Summary Statistics** - Active days, total minutes, average daily activity -- ✅ **Visual Timeline** - Date-based activity visualization -- ✅ **Responsive Scaling** - Chart adapts to different screen sizes - -### AchievementsWidget - Progress Tracking -- ✅ **Achievement Cards** - Progress bars, unlock dates, descriptions -- ✅ **Status Indicators** - Locked/unlocked visual states -- ✅ **Progress Tracking** - Percentage completion for locked achievements -- ✅ **Category Icons** - Meaningful icons for different achievement types -- ✅ **Recent Activity** - Highlighting newly unlocked achievements - -### PackProgressWidget - Pack Completion -- ✅ **Pack Overview** - Completion status, accuracy, study time -- ✅ **Progress Visualization** - Linear progress bars with completion % -- ✅ **Statistics Display** - Accuracy percentages, attempt counts, time spent -- ✅ **Completion Badges** - Visual indicators for finished packs -- ✅ **Detailed Metrics** - Last studied dates, current progress status - -### UI/UX Features Implemented -- ✅ **Loading States** - Skeleton screens and progress indicators -- ✅ **Error Handling** - User-friendly error messages with retry options -- ✅ **Pull-to-Refresh** - Swipe down to refresh data -- ✅ **Empty States** - Meaningful messages when no data is available -- ✅ **Responsive Layout** - Works on different screen sizes -- ✅ **Material Design** - Consistent with app design language -- ✅ **Accessibility** - Proper contrast, readable fonts, semantic elements - -### Technical Implementation -- ✅ **State-Driven UI** - Reactive updates based on StatisticsState changes -- ✅ **Performance Optimized** - Efficient list rendering and pagination -- ✅ **Type Safety** - Strong typing throughout the UI components -- ✅ **Error Boundaries** - Graceful error handling at component level -- ✅ **Clean Architecture** - Separation of UI, state, and business logic - -**Integration Points:** -- StatisticsStateManager for data management -- UserScope for dependency injection -- Material Design theme system -- yx_state for reactive state updates -- GoRouter for navigation - -**UI Architecture:** -- **Component-Based** - Modular, reusable widgets -- **State-Driven** - UI reacts to state changes automatically -- **Performance-Focused** - Optimized rendering and memory usage -- **Accessible** - WCAG compliant design patterns -- **Responsive** - Mobile-first design approach - -**Next Steps:** -- Phase 4: Integrate into profile/settings pages -- Phase 5: Add animations and polish - ---- - -**Report Generated:** November 8, 2025 -**Generated By:** AI Assistant -**Last Build:** Success ✅ -**Tests:** 128/129 passing ✅ (one minor test adjustment needed) - diff --git a/mnemo_cards_web_v2/STATISTICS_TASKS.md b/mnemo_cards_web_v2/STATISTICS_TASKS.md deleted file mode 100644 index ec08213..0000000 --- a/mnemo_cards_web_v2/STATISTICS_TASKS.md +++ /dev/null @@ -1,1594 +0,0 @@ -# Statistics Frontend Tasks - -**Project:** mnemo_cards_web_v2 -**Feature:** Statistics System Upgrade - Frontend -**Created:** 2025-11-08 - ---- - -## Phase 1: Frontend Services - -### Task F1.1: Update HttpRepositoryV2 - -**Estimated Time:** 2-3 hours - -**File:** `lib/domain/services/http_repository_v2.dart` - -**Add Methods:** -```dart -class HttpRepositoryV2 { - // Existing methods... - - /// Get detailed user statistics - Future getDetailedStatistics() async { - final response = await _get('/users/me/statistics/detailed'); - return UserDataDto.fromJson(response); - } - - /// Get packs statistics - Future> getPacksStatistics({String? packId}) async { - final queryParams = packId != null ? '?packId=$packId' : ''; - final response = await _get('/users/me/statistics/packs$queryParams'); - return (response as List) - .map((e) => PackProgressDto.fromJson(e as Map)) - .toList(); - } - - /// Get words statistics with pagination - Future> getWordsStatistics({ - String? packId, - int limit = 50, - int offset = 0, - String sortBy = 'difficulty', - bool needsReview = false, - }) async { - final queryParams = { - 'limit': limit.toString(), - 'offset': offset.toString(), - 'sortBy': sortBy, - 'needsReview': needsReview.toString(), - if (packId != null) 'packId': packId, - }; - - final query = queryParams.entries - .map((e) => '${e.key}=${e.value}') - .join('&'); - - return await _get('/users/me/statistics/words?$query'); - } - - /// Get timeline statistics - Future> getTimelineStatistics({ - required String period, - DateTime? from, - DateTime? to, - }) async { - final queryParams = { - 'period': period, - if (from != null) 'from': from.toIso8601String(), - if (to != null) 'to': to.toIso8601String(), - }; - - final query = queryParams.entries - .map((e) => '${e.key}=${e.value}') - .join('&'); - - return await _get('/users/me/statistics/timeline?$query'); - } - - /// Record study session - Future recordStudySession(StudySessionDto session) async { - await _post('/users/me/sessions', body: session.toJson()); - } - - /// Get achievements - Future> getAchievements() async { - final response = await _get('/users/me/achievements'); - return (response as List) - .map((e) => AchievementDto.fromJson(e as Map)) - .toList(); - } -} -``` - -**Steps:** -- [ ] Add getDetailedStatistics method -- [ ] Add getPacksStatistics method with optional packId -- [ ] Add getWordsStatistics method with all filters -- [ ] Add getTimelineStatistics method -- [ ] Add recordStudySession method -- [ ] Add getAchievements method -- [ ] Add error handling for all methods -- [ ] Write unit tests with mocked responses - ---- - -### Task F1.2: Create Enhanced StatisticsService - -**Estimated Time:** 4-5 hours - -**File:** `lib/domain/services/statistics_service.dart` (rewrite) - -**New Models File:** `lib/domain/models/statistics_models.dart` (new) - -**Models:** -```dart -/// Detailed user statistics -class DetailedUserStatistics { - final int totalWords; - final Duration totalStudyTime; - final int testsCompleted; - final int currentStreak; - final int longestStreak; - final double averageAccuracy; - final List recentAchievements; - final Map packStats; - - const DetailedUserStatistics({...}); -} - -/// Pack statistics -class PackStatistics { - final String packId; - final String packName; - final int totalCards; - final int learnedCards; - final double progress; - final Duration studyTime; - final DateTime? lastStudyDate; - final double accuracy; - - const PackStatistics({...}); - - factory PackStatistics.fromDto(PackProgressDto dto, String packName) {...} -} - -/// Words statistics data with pagination -class WordsStatisticsData { - final List words; - final int totalCount; - final int page; - final int pageSize; - final bool hasMore; - - const WordsStatisticsData({...}); -} - -/// Individual word statistics -class WordStatistics { - final String word; - final String? translation; - final double correctRate; - final int totalAttempts; - final DateTime? lastReviewed; - final double difficultyScore; - final bool needsReview; - final String? packName; - - const WordStatistics({...}); - - factory WordStatistics.fromDto(DetailedWordStatisticsDto dto) {...} -} - -/// Timeline data -class TimelineData { - final List dailyActivity; - final Map hourlyActivity; // hour -> duration - final Map weekdayActivity; // weekday -> duration - - const TimelineData({...}); -} - -/// Daily activity -class DailyActivity { - final DateTime date; - final int wordsLearned; - final Duration studyTime; - final int testsCompleted; - final bool hasActivity; - - const DailyActivity({...}); -} - -/// Achievement -class Achievement { - final String id; - final String title; - final String description; - final String? iconUrl; - final DateTime? unlockedAt; - final bool isLocked; - final double progress; // 0.0 to 1.0 - final AchievementType type; - - const Achievement({...}); - - bool get isUnlocked => unlockedAt != null; - - factory Achievement.fromDto(AchievementDto dto) {...} -} -``` - -**Service:** -```dart -class StatisticsService { - final HttpRepositoryV2 _repository; - - StatisticsService(this._repository); - - /// Get detailed statistics - Future getDetailedStatistics() async { - final userDataDto = await _repository.getDetailedStatistics(); - return _convertToDetailedStatistics(userDataDto); - } - - /// Get packs statistics - Future> getPacksStatistics({String? packId}) async { - final dtos = await _repository.getPacksStatistics(packId: packId); - // Convert DTOs to PackStatistics (need to fetch pack names) - return _convertToPackStatistics(dtos); - } - - /// Get words statistics with pagination - Future getWordsStatistics({ - String? packId, - int page = 0, - int pageSize = 50, - WordsSortOption sortBy = WordsSortOption.difficulty, - bool needsReview = false, - }) async { - final response = await _repository.getWordsStatistics( - packId: packId, - limit: pageSize, - offset: page * pageSize, - sortBy: sortBy.value, - needsReview: needsReview, - ); - - return _convertToWordsStatisticsData(response, page, pageSize); - } - - /// Get timeline statistics - Future getTimelineStatistics({ - required TimelinePeriod period, - DateTime? from, - DateTime? to, - }) async { - final response = await _repository.getTimelineStatistics( - period: period.value, - from: from, - to: to, - ); - - return _convertToTimelineData(response); - } - - // Session management - String? _currentSessionId; - DateTime? _sessionStartTime; - - /// Start study session - String startSession({String? packId, String? testId}) { - _currentSessionId = _generateSessionId(); - _sessionStartTime = DateTime.now(); - - // Will be sent to backend when ended - return _currentSessionId!; - } - - /// End study session - Future endSession(String sessionId, { - int wordsLearned = 0, - int testsCompleted = 0, - double accuracy = 0.0, - }) async { - if (_currentSessionId != sessionId) return; - if (_sessionStartTime == null) return; - - final session = StudySessionDto( - sessionId: sessionId, - startTime: _sessionStartTime!, - endTime: DateTime.now(), - wordsLearned: wordsLearned, - testsCompleted: testsCompleted, - accuracy: accuracy, - ); - - await _repository.recordStudySession(session); - - _currentSessionId = null; - _sessionStartTime = null; - } - - /// Get achievements - Future> getAchievements() async { - final dtos = await _repository.getAchievements(); - return dtos.map((dto) => Achievement.fromDto(dto)).toList(); - } - - /// Get new (recently unlocked) achievements - Future> getNewAchievements() async { - final achievements = await getAchievements(); - final now = DateTime.now(); - final threeDaysAgo = now.subtract(const Duration(days: 3)); - - return achievements - .where((a) => - a.isUnlocked && - a.unlockedAt!.isAfter(threeDaysAgo)) - .toList(); - } - - // Private helper methods - DetailedUserStatistics _convertToDetailedStatistics(UserDataDto dto) {...} - List _convertToPackStatistics(List dtos) {...} - WordsStatisticsData _convertToWordsStatisticsData(Map response, int page, int pageSize) {...} - TimelineData _convertToTimelineData(Map response) {...} - String _generateSessionId() => 'session_${DateTime.now().millisecondsSinceEpoch}'; -} - -/// Sort options for words -enum WordsSortOption { - difficulty('difficulty'), - accuracy('accuracy'), - recent('recent'), - alphabetical('alphabetical'); - - final String value; - const WordsSortOption(this.value); -} - -/// Timeline period -enum TimelinePeriod { - day('day'), - week('week'), - month('month'), - year('year'); - - final String value; - const TimelinePeriod(this.value); -} -``` - -**Steps:** -- [ ] Create statistics_models.dart with all model classes -- [ ] Rewrite StatisticsService with real logic -- [ ] Implement all conversion methods -- [ ] Add session tracking logic -- [ ] Add error handling -- [ ] Write comprehensive unit tests - ---- - -### Task F1.3: Create State Managers - -**Estimated Time:** 3-4 hours - -#### 1. StatisticsStateManager - -**File:** `lib/domain/state/statistics_state_manager.dart` (new) - -```dart -@freezed -class StatisticsState with _$StatisticsState { - const factory StatisticsState.loading() = _Loading; - const factory StatisticsState.loaded(DetailedUserStatistics statistics) = _Loaded; - const factory StatisticsState.error(String message) = _Error; -} - -class StatisticsStateManager extends StateManager { - final StatisticsService _service; - - StatisticsStateManager(this._service) - : super(const StatisticsState.loading()); - - Future loadStatistics() => handle((emit) async { - emit(const StatisticsState.loading()); - try { - final statistics = await _service.getDetailedStatistics(); - emit(StatisticsState.loaded(statistics)); - } catch (e) { - emit(StatisticsState.error(e.toString())); - } - }); - - Future refreshStatistics() => loadStatistics(); -} -``` - -#### 2. PacksStatisticsStateManager - -**File:** `lib/domain/state/packs_statistics_state_manager.dart` (new) - -```dart -@freezed -class PacksStatisticsState with _$PacksStatisticsState { - const factory PacksStatisticsState.loading() = _Loading; - const factory PacksStatisticsState.loaded(List packs) = _Loaded; - const factory PacksStatisticsState.error(String message) = _Error; -} - -class PacksStatisticsStateManager extends StateManager { - final StatisticsService _service; - - PacksStatisticsStateManager(this._service) - : super(const PacksStatisticsState.loading()); - - Future loadStatistics({String? packId}) => handle((emit) async { - emit(const PacksStatisticsState.loading()); - try { - final packs = await _service.getPacksStatistics(packId: packId); - emit(PacksStatisticsState.loaded(packs)); - } catch (e) { - emit(PacksStatisticsState.error(e.toString())); - } - }); -} -``` - -#### 3. WordsStatisticsStateManager - -**File:** `lib/domain/state/words_statistics_state_manager.dart` (new) - -```dart -@freezed -class WordsStatisticsState with _$WordsStatisticsState { - const factory WordsStatisticsState.loading() = _Loading; - const factory WordsStatisticsState.loaded(WordsStatisticsData data) = _Loaded; - const factory WordsStatisticsState.error(String message) = _Error; -} - -class WordsStatisticsStateManager extends StateManager { - final StatisticsService _service; - - WordsStatisticsStateManager(this._service) - : super(const WordsStatisticsState.loading()); - - Future loadStatistics({ - String? packId, - int page = 0, - WordsSortOption sortBy = WordsSortOption.difficulty, - bool needsReview = false, - }) => handle((emit) async { - emit(const WordsStatisticsState.loading()); - try { - final data = await _service.getWordsStatistics( - packId: packId, - page: page, - sortBy: sortBy, - needsReview: needsReview, - ); - emit(WordsStatisticsState.loaded(data)); - } catch (e) { - emit(WordsStatisticsState.error(e.toString())); - } - }); - - Future loadMore() => handle((emit) async { - final currentState = state; - if (currentState is! _Loaded) return; - - final currentData = currentState.data; - if (!currentData.hasMore) return; - - // Load next page and append - // Implementation... - }); -} -``` - -#### 4. AchievementsStateManager - -**File:** `lib/domain/state/achievements_state_manager.dart` (new) - -```dart -@freezed -class AchievementsState with _$AchievementsState { - const factory AchievementsState.loading() = _Loading; - const factory AchievementsState.loaded(List achievements) = _Loaded; - const factory AchievementsState.error(String message) = _Error; -} - -class AchievementsStateManager extends StateManager { - final StatisticsService _service; - - AchievementsStateManager(this._service) - : super(const AchievementsState.loading()); - - Future loadAchievements() => handle((emit) async { - emit(const AchievementsState.loading()); - try { - final achievements = await _service.getAchievements(); - emit(AchievementsState.loaded(achievements)); - } catch (e) { - emit(AchievementsState.error(e.toString())); - } - }); - - List get unlockedAchievements { - final currentState = state; - if (currentState is! _Loaded) return []; - return currentState.achievements.where((a) => a.isUnlocked).toList(); - } - - List get lockedAchievements { - final currentState = state; - if (currentState is! _Loaded) return []; - return currentState.achievements.where((a) => a.isLocked).toList(); - } -} -``` - -**Steps:** -- [ ] Create all state manager files -- [ ] Generate freezed classes -- [ ] Add to UserScope DI module -- [ ] Write unit tests for each state manager - ---- - -### Task F1.4: Add to DI Module - -**Estimated Time:** 1 hour - -**File:** `lib/di/user_scope/modules/statistics_module.dart` (new) - -```dart -@module -abstract class StatisticsModule { - @lazySingleton - StatisticsService statisticsService(HttpRepositoryV2 repository) { - return StatisticsService(repository); - } - - @lazySingleton - StatisticsStateManager statisticsStateManager(StatisticsService service) { - return StatisticsStateManager(service); - } - - @lazySingleton - PacksStatisticsStateManager packsStatisticsStateManager( - StatisticsService service, - ) { - return PacksStatisticsStateManager(service); - } - - @lazySingleton - WordsStatisticsStateManager wordsStatisticsStateManager( - StatisticsService service, - ) { - return WordsStatisticsStateManager(service); - } - - @lazySingleton - AchievementsStateManager achievementsStateManager( - StatisticsService service, - ) { - return AchievementsStateManager(service); - } -} -``` - -**Steps:** -- [ ] Create statistics_module.dart -- [ ] Add module to UserScope -- [ ] Run DI code generation -- [ ] Verify injection works - ---- - -## Phase 2: UI Components - Statistics Widgets - -### Task F2.1: Create Base Statistics Widgets - -**Estimated Time:** 6-8 hours - -#### 1. StatsCard - -**File:** `lib/presentation/widgets/stats/stats_card.dart` (new) - -```dart -class StatsCard extends StatelessWidget { - final IconData icon; - final String label; - final String value; - final Color? color; - final VoidCallback? onTap; - - const StatsCard({ - required this.icon, - required this.label, - required this.value, - this.color, - this.onTap, - super.key, - }); - - @override - Widget build(BuildContext context) { - // Beautiful card with gradient, icon, value, label - // Shimmer loading animation - // Counter animation for value - } -} -``` - -#### 2. CircularProgressWidget - -**File:** `lib/presentation/widgets/stats/circular_progress_widget.dart` - -```dart -class CircularProgressWidget extends StatelessWidget { - final double progress; // 0.0 to 1.0 - final double size; - final Color? color; - final String? centerText; - - const CircularProgressWidget({ - required this.progress, - this.size = 100, - this.color, - this.centerText, - super.key, - }); - - @override - Widget build(BuildContext context) { - // Custom circular progress with gradient - // Percentage or custom text in center - // Animation - } -} -``` - -#### 3. ActivityHeatmap - -**File:** `lib/presentation/widgets/stats/activity_heatmap.dart` - -```dart -class ActivityHeatmap extends StatelessWidget { - final List activities; - final int daysToShow; - - const ActivityHeatmap({ - required this.activities, - this.daysToShow = 30, - super.key, - }); - - @override - Widget build(BuildContext context) { - // GitHub-style heatmap - // Tooltips on hover - // Color intensity based on activity - } -} -``` - -#### 4. StreakCalendar - -**File:** `lib/presentation/widgets/stats/streak_calendar.dart` - -```dart -class StreakCalendar extends StatelessWidget { - final int currentStreak; - final int longestStreak; - final List studyDates; - - const StreakCalendar({ - required this.currentStreak, - required this.longestStreak, - required this.studyDates, - super.key, - }); - - @override - Widget build(BuildContext context) { - // Calendar view with streak visualization - // Fire icon for current streak - // Trophy icon for longest streak - } -} -``` - -#### 5. TimelineChart - -**File:** `lib/presentation/widgets/stats/timeline_chart.dart` - -```dart -class TimelineChart extends StatelessWidget { - final TimelineData data; - final TimelinePeriod period; - - const TimelineChart({ - required this.data, - required this.period, - super.key, - }); - - @override - Widget build(BuildContext context) { - // Line chart using fl_chart - // Interactive tooltips - // Smooth animations - } -} -``` - -**Steps:** -- [ ] Create all widget files -- [ ] Implement beautiful UI for each -- [ ] Add animations -- [ ] Make responsive -- [ ] Add loading states -- [ ] Write widget tests - ---- - -## Phase 3: UI Pages - Profile Redesign - -### Task F3.1: Redesign ProfilePage - -**Estimated Time:** 12-15 hours - -**File:** `lib/presentation/pages/profile/profile_page.dart` (major rewrite) - -**New Components to Create:** - -#### 1. ProfileUserHeader - -**File:** `lib/presentation/pages/profile/widgets/profile_user_header.dart` - -```dart -class ProfileUserHeader extends StatelessWidget { - final UserDto user; - final int currentStreak; - - const ProfileUserHeader({ - required this.user, - required this.currentStreak, - super.key, - }); - - @override - Widget build(BuildContext context) { - return Card( - child: Padding( - child: Row( - children: [ - // Large avatar with gradient border - _buildAvatar(), - - // User info - Expanded( - child: Column( - children: [ - _buildNameAndEmail(), - _buildBadges(), // streak, subscription, level - ], - ), - ), - ], - ), - ), - ); - } -} -``` - -#### 2. QuickStatsGrid - -**File:** `lib/presentation/pages/profile/widgets/quick_stats_grid.dart` - -```dart -class QuickStatsGrid extends StatelessWidget { - final DetailedUserStatistics statistics; - - const QuickStatsGrid({ - required this.statistics, - super.key, - }); - - @override - Widget build(BuildContext context) { - return GridView.count( - crossAxisCount: 2, - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - children: [ - StatsCard( - icon: Icons.book, - label: 'Words Learned', - value: statistics.totalWords.toString(), - ), - StatsCard( - icon: Icons.timer, - label: 'Study Time', - value: _formatDuration(statistics.totalStudyTime), - ), - StatsCard( - icon: Icons.quiz, - label: 'Tests Completed', - value: statistics.testsCompleted.toString(), - ), - StatsCard( - icon: Icons.trending_up, - label: 'Accuracy', - value: '${(statistics.averageAccuracy * 100).toStringAsFixed(1)}%', - ), - ], - ); - } -} -``` - -#### 3. StreakCard - -**File:** `lib/presentation/pages/profile/widgets/streak_card.dart` - -```dart -class StreakCard extends StatelessWidget { - final int currentStreak; - final int longestStreak; - final List studyDates; - - const StreakCard({ - required this.currentStreak, - required this.longestStreak, - required this.studyDates, - super.key, - }); - - @override - Widget build(BuildContext context) { - return Card( - child: Padding( - child: Column( - children: [ - _buildHeader(), - const SizedBox(height: 16), - StreakCalendar( - currentStreak: currentStreak, - longestStreak: longestStreak, - studyDates: studyDates, - ), - ], - ), - ), - ); - } -} -``` - -#### 4. PackProgressCard - -**File:** `lib/presentation/pages/profile/widgets/pack_progress_card.dart` - -```dart -class PackProgressCard extends StatelessWidget { - final PackStatistics packStats; - final VoidCallback? onTap; - - const PackProgressCard({ - required this.packStats, - this.onTap, - super.key, - }); - - @override - Widget build(BuildContext context) { - return Card( - child: InkWell( - onTap: onTap, - child: Padding( - child: Row( - children: [ - // Pack image - _buildPackImage(), - - const SizedBox(width: 16), - - // Pack info and progress - Expanded( - child: Column( - children: [ - _buildPackName(), - _buildProgressBar(), - _buildStats(), - ], - ), - ), - - // Progress circle - CircularProgressWidget( - progress: packStats.progress, - size: 60, - ), - ], - ), - ), - ), - ); - } -} -``` - -#### 5. AchievementBadge - -**File:** `lib/presentation/pages/profile/widgets/achievement_badge.dart` - -```dart -class AchievementBadge extends StatelessWidget { - final Achievement achievement; - final VoidCallback? onTap; - - const AchievementBadge({ - required this.achievement, - this.onTap, - super.key, - }); - - @override - Widget build(BuildContext context) { - return GestureDetector( - onTap: onTap, - child: Tooltip( - message: achievement.description, - child: Container( - width: 80, - height: 100, - child: Column( - children: [ - // Badge icon/image - _buildBadgeIcon(), - - const SizedBox(height: 8), - - // Badge title - Text( - achievement.title, - maxLines: 2, - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodySmall, - ), - ], - ), - ), - ), - ); - } -} -``` - -**Main ProfilePage Structure:** - -```dart -class ProfilePage extends StatefulWidget { - const ProfilePage({super.key}); - - @override - State createState() => _ProfilePageState(); -} - -class _ProfilePageState extends State { - @override - void initState() { - super.initState(); - // Load statistics on page open - _loadStatistics(); - } - - void _loadStatistics() { - final statisticsManager = context.read(); - statisticsManager.loadStatistics(); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Profile'), - actions: [ - IconButton( - icon: const Icon(Icons.settings), - onPressed: () => context.go('/settings'), - ), - ], - ), - body: RefreshIndicator( - onRefresh: () async { - await _loadStatistics(); - }, - child: ScopeBuilder( - builder: (context, userScope) { - if (userScope == null) { - return const Center(child: CircularProgressIndicator()); - } - - return StateBuilder( - stateReadable: userScope.userStateManager, - builder: (context, userState, _) { - return userState.when( - guest: () => _buildGuestView(context), - authenticated: (user) => _buildAuthenticatedView( - context, - user, - userScope, - ), - loading: () => const Center( - child: CircularProgressIndicator(), - ), - ); - }, - ); - }, - ), - ), - ); - } - - Widget _buildAuthenticatedView( - BuildContext context, - UserDto user, - UserScope userScope, - ) { - return StateBuilder( - stateReadable: userScope.statisticsStateManager, - builder: (context, statisticsState, _) { - return statisticsState.when( - loading: () => _buildLoadingSkeleton(), - loaded: (statistics) => _buildProfileContent( - context, - user, - statistics, - userScope, - ), - error: (message) => _buildErrorView(message), - ); - }, - ); - } - - Widget _buildProfileContent( - BuildContext context, - UserDto user, - DetailedUserStatistics statistics, - UserScope userScope, - ) { - return SingleChildScrollView( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // User header with avatar and badges - ProfileUserHeader( - user: user, - currentStreak: statistics.currentStreak, - ), - - const SizedBox(height: 24), - - // Quick stats grid (4 cards) - QuickStatsGrid(statistics: statistics), - - const SizedBox(height: 24), - - // Streak card with calendar - StreakCard( - currentStreak: statistics.currentStreak, - longestStreak: statistics.longestStreak, - studyDates: [], // from statistics - ), - - const SizedBox(height: 24), - - // Activity chart - _buildActivitySection(userScope), - - const SizedBox(height: 24), - - // Packs progress - _buildPacksProgressSection( - context, - statistics.packStats.values.toList(), - ), - - const SizedBox(height: 24), - - // Achievements - _buildAchievementsSection( - context, - statistics.recentAchievements, - ), - - const SizedBox(height: 24), - - // Account actions - _buildAccountActionsCard(context), - ], - ), - ); - } - - Widget _buildActivitySection(UserScope userScope) { - // TimelineChart with tabs for different periods - } - - Widget _buildPacksProgressSection( - BuildContext context, - List packs, - ) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Your Packs Progress', - style: Theme.of(context).textTheme.titleLarge, - ), - TextButton( - onPressed: () => context.go('/statistics/packs'), - child: const Text('View All'), - ), - ], - ), - const SizedBox(height: 16), - ...packs.take(3).map((pack) => Padding( - padding: const EdgeInsets.only(bottom: 12), - child: PackProgressCard( - packStats: pack, - onTap: () => context.go('/packs/${pack.packId}'), - ), - )), - ], - ); - } - - Widget _buildAchievementsSection( - BuildContext context, - List achievements, - ) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Recent Achievements', - style: Theme.of(context).textTheme.titleLarge, - ), - TextButton( - onPressed: () => context.go('/achievements'), - child: const Text('View All'), - ), - ], - ), - const SizedBox(height: 16), - SizedBox( - height: 120, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: achievements.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.only(right: 16), - child: AchievementBadge( - achievement: achievements[index], - onTap: () => context.go('/achievements'), - ), - ); - }, - ), - ), - ], - ); - } -} -``` - -**Steps:** -- [ ] Create all widget files -- [ ] Implement ProfileUserHeader -- [ ] Implement QuickStatsGrid -- [ ] Implement StreakCard -- [ ] Implement PackProgressCard -- [ ] Implement AchievementBadge -- [ ] Rewrite ProfilePage with new layout -- [ ] Add skeleton loading states -- [ ] Add error states -- [ ] Make responsive (mobile/tablet/desktop) -- [ ] Add animations -- [ ] Write widget tests - ---- - -## Phase 4: UI Pages - Statistics Pages - -### Task F4.1: Create WordsStatisticsPage - -**Estimated Time:** 6-8 hours - -**File:** `lib/presentation/pages/statistics/words_statistics_page.dart` (new) - -**Structure:** -- AppBar with search -- Filter bar (pack, sort, needs review toggle) -- Paginated list of WordStatisticsCard -- Load more button - -**Components:** - -1. `WordStatisticsCard` (`widgets/word_statistics_card.dart`) -2. `WordsFilterBar` (`widgets/words_filter_bar.dart`) - -**Steps:** -- [ ] Create WordsStatisticsPage -- [ ] Create WordStatisticsCard -- [ ] Create WordsFilterBar -- [ ] Implement pagination -- [ ] Implement search -- [ ] Implement filtering and sorting -- [ ] Add empty state -- [ ] Add loading skeleton -- [ ] Write widget tests - ---- - -### Task F4.2: Create PacksStatisticsPage - -**Estimated Time:** 8-10 hours - -**File:** `lib/presentation/pages/statistics/packs_statistics_page.dart` (new) - -**Structure:** -- AppBar with sort menu -- Grid/List of PackStatisticsCard -- Detailed page for each pack - -**Additional Page:** - -**File:** `lib/presentation/pages/statistics/pack_statistics_details_page.dart` - -**Structure:** -- Pack header with overall stats -- Progress timeline chart -- Cards list with individual progress -- Study history timeline - -**Steps:** -- [ ] Create PacksStatisticsPage -- [ ] Create PackStatisticsDetailsPage -- [ ] Create PackHeaderCard widget -- [ ] Create ProgressTimelineChart widget -- [ ] Create CardProgressItem widget -- [ ] Implement navigation -- [ ] Add empty state -- [ ] Write widget tests - ---- - -### Task F4.3: Create AchievementsPage - -**Estimated Time:** 6-8 hours - -**File:** `lib/presentation/pages/achievements/achievements_page.dart` (new) - -**Structure:** -- AppBar with progress indicator (X/Y unlocked) -- Tabs (All / Unlocked / Locked) -- Grid of AchievementCard -- Unlock animation for new achievements - -**Components:** - -1. `AchievementCard` (detailed card, not just badge) -2. `AchievementUnlockDialog` - shown when new achievement unlocked - -**Steps:** -- [ ] Create AchievementsPage -- [ ] Create AchievementCard widget -- [ ] Create AchievementUnlockDialog -- [ ] Implement tabs filtering -- [ ] Add unlock animations -- [ ] Add confetti effect for unlocks -- [ ] Write widget tests - ---- - -## Phase 5: Settings Page - -### Task F5.1: Create SettingsPage - -**Estimated Time:** 10-12 hours - -**File:** `lib/presentation/pages/settings/settings_page.dart` (new) - -**Structure:** -- Appearance section (theme, color, font size, language) -- Learning section (daily goal, reminders, auto-play, etc.) -- Privacy section (analytics, ads) -- Account section (email, name, password, delete) -- Data section (export, import, clear cache) -- About section (version, terms, privacy policy) - -**Components:** - -1. **SettingsSection** (`widgets/settings_section.dart`) -2. **SettingsTile** (`widgets/settings_tile.dart`) -3. **ThemeSelector** (`widgets/theme_selector.dart`) -4. **ColorPicker** (`widgets/color_picker_widget.dart`) -5. **TimePickerSetting** (`widgets/time_picker_setting.dart`) - -**Steps:** -- [ ] Create SettingsPage with all sections -- [ ] Create SettingsSection widget -- [ ] Create SettingsTile widget -- [ ] Create ThemeSelector widget -- [ ] Create ColorPicker widget -- [ ] Create TimePickerSetting widget -- [ ] Implement settings save/load -- [ ] Add confirmation dialogs for destructive actions -- [ ] Write widget tests - ---- - -### Task F5.2: Extend UserSettingsDto - -**Estimated Time:** 2-3 hours - -**File:** `mnemo_cards_common/lib/src/dtos/user/settings/user_settings_dto.dart` - -**Add Fields:** -```dart -@JsonSerializable() -@CopyWith() -class UserSettingsDto { - // Appearance - final String theme; // 'light', 'dark', 'system' - final String? primaryColor; - final double fontSize; // 0.8 - 1.2 - final String language; - - // Learning - final int dailyGoalWords; - final bool reminderEnabled; - final String? reminderTime; - final bool autoPlayAudio; - final bool showTranslations; - final int cardsPerSession; - - // Privacy - final bool analyticsEnabled; - final bool personalizedAdsEnabled; - - // Notifications - final bool pushNotificationsEnabled; - final bool emailNotificationsEnabled; -} -``` - -**Steps:** -- [ ] Add new fields to UserSettingsDto -- [ ] Run codegen -- [ ] Update backend to support new fields -- [ ] Write tests - ---- - -### Task F5.3: Create SettingsStateManager - -**Estimated Time:** 2 hours - -**File:** `lib/domain/state/settings_state_manager.dart` (new) - -```dart -class SettingsStateManager extends StateManager { - final HttpRepositoryV2 _repository; - final SharedPreferences _prefs; - - SettingsStateManager(this._repository, this._prefs) - : super(_loadFromPrefs(_prefs)); - - static UserSettingsDto _loadFromPrefs(SharedPreferences prefs) { - // Load from local storage - } - - Future updateSettings(UserSettingsDto settings) => handle((emit) async { - emit(settings); - await _saveToPrefs(settings); - await _repository.updateUserSettings(settings); - }); - - Future _saveToPrefs(UserSettingsDto settings) async { - // Save to local storage - } -} -``` - -**Steps:** -- [ ] Create SettingsStateManager -- [ ] Implement local storage -- [ ] Implement server sync -- [ ] Add to DI -- [ ] Write unit tests - ---- - -### Task F5.4: Apply Settings Throughout App - -**Estimated Time:** 6-8 hours - -**Apply Settings In:** - -1. **Theme** - Update ThemeStateManager -2. **Font Size** - Apply scaling factor -3. **Learning** - Use in CardFlipper, tests -4. **Daily Goal** - Show on ProfilePage - -**Files to Modify:** -- `lib/domain/state/theme_state_manager.dart` -- `lib/presentation/widgets/card_flipper/card_flipper.dart` -- `lib/presentation/pages/profile/profile_page.dart` - -**Steps:** -- [ ] Update ThemeStateManager to support custom colors -- [ ] Apply font size scaling -- [ ] Use learning settings in CardFlipper -- [ ] Show daily goal tracking on ProfilePage -- [ ] Implement reminder notifications (web) -- [ ] Write tests - ---- - -## Phase 6: Polish and Animations - -### Task F6.1: Add Animations - -**Estimated Time:** 6-8 hours - -**Animations to Add:** - -1. **Page Transitions** - Hero animations -2. **Counter Animations** - Animated numbers -3. **Chart Animations** - fl_chart animations -4. **Achievement Unlock** - Confetti + scale animation -5. **Shimmer Loading** - Skeleton screens -6. **Pull to Refresh** - Custom refresh indicator - -**Files:** -- Create `lib/presentation/animations/` directory -- `animated_counter.dart` -- `shimmer_loading.dart` -- `achievement_confetti.dart` - -**Dependencies to Add:** -- fl_chart -- shimmer -- confetti -- lottie (optional) - -**Steps:** -- [ ] Create AnimatedCounter widget -- [ ] Add shimmer loaders to all pages -- [ ] Add Hero animations for images -- [ ] Create achievement unlock animation -- [ ] Add confetti effect -- [ ] Add pull-to-refresh -- [ ] Write widget tests - ---- - -## Phase 7: Testing - -### Task F7.1: Unit Tests - -**Estimated Time:** 4-5 hours - -**Test Files:** -- `test/domain/services/statistics_service_test.dart` -- `test/domain/state/statistics_state_manager_test.dart` -- `test/domain/state/settings_state_manager_test.dart` -- `test/domain/models/statistics_models_test.dart` - -**Steps:** -- [ ] Write StatisticsService tests -- [ ] Write state manager tests -- [ ] Write model conversion tests -- [ ] Write settings logic tests - ---- - -### Task F7.2: Widget Tests - -**Estimated Time:** 6-8 hours - -**Test Files:** -- `test/presentation/pages/profile/profile_page_test.dart` -- `test/presentation/pages/statistics/words_statistics_page_test.dart` -- `test/presentation/pages/statistics/packs_statistics_page_test.dart` -- `test/presentation/pages/achievements/achievements_page_test.dart` -- `test/presentation/pages/settings/settings_page_test.dart` -- `test/presentation/widgets/stats/*_test.dart` - -**Steps:** -- [ ] Write ProfilePage tests -- [ ] Write statistics pages tests -- [ ] Write AchievementsPage tests -- [ ] Write SettingsPage tests -- [ ] Write widget tests for all custom widgets - ---- - -### Task F7.3: Integration Tests - -**Estimated Time:** 4-6 hours - -**Test File:** `integration_test/statistics_flow_test.dart` - -**Tests:** -- Load statistics flow -- Navigate through statistics pages -- Update settings flow -- Achievement unlock flow - -**Steps:** -- [ ] Create integration test file -- [ ] Write statistics load test -- [ ] Write navigation test -- [ ] Write settings update test -- [ ] Write achievement test - ---- - -## Phase 8: Documentation - -### Task F8.1: Update Documentation - -**Estimated Time:** 2-3 hours - -**Files to Update:** -- `PROGRESS.md` - Add completed work -- `TODO.md` - Update task statuses -- `README.md` - Add new features documentation -- Create `STATISTICS_UI_GUIDE.md` - UI component documentation - -**Steps:** -- [ ] Update PROGRESS.md with detailed changes -- [ ] Mark completed tasks in TODO.md -- [ ] Update README with new features -- [ ] Create UI guide with screenshots - ---- - -## Summary - -**Total Frontend Estimated Time:** 93-119 hours - -**Priority Order:** -1. **Phase 1** - Services (10-13 hours) ✅ HIGHEST -2. **Phase 3** - Profile UI (12-15 hours) ✅ HIGHEST -3. **Phase 5.1-5.3** - Settings Page (14-17 hours) ✅ HIGH -4. **Phase 2** - Stats Widgets (6-8 hours) 🟡 MEDIUM -5. **Phase 4** - Statistics Pages (20-26 hours) 🟡 MEDIUM -6. **Phase 5.4** - Apply Settings (6-8 hours) 🟡 MEDIUM -7. **Phase 6** - Animations (6-8 hours) 🟢 LOW -8. **Phase 7** - Testing (14-19 hours) 🟢 LOW -9. **Phase 8** - Documentation (2-3 hours) 🟢 LOW - -**Dependencies:** -- Phase 1 must be done first (services) -- Phase 2 needed for Phase 3 (widgets for profile) -- Phase 5.1-5.3 for settings -- Phase 6 can be done in parallel with other UI work -- Phase 7 should be done alongside development -- Phase 8 done last - ---- - -**Start Date:** TBD -**Target Completion:** TBD -**Current Status:** Planning Complete, Ready to Start - diff --git a/mnemo_cards_web_v2/STATISTICS_UPGRADE_PLAN.md b/mnemo_cards_web_v2/STATISTICS_UPGRADE_PLAN.md deleted file mode 100644 index c5da40a..0000000 --- a/mnemo_cards_web_v2/STATISTICS_UPGRADE_PLAN.md +++ /dev/null @@ -1,1259 +0,0 @@ -# Statistics Upgrade Plan - -## Дата создания: 8 ноября 2025 - -## Цель -Расширить систему сбора и отображения статистики пользователя для создания детализированной страницы профиля с красивым UI и настройками приложения. - ---- - -## 1. Текущее состояние (Current State) - -### Backend (mnemo_cards_backend) - -**Модели данных:** -- `UserModel` - основная модель пользователя (Isar) -- `UserDataModel` - данные пользователя со статистикой - - `words` - список `WordStatisticsModel` - - `testsStatistics` - список `TestStatisticsModel` - - `lastTimeOnline` - DateTime - - `lastTestSessionToken` - String - -**DTOs (mnemo_cards_common):** -- `UserDto` - базовая информация пользователя - - id, name, email, admin - - packs (список ID паков) - - purchases (список ID покупок) - - subscription (bool) - - subscriptionFeatures (Set) - - userDataDto, userSettingsDto - -- `UserDataDto` - статистика пользователя - - allWordsStatistics (AllWordsStatisticsDto) - - allTestsStatistics (AllTestsStatisticsDto) - -- `WordStatisticsDto` - статистика по слову - - word (String) - - correct, incorrect, skipped (double) - - questionTypes (Set) - -- `TestStatisticsDto` - статистика по тесту - - testId (int) - - words (AllWordsStatisticsDto) - - sessionToken (String) - - attempts (int) - -**API Endpoints (v2):** -- GET `/api/v2/users/me` - получить текущего пользователя -- POST `/api/v2/users/me/settings` - обновить настройки -- POST `/api/v2/users/me/statistics` - добавить статистику теста -- GET `/api/v2/users/me/purchases` - получить покупки - -### Frontend (mnemo_cards_web_v2) - -**Текущее отображение:** -- `ProfilePage` - базовая страница профиля - - User header (avatar, name, email) - - Basic statistics (mocked) - - Simple chart (daily progress) - - Account info card - - Settings section (dark mode, language) - - Logout button - -**Сервисы:** -- `StatisticsService` - генерирует MOCK статистику - - calculateLearnedWords (mock: packs * 10) - - calculateTestsCompleted (mock) - - calculateStudyTime (mock) - - generateDailyProgress (mock) - -**Проблемы:** -- ❌ Вся статистика - это моки -- ❌ Нет детализации по пакам -- ❌ Нет детализации по словам -- ❌ Нет реального отслеживания прогресса -- ❌ Нет красивого UI для настроек -- ❌ Нет расширенных метрик - ---- - -## 2. Желаемое состояние (Desired State) - -### Расширенная статистика - -**Общая статистика:** -1. Количество изученных слов (реальное) -2. Общее время обучения -3. Пройдено тестов -4. Текущая серия дней (streak) -5. Точность ответов (accuracy %) -6. Любимые языки / категории -7. Прогресс по уровням - -**Статистика по пакам:** -1. Прогресс по каждому паку (%) -2. Количество изученных карточек в паке -3. Время, потраченное на пак -4. Дата последнего обучения -5. Любимые паки (по времени/активности) -6. Сложные слова в паке - -**Статистика по словам:** -1. Список всех изученных слов -2. Уровень знания каждого слова -3. История ответов на слово -4. Типы вопросов, в которых встречалось слово -5. Процент правильных ответов -6. Дата последнего повторения -7. Сложные слова (требуют повторения) - -**Временная статистика:** -1. Активность по дням недели -2. Активность по времени суток -3. Дневной прогресс (последние 30 дней) -4. Недельный прогресс -5. Месячный прогресс -6. Общий прогресс за все время - -**Достижения и цели:** -1. Достигнутые цели -2. Текущие цели -3. Значки/достижения (badges) -4. Рекорды - ---- - -## 3. План реализации (Implementation Plan) - -### Phase 1: Backend - Расширение моделей и сбора данных - -#### 1.1. Расширить модели данных (Backend) - -**Файлы для изменения:** -- `mnemo_cards_common/lib/src/dtos/user/data/user_data_dto.dart` -- `mnemo_cards_common_backend/lib/src/models/user_data_model.dart` - -**Новые поля в UserDataDto:** -```dart -class UserDataDto { - // Существующие - final AllWordsStatisticsDto? allWordsStatistics; - final AllTestsStatisticsDto? allTestsStatistics; - - // Новые - final DateTime? lastTimeOnline; - final int totalStudyTimeMinutes; // общее время обучения - final int currentStreak; // текущая серия дней - final int longestStreak; // самая длинная серия - final Map packProgress; // прогресс по пакам - final List studyDates; // даты обучения - final Map categoryMinutes; // время по категориям - final List achievements; // достижения -} -``` - -**Новые DTO:** - -1. **PackProgressDto** (`mnemo_cards_common/lib/src/dtos/user/data/pack_progress_dto.dart`) -```dart -class PackProgressDto { - final String packId; - final int totalCards; - final int learnedCards; - final int studyTimeMinutes; - final DateTime? lastStudyDate; - final DateTime? firstStudyDate; - final Map cardAttempts; // cardId -> attempts count - final double averageAccuracy; -} -``` - -2. **AchievementDto** (`mnemo_cards_common/lib/src/dtos/user/achievement_dto.dart`) -```dart -class AchievementDto { - final String id; - final String title; - final String description; - final String iconUrl; - final DateTime unlockedAt; - final AchievementType type; -} -``` - -3. **DetailedWordStatisticsDto** (расширение существующего) -```dart -class DetailedWordStatisticsDto extends WordStatisticsDto { - final DateTime? lastReviewed; - final DateTime? firstLearned; - final List recentAttempts; // последние 10 попыток - final double difficultyScore; // оценка сложности (0-1) - final bool needsReview; // требует повторения - final String? packId; // из какого пака -} -``` - -4. **StudySessionDto** (новый - для отслеживания сессий) -```dart -class StudySessionDto { - final String sessionId; - final DateTime startTime; - final DateTime endTime; - final int wordsLearned; - final int testsCompleted; - final double accuracy; - final String? packId; - final String? testId; -} -``` - -**Задачи:** -- [ ] Создать новые DTO классы -- [ ] Добавить новые поля в UserDataDto -- [ ] Создать соответствующие Isar модели -- [ ] Добавить миграцию базы данных -- [ ] Обновить метод toDto() в UserDataModel -- [ ] Написать unit тесты для новых моделей - -**Оценка времени:** 4-6 часов - ---- - -#### 1.2. Расширить API для статистики (Backend) - -**Новые endpoints в `/api/v2/users/`:** - -1. **GET `/api/v2/users/me/statistics/detailed`** - детальная статистика - - Возвращает полную UserDataDto с расширенными полями - -2. **GET `/api/v2/users/me/statistics/packs`** - статистика по пакам - - Query params: `packId` (optional) - - Возвращает список PackProgressDto - -3. **GET `/api/v2/users/me/statistics/words`** - статистика по словам - - Query params: `packId`, `limit`, `offset`, `sortBy`, `needsReview` - - Возвращает список DetailedWordStatisticsDto с пагинацией - -4. **GET `/api/v2/users/me/statistics/timeline`** - временная статистика - - Query params: `period` (day/week/month/year), `from`, `to` - - Возвращает данные для графиков активности - -5. **POST `/api/v2/users/me/sessions`** - начать/завершить сессию обучения - - Body: StudySessionDto - - Отслеживает время обучения - -6. **GET `/api/v2/users/me/achievements`** - получить достижения - - Возвращает список AchievementDto - -**Файлы:** -- `mnemo_cards_backend/lib/api/v2/users_api_v2.dart` - добавить новые endpoints -- `mnemo_cards_backend/lib/user/user_manager.dart` - добавить методы расчета - -**Логика расчета статистики:** - -```dart -class StatisticsCalculator { - // Расчет прогресса по паку - PackProgressDto calculatePackProgress(UserModel user, String packId); - - // Расчет серии дней - int calculateStreak(List studyDates); - - // Расчет сложных слов - List findDifficultWords(UserDataModel data, {int limit = 20}); - - // Расчет точности - double calculateAccuracy(AllWordsStatisticsDto stats); - - // Расчет времени обучения по датам - Map calculateDailyStudyTime(List sessions); -} -``` - -**Задачи:** -- [ ] Создать StatisticsCalculator сервис -- [ ] Добавить новые endpoints в UsersApiV2 -- [ ] Реализовать методы расчета в UserManager -- [ ] Добавить middleware для отслеживания времени -- [ ] Написать integration тесты для новых endpoints -- [ ] Обновить OpenAPI спецификацию - -**Оценка времени:** 8-10 часов - ---- - -#### 1.3. Автоматический сбор статистики (Backend) - -**Tracking механизмы:** - -1. **Session Tracking Middleware** - - Отслеживает начало/конец сессий - - Автоматически обновляет lastTimeOnline - - Рассчитывает время онлайн - -2. **Test Completion Hook** - - При завершении теста обновляет: - - Статистику по словам - - Прогресс по паку - - Общее количество тестов - - Streak (если нужно) - -3. **Card Learning Hook** - - При изучении карточки обновляет: - - Счетчик изученных карточек - - Прогресс по паку - - Статистику слова - -4. **Achievement Checker** - - Проверяет условия достижений после каждого действия - - Выдает новые достижения - -**Файлы:** -- `mnemo_cards_backend/lib/statistics/session_tracker.dart` (новый) -- `mnemo_cards_backend/lib/statistics/achievement_manager.dart` (новый) -- `mnemo_cards_backend/lib/user/user_manager.dart` (расширить) - -**Задачи:** -- [ ] Создать SessionTracker -- [ ] Создать AchievementManager -- [ ] Добавить hooks в существующие endpoints -- [ ] Добавить фоновую задачу для расчета streak -- [ ] Написать unit тесты - -**Оценка времени:** 6-8 часов - ---- - -### Phase 2: Frontend - Новые сервисы и state management - -#### 2.1. Обновить HTTP Repository (Frontend) - -**Файл:** `mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart` - -**Новые методы:** -```dart -class HttpRepositoryV2 { - // Существующие методы... - - // Новые методы для статистики - Future getDetailedStatistics(); - Future> getPacksStatistics({String? packId}); - Future> getWordsStatistics({ - String? packId, - int? limit, - int? offset, - String? sortBy, - bool? needsReview, - }); - Future getTimelineStatistics({ - required String period, - DateTime? from, - DateTime? to, - }); - Future startStudySession(StudySessionDto session); - Future endStudySession(String sessionId, StudySessionDto session); - Future> getAchievements(); -} -``` - -**Задачи:** -- [ ] Добавить новые методы в HttpRepositoryV2 -- [ ] Создать классы для response моделей -- [ ] Добавить error handling -- [ ] Написать unit тесты - -**Оценка времени:** 2-3 часа - ---- - -#### 2.2. Создать расширенный StatisticsService (Frontend) - -**Файл:** `mnemo_cards_web_v2/lib/domain/services/statistics_service.dart` (переписать) - -**Новая структура:** -```dart -class StatisticsService { - final HttpRepositoryV2 _repository; - - // Получение полной статистики - Future getDetailedStatistics(); - - // Получение статистики по пакам - Future> getPacksStatistics({String? packId}); - - // Получение статистики по словам - Future getWordsStatistics({ - String? packId, - int page = 0, - int pageSize = 50, - WordsSortOption sortBy = WordsSortOption.difficulty, - bool needsReview = false, - }); - - // Получение временной статистики - Future getTimelineStatistics({ - required TimelinePeriod period, - DateTime? from, - DateTime? to, - }); - - // Управление сессиями - String startSession({String? packId, String? testId}); - Future endSession(String sessionId); - - // Достижения - Future> getAchievements(); - Future> getNewAchievements(); -} -``` - -**Новые модели (Frontend):** -```dart -class DetailedUserStatistics { - final int totalWords; - final int totalStudyTime; - final int testsCompleted; - final int currentStreak; - final int longestStreak; - final double averageAccuracy; - final List recentAchievements; - final Map packStats; -} - -class PackStatistics { - final String packId; - final String packName; - final int totalCards; - final int learnedCards; - final double progress; - final int studyTimeMinutes; - final DateTime? lastStudyDate; - final double accuracy; -} - -class WordsStatisticsData { - final List words; - final int totalCount; - final int page; - final int pageSize; -} - -class WordStatistics { - final String word; - final String translation; - final double correctRate; - final int totalAttempts; - final DateTime? lastReviewed; - final double difficultyScore; - final bool needsReview; - final String? packName; -} - -class TimelineData { - final List dailyActivity; - final List weeklyActivity; - final Map hourlyActivity; // час -> минут - final Map weekdayActivity; // день недели -> минут -} - -class Achievement { - final String id; - final String title; - final String description; - final String iconUrl; - final DateTime? unlockedAt; - final bool isLocked; - final double progress; // для незавершенных -} -``` - -**Задачи:** -- [ ] Переписать StatisticsService с реальной логикой -- [ ] Создать новые модели данных -- [ ] Добавить кэширование статистики -- [ ] Написать unit тесты - -**Оценка времени:** 4-5 часов - ---- - -#### 2.3. Создать State Manager для статистики (Frontend) - -**Файл:** `mnemo_cards_web_v2/lib/domain/state/statistics_state_manager.dart` (новый) - -**State:** -```dart -@freezed -class StatisticsState with _$StatisticsState { - const factory StatisticsState.loading() = _Loading; - const factory StatisticsState.loaded(DetailedUserStatistics statistics) = _Loaded; - const factory StatisticsState.error(String message) = _Error; -} -``` - -**State Manager:** -```dart -class StatisticsStateManager extends StateManager { - final StatisticsService _service; - - StatisticsStateManager(this._service) : super(const StatisticsState.loading()); - - Future loadStatistics() async { /* ... */ } - Future refreshStatistics() async { /* ... */ } -} -``` - -**Дополнительные state managers:** - -1. **PacksStatisticsStateManager** - статистика по пакам -2. **WordsStatisticsStateManager** - статистика по словам -3. **TimelineStatisticsStateManager** - временная статистика -4. **AchievementsStateManager** - достижения - -**Задачи:** -- [ ] Создать StatisticsStateManager -- [ ] Создать дополнительные state managers -- [ ] Добавить в UserScope module -- [ ] Написать unit тесты - -**Оценка времени:** 3-4 часа - ---- - -### Phase 3: Frontend - Красивый UI для профиля - -#### 3.1. Редизайн ProfilePage - -**Файл:** `mnemo_cards_web_v2/lib/presentation/pages/profile/profile_page.dart` (переписать) - -**Новая структура:** - -``` -ProfilePage (Scaffold) -├── AppBar -│ ├── Title -│ ├── Actions (settings icon) -├── Body (ScrollView) -│ ├── UserHeaderCard (расширенная) -│ │ ├── Avatar (большой) -│ │ ├── User info -│ │ ├── Subscription badge -│ │ ├── Streak indicator -│ │ └── Level badge -│ │ -│ ├── QuickStatsGrid (4 карточки в ряд) -│ │ ├── Total Words -│ │ ├── Study Time -│ │ ├── Tests Completed -│ │ └── Accuracy -│ │ -│ ├── StreakCard (визуализация серии) -│ │ ├── Calendar view (последние 30 дней) -│ │ └── Current/Longest streak -│ │ -│ ├── ActivityChartCard -│ │ ├── Tabs (Day/Week/Month/Year) -│ │ ├── Beautiful chart -│ │ └── Activity heatmap -│ │ -│ ├── PacksProgressSection -│ │ ├── Title "Your Packs Progress" -│ │ ├── List of PackProgressCard -│ │ │ ├── Pack image -│ │ │ ├── Pack name -│ │ │ ├── Progress bar -│ │ │ ├── Stats (learned/total) -│ │ │ └── Last study date -│ │ └── "View All" button -│ │ -│ ├── AchievementsSection -│ │ ├── Title "Achievements" -│ │ ├── Horizontal scroll of achievement badges -│ │ └── "View All" button -│ │ -│ └── AccountActionsCard -│ ├── Edit Profile -│ ├── Settings -│ ├── Subscription -│ └── Logout -``` - -**Компоненты для создания:** - -1. **UserHeaderCard** (`profile_user_header.dart`) - - Большой avatar с gradient border - - Имя, email - - Badges (streak, level, subscription) - - Красивая типографика - -2. **QuickStatsGrid** (`profile_quick_stats.dart`) - - Grid из 4 карточек - - Иконки + число + label - - Анимации при загрузке - - Responsive (2x2 на мобильном) - -3. **StreakCard** (`profile_streak_card.dart`) - - Calendar heatmap (30 дней) - - Текущая/максимальная серия - - Fire icon для streak - - Красивые градиенты - -4. **ActivityChartCard** (`profile_activity_chart.dart`) - - Tabs для периодов - - fl_chart для графиков - - Heatmap для времени суток - - Weekday activity chart - -5. **PackProgressCard** (`profile_pack_progress_card.dart`) - - Pack image - - Progress indicator (circular или linear) - - Stats chips - - Tap -> navigate to pack details - -6. **AchievementBadge** (`profile_achievement_badge.dart`) - - Иконка достижения - - Tooltip с описанием - - Locked/unlocked state - - Shine animation для новых - -**Задачи:** -- [ ] Создать новые компоненты -- [ ] Переписать ProfilePage с новым layout -- [ ] Добавить анимации и transitions -- [ ] Сделать responsive design -- [ ] Добавить skeleton loaders -- [ ] Написать widget тесты - -**Оценка времени:** 12-15 часов - ---- - -#### 3.2. Создать страницу детальной статистики по словам - -**Файл:** `mnemo_cards_web_v2/lib/presentation/pages/statistics/words_statistics_page.dart` (новый) - -**Структура:** - -``` -WordsStatisticsPage (Scaffold) -├── AppBar -│ ├── Title "Words Statistics" -│ ├── Search field -│ ├── Filter button -├── Body -│ ├── FilterBar -│ │ ├── Pack selector -│ │ ├── Sort options (difficulty, accuracy, recent) -│ │ ├── "Needs Review" toggle -│ │ -│ ├── WordsList (paginated) -│ │ └── WordStatisticsCard (для каждого слова) -│ │ ├── Word + translation -│ │ ├── Pack badge -│ │ ├── Accuracy indicator -│ │ ├── Attempts count -│ │ ├── Last reviewed date -│ │ ├── Difficulty indicator -│ │ └── "Needs Review" badge -│ │ -│ └── LoadMore button / Infinite scroll -``` - -**Задачи:** -- [ ] Создать WordsStatisticsPage -- [ ] Создать WordStatisticsCard компонент -- [ ] Добавить фильтрацию и сортировку -- [ ] Добавить пагинацию -- [ ] Добавить поиск -- [ ] Написать widget тесты - -**Оценка времени:** 6-8 часов - ---- - -#### 3.3. Создать страницу детальной статистики по пакам - -**Файл:** `mnemo_cards_web_v2/lib/presentation/pages/statistics/packs_statistics_page.dart` (новый) - -**Структура:** - -``` -PacksStatisticsPage (Scaffold) -├── AppBar -│ ├── Title "Packs Statistics" -│ ├── Sort menu -├── Body -│ ├── PacksGrid / PacksList -│ │ └── PackStatisticsCard -│ │ ├── Pack image -│ │ ├── Pack name -│ │ ├── Progress (circular chart) -│ │ ├── Study time -│ │ ├── Learned cards count -│ │ ├── Accuracy -│ │ ├── Last study date -│ │ └── Tap -> PackStatisticsDetailsPage -``` - -**Детальная страница пака:** -**Файл:** `pack_statistics_details_page.dart` - -``` -PackStatisticsDetailsPage (Scaffold) -├── AppBar (pack name) -├── Body -│ ├── PackHeaderCard -│ │ ├── Pack image -│ │ ├── Overall progress -│ │ ├── Total stats -│ │ -│ ├── ProgressTimelineChart -│ │ └── Chart of progress over time -│ │ -│ ├── CardsListSection -│ │ ├── Title "Cards Progress" -│ │ └── List of cards with individual progress -│ │ ├── Card preview -│ │ ├── Word -│ │ ├── Times reviewed -│ │ ├── Accuracy -│ │ -│ └── StudyHistorySection -│ └── Timeline of study sessions -``` - -**Задачи:** -- [ ] Создать PacksStatisticsPage -- [ ] Создать PackStatisticsCard -- [ ] Создать PackStatisticsDetailsPage -- [ ] Добавить графики прогресса -- [ ] Написать widget тесты - -**Оценка времени:** 8-10 часов - ---- - -#### 3.4. Создать страницу достижений - -**Файл:** `mnemo_cards_web_v2/lib/presentation/pages/achievements/achievements_page.dart` (новый) - -**Структура:** - -``` -AchievementsPage (Scaffold) -├── AppBar -│ ├── Title "Achievements" -│ ├── Progress indicator (X/Y unlocked) -├── Body -│ ├── Tabs -│ │ ├── All -│ │ ├── Unlocked -│ │ ├── Locked -│ │ -│ └── AchievementsGrid -│ └── AchievementCard -│ ├── Icon/Badge -│ ├── Title -│ ├── Description -│ ├── Progress bar (for locked) -│ ├── Unlock date (for unlocked) -│ └── Shimmer effect for locked -``` - -**Типы достижений:** -- First Steps (first word, first test, first pack) -- Streaks (3 days, 7 days, 30 days, 100 days) -- Words Master (10, 50, 100, 500, 1000 words) -- Perfect Score (100% on test) -- Speed Learner (complete pack in 1 day) -- Night Owl (study at night) -- Early Bird (study in morning) -- Dedicated (total study time milestones) - -**Задачи:** -- [ ] Создать AchievementsPage -- [ ] Создать AchievementCard компонент -- [ ] Добавить фильтрацию по статусу -- [ ] Добавить анимации unlock -- [ ] Создать achievement icons/badges -- [ ] Написать widget тесты - -**Оценка времени:** 6-8 часов - ---- - -### Phase 4: Frontend - Улучшенные настройки приложения - -#### 4.1. Создать отдельную страницу Settings - -**Файл:** `mnemo_cards_web_v2/lib/presentation/pages/settings/settings_page.dart` (новый) - -**Структура:** - -``` -SettingsPage (Scaffold) -├── AppBar -│ ├── Title "Settings" -│ ├── Back button -├── Body (ListView) -│ ├── Appearance Section -│ │ ├── Theme (Light/Dark/System) -│ │ ├── Primary Color picker -│ │ ├── Font Size slider -│ │ └── Language selector -│ │ -│ ├── Learning Section -│ │ ├── Daily Goal (words per day) -│ │ ├── Reminder notifications toggle -│ │ ├── Reminder time picker -│ │ ├── Auto-play audio toggle -│ │ ├── Show translations toggle -│ │ └── Cards per session -│ │ -│ ├── Privacy Section -│ │ ├── Analytics toggle -│ │ ├── Personalized ads toggle -│ │ └── Data collection info -│ │ -│ ├── Account Section -│ │ ├── Email (readonly/editable) -│ │ ├── Name (editable) -│ │ ├── Change password -│ │ └── Delete account -│ │ -│ ├── Data Section -│ │ ├── Export data -│ │ ├── Import data -│ │ ├── Clear cache -│ │ └── Reset progress (dangerous) -│ │ -│ └── About Section -│ ├── Version -│ ├── Terms of Service -│ ├── Privacy Policy -│ └── Contact Support -``` - -**Расширить UserSettingsDto:** - -**Файл:** `mnemo_cards_common/lib/src/dtos/user/settings/user_settings_dto.dart` - -```dart -class UserSettingsDto { - // Appearance - final String theme; // 'light', 'dark', 'system' - final String? primaryColor; - final double fontSize; // 0.8 - 1.2 - final String language; - - // Learning - final int dailyGoalWords; - final bool reminderEnabled; - final String? reminderTime; // "HH:mm" - final bool autoPlayAudio; - final bool showTranslations; - final int cardsPerSession; - - // Privacy - final bool analyticsEnabled; - final bool personalizedAdsEnabled; - - // Notifications (web - не критично) - final bool pushNotificationsEnabled; - final bool emailNotificationsEnabled; -} -``` - -**Компоненты:** - -1. **SettingsSection** (`settings_section.dart`) - - Section header - - Divider - - Settings items - -2. **SettingsTile** (`settings_tile.dart`) - - Leading icon - - Title + subtitle - - Trailing widget (switch/arrow/value) - - Tap handler - -3. **ThemeSelector** (`theme_selector.dart`) - - Radio buttons для Light/Dark/System - - Preview chips - -4. **ColorPicker** (`color_picker.dart`) - - Grid of colors - - Custom color picker - -5. **TimePickerSetting** (`time_picker_setting.dart`) - - Time input - - Native time picker - -**Задачи:** -- [ ] Расширить UserSettingsDto -- [ ] Создать SettingsPage с новым UI -- [ ] Создать компоненты для settings -- [ ] Добавить настройки в backend API -- [ ] Создать SettingsStateManager -- [ ] Сохранять настройки локально и на сервере -- [ ] Написать unit и widget тесты - -**Оценка времени:** 10-12 часов - ---- - -#### 4.2. Интегрировать настройки в приложение - -**Применение настроек:** - -1. **Theme Settings** - - Обновить ThemeStateManager для поддержки custom colors - - Добавить font size scaling - -2. **Learning Settings** - - Использовать в CardFlipper - - Применять в тестах - - Показывать daily goal на ProfilePage - -3. **Reminder Notifications** - - Локальные напоминания (web notifications API) - - Backend cron job для email напоминаний - -**Файлы для изменения:** -- `lib/domain/state/theme_state_manager.dart` -- `lib/presentation/widgets/card_flipper/card_flipper.dart` -- `lib/di/user_scope/modules/settings_module.dart` - -**Задачи:** -- [ ] Обновить ThemeStateManager -- [ ] Применить настройки в UI -- [ ] Добавить daily goal tracking -- [ ] Реализовать напоминания -- [ ] Написать тесты - -**Оценка времени:** 6-8 часов - ---- - -### Phase 5: Визуальные улучшения и анимации - -#### 5.1. Создать красивые компоненты для статистики - -**Новые виджеты:** - -1. **StatsCard** (`widgets/stats/stats_card.dart`) - - Универсальная карточка для stats - - Gradient background - - Icon + Value + Label - - Shimmer loading state - - Counter animation - -2. **CircularProgressIndicator** (custom) - - Красивый circular progress - - Gradient stroke - - Percentage в центре - - Анимация заполнения - -3. **LinearProgressBar** (custom) - - Gradient background - - Smooth animation - - Labels (start/end) - - Multiple segments support - -4. **ActivityHeatmap** (`widgets/stats/activity_heatmap.dart`) - - GitHub-style heatmap - - Customizable colors - - Tooltips на hover - - Responsive - -5. **StreakCalendar** (`widgets/stats/streak_calendar.dart`) - - Calendar view с индикацией - - Highlight current streak - - Tooltips для каждого дня - -6. **TimelineChart** (`widgets/stats/timeline_chart.dart`) - - Использовать fl_chart - - Line chart для прогресса - - Bar chart для активности - - Interactive tooltips - -7. **RadarChart** (`widgets/stats/radar_chart.dart`) - - Для отображения skills по категориям - - fl_chart RadarChart - -**Задачи:** -- [ ] Создать все новые виджеты -- [ ] Добавить анимации -- [ ] Сделать responsive -- [ ] Добавить loading states -- [ ] Написать widget тесты - -**Оценка времени:** 10-12 часов - ---- - -#### 5.2. Добавить анимации и transitions - -**Анимации:** - -1. **Page Transitions** - - Smooth navigation между Profile -> Statistics -> Settings - - Hero animations для images/avatars - -2. **Stats Counter Animation** - - Animated counting для чисел - - Использовать AnimatedCount widget - -3. **Chart Animations** - - fl_chart встроенные анимации - - Staggered animation для bars - -4. **Achievement Unlock Animation** - - Confetti effect - - Scale + Fade animation - - Sound effect (optional) - -5. **Shimmer Loading** - - Skeleton screens для всех страниц - - Shimmer effect - -6. **Pull to Refresh** - - Custom refresh indicator - -**Пакеты:** -- fl_chart (для графиков) -- shimmer (для loading) -- confetti (для celebrations) -- lottie (для сложных анимаций) - -**Задачи:** -- [ ] Добавить Hero animations -- [ ] Создать AnimatedCounter widget -- [ ] Добавить shimmer loaders -- [ ] Реализовать achievement unlock animation -- [ ] Добавить pull-to-refresh -- [ ] Написать тесты - -**Оценка времени:** 6-8 часов - ---- - -### Phase 6: Testing & Documentation - -#### 6.1. Unit Tests - -**Backend тесты:** -- [ ] StatisticsCalculator tests -- [ ] PackProgressDto tests -- [ ] Achievement logic tests -- [ ] Session tracking tests -- [ ] UserDataModel conversion tests - -**Frontend тесты:** -- [ ] StatisticsService tests -- [ ] StatisticsStateManager tests -- [ ] Settings logic tests -- [ ] Calculations tests - -**Оценка времени:** 6-8 часов - ---- - -#### 6.2. Widget Tests - -**Frontend widget тесты:** -- [ ] ProfilePage tests -- [ ] WordsStatisticsPage tests -- [ ] PacksStatisticsPage tests -- [ ] AchievementsPage tests -- [ ] SettingsPage tests -- [ ] All custom widgets tests - -**Оценка времени:** 8-10 часов - ---- - -#### 6.3. Integration Tests - -**E2E тесты:** -- [ ] Load statistics flow -- [ ] Navigate through statistics pages -- [ ] Update settings flow -- [ ] Achievement unlock flow - -**Оценка времени:** 4-6 часов - ---- - -#### 6.4. Documentation - -**Обновить документацию:** -- [ ] Update TODO.md -- [ ] Update PROGRESS.md -- [ ] Create STATISTICS_API.md (API documentation) -- [ ] Create STATISTICS_UI.md (UI guidelines) -- [ ] Update README.md - -**Оценка времени:** 2-3 часа - ---- - -## 4. Общая оценка времени - -### Backend -- Phase 1.1: Расширение моделей - 4-6 часов -- Phase 1.2: API endpoints - 8-10 часов -- Phase 1.3: Автоматический сбор - 6-8 часов -- **Backend Total:** 18-24 часа - -### Frontend - Сервисы и State -- Phase 2.1: HTTP Repository - 2-3 часа -- Phase 2.2: StatisticsService - 4-5 часов -- Phase 2.3: State Managers - 3-4 часа -- **Services Total:** 9-12 часов - -### Frontend - UI -- Phase 3.1: ProfilePage редизайн - 12-15 часов -- Phase 3.2: Words Statistics Page - 6-8 часов -- Phase 3.3: Packs Statistics Page - 8-10 часов -- Phase 3.4: Achievements Page - 6-8 часов -- Phase 4.1: Settings Page - 10-12 часов -- Phase 4.2: Settings Integration - 6-8 часов -- Phase 5.1: Stats Widgets - 10-12 часов -- Phase 5.2: Animations - 6-8 часов -- **UI Total:** 64-81 час - -### Testing & Documentation -- Phase 6.1: Unit Tests - 6-8 часов -- Phase 6.2: Widget Tests - 8-10 часов -- Phase 6.3: Integration Tests - 4-6 часов -- Phase 6.4: Documentation - 2-3 часа -- **Testing Total:** 20-27 часов - -### **ОБЩАЯ ОЦЕНКА: 111-144 часа** - ---- - -## 5. Приоритезация - -### Высокий приоритет (MVP) -1. ✅ Backend: Расширение моделей (Phase 1.1) -2. ✅ Backend: Основные API endpoints (Phase 1.2) -3. ✅ Frontend: StatisticsService (Phase 2.2) -4. ✅ Frontend: ProfilePage редизайн (Phase 3.1) -5. ✅ Frontend: Settings Page (Phase 4.1) - -### Средний приоритет -6. ⬜ Backend: Автоматический сбор (Phase 1.3) -7. ⬜ Frontend: Words Statistics Page (Phase 3.2) -8. ⬜ Frontend: Packs Statistics Page (Phase 3.3) -9. ⬜ Frontend: Settings Integration (Phase 4.2) -10. ⬜ Frontend: Stats Widgets (Phase 5.1) - -### Низкий приоритет (Nice to have) -11. ⬜ Frontend: Achievements Page (Phase 3.4) -12. ⬜ Frontend: Animations (Phase 5.2) -13. ⬜ Tests (Phase 6) - ---- - -## 6. Зависимости - -``` -Phase 1.1 (Backend Models) - ↓ -Phase 1.2 (Backend API) + Phase 2.1 (Frontend HTTP) - ↓ -Phase 2.2 (Frontend Service) + Phase 2.3 (Frontend State) - ↓ -Phase 3.1 (Profile UI) - ↓ -Phase 3.2, 3.3, 3.4 (Statistics UI) + Phase 4.1 (Settings UI) - ↓ -Phase 1.3 (Auto tracking) + Phase 4.2 (Settings Integration) - ↓ -Phase 5.1, 5.2 (Visual improvements) - ↓ -Phase 6 (Testing) -``` - ---- - -## 7. Технологии и библиотеки - -### Backend -- Dart 3.0+ -- Isar (database) -- Shelf (HTTP) -- GetIt + Injectable (DI) -- Build Runner (codegen) - -### Frontend -- Flutter 3.x -- yx_state + yx_scope (state management) -- fl_chart (charts) -- shimmer (loading) -- confetti (celebrations) -- lottie (animations) -- shared_preferences (local storage) -- go_router (navigation) - ---- - -## 8. Риски и митигация - -### Риски: -1. **Большой объем работы** - может занять много времени - - Митигация: Разделить на фазы, начать с MVP - -2. **Performance issues** - много данных статистики - - Митигация: Пагинация, кэширование, оптимизация запросов - -3. **Backend breaking changes** - изменения в API - - Митигация: Версионирование API (v2), постепенная миграция - -4. **UI complexity** - сложные графики и анимации - - Митигация: Использовать проверенные библиотеки (fl_chart) - -5. **Testing overhead** - много тестов для написания - - Митигация: Писать тесты параллельно с разработкой - ---- - -## 9. Acceptance Criteria - -### Для MVP (Высокий приоритет): - -✅ **Backend:** -- [ ] Новые DTO созданы и работают -- [ ] API endpoints для статистики работают -- [ ] Данные корректно сохраняются в БД -- [ ] Unit тесты покрывают новую логику - -✅ **Frontend:** -- [ ] ProfilePage показывает реальную статистику -- [ ] Statistics виджеты красивые и responsive -- [ ] Settings Page полностью функциональна -- [ ] Настройки применяются в приложении -- [ ] Данные загружаются без ошибок - -✅ **Quality:** -- [ ] Нет критических багов -- [ ] Linter проходит -- [ ] Основные тесты написаны -- [ ] PROGRESS.md и TODO.md обновлены - ---- - -## 10. Следующие шаги - -1. **Создать задачи в TODO.md** - разбить план на конкретные задачи -2. **Настроить workflow_state.md** - начать отслеживание прогресса -3. **Начать с Phase 1.1** - расширение моделей данных -4. **Итерировать** - работать фазами, тестировать каждую фазу - ---- - -## Changelog - -- **2025-11-08**: Initial plan created - diff --git a/mnemo_cards_web_v2/TASKS_PLAN.md b/mnemo_cards_web_v2/TASKS_PLAN.md deleted file mode 100644 index 151edea..0000000 --- a/mnemo_cards_web_v2/TASKS_PLAN.md +++ /dev/null @@ -1,287 +0,0 @@ -# План реализации механики заданий (Tasks) - -## Обзор - -Механика заданий позволяет пользователям выполнять различные задачи для изучения языков. Задания могут быть как внутри приложения (тесты, игры), так и внешними (подписки, реальные разговоры). Задания формируются и хранятся на бэкенде. - -## Примеры заданий -- Пройди 3 теста сегодня -- Подпишись на канал в Telegram -- Сделай заказ в ресторане на испанском и запиши это на видео - -## Архитектура - -### Модели данных - -#### Task (Задание) -```dart -@freezed -class Task with _$Task { - const factory Task({ - required String id, - required String title, - required String description, - required TaskType type, - required TaskDifficulty difficulty, - required List rewards, - required TaskStatus status, - required DateTime createdAt, - required DateTime expiresAt, - DateTime? completedAt, - String? proofUrl, // ссылка на доказательство (видео, фото) - }) = _Task; -} -``` - -#### TaskType (Тип задания) -```dart -enum TaskType { - appInternal, // внутри приложения (тесты, игры) - external, // внешние задания (реальные ситуации) - social, // социальные (подписки, репосты) -} -``` - -#### TaskDifficulty (Сложность) -```dart -enum TaskDifficulty { - easy, - medium, - hard, -} -``` - -#### TaskStatus (Статус) -```dart -enum TaskStatus { - available, // доступно для выполнения - inProgress, // в процессе выполнения - completed, // выполнено - expired, // истекло - failed, // провалено -} -``` - -#### TaskReward (Награда) -```dart -@freezed -class TaskReward with _$TaskReward { - const factory TaskReward({ - required RewardType type, - required int amount, - }) = _TaskReward; -} - -enum RewardType { - xp, // опыт - coins, // монеты - achievement, // достижение -} -``` - -#### TaskProgress (Прогресс пользователя) -```dart -@freezed -class TaskProgress with _$TaskProgress { - const factory TaskProgress({ - required String userId, - required Map taskStatuses, - required Map completedTasks, - required int totalXp, - required int totalCoins, - required List achievements, - }) = _TaskProgress; -} -``` - -### API Endpoints - -#### Получение списка заданий -``` -GET /api/tasks -Query params: -- user_id: String -- status: TaskStatus? (фильтр по статусу) -- type: TaskType? (фильтр по типу) -- limit: int? (ограничение количества) -``` - -#### Получение конкретного задания -``` -GET /api/tasks/{taskId} -``` - -#### Обновление статуса задания -``` -PUT /api/tasks/{taskId}/status -Body: { - "status": TaskStatus, - "proof_url": String?, // для внешних заданий -} -``` - -#### Получение прогресса пользователя -``` -GET /api/users/{userId}/task-progress -``` - -#### Обновление прогресса -``` -PUT /api/users/{userId}/task-progress -Body: { - "task_id": String, - "status": TaskStatus, - "proof_url": String?, -} -``` - -## State Management - -### TasksStateManager -```dart -class TasksStateManager extends YxStateManager { - final TasksRepository _repository; - final UserStateManager _userManager; - - // Методы: - Future loadTasks(); - Future loadUserProgress(); - Future updateTaskStatus(String taskId, TaskStatus status); - Future submitTaskProof(String taskId, String proofUrl); - Future> getAvailableTasks(); - Future> getCompletedTasks(); - Future getUserProgress(); -} -``` - -### TasksState -```dart -@freezed -class TasksState with _$TasksState { - const factory TasksState({ - required List tasks, - required TaskProgress? userProgress, - required bool isLoading, - required String? error, - }) = _TasksState; -} -``` - -## UI Компоненты - -### Страница заданий (TasksPage) -- Список доступных заданий -- Фильтры по типу/статусу -- Прогресс бар -- Награды - -### Карточка задания (TaskCard) -- Заголовок и описание -- Тип и сложность -- Статус -- Кнопка действия (начать/завершить) -- Награды - -### Модальное окно подтверждения (TaskConfirmationDialog) -- Для внешних заданий -- Загрузка доказательства (фото/видео) -- Подтверждение выполнения - -### Виджет прогресса (TasksProgressWidget) -- Общий прогресс -- Количество выполненных заданий -- XP и монеты - -## Интеграция с существующими скоупами - -### UserScope -Добавить TasksStateManager в UserScope: -```dart -class UserScope extends YxScope { - late final TasksStateManager tasksManager; - - @override - Future init() async { - tasksManager = TasksStateManager( - repository: ref.read(tasksRepositoryProvider), - userManager: ref.read(userStateManagerProvider), - ); - await tasksManager.init(); - } -} -``` - -### Навигация -Добавить маршрут `/tasks` в роутер. - -## Этапы реализации - -### Этап 1: Модели данных и API -1. Создать модели Task, TaskProgress и перечисления -2. Реализовать TasksRepository с моковыми данными -3. Настроить API клиент для работы с бэкендом - -### Этап 2: State Management -1. Создать TasksStateManager -2. Интегрировать в UserScope -3. Реализовать бизнес-логику загрузки и обновления заданий - -### Этап 3: UI Компоненты -1. Создать TaskCard виджет -2. Реализовать TasksPage -3. Добавить фильтры и сортировку -4. Создать TaskConfirmationDialog - -### Этап 4: Интеграция -1. Добавить навигацию -2. Обновить главное меню (добавить вкладку Задания) -3. Интегрировать с системой наград - -### Этап 5: Тестирование -1. Unit тесты для state manager -2. Widget тесты для UI компонентов -3. Integration тесты - -### Этап 6: Бэкенд интеграция -1. Заменить моковые данные на реальные API вызовы -2. Обработать ошибки сети -3. Добавить кэширование - -## Требования к дизайну - -### Адаптивность -- Поддержка мобильных устройств (хотя проект web-only) -- Responsive дизайн для разных экранов - -### UX/UI -- Ясные инструкции для каждого задания -- Визуальная обратная связь при выполнении -- Анимации для наград -- Push-уведомления о новых заданиях - -### Доступность -- Поддержка клавиатуры -- Screen reader compatibility -- Высокий контраст - -## Метрики и аналитика - -- Количество выполненных заданий -- Время выполнения заданий -- Популярность типов заданий -- Конверсия в повторные использования - -## Безопасность - -- Валидация proof_url на клиенте -- Проверка на бэкенде -- Защита от спама (rate limiting) -- Модерация контента для пользовательских доказательств - -## Будущие улучшения - -1. **Персонализация**: Задания на основе прогресса пользователя -2. **Социальные фичи**: Совместные задания, лидерборды -3. **Геймификация**: Серии заданий, достижения -4. **AI генерация**: Автоматическое создание заданий -5. **Мобильная интеграция**: QR-коды для внешних заданий diff --git a/mnemo_cards_web_v2/TODO.md b/mnemo_cards_web_v2/TODO.md deleted file mode 100644 index 90d0863..0000000 --- a/mnemo_cards_web_v2/TODO.md +++ /dev/null @@ -1,709 +0,0 @@ -# TODO - mnemo_cards_web_v2 - -## Status: Active Development -**Last Updated:** November 8, 2025 - ---- - -## 🔥 Bug Fixes & Maintenance - -### PURCHASE-1: Purchase Page Loading Issue - FIXED ✅ -**Priority:** HIGH -**Status:** ✅ COMPLETED -**Time Spent:** 2 hours -**Date Fixed:** November 8, 2025 - -**Issue:** Purchase page (`/purchase/5`) was not loading due to JSON deserialization problems. - -**Root Cause:** -- Constructor `CardPackBuyDto` incorrectly marked nullable fields as required -- UI method `_buildItem` used `item.toString()` which doesn't work for polymorphic Item subclasses - -**Solution Applied:** -- Fixed `CardPackBuyDto` constructor to properly handle nullable fields -- Implemented type-safe rendering for different Item types (TextItem, SpacerItem, ButtonItem) -- Added proper spacing and visual elements for each item type - -**Result:** Purchase page now loads correctly and displays pack information properly. - ---- - -## 🔥 New Features - -### TASKS-1: Tasks System Implementation - PHASE 1 COMPLETE ✅ -**Priority:** HIGH -**Status:** ✅ Phase 1 Complete, Ready for Phase 2 -**Estimated Time:** 40-60 hours total - -**Plan Document:** `TASKS_PLAN.md` - -**Goal:** Реализовать механику заданий для mnemo_cards_web_v2 - систему заданий, которые пользователь выполняет как в приложении, так и в реальном мире. - -**Current Phase:** Phase 1 (Frontend Infrastructure) - Complete ✅ - -**Completed in Phase 1:** -- ✅ Created comprehensive task data models (Task, TaskProgress, TaskReward, enums) -- ✅ Implemented TasksRepository with mock data for development -- ✅ Created TasksStateManager with full state management using yx_state -- ✅ Added TasksModule to UserScope with proper dependency injection -- ✅ Built TaskCard widget with rewards display and action buttons -- ✅ Implemented TasksPage with filtering, tabs, and search functionality -- ✅ Added navigation route `/tasks` and updated bottom navigation -- ✅ Updated MainShell to include "Задания" tab -- ✅ Integrated with existing yx_scope/yx_state architecture -- ✅ Created unit tests for all components - -**Next Actions:** -- [ ] Phase 2: Backend Integration (API endpoints, real data) - 12-16 hours -- [ ] Phase 3: Advanced Features (task creation, admin panel) - 8-12 hours -- [ ] Phase 4: Polish & Analytics (animations, tracking) - 8-12 hours -- [ ] Phase 5: Testing & Deployment (integration tests, production) - 8-12 hours - -See `TASKS_PLAN.md` for complete breakdown. - ---- - -### CHAT-1: Chat Module Implementation - MODULARIZATION COMPLETE ✅ -**Priority:** HIGH -**Status:** ✅ Modularization Complete, Ready for Phase 2 -**Estimated Time:** 60-80 hours total - -**Plan Document:** `CHAT_PLAN.md` - -**Goal:** Реализовать функциональность чата для общения пользователя с LLM через сервер, поддерживая текст и аудио сообщения. - -**Current Phase:** Phase 1 (Infrastructure) - Complete ✅ - -**Completed:** -- ✅ **Modularization**: Created separate `mnemo_cards_chat` Flutter package -- ✅ **Architecture**: Clean architecture with ChatRepository interface for loose coupling -- ✅ **Models**: Comprehensive data models (ChatMessage, AudioMessage, ChatSession, ChatParticipant) -- ✅ **Services**: ChatService with business logic and ChatRepository abstraction -- ✅ **State Management**: Simplified ChatStateManager with manual state classes -- ✅ **DI Integration**: ChatModule for yx_scope integration in main application -- ✅ **Code Generation**: All freezed/json_serializable generation working -- ✅ **Compilation**: Module compiles successfully and integrates cleanly - -**Next Actions:** -- [ ] Phase 2: UI Components (MessageBubble, ChatInput, AudioRecorder, ChatPage) - 16-20 hours -- [ ] Phase 3: Audio Functionality (recording, playback, Web Audio API) - 12-16 hours -- [ ] Phase 4: Integration & Polish (navigation, error handling, theming) - 8-12 hours -- [ ] Phase 5: Backend Integration & Testing (API endpoints, LLM integration) - 8-12 hours - -See `CHAT_PLAN.md` for complete breakdown. - -### GT-1: Game Tests Implementation - PLANNING COMPLETE ✅ -**Priority:** HIGH -**Status:** 🟡 Planning Complete, Ready to Start -**Estimated Time:** 40-60 hours total - -**Plan Document:** `GAME_TESTS_IMPLEMENTATION_PLAN.md` - -**Goal:** Реализовать систему игровых тестов в mnemo_cards_web_v2, начиная с простых тестов с выбором 1 варианта из нескольких, с соблюдением архитектуры yx_scope/yx_state. - -**Current Phase:** Planning Complete - -**Current Phase:** Phase 4 Complete ✅ - UX Improvements FINISHED -**Status:** ✅ **GAME SYSTEM WITH ENHANCED UX READY** - -**Successfully Implemented:** -- [x] Phase 1: Basic Infrastructure ✅ -- [x] Phase 2: Multiple Choice Tests ✅ -- [x] Phase 4: UX Improvements (animations, sounds, theming) ✅ -- [x] Phase 5: Advanced Question Types ✅ - -**Question Types Available:** -- [x] **Multiple Choice** - Fully implemented and working -- [x] **Input Letters** - Fully implemented and working -- [x] **Match** - UI ready, waiting for backend support -- [x] **Matrix** - UI ready, waiting for backend support - -**UX Enhancements Added:** -- [x] **Sound Effects** - Complete audio feedback system -- [x] **Animations** - Smooth transitions and visual feedback -- [x] **Dark Theme** - Full compatibility with light/dark themes -- [x] **Performance** - Optimized animations and resource usage - -**Remaining Phases (Optional):** -- [ ] Phase 3: Statistics & Analytics (results submission) - 4-6 hours - -**Game System is Production Ready!** 🎮✨ - -See `GAME_TESTS_IMPLEMENTATION_PLAN.md` for complete breakdown. - ---- - -### STAT-1: Statistics System Upgrade - PLANNING COMPLETE ✅ -**Priority:** HIGH -**Status:** 🟡 Planning Complete, Ready to Start -**Estimated Time:** 111-144 hours total - -**Plan Document:** `STATISTICS_UPGRADE_PLAN.md` - -**Goal:** Расширить систему сбора и отображения статистики пользователя для создания детализированной страницы профиля с красивым UI и настройками приложения. - -**Current Phase:** Phase 1 - Backend Models and DTOs - -**Next Actions:** -- [ ] Phase 1.1: Расширить модели данных (4-6 hours) -- [ ] Phase 1.2: Создать новые API endpoints (8-10 hours) -- [ ] Phase 2.2: Переписать StatisticsService (4-5 hours) -- [ ] Phase 3.1: Редизайн ProfilePage (12-15 hours) -- [ ] Phase 4.1: Создать Settings Page (10-12 hours) - -See `STATISTICS_UPGRADE_PLAN.md` for complete breakdown. - ---- - -## 🔴 Critical Issues - -### CI-1: Fix Telegram Package Compilation Errors ✅ COMPLETE -**Priority:** HIGH -**Status:** ✅ Complete - -**Problem:** `telegram_web_app-0.3.3` package has compilation errors with `JSExportedDartFunction` type -**Impact:** Tests cannot run, app may not compile -**Solution:** Either update package version, remove dependency, or add conditional compilation - ---- - -### CI-2: Card Images Not Displaying ✅ COMPLETE -**Priority:** HIGH -**Status:** ✅ Complete -**Date Fixed:** December 19, 2024 - -**Problem:** Card word images not showing in packs -**Impact:** Users cannot see card images in pack lists, details, or card viewer -**Root Cause:** Frontend using deprecated `ApiConfig` generating wrong v1 API URLs instead of v2 -**Solution:** -- Updated all frontend widgets to use `ApiConfigV2.getCardImageUrl()` -- Modified backend to allow public image access for enabled packs -- Added proper validation (pack exists, enabled, card belongs to pack) -- Enhanced error handling in backend endpoint - -**Files Fixed:** -- `lib/presentation/widgets/pack_card_item.dart` ✅ -- `lib/presentation/widgets/card_flipper/card_flipper.dart` ✅ -- `lib/presentation/widgets/card_viewer.dart` ✅ -- `lib/presentation/pages/pack_details/pack_details_page.dart` ✅ -- `mnemo_cards_backend/lib/api/v2/packs_api_v2.dart` ✅ - -**Tests Added:** -- `mnemo_cards_backend/test/api/v2/packs_api_v2_test.dart` (6 new tests) ✅ - ---- - -### CI-3: Fix Failing Tests (24 failures) -**Priority:** MEDIUM -**Status:** 🟡 In Progress - -**Problem:** 24 tests are failing (177 passing) -**Impact:** Mostly empty test files causing compilation errors -**Action:** Fix test_page_test.dart empty file, investigate other failures -**Notes:** Lower priority - most failures are from empty test files - ---- - -## 🟡 Backend Integration Tasks - -### BI-0: API v2 Backend Implementation ✅ PHASE 1.2 COMPLETE -**Priority:** HIGH -**Status:** Phase 1.2 Complete (Auth API) -**Latest Update:** October 29, 2025 - -**Phase 1.1 - JWT Service ✅ COMPLETE:** -- ✅ Fixed JWT crypto implementation with proper HMAC-SHA256 -- ✅ Created RefreshTokenModel Isar model for token storage -- ✅ Implemented token storage, blacklisting, and cleanup methods -- ✅ Written comprehensive unit tests (15 tests, all passing) - -**Phase 1.2 - Authentication API v2 ✅ COMPLETE:** -- ✅ Google OAuth flow implemented and tested -- ✅ Token refresh mechanism implemented and tested -- ✅ Logout endpoint with refresh token blacklisting -- ✅ Get current user endpoint -- ✅ Comprehensive integration tests (12 tests, all passing) -- ✅ Improved error handling and error responses -- ✅ Updated HttpRepositoryV2 logout to send refresh token - -**Next Steps (Phase 1.3):** -- ⬜ Implement Packs API v2 with pagination and filtering -- ⬜ Implement Tests API v2 -- ⬜ Implement remaining v2 APIs (Games, Purchases, Subscriptions, Promocodes) - -**Files Created/Modified:** -- `mnemo_cards_backend/lib/api/v2/auth_api_v2.dart` ✅ -- `mnemo_cards_backend/lib/api/v2/jwt_service.dart` ✅ -- `mnemo_cards_backend/test/api/v2/auth_api_v2_test.dart` ✅ (12 tests) -- `mnemo_cards_backend/test/api/v2/jwt_service_test.dart` ✅ (15 tests) -- `mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart` ✅ - ---- - -### BI-1: Card Flipping Functionality ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Estimated Time:** 0 hours (already implemented) - -**Description:** Card flipping functionality is already fully implemented - -**Verification:** -- ✅ CardFlipper widget exists and works -- ✅ Card flip UI with animations implemented -- ✅ Progress tracking implemented -- ✅ Integration with PackDetailsPage complete - -**Files Verified:** -- `lib/presentation/widgets/card_flipper/card_flipper.dart` ✅ -- `lib/domain/services/card_flipper_service.dart` ✅ -- `lib/di/user_scope/modules/card_flipper_module.dart` ✅ - ---- - -### BI-2: Pack Purchase Functionality ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Date Completed:** November 8, 2025 -**Time Spent:** 5 hours - -**Description:** Implement pack purchase flow with payment integration - -- **Progress:** -- [x] Implemented API v2 client helpers and `PurchasesService` with DI wiring -- [x] Added unit tests validating service → repository delegation -- [x] Created `PurchaseStateManager` with freezed states -- [x] Created `PurchasePage` with YooKassa payment integration -- [x] Added purchase module to DI -- [x] Added purchase route to app_router -- [x] Wrote comprehensive unit tests for state manager - -**Features Implemented:** -- [x] Purchase page UI with pack preview -- [x] YooKassa payment integration -- [x] Payment URL launching -- [x] Payment verification dialog -- [x] Success/error states handling -- [x] Purchase state management with yx_state -- [x] Purchase module with DI wiring - -**API Endpoints Used:** -- GET `/api/v2/packs/{packId}/buy` - Get purchase page info ✅ -- POST `/api/v2/purchases/packs/{packId}` - Create pack purchase intent ✅ -- POST `/api/v2/purchases/payments` - Create YooKassa payment ✅ -- GET `/api/v2/purchases/payments/{paymentId}/verify` - Verify payment status ✅ - -**Files Created/Updated:** -- `lib/domain/models/purchase_models.dart` ✅ -- `lib/domain/services/http_repository_v2.dart` ✅ -- `lib/domain/services/purchases_service.dart` ✅ -- `lib/domain/state/purchase_state_manager.dart` ✅ (NEW) -- `lib/di/user_scope/modules/purchase_module.dart` ✅ (NEW) -- `lib/di/user_scope/modules/purchases_module.dart` ✅ -- `lib/di/user_scope/user_scope.dart` ✅ -- `lib/di/user_scope/user_scope_container.dart` ✅ -- `lib/presentation/pages/purchase/purchase_page.dart` ✅ (NEW) -- `lib/presentation/router/app_router.dart` ✅ -- `test/domain/services/purchases_service_test.dart` ✅ -- `test/domain/state/purchase_state_manager_test.dart` ✅ (NEW) - ---- - -### BI-2B: Pack Purchase Status Check ✅ COMPLETE -**Priority:** HIGH -**Status:** ✅ Complete -**Date Completed:** November 8, 2025 -**Time Spent:** 2 hours - -**Description:** Modify PackDetailsPage to check pack purchase status and redirect to purchase page if pack is not purchased. - -**Features Implemented:** -- [x] Updated PackDetailsPage to use `GetCardPackResponse` union type -- [x] Added purchase status check in `_loadPack()` method -- [x] Implemented automatic redirect to `/purchase/:packId` for unpurchased packs -- [x] Maintained proper loading and error states -- [x] Updated all methods to handle `CardPackDto` type casting -- [x] Verified app compiles successfully with new logic - -**Technical Implementation:** -- [x] Response type checking: `packResponse.responseType == GetCardPackResponseType.buy` -- [x] Automatic redirect: `context.push('/purchase/${widget.packId}');` for unpurchased packs -- [x] Type safety: Proper `as CardPackDto` casting after purchase verification -- [x] Backward compatibility: All existing functionality preserved for purchased packs - -**User Experience:** -- [x] Unpurchased packs: Direct redirect to purchase page (no details shown) -- [x] Purchased packs: Full pack details page with all features -- [x] Error states: Proper error handling for network issues -- [x] Loading states: Smooth loading experience maintained - -**Files Modified:** -- `lib/presentation/pages/pack_details/pack_details_page.dart` ✅ - ---- - -### BI-2A: Ads Reward Unlock Flow ✅ COMPLETE -**Priority:** HIGH -**Status:** ✅ Complete - Real Adsgram Integration -**Date Completed:** November 8, 2025 -**Time Spent:** 6 hours - -**Description:** Allow users to unlock specific packs/products on the web by watching a rewarded ad, similar to the mobile experience. - -**Progress:** -- [x] Implemented AdsRewardService, AdsRewardStateManager, and user scope module with unit tests -- [x] Added animated shuffle transitions for pack card grid/list views -- [x] Created AdsRewardButton widget with state management integration -- [x] Integrated AdsRewardButton into pack_details_page.dart -- [x] Added Adsgram SDK integration for rewarded ads -- [x] Added loading, success, and error states to UI -- [x] Wrote widget tests for AdsRewardButton - -**Features Implemented:** -- [x] Detect packs eligible for ad unlock and surface CTA in UI -- [x] Integrate Adsgram rewarded ad web SDK with proper lifecycle handling -- [x] Track ad playback state, completion, and failure -- [x] Call `/ads/product/acquire/` upon rewarded completion and refresh user entitlements -- [x] Provide user feedback (loading, success, retry prompts) -- [x] Emit analytics events for impressions, completions, failures -- [x] Added Adsgram block ID configuration (16505) -- [x] Implemented reward callback endpoint `/adsgram/reward?userId=[userId]` -- [x] JavaScript interop with bidirectional callbacks -- [x] Real Adsgram SDK integration (no simulation) -- [x] Enhanced web/foos.js with callback system - -**API Endpoints Used:** -- POST `/ads/product/acquire/` - Grant product after rewarded ad ✅ -- GET `/api/v2/packs/{packId}/buy` - Check ad availability ✅ -- GET `/api/v2/adsgram/reward?userId={userId}` - Adsgram reward callback ✅ - -**Files Created/Updated:** -- `lib/presentation/widgets/ads_reward_button.dart` ✅ (NEW) -- `lib/domain/config/api_config_v2.dart` ✅ (ads config) -- `lib/presentation/pages/pack_details/pack_details_page.dart` ✅ (integration) -- `pubspec.yaml` ✅ (adsgram dependency) -- `test/presentation/widgets/ads_reward_button_test.dart` ✅ (NEW) ---- - -### BI-3: Subscription Management -**Priority:** MEDIUM -**Status:** 🟡 Partial (SubscriptionService exists) -**Estimated Time:** 4-6 hours - -**Description:** Complete subscription purchase and management - -**Features Needed:** -- [ ] Subscription page UI -- [ ] View available subscription plans -- [ ] Purchase subscription -- [ ] Cancel subscription -- [ ] Show subscription status on ProfilePage - -**API Endpoints:** -- GET `/subscription/page` - Get subscription info ✅ (implemented) -- POST `/subscription/add` - Purchase subscription ✅ (implemented) -- POST `/subscription/delete/` - Cancel subscription - -**Files to Create:** -- `lib/presentation/pages/subscription/subscription_page.dart` -- Update `subscription_service.dart` with cancel method -- Add route to `app_router.dart` - ---- - -### BI-4: Vocabulary/Review Page -**Priority:** LOW -**Status:** ⬜ Not Started -**Estimated Time:** 6-8 hours - -**Description:** Create vocabulary page to review all learned words across packs - -**Features Needed:** -- [ ] VocabularyPage in bottom navigation -- [ ] Display all learned cards -- [ ] Filter by pack, language -- [ ] Search functionality -- [ ] Review cards -- [ ] Export vocabulary - -**API Endpoints:** -- GET `/cards` - Fetch all cards -- GET `/user/data` - Get user's learning progress - -**Files to Create:** -- `lib/presentation/pages/vocabulary/vocabulary_page.dart` -- `lib/domain/services/vocabulary_service.dart` -- `lib/domain/state/vocabulary_state_manager.dart` -- `lib/di/user_scope/modules/vocabulary_module.dart` - ---- - -### BI-5: Promocode Functionality -**Priority:** LOW -**Status:** 🟡 Partial (Service migrated; awaiting UI) -**Estimated Time:** 3-4 hours - -**Description:** UI for entering and applying promocodes - -**Features Needed:** -- [ ] Promocode input field on ProfilePage or PurchasePage -- [ ] Apply promocode -- [ ] Show promocode benefits -- [ ] Validate promocode - -**API Endpoints:** -- POST `/user/promocode` - Apply promocode ✅ (implemented) -- GET `/promocode/list` - List available promocodes ✅ (implemented) - -**Files to Create:** -- `lib/presentation/widgets/promocode_input.dart` -- Update `promocode_service.dart` UI integration - ---- - -### BI-6: Settings Page -**Priority:** LOW -**Status:** ⬜ Not Started -**Estimated Time:** 2-3 hours - -**Description:** Separate settings page (currently settings are in ProfilePage) - -**Features Needed:** -- [ ] Separate SettingsPage -- [ ] Theme toggle -- [ ] Language selection -- [ ] Sound effects toggle -- [ ] Notifications settings -- [ ] Account settings - -**API Endpoints:** -- POST `/user/settings` - Update user settings - -**Files to Create:** -- `lib/presentation/pages/settings/settings_page.dart` -- `lib/domain/state/settings_state_manager.dart` - ---- - -### BI-7: Card Images Display ✅ COMPLETE -**Priority:** HIGH -**Status:** ✅ Complete -**Estimated Time:** 0 hours (already implemented) - -**Description:** Display card images in PackDetailsPage and CardFlipper - -**Features Needed:** -- [x] Fetch card images from backend (using Image.network with ApiConfig.getCardImageUrl) -- [x] Display in card list (PackDetailsPage._buildCardImage) -- [x] Display in card viewer (CardViewer._buildImage) -- [x] Display in card flipper (CardFlipper._buildImage) - -**Notes:** Card images are already fully implemented using Image.network. Flutter handles caching automatically. No additional work needed. - ---- - -### BI-8: Card Flipper Responsive Layout ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Estimated Time:** 2 hours - -**Description:** Align web CardFlipper experience with mobile adaptive behavior by introducing responsive layouts while preserving existing state and animations. - -**Features Delivered:** -- [x] Breakpoint resolver (compact / medium / expanded) via `LayoutBuilder` -- [x] Adaptive card sizing that respects viewport height and width -- [x] Responsive progress indicator and control clusters per breakpoint -- [x] Optional `stateManagerOverride` parameter for isolated widget testing -- [x] Widget tests covering compact, tablet, wide desktop, and tall desktop scenarios - -**Notes:** No backend changes required. Verify new widget tests in `card_flipper_responsive_test.dart` during CI. - ---- - -### BI-9: Card Viewer Study Flow ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Estimated Time:** 2 hours - -**Description:** Launch fullscreen study mode directly from pack card taps, mirroring mobile UX without redundant controls. - -**Features Delivered:** -- [x] Removed dedicated “Изучение” CTA from pack controls -- [x] Routed taps through `CardViewer` with ordered card lists (shuffle + favorites aware) -- [x] Started study at tapped card index with consistent navigation -- [x] Added widget tests covering initial index, swiping order, and flip interaction - -**Notes:** Learning progress marking remains handled externally via `_markCardLearned`. Future enhancements can add per-card callbacks if needed. - ---- - -### BI-10: Pack Details Shuffle Animation ✅ COMPLETE -**Priority:** LOW -**Status:** ✅ Complete -**Estimated Time:** 1 hour - -**Description:** Make pack card shuffling feel responsive and delightful with animated transitions and control feedback. - -**Features Delivered:** -- [x] Added reusable `ShuffleAnimatedSwitcher` for fade + scale transitions across grid/list shuffles -- [x] Highlighted shuffle control with active state styling and `AnimatedRotation` feedback -- [x] Animated card reordering with movement-aware wrappers plus widget/unit coverage - -**Notes:** Animation is triggered whenever shuffle/favorites state changes via `_shuffleAnimationKey`. Scroll position resets intentionally to showcase rearranged cards. - ---- - -## 🟢 Quality & Testing Tasks - -### QT-1: Increase Test Coverage -**Priority:** MEDIUM -**Status:** 🔴 In Progress -**Progress:** ~70% coverage - -**Areas Needing Tests:** -- [ ] pack_progress_service_test.dart -- [ ] promocode_service_test.dart (partial) -- [ ] subscription_service_test.dart (partial) -- [ ] card_flipper_service_test.dart -- [ ] All new pages - ---- - -### QT-2: Fix Linter Issues -**Priority:** LOW -**Status:** ⬜ Not Started - -**Action:** Run `flutter analyze` and fix all warnings - ---- - -### QT-3: Integration Tests -**Priority:** LOW -**Status:** ⬜ Not Started - -**Tests Needed:** -- [ ] Full auth flow -- [ ] Pack browsing and purchase -- [ ] Test taking flow -- [ ] Card learning flow - ---- - -## 🚫 Blocked/Deferred Tasks - -### BD-1: Telegram Authentication ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Completion Date:** November 8, 2025 - -**Outcome:** Web-initiated Telegram login bridge with 5-minute codes, bot claims, and improved web UI. - -**Highlights:** -- Implemented backend `/auth/telegram/web-code`, `/claim-code`, and `/code-status/{code}` endpoints -- Updated Telegram bot to accept `login_` payloads and keep `/code` fallback -- Added web login UI for code generation, bot deep-link, status polling, and auto-login -- Created unit tests for auth service helpers and code status parsing - ---- - -### UI-1: PackTip Support Implementation ✅ COMPLETE -**Priority:** MEDIUM -**Status:** ✅ Complete -**Estimated Time:** 3 hours -**Actual Time:** 5 hours - -**Description:** Add support for CardPackPreviewDto.tip field to display small icons or badges in corners or right side of pack cards, adapting PackTip functionality from mobile app to web version for both horizontal and vertical card layouts. - -**Completed Tasks:** -- ✅ Created PackTipExt extension for PackTip.build() method -- ✅ Implemented support for all PackTipType variants (asset, base64, text, unknown) -- ✅ Added _buildPackTip() method to PackCard widget (horizontal layout) -- ✅ Added _buildPackTip() method to PackCardVertical widget (vertical layout) -- ✅ Implemented support for all PackTipPosition values (topRight, bottomRight, fullRight) -- ✅ Adapted fullRight positioning: right side for horizontal, bottom banner for vertical cards -- ✅ Refactored both card layouts to use Stack for tip overlays -- ✅ Added proper theming and error handling -- ✅ Verified build success and code quality - -**Files Created/Modified:** -- `lib/utils/pack_tip_extension.dart` - PackTipExt extension -- `lib/presentation/widgets/pack_card.dart` - PackTip integration for horizontal cards -- `lib/presentation/widgets/pack_card_vertical.dart` - PackTip integration for vertical cards - -**Technical Details:** -- Extension pattern for clean PackTip rendering -- Stack-based overlay system for tip positioning on both card types -- Adaptive positioning logic for horizontal vs vertical layouts -- Full compatibility with mobile PackTip system -- Type-safe implementation with proper error handling - -**Next Steps:** -- Test with real backend PackTip data -- Monitor performance with multiple tips -- Consider animation enhancements - ---- - -### BD-2: API v2 Implementation 🔄 IN PROGRESS -**Priority:** HIGH -**Status:** 🟡 In Progress -**Estimated Time:** 34-46 hours for core work - -**Description:** Implement API v2 with OAuth2/JWT, RESTful patterns, and versioning - -**Current Status:** -- ✅ Backend: AuthApiV2, JwtService, authorizeV2 middleware created -- ✅ Web: ApiConfigV2, HttpRepositoryV2 created -- ✅ AuthService migrated to use v2 -- ⚠️ Backend: JWT crypto needs proper implementation -- ⚠️ Backend: Remaining v2 endpoints need implementation -- ⚠️ Web: Remaining services need migration to v2 - -**See:** `FUTURE_TASKS_PLAN.md` for detailed breakdown - ---- - -## 📊 Progress Summary - -**Total Tasks:** 18 -**Completed:** 1 -**In Progress:** 2 -**Not Started:** 13 -**Blocked/Deferred:** 2 - -**Priority Breakdown:** -- 🔴 HIGH: 5 tasks -- 🟡 MEDIUM: 7 tasks -- 🟢 LOW: 5 tasks - ---- - -## 🎯 Recommended Next Steps (See FUTURE_TASKS_PLAN.md for details) - -### Immediate Priority (Phase 1 - Backend v2) -1. **Fix JWT Service** - Use proper crypto library for HMAC-SHA256 -2. **Complete Auth API v2** - Test and verify Google OAuth flow -3. **Implement Packs API v2** - Complete all pack endpoints -4. **Implement Tests API v2** - Complete test endpoints -5. **Implement remaining v2 APIs** - Games, Purchases, Subscriptions, Promocodes - -### Next Priority (Phase 2 - Web Migration) -1. **Complete HttpRepositoryV2** - Add all missing methods -2. **Migrate PackManager** - Update to use v2 -3. **Migrate remaining services** - GamesManager, TestManager, etc. -4. **Remove v1 dependencies** - Clean up deprecated code - -### After Migration (Phase 3 - Features) -1. **Pack Purchase Flow** - Implement purchase UI and flow -2. **Subscription Management** - Complete subscription UI -3. **Promocode UI** - Add promocode input and application - -**For complete detailed plan, see:** `FUTURE_TASKS_PLAN.md` - ---- - -**Note:** Tasks are prioritized based on: -- User impact -- Technical dependencies -- Development effort -- Backend availability - diff --git a/mnemo_cards_web_v2/TROUBLESHOOTING.md b/mnemo_cards_web_v2/TROUBLESHOOTING.md deleted file mode 100644 index c04bdbb..0000000 --- a/mnemo_cards_web_v2/TROUBLESHOOTING.md +++ /dev/null @@ -1,291 +0,0 @@ -# 🔧 Устранение неполадок (Troubleshooting) - -## 404 Error на `/packs/previews` - -### Симптомы -``` -GET http://localhost:8000/packs/previews 404 (Not Found) -``` - -### Причины и решения - -#### 1️⃣ Backend запущен старой версией - -**Проверка:** -```bash -curl http://localhost:8000/packs/previews -H "app_version: 1.1.0" -# Если возвращает: {"detail":"Not Found"} -``` - -**Решение:** -```bash -cd mnemo_cards_backend -./restart_dev.sh -``` - -Или вручную: -```bash -# Остановить старый процесс -kill -9 $(lsof -ti:8000) - -# Запустить заново -./run_dev.sh -``` - -#### 2️⃣ Backend не запущен - -**Проверка:** -```bash -lsof -ti:8000 -# Если ничего не выводит - backend не запущен -``` - -**Решение:** -```bash -cd mnemo_cards_backend -./run_dev.sh -``` - -#### 3️⃣ Неправильный порт в frontend - -**Проверка:** -Откройте `mnemo_cards_web_v2/lib/domain/config/api_config.dart`: -```dart -static String get baseUrl => const String.fromEnvironment( - 'API_BASE_URL', - defaultValue: 'http://localhost:8000', // ← Должен быть 8000 -); -``` - -**Решение:** -Если порт неправильный, исправьте и перезапустите Flutter: -```bash -# Ctrl+C чтобы остановить -flutter run -d chrome -``` - -#### 4️⃣ Generated код устарел - -**Проверка:** -Если вы изменяли `@Route` аннотации в backend - -**Решение:** -```bash -cd mnemo_cards_backend -dart run build_runner build --delete-conflicting-outputs -./run_dev.sh -``` - ---- - -## CORS Error - -### Симптомы -``` -Access to XMLHttpRequest at 'http://localhost:8000/...' from origin '...' -has been blocked by CORS policy -``` - -**См. [CORS_FIX.md](CORS_FIX.md) для подробного решения** - -**Быстрое решение:** -1. Убедитесь что backend запущен с новой версией (с CORS настройками) -2. Перезапустите backend: `./restart_dev.sh` -3. Очистите кэш браузера: Ctrl+Shift+Delete -4. Перезагрузите страницу: Ctrl+R - ---- - -## Проблемы с авторизацией - -### Симптомы -``` -GET http://localhost:8000/pack/123 401 (Unauthorized) -``` - -### Причины - -Некоторые endpoints требуют авторизации: -- `/pack/:id` - требует user_token -- `/packs/actions` - требует user_token -- `/user` - требует user_token - -Endpoints БЕЗ авторизации: -- ✅ `/packs/previews` - доступен всем -- ✅ `/games` - доступен всем -- ✅ `/user/create` - для создания пользователя - -### Решение - -1. Пройдите авторизацию через Google Sign-In -2. Token должен автоматически сохраниться -3. Все последующие запросы будут включать token - -**Проверка token:** -Откройте DevTools → Application → Local Storage → Shared Preferences -Должен быть ключ `auth_token` - ---- - -## Backend не стартует - -### Симптом 1: Port already in use -``` -SocketException: Failed to create server socket (OS Error: Address already in use) -``` - -**Решение:** -```bash -# Найти и убить процесс на порту 8000 -kill -9 $(lsof -ti:8000) - -# Или использовать другой порт -dart run lib/main.dart -p 8001 --isar isar --workdir $(pwd) -``` - -### Симптом 2: Isar database locked -``` -IsarError: Database is already open in another instance -``` - -**Решение:** -```bash -# Закрыть все процессы использующие Isar -pkill -f dart - -# Удалить lock файл -rm -rf isar/*.lock - -# Перезапустить -./run_dev.sh -``` - -### Симптом 3: Missing dependencies -``` -Error: Could not resolve the package 'some_package' -``` - -**Решение:** -```bash -dart pub get -./run_dev.sh -``` - ---- - -## Flutter Web не запускается - -### Симптом 1: Chrome not found - -**Решение:** -```bash -# Укажите путь к Chrome -export CHROME_EXECUTABLE="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" -flutter run -d chrome -``` - -### Симптом 2: Build failed - -**Решение:** -```bash -flutter clean -flutter pub get -flutter run -d chrome -``` - ---- - -## Диагностические команды - -### Проверить backend -```bash -# Запущен ли backend -lsof -ti:8000 - -# Доступен ли API -curl http://localhost:8000/games - -# Проверить CORS -curl -X OPTIONS -H "Origin: http://localhost:8080" http://localhost:8000/games -v -``` - -### Проверить frontend config -```bash -# Показать текущий API URL -grep -A2 "baseUrl" mnemo_cards_web_v2/lib/domain/config/api_config.dart -``` - -### Логи backend -Backend выводит все запросы в консоль: -``` -[app] GET /packs/previews -[app] POST /user/create -``` - -Смотрите терминал где запущен `./run_dev.sh` - -### Логи frontend -Откройте DevTools (F12) → Console -Все HTTP ошибки будут показаны там - ---- - -## Полезные скрипты - -### Backend -```bash -cd mnemo_cards_backend - -# Запуск -./run_dev.sh - -# Перезапуск с регенерацией кода -./restart_dev.sh - -# Тестирование API -./test_api.sh -``` - -### Frontend -```bash -cd mnemo_cards_web_v2 - -# Запуск -flutter run -d chrome - -# Тесты -flutter test - -# Анализ кода -flutter analyze -``` - ---- - -## Еще помогает? - -1. ✅ Перезагрузите IDE (Cursor/VS Code) -2. ✅ Перезагрузите терминалы -3. ✅ Очистите кэш Flutter: `flutter clean` -4. ✅ Обновите зависимости: `flutter pub get` -5. ✅ Проверьте что используете правильную ветку git -6. ✅ Проверьте `.gitignore` - может файлы не закоммичены - ---- - -## Дополнительные ресурсы - -- [QUICK_START.md](QUICK_START.md) - Быстрый старт -- [DEV_SETUP.md](DEV_SETUP.md) - Инструкция по разработке -- [CORS_FIX.md](CORS_FIX.md) - Решение CORS проблем -- [API_INTEGRATION_TEMP.md](API_INTEGRATION_TEMP.md) - API документация - ---- - -**Если ничего не помогло - создайте issue с:** -1. Версия Flutter (`flutter --version`) -2. Версия Dart (`dart --version`) -3. OS версия -4. Полный текст ошибки -5. Логи backend и frontend - diff --git a/mnemo_cards_web_v2/WORK_COMPLETE.md b/mnemo_cards_web_v2/WORK_COMPLETE.md deleted file mode 100644 index ea6afdd..0000000 --- a/mnemo_cards_web_v2/WORK_COMPLETE.md +++ /dev/null @@ -1,168 +0,0 @@ -# Backend Integration Work - Complete - -**Date:** October 28, 2025 -**Project:** mnemo_cards_web_v2 -**Objective:** Integrate backend with web app - ---- - -## ✅ Completed Tasks - -### Task 1: Pack Images Display (100% Complete) - -**What Was Done:** -- Created `ImageCacheService` for caching decoded base64 images -- Created `ImageCacheModule` and integrated into UserScope -- Updated `PackCard` widget to display cached pack cover images -- Updated `PackDetailsHeader` to display cached pack icons -- Maintained Hero animations for smooth transitions -- Graceful fallback to placeholder icons for missing images - -**Results:** -- ✅ 15 comprehensive unit tests written and passing -- ✅ Zero linter errors -- ✅ Clean architecture maintained -- ✅ Performance optimized with caching - -**Files Created:** -- `lib/domain/services/image_cache_service.dart` -- `lib/di/user_scope/modules/image_cache_module.dart` -- `test/domain/services/image_cache_service_test.dart` - -**Files Modified:** -- `lib/di/user_scope/user_scope.dart` -- `lib/di/user_scope/user_scope_container.dart` -- `lib/presentation/widgets/pack_card.dart` -- `lib/presentation/widgets/pack_details_header.dart` - ---- - -### Task 2: Tests Functionality Verification (100% Complete) - -**What Was Done:** -- Verified `TestManager` service integration with `HttpRepository` -- Wrote 6 comprehensive unit tests for TestManager -- Verified full test flow: PackDetailsPage → TestPage -- Confirmed test loading, taking, completing, and result display -- Verified statistics submission to backend -- Confirmed progress tracking during tests - -**Results:** -- ✅ 6 comprehensive unit tests written and passing -- ✅ All acceptance criteria met -- ✅ No navigation or state management issues -- ✅ Clean code with proper error handling - -**Files Created:** -- `test/domain/services/test_manager_test.dart` - -**Files Verified:** -- `lib/domain/services/test_manager.dart` -- `lib/presentation/pages/test/test_page.dart` -- `lib/presentation/pages/pack_details/pack_details_page.dart` - ---- - -## ❌ Deferred Tasks - -### Task 3: Telegram Code-Based Authentication - -**Status:** BLOCKED -**Reason:** Requires backend API endpoints that don't currently exist - -**What Would Be Needed:** -- Backend endpoints: `/auth/telegram/request`, `/auth/telegram/verify` -- Telegram bot modifications to handle `/auth` command -- Code generation and storage mechanism -- Code timeout and validation logic - -**Decision:** Deferred until backend team can implement required endpoints - ---- - -### Task 4: API v2 Design - -**Status:** DEFERRED -**Reason:** Major refactoring outside current scope - -**What Would Be Needed:** -- Migration from custom auth to standard OAuth2/JWT -- RESTful API patterns -- API versioning strategy -- Comprehensive backend refactoring - -**Decision:** Deferred as this requires major backend architectural changes - ---- - -## 📊 Overall Impact - -### Tests Added -- **ImageCacheService:** 15 tests -- **TestManager:** 6 tests -- **Total New Tests:** 21 tests -- **All Tests Passing:** 134/134 ✅ - -### Code Quality -- ✅ Zero linter errors introduced -- ✅ Clean architecture maintained throughout -- ✅ Follows yx_scope and yx_state patterns -- ✅ Comprehensive error handling - -### Progress -- **Before:** ~85% complete (Stage 6) -- **After:** ~88% complete (Stage 6+ with backend integration) -- **Improvement:** +3% overall progress - ---- - -## 🎯 Acceptance Checklist - -- [x] Builds successfully -- [x] Linters/type checks pass -- [x] All existing tests pass -- [x] New tests cover new behavior -- [x] PROGRESS.md updated -- [x] Tasks.md updated -- [x] workflow_state.md updated -- [x] Clean architecture maintained -- [x] No breaking changes introduced - ---- - -## 📝 Notes for Future Work - -1. **Pack Images:** - - Images load from base64 in API responses (CardPackPreviewDto.imageBase64) - - Cached using ImageCacheService (similar to mobile app's ImagesHolder) - - Consider adding image preloading for better UX - -2. **Tests Functionality:** - - Currently uses simplified statistics (AllWordsStatisticsDto.empty()) - - Consider enhancing to capture detailed word-level statistics - - Test results history view could be added as enhancement - -3. **Telegram Auth:** - - Requires backend API development - - Bot modifications needed - - Consider security implications of code-based auth - -4. **API v2:** - - Major refactoring project - - Should involve full backend team - - Consider gradual migration strategy - ---- - -## ✨ Conclusion - -Successfully completed 2 of 2 achievable tasks without backend modifications. The web app now: -- ✅ Displays pack cover images with caching -- ✅ Has fully functional and tested test-taking flow -- ✅ Maintains clean architecture and code quality -- ✅ Has 21 new passing tests - -Tasks 3 and 4 are properly documented and deferred pending backend support. - -**Work Status:** COMPLETE ✅ - diff --git a/mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart b/mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart index 2e84dc1..1f5aeeb 100644 --- a/mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart +++ b/mnemo_cards_web_v2/lib/domain/services/http_repository_v2.dart @@ -61,23 +61,54 @@ class HttpRepositoryV2 { (uri != null && uri.path.endsWith(ApiConfigV2.authRefresh)); } + /// Check if the request path is a public auth endpoint (doesn't require token) + bool _isPublicAuthRequest(String path, Uri? uri) { + // Normalize path - remove /api/v2 prefix if present + String normalizedPath = uri?.path ?? path; + if (normalizedPath.startsWith('/api/v2')) { + normalizedPath = normalizedPath.substring('/api/v2'.length); + } + // Ensure path starts with / + if (!normalizedPath.startsWith('/')) { + normalizedPath = '/$normalizedPath'; + } + + // Check exact matches + if (normalizedPath == ApiConfigV2.authGoogle || + normalizedPath == ApiConfigV2.authTelegram || + normalizedPath == ApiConfigV2.authTelegramWebCode || + normalizedPath == ApiConfigV2.authRefresh) { + return true; + } + + // Check dynamic paths (e.g., /auth/telegram/code-status/) + if (normalizedPath.startsWith('/auth/telegram/code-status/')) { + return true; + } + + return false; + } + void _setupInterceptors() { _dio.interceptors.add( InterceptorsWrapper( onRequest: (options, handler) async { // Check if this is a refresh token request - skip auth for it final isRefreshRequest = _isRefreshRequest(options.path, options.uri); + + // Check if this is a public auth endpoint - skip auth for it + final isPublicAuthRequest = _isPublicAuthRequest(options.path, options.uri); - // Add Bearer token for authenticated requests (except refresh) - if (!isRefreshRequest) { + // Add Bearer token for authenticated requests (except refresh and public auth endpoints) + if (!isRefreshRequest && !isPublicAuthRequest) { final token = await getAccessToken(); if (token != null) { options.headers['Authorization'] = 'Bearer $token'; } } - // Skip verbose logging for refresh requests to reduce spam - if (!isRefreshRequest) { + // Skip verbose logging for refresh and public auth requests to reduce spam + if (!isRefreshRequest && !isPublicAuthRequest) { log( 'API v2 Request: ${options.method} ${options.path}\n' 'Headers: ${options.headers.containsKey('Authorization') ? 'Bearer token present' : 'No auth'}', @@ -88,13 +119,17 @@ class HttpRepositoryV2 { return handler.next(options); }, onResponse: (response, handler) { - // Skip verbose logging for refresh requests to reduce spam + // Skip verbose logging for refresh and public auth requests to reduce spam final isRefreshRequest = _isRefreshRequest( response.requestOptions.path, response.requestOptions.uri, ); + final isPublicAuthRequest = _isPublicAuthRequest( + response.requestOptions.path, + response.requestOptions.uri, + ); - if (!isRefreshRequest) { + if (!isRefreshRequest && !isPublicAuthRequest) { log( 'API v2 Response: ${response.statusCode} ${response.requestOptions.path}', name: 'HttpRepositoryV2', @@ -108,6 +143,10 @@ class HttpRepositoryV2 { requestPath, error.requestOptions.uri, ); + final isPublicAuthRequest = _isPublicAuthRequest( + requestPath, + error.requestOptions.uri, + ); // Check if we've already attempted refresh for this request final hasAttemptedRefresh = @@ -116,9 +155,11 @@ class HttpRepositoryV2 { // Handle 401 Unauthorized - try to refresh token // But don't try to refresh if: // 1. This IS the refresh request itself - // 2. We've already attempted refresh for this request (prevent infinite loops) + // 2. This IS a public auth endpoint (shouldn't need token) + // 3. We've already attempted refresh for this request (prevent infinite loops) if (error.response?.statusCode == 401 && !isRefreshRequest && + !isPublicAuthRequest && !hasAttemptedRefresh) { // Mark this request as having attempted refresh error.requestOptions.extra[_refreshAttemptedKey] = true;