TKK_E32230206/lib/features/auth/auth_notifier.dart

106 lines
4.0 KiB
Dart

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:onesignal_flutter/onesignal_flutter.dart';
import '../../repositories/auth_repository.dart';
import '../../services/supabase_auth_service.dart'; // Dibutuhkan untuk DI di authRepositoryProvider
import 'auth_state.dart';
// ── Provider ────────────────────────────────────────────────────
/// Provider global untuk [AuthRepository].
final authRepositoryProvider = Provider<AuthRepository>(
(ref) => AuthRepository(SupabaseAuthService()),
);
/// Provider utama untuk mengelola status autentikasi di seluruh aplikasi.
final authProvider = StateNotifierProvider<AuthNotifier, AuthState>(
(ref) => AuthNotifier(ref.read(authRepositoryProvider)),
);
// ── Notifier ────────────────────────────────────────────────────
/// Notifier yang mengelola logika bisnis autentikasi pengguna.
/// Berfungsi sebagai penghubung antara UI dan [AuthRepository], serta mengontrol pendaftaran OneSignal Push Notification.
class AuthNotifier extends StateNotifier<AuthState> {
final AuthRepository _repo;
AuthNotifier(this._repo) : super(const AuthIdle());
/// Memeriksa status sesi login yang tersimpan di perangkat lokal.
/// Dipanggil pertama kali saat aplikasi dibuka untuk fitur Auto-Login.
Future<void> checkAuthStatus() async {
state = const AuthLoading();
try {
// Mengambil sesi aktif dari repository
final user = await _repo.checkSession();
if (user != null) {
// Jika sesi valid, login ke OneSignal menggunakan ID user untuk pengiriman notifikasi personal
OneSignal.login(user.id);
state = AuthSuccess(user);
} else {
state = const AuthIdle();
}
} catch (e) {
state = const AuthIdle();
}
}
/// Memproses login pengguna menggunakan email dan password.
Future<void> login(String email, String password) async {
state = const AuthLoading();
try {
final user = await _repo.login(email, password);
// Daftarkan ke OneSignal saat login berhasil
OneSignal.login(user.id);
state = AuthSuccess(user);
} catch (e) {
state = AuthError(e.toString().replaceFirst('Exception: ', ''));
}
}
/// Memproses registrasi akun baru (Nama, Email, Password).
Future<void> register(
String name, String email, String password) async {
state = const AuthLoading();
try {
final user = await _repo.register(name, email, password);
// Daftarkan ke OneSignal saat registrasi berhasil
OneSignal.login(user.id);
state = AuthSuccess(user);
} catch (e) {
state = AuthError(e.toString().replaceFirst('Exception: ', ''));
}
}
/// Menghubungkan akun pengguna dengan perangkat IoT ESP32 berdasarkan [claimCode] dari alat.
/// Setelah berhasil diklaim, state [AuthState] akan diperbarui dengan data `deviceId` yang baru.
Future<void> claimDevice(String claimCode) async {
final currentState = state;
if (currentState is! AuthSuccess) return;
state = const AuthLoading();
try {
final deviceId = await _repo.claimDevice(currentState.user.id, claimCode);
// Update UserModel dengan deviceId baru secara immutable
final updatedUser = currentState.user.copyWith(deviceId: deviceId);
state = AuthSuccess(updatedUser);
} catch (e) {
// Revert ke state sebelumnya jika terjadi error klaim
state = currentState;
rethrow;
}
}
/// Keluar dari sesi login pengguna.
/// Menghapus kredensial dari Supabase, memutus sesi OneSignal, dan mereset state ke [AuthIdle].
Future<void> logout() async {
OneSignal.logout();
await _repo.logout();
state = const AuthIdle();
}
/// Mereset kondisi error saat ini kembali ke [AuthIdle].
void resetError() {
if (state is AuthError) state = const AuthIdle();
}
}