slrpg-app/lib/src/shared/data/repositories/user_repository.dart

145 lines
4.3 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:drift/drift.dart';
import 'package:logger/logger.dart';
import 'package:slrpg_app/main.dart';
import '../local/app_database.dart';
import '../remote/api_client.dart';
final userRepositoryProvider = Provider<UserRepository>((ref) {
final db = ref.watch(appDatabaseProvider);
final apiClient = ref.watch(apiClientProvider);
return UserRepository(db: db, apiClient: apiClient);
});
class UserRepository {
final AppDatabase db;
final ApiClient apiClient;
final _logger = Logger();
UserRepository({required this.db, required this.apiClient});
Future<UserCollection?> getLocalUser() async {
return await (db.select(db.users)..limit(1)).getSingleOrNull();
}
Future<void> saveLocalUser(UserCollection user) async {
final companion = user.toCompanion(true).copyWith(
updatedAt: Value(DateTime.now()),
);
await db.into(db.users).insertOnConflictUpdate(companion);
}
Future<void> updateXP(int xpToAdd) async {
final user = await getLocalUser();
if (user != null) {
final newXp = user.xp + xpToAdd;
final companion = UsersCompanion(
xp: Value(newXp),
isDirty: const Value(true),
updatedAt: Value(DateTime.now()),
);
await (db.update(db.users)..where((u) => u.id.equals(user.id)))
.write(companion);
}
}
Future<void> updateLevel(int newLevel) async {
final user = await getLocalUser();
if (user != null) {
final companion = UsersCompanion(
level: Value(newLevel),
isDirty: const Value(true),
updatedAt: Value(DateTime.now()),
);
await (db.update(db.users)..where((u) => u.id.equals(user.id)))
.write(companion);
}
}
Future<void> updateBodyweight(double bodyweight) async {
final user = await getLocalUser();
if (user != null) {
final companion = UsersCompanion(
currentBodyweight: Value(bodyweight),
isDirty: const Value(true),
updatedAt: Value(DateTime.now()),
);
await (db.update(db.users)..where((u) => u.id.equals(user.id)))
.write(companion);
try {
await apiClient.updateBodyweight(bodyweight);
} catch (e) {
_logger.w('Failed to update bodyweight online, will sync later: $e');
}
}
}
Future<void> updateInventory(Map<String, dynamic> inventory) async {
final user = await getLocalUser();
if (user != null) {
final companion = UsersCompanion(
inventorySettings: Value(inventory),
isDirty: const Value(true),
updatedAt: Value(DateTime.now()),
);
await (db.update(db.users)..where((u) => u.id.equals(user.id)))
.write(companion);
try {
await apiClient.updateInventory(inventory);
} catch (e) {
_logger.w('Failed to update inventory online, will sync later: $e');
}
}
}
Future<Map<String, dynamic>> getInventorySettingsAsync() async {
final user = await getLocalUser();
if (user?.inventorySettings != null) {
return user!.inventorySettings!;
}
return {
'bar_weight': 20.0,
'plates': [20, 20, 10, 10, 5, 5, 2.5, 2.5, 1.25, 1.25],
'bands': [],
};
}
Future<List<double>> getAvailablePlates() async {
final inventory = await getInventorySettingsAsync();
final plates = inventory['plates'] as List?;
return plates?.map((e) => (e as num).toDouble()).toList() ?? [];
}
Future<double> getBarWeight() async {
final inventory = await getInventorySettingsAsync();
return (inventory['bar_weight'] as num?)?.toDouble() ?? 20.0;
}
Future<void> resetProgress() async {
final user = await getLocalUser();
if (user != null) {
try {
await apiClient.resetProgress();
} catch (e) {
_logger.e('Failed to reset progress on server: $e');
throw Exception(
"Server connection required to reset progress. Please try again when online.");
}
final companion = UsersCompanion(
xp: const Value(0),
level: const Value(1),
isDirty: const Value(false),
updatedAt: Value(DateTime.now()),
);
await (db.update(db.users)..where((u) => u.id.equals(user.id)))
.write(companion);
await db.delete(db.cycles).go();
await db.delete(db.workouts).go();
}
}
}