Основываясь на предоставленных изменениях, я предлагаю следующий коммит:
feat: добавить поддержку пользователей в приложение учета бюджета
This commit is contained in:
@@ -41,4 +41,28 @@ class HiveCategoryRepository implements ICategoryRepository {
|
||||
Future<List<Category>> getExpenseCategories() async {
|
||||
return _box.values.where((c) => !c.isIncome).toList();
|
||||
}
|
||||
|
||||
// Новые методы для работы с пользователями
|
||||
|
||||
@override
|
||||
Future<List<Category>> getAllByUser(String userId) async {
|
||||
// Фильтруем все категории по userId
|
||||
return _box.values.where((c) => c.userId == userId).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Category>> getIncomeCategoriesByUser(String userId) async {
|
||||
// Получаем только категории доходов конкретного пользователя
|
||||
return _box.values
|
||||
.where((c) => c.userId == userId && c.isIncome)
|
||||
.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<Category>> getExpenseCategoriesByUser(String userId) async {
|
||||
// Получаем только категории расходов конкретного пользователя
|
||||
return _box.values
|
||||
.where((c) => c.userId == userId && !c.isIncome)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import '/data/repositories/interfaces/iuser_repository.dart';
|
||||
import '/models/user.dart';
|
||||
|
||||
/// Реализация репозитория пользователей с использованием Hive
|
||||
/// Hive - это быстрая NoSQL база данных для Flutter
|
||||
class HiveUserRepository implements IUserRepository {
|
||||
final Box<User> _box; // Hive box для хранения пользователей
|
||||
|
||||
/// Конструктор принимает готовый Hive box
|
||||
HiveUserRepository(this._box);
|
||||
|
||||
@override
|
||||
Future<List<User>> getAll() async {
|
||||
// Возвращаем все значения из box как список
|
||||
return _box.values.toList();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<User?> getById(String id) async {
|
||||
// Получаем пользователя по ключу (id)
|
||||
return _box.get(id);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<User?> getByEmail(String email) async {
|
||||
// Ищем пользователя по email среди всех пользователей
|
||||
try {
|
||||
return _box.values.firstWhere((user) => user.email == email);
|
||||
} catch (e) {
|
||||
// Если пользователь не найден, возвращаем null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> add(User user) async {
|
||||
// Сохраняем пользователя с его id как ключом
|
||||
await _box.put(user.id, user);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update(User user) async {
|
||||
// Обновление = перезапись существующего пользователя
|
||||
await add(user);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(String id) async {
|
||||
// Удаляем пользователя по id
|
||||
await _box.delete(id);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import '/models/category.dart';
|
||||
|
||||
abstract class ICategoryRepository {
|
||||
// Старые методы для обратной совместимости
|
||||
Future<List<Category>> getAll();
|
||||
Future<Category?> getById(String id);
|
||||
Future<void> add(Category category);
|
||||
@@ -8,4 +9,14 @@ abstract class ICategoryRepository {
|
||||
Future<void> delete(String id);
|
||||
Future<List<Category>> getIncomeCategories();
|
||||
Future<List<Category>> getExpenseCategories();
|
||||
|
||||
// Новые методы для работы с пользователями
|
||||
/// Получить все категории конкретного пользователя
|
||||
Future<List<Category>> getAllByUser(String userId);
|
||||
|
||||
/// Получить категории доходов конкретного пользователя
|
||||
Future<List<Category>> getIncomeCategoriesByUser(String userId);
|
||||
|
||||
/// Получить категории расходов конкретного пользователя
|
||||
Future<List<Category>> getExpenseCategoriesByUser(String userId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import '/models/user.dart';
|
||||
|
||||
/// Интерфейс для работы с пользователями в базе данных
|
||||
/// Определяет основные операции CRUD (Create, Read, Update, Delete)
|
||||
abstract class IUserRepository {
|
||||
/// Получить всех пользователей
|
||||
Future<List<User>> getAll();
|
||||
|
||||
/// Получить пользователя по ID
|
||||
Future<User?> getById(String id);
|
||||
|
||||
/// Получить пользователя по email (для входа в систему)
|
||||
Future<User?> getByEmail(String email);
|
||||
|
||||
/// Добавить нового пользователя
|
||||
Future<void> add(User user);
|
||||
|
||||
/// Обновить существующего пользователя
|
||||
Future<void> update(User user);
|
||||
|
||||
/// Удалить пользователя
|
||||
Future<void> delete(String id);
|
||||
}
|
||||
@@ -31,6 +31,11 @@ class Category {
|
||||
/// false - расход (например покупки)
|
||||
final bool isIncome;
|
||||
|
||||
@HiveField(5)
|
||||
/// Идентификатор пользователя, которому принадлежит эта категория
|
||||
/// Это позволяет разделять категории между разными пользователями
|
||||
final String userId;
|
||||
|
||||
/// Конструктор с обязательными параметрами
|
||||
Category({
|
||||
String? id,
|
||||
@@ -38,6 +43,7 @@ class Category {
|
||||
required this.color,
|
||||
required this.icon,
|
||||
required this.isIncome,
|
||||
required this.userId, // Теперь userId обязательный параметр
|
||||
}) : id = id ?? IdGenerator.generateId();
|
||||
|
||||
/// Метод для преобразования объекта в Map (полезно для работы с БД)
|
||||
@@ -48,6 +54,7 @@ class Category {
|
||||
'color': color.value, // Сохраняем только значение цвета
|
||||
'icon': icon.codePoint,
|
||||
'isIncome': isIncome,
|
||||
'userId': userId, // Добавляем userId в Map
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,6 +66,7 @@ class Category {
|
||||
color: Color(map['color']),
|
||||
icon: IconData(map['icon'], fontFamily: 'MaterialIcons'),
|
||||
isIncome: map['isIncome'],
|
||||
userId: map['userId'], // Добавляем userId при создании из Map
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import '../utils/id_generator.dart';
|
||||
|
||||
// Указываем Hive, что это модель для хранения в базе данных
|
||||
// typeId: 3 - уникальный идентификатор типа для Hive (у нас уже есть 0,1,2)
|
||||
part 'user.g.dart';
|
||||
|
||||
@HiveType(typeId: 3)
|
||||
/// Модель пользователя приложения
|
||||
/// Содержит основную информацию для идентификации пользователя
|
||||
class User {
|
||||
/// Уникальный идентификатор пользователя
|
||||
@HiveField(0) // Поле 0 в Hive - первое поле модели
|
||||
final String id;
|
||||
|
||||
/// Имя пользователя для отображения в интерфейсе
|
||||
@HiveField(1) // Поле 1 в Hive - второе поле модели
|
||||
final String name;
|
||||
|
||||
/// Email пользователя (может использоваться для входа в будущем)
|
||||
@HiveField(2) // Поле 2 в Hive - третье поле модели
|
||||
final String email;
|
||||
|
||||
/// Конструктор пользователя
|
||||
/// id генерируется автоматически, если не передан
|
||||
User({
|
||||
String? id, // Опциональный параметр - если null, сгенерируется автоматически
|
||||
required this.name, // Обязательный параметр
|
||||
required this.email, // Обязательный параметр
|
||||
}) : id = id ?? IdGenerator.generateId(); // Если id не передан, генерируем новый
|
||||
|
||||
/// Преобразование объекта в Map для сохранения в JSON или передачи по сети
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'id': id,
|
||||
'name': name,
|
||||
'email': email,
|
||||
};
|
||||
}
|
||||
|
||||
/// Создание объекта User из Map (например, при загрузке из JSON)
|
||||
factory User.fromMap(Map<String, dynamic> map) {
|
||||
return User(
|
||||
id: map['id'],
|
||||
name: map['name'],
|
||||
email: map['email'],
|
||||
);
|
||||
}
|
||||
|
||||
/// Переопределяем toString для удобного отображения в логах
|
||||
@override
|
||||
String toString() {
|
||||
return 'User(id: $id, name: $name, email: $email)';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hive_ce/hive.dart';
|
||||
import '/models/user.dart';
|
||||
import '/data/repositories/interfaces/iuser_repository.dart';
|
||||
|
||||
/// Сервис для управления текущим пользователем приложения
|
||||
/// Использует ChangeNotifier для уведомления UI об изменениях
|
||||
class UserService extends ChangeNotifier {
|
||||
// Ключ для сохранения ID текущего пользователя в настройках
|
||||
static const String _currentUserKey = 'currentUserId';
|
||||
|
||||
late final Box _settingsBox; // Box для хранения настроек
|
||||
final IUserRepository _userRepository; // Репозиторий для работы с пользователями
|
||||
|
||||
User? _currentUser; // Текущий активный пользователь
|
||||
|
||||
/// Геттер для получения текущего пользователя
|
||||
User? get currentUser => _currentUser;
|
||||
|
||||
/// Проверяем, есть ли активный пользователь
|
||||
bool get hasCurrentUser => _currentUser != null;
|
||||
|
||||
/// Конструктор сервиса
|
||||
UserService(this._userRepository) {
|
||||
_settingsBox = Hive.box('settings');
|
||||
_loadCurrentUser(); // Загружаем сохраненного пользователя при запуске
|
||||
}
|
||||
|
||||
/// Загружаем текущего пользователя из настроек
|
||||
Future<void> _loadCurrentUser() async {
|
||||
final userId = _settingsBox.get(_currentUserKey);
|
||||
if (userId != null) {
|
||||
_currentUser = await _userRepository.getById(userId);
|
||||
notifyListeners(); // Уведомляем UI об изменении
|
||||
}
|
||||
}
|
||||
|
||||
/// Устанавливаем текущего пользователя
|
||||
Future<void> setCurrentUser(User user) async {
|
||||
_currentUser = user;
|
||||
// Сохраняем ID пользователя в настройках для следующего запуска
|
||||
await _settingsBox.put(_currentUserKey, user.id);
|
||||
notifyListeners(); // Уведомляем UI об изменении
|
||||
}
|
||||
|
||||
/// Выход из аккаунта (сброс текущего пользователя)
|
||||
Future<void> logout() async {
|
||||
_currentUser = null;
|
||||
await _settingsBox.delete(_currentUserKey);
|
||||
notifyListeners(); // Уведомляем UI об изменении
|
||||
}
|
||||
|
||||
/// Создание нового пользователя и установка его как текущего
|
||||
Future<void> createAndSetUser(String name, String email) async {
|
||||
final user = User(name: name, email: email);
|
||||
await _userRepository.add(user);
|
||||
await setCurrentUser(user);
|
||||
}
|
||||
|
||||
/// Получение всех пользователей (для выбора)
|
||||
Future<List<User>> getAllUsers() async {
|
||||
return await _userRepository.getAll();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user