Начальный коммит
This commit is contained in:
75
lib/Pages/controllers/AuthController.dart
Normal file
75
lib/Pages/controllers/AuthController.dart
Normal file
@@ -0,0 +1,75 @@
|
||||
// lib/controllers/auth_controller.dart
|
||||
import 'package:Stocky/services/api/api_service.dart';
|
||||
import 'package:Stocky/services/local/StorageService.dart';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AuthController extends GetxController {
|
||||
// Состояния
|
||||
final _state = 'inputPhone'.obs;
|
||||
|
||||
final ApiService apicontr = Get.find<ApiService>();
|
||||
Rx<String> phoneNumber = ''.obs;
|
||||
Rx<String> verificationCode = ''.obs;
|
||||
|
||||
// Получаем текущее состояние
|
||||
String get state => _state.value;
|
||||
|
||||
// Меняем состояние
|
||||
void setState(String newState) {
|
||||
_state.value = newState;
|
||||
}
|
||||
|
||||
// Ввод номера
|
||||
void phoneNumberInput(String value) {
|
||||
phoneNumber.value = value;
|
||||
}
|
||||
|
||||
// Проверка номера
|
||||
bool get isPhoneNumberValid {
|
||||
final clean = phoneNumber.value.replaceAll(RegExp(r'[^0-9]'), '');
|
||||
return clean.length == 11 && clean.startsWith('7'); // или 10, если без +7
|
||||
}
|
||||
|
||||
// Получить "чистый" номер (для отправки на сервер)
|
||||
String get phoneNumberClean {
|
||||
return phoneNumber.value.replaceAll(RegExp(r'[^0-9]'), '');
|
||||
}
|
||||
|
||||
// Ввод кода
|
||||
void verificationCodeInput(String value) {
|
||||
verificationCode.value = value;
|
||||
}
|
||||
|
||||
Future<void> sendCode() async {
|
||||
if (phoneNumber.value.isEmpty) {
|
||||
Get.snackbar('Ошибка', 'Введите номер телефона');
|
||||
return;
|
||||
}
|
||||
if (!isPhoneNumberValid) {
|
||||
Get.snackbar('Ошибка', 'Неверный номер телефона');
|
||||
return;
|
||||
}
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
setState('inputCode');
|
||||
await apicontr.registerByPhone(phoneNumberClean);
|
||||
}
|
||||
|
||||
// Подтвердить код
|
||||
Future<void> submit() async {
|
||||
if (verificationCode.value.isEmpty) {
|
||||
Get.snackbar('Ошибка', 'Введите код подтверждения');
|
||||
return;
|
||||
}
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
final reg = await apicontr.loginByPhone(
|
||||
phoneNumber.value,
|
||||
verificationCode.value,
|
||||
);
|
||||
if (reg) {
|
||||
Get.find<LocalStorageService>().putNumber(phoneNumber.value);
|
||||
Get.snackbar('Успешно', 'Вы вошли!');
|
||||
Get.offAllNamed('/home');
|
||||
}
|
||||
}
|
||||
}
|
||||
233
lib/Pages/controllers/MainController.dart
Normal file
233
lib/Pages/controllers/MainController.dart
Normal file
@@ -0,0 +1,233 @@
|
||||
import 'package:Stocky/models/task_adapter.dart';
|
||||
import 'package:Stocky/models/Documents.dart';
|
||||
import 'package:Stocky/services/api/api_service.dart';
|
||||
import 'package:Stocky/services/api/push_notification_service.dart';
|
||||
import 'package:Stocky/services/local/StorageService.dart';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class MainController extends GetxController {
|
||||
final username = ''.obs;
|
||||
|
||||
final tasks = <Task>[].obs;
|
||||
final documents = <Document>[].obs;
|
||||
final RxBool isLoading = false.obs;
|
||||
|
||||
final RxBool isTask = true.obs;
|
||||
final RxBool isProj = true.obs;
|
||||
|
||||
bool _isSyncingTasks = false;
|
||||
|
||||
Future<void> getSettings() async {
|
||||
username.value = await Get.find<LocalStorageService>().getUsername();
|
||||
}
|
||||
|
||||
Future<void> fetchTasks() async {
|
||||
if (_isSyncingTasks) return;
|
||||
_isSyncingTasks = true;
|
||||
|
||||
try {
|
||||
isLoading.value = true;
|
||||
final localTasks = Get.find<LocalStorageService>().getTasks();
|
||||
|
||||
if (localTasks.isEmpty) {
|
||||
await _fetchTasksFromServer();
|
||||
} else {
|
||||
await _syncTasksWithServer(localTasks);
|
||||
}
|
||||
|
||||
final activeTasks = await Get.find<LocalStorageService>()
|
||||
.getCompletedTasks();
|
||||
|
||||
tasks.assignAll(activeTasks);
|
||||
} catch (e) {
|
||||
print('Ошибка при синхронизации задач: $e');
|
||||
} finally {
|
||||
_isSyncingTasks = false;
|
||||
isLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _syncTasksWithServer(List<Task> localTasks) async {
|
||||
try {
|
||||
// Шаг 1: Обрабатываем все несинхронизированные задачи
|
||||
final unsyncedTasks = localTasks.where((t) => !t.isSynced).toList();
|
||||
for (final task in unsyncedTasks) {
|
||||
if (task.isDeletedLocally == true) {
|
||||
// Удаление: пытаемся удалить на сервере
|
||||
final deleted = await Get.find<ApiService>().deleteTask(
|
||||
task.id.toString(),
|
||||
);
|
||||
if (deleted) {
|
||||
Get.find<LocalStorageService>().removeTask(task.id);
|
||||
} else {
|
||||
// Не удалось — оставляем помеченной, попробуем позже
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
// Создание или обновление
|
||||
final syncedTask = await Get.find<ApiService>().upsertTask(task);
|
||||
if (syncedTask != null) {
|
||||
syncedTask.isSynced = true;
|
||||
syncedTask.isDeletedLocally = false;
|
||||
Get.find<LocalStorageService>().updateTask(syncedTask);
|
||||
}
|
||||
// Если не удалось — остаётся с isSynced = false
|
||||
}
|
||||
}
|
||||
|
||||
// Шаг 2: Получаем актуальный список с сервера
|
||||
final serverTasks = await Get.find<ApiService>().fetchTasks();
|
||||
await Get.find<LocalStorageService>().saveTasks(serverTasks);
|
||||
} catch (e) {
|
||||
print('Ошибка синхронизации: $e');
|
||||
// В случае ошибки — восстанавливаем локальный список
|
||||
tasks.assignAll(localTasks);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchTasksFromServer() async {
|
||||
try {
|
||||
final serverTasks = await Get.find<ApiService>().fetchTasks();
|
||||
await Get.find<LocalStorageService>().saveTasks(serverTasks);
|
||||
tasks.assignAll(serverTasks);
|
||||
} catch (e) {
|
||||
print('Ошибка загрузки задач с сервера: $e');
|
||||
// Остаёмся с пустым списком
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> assignTaskToCurrentUser(Task task) async {
|
||||
task.executor = username.value;
|
||||
task.isSynced = false;
|
||||
updateTask(task);
|
||||
}
|
||||
|
||||
Future<void> completeTask(Task task) async {
|
||||
task.isCompleted = true;
|
||||
task.endTime = DateTime.now();
|
||||
task.isSynced = false;
|
||||
updateTask(task);
|
||||
final activeTasks = await Get.find<LocalStorageService>()
|
||||
.getCompletedTasks();
|
||||
|
||||
tasks.assignAll(activeTasks);
|
||||
}
|
||||
|
||||
Future<void> addTask(Task task) async {
|
||||
task.isSynced = false;
|
||||
task.isDeletedLocally = false;
|
||||
|
||||
Get.find<LocalStorageService>().addTask(task);
|
||||
tasks.add(task);
|
||||
|
||||
_syncTaskToServer(task);
|
||||
}
|
||||
|
||||
Future<void> updateTask(Task updatedTask) async {
|
||||
final index = tasks.indexWhere((t) => t.id == updatedTask.id);
|
||||
if (index == -1) return;
|
||||
|
||||
updatedTask.isSynced = false;
|
||||
updatedTask.isDeletedLocally = false;
|
||||
|
||||
Get.find<LocalStorageService>().updateTask(updatedTask);
|
||||
tasks[index] = updatedTask;
|
||||
|
||||
_syncTaskToServer(updatedTask);
|
||||
}
|
||||
|
||||
Future<void> deleteTask(Task task) async {
|
||||
final index = tasks.indexWhere((t) => t.id == task.id);
|
||||
if (index == -1) return;
|
||||
|
||||
try {
|
||||
final success = await Get.find<ApiService>().deleteTask(
|
||||
task.id.toString(),
|
||||
);
|
||||
if (success) {
|
||||
Get.find<LocalStorageService>().removeTask(task.id);
|
||||
tasks.removeAt(index);
|
||||
} else {
|
||||
// Нет связи — помечаем для отложенного удаления
|
||||
_markTaskForDeletion(task);
|
||||
}
|
||||
} catch (e) {
|
||||
print('Ошибка при удалении задачи: $e');
|
||||
_markTaskForDeletion(task);
|
||||
}
|
||||
}
|
||||
|
||||
void _markTaskForDeletion(Task task) {
|
||||
task.isDeletedLocally = true;
|
||||
task.isSynced = false;
|
||||
Get.find<LocalStorageService>().updateTask(task);
|
||||
}
|
||||
|
||||
Future<void> _syncTaskToServer(Task task) async {
|
||||
final storage = Get.find<LocalStorageService>();
|
||||
|
||||
if (task.isDeletedLocally == true) {
|
||||
final success = await Get.find<ApiService>().deleteTask(
|
||||
task.id.toString(),
|
||||
);
|
||||
if (success) {
|
||||
storage.removeTask(task.id);
|
||||
tasks.removeWhere((t) => t.id == task.id);
|
||||
} else {
|
||||
// Оставить помеченной — будет обработано при полной синхронизации
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final syncedTask = await Get.find<ApiService>().upsertTask(task);
|
||||
if (syncedTask == null) return;
|
||||
|
||||
if (syncedTask.id != task.id) {
|
||||
syncedTask.isSynced = true;
|
||||
syncedTask.isDeletedLocally = false;
|
||||
await storage.replaceTask(task.id, syncedTask);
|
||||
} else {
|
||||
task.isSynced = true;
|
||||
task.isDeletedLocally = false;
|
||||
await storage.updateTask(syncedTask);
|
||||
}
|
||||
|
||||
final index = tasks.indexWhere((t) => t.id == task.id);
|
||||
if (index != -1) {
|
||||
if (syncedTask.id != task.id) {
|
||||
tasks.removeAt(index);
|
||||
tasks.add(syncedTask);
|
||||
} else {
|
||||
tasks[index] = syncedTask;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Ошибка синхронизации: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Task? openTask(String taskId) {
|
||||
return tasks.firstWhereOrNull((task) => task.id == taskId);
|
||||
}
|
||||
|
||||
@override
|
||||
void onInit() async {
|
||||
super.onInit();
|
||||
|
||||
Get.find<PushNotificationService>().foregroundMessageStream.listen((
|
||||
message,
|
||||
) {
|
||||
// _handleMessageAction(message); // тот же метод, что и выше
|
||||
});
|
||||
|
||||
getSettings();
|
||||
|
||||
fetchTasks();
|
||||
}
|
||||
|
||||
void openTaskFromNotification(String taskId) {
|
||||
Get.toNamed('/task', arguments: {'id': taskId});
|
||||
}
|
||||
}
|
||||
32
lib/Pages/controllers/SplashScreenController.dart
Normal file
32
lib/Pages/controllers/SplashScreenController.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:Stocky/services/local/StorageService.dart';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class SplashScreenController extends GetxController {
|
||||
late Future<bool> _authCheck;
|
||||
|
||||
@override
|
||||
void onInit() {
|
||||
super.onInit();
|
||||
_authCheck = _checkAuthentication();
|
||||
}
|
||||
|
||||
Future<bool> _checkAuthentication() async {
|
||||
final LocalStorageService settings = Get.find<LocalStorageService>();
|
||||
final accessToken = settings.getAccessToken();
|
||||
if (accessToken != null && accessToken.isNotEmpty) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<void> navigateBasedOnAuth() async {
|
||||
final isAuthenticated = await _authCheck;
|
||||
|
||||
if (isAuthenticated) {
|
||||
Get.offAllNamed('/home');
|
||||
} else {
|
||||
Get.offAllNamed('/login');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user