780 lines
24 KiB
Markdown
780 lines
24 KiB
Markdown
# План разработки 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<ThemeState> {
|
||
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<UserState> {
|
||
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<CardPackDto> packs) = _Loaded;
|
||
const factory PacksState.error(String message) = _Error;
|
||
}
|
||
|
||
class PacksStateManager extends StateManager<PacksState> {
|
||
final HttpRepositoryV2 _repository;
|
||
|
||
PacksStateManager(this._repository)
|
||
: super(const PacksState.loading());
|
||
|
||
Future<void> 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<GameDto> 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<UserDto> 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<UserDto> 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<AppScopeContainer>(
|
||
holder: appScopeHolder,
|
||
child: ScopeBuilder<AppScopeContainer>.withPlaceholder(
|
||
builder: (context, appScope) {
|
||
// Вложенный ScopeProvider для UserScope
|
||
return ScopeProvider<UserScopeContainer>(
|
||
holder: appScope.userScopeHolder,
|
||
child: ScopeBuilder<UserScopeContainer>.withPlaceholder(
|
||
builder: (context, userScope) {
|
||
return StateManagerBuilder<ThemeState>(
|
||
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<AppScopeContainer>(
|
||
builder: (context, appScope) {
|
||
return ScopeBuilder<UserScopeContainer>(
|
||
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<UserScopeContainer>(
|
||
builder: (context, userScope) {
|
||
return StateManagerBuilder<PacksState>(
|
||
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 дней**
|
||
|
||
Готов к началу разработки! 🚀
|
||
|