import 'package:supabase_flutter/supabase_flutter.dart'; class SupabaseService { static final SupabaseService _instance = SupabaseService._internal(); factory SupabaseService() => _instance; SupabaseService._internal(); final supabase = Supabase.instance.client; // ============================================================ // AUTH // ============================================================ Future signUp( String email, String password, String fullName) async { final response = await supabase.auth.signUp( email: email, password: password, ); if (response.user != null) { await supabase.from('profiles').insert({ 'id': response.user!.id, 'nama_lengkap': fullName, 'username': email.split('@')[0], }); } return response; } Future signIn(String email, String password) async { return await supabase.auth.signInWithPassword( email: email, password: password, ); } Future signOut() async { await supabase.auth.signOut(); } User? get currentUser => supabase.auth.currentUser; // ============================================================ // PROFILE // ============================================================ // Ambil profil dari tabel profiles berdasarkan user yang login Future?> getProfile() async { final user = currentUser; if (user == null) return null; final response = await supabase .from('profiles') .select() .eq('id', user.id) .single(); return response; } // Update password akun yang sedang login Future updatePassword(String passwordBaru) async { await supabase.auth.updateUser( UserAttributes(password: passwordBaru), ); } // Kirim OTP ke email Future resetPassword(String email) async { await supabase.auth.signInWithOtp( email: email, shouldCreateUser: false, // jangan buat user baru ); } // Verifikasi OTP yang diinput user Future verifyOTP(String email, String token) async { await supabase.auth.verifyOTP( email: email, token: token, type: OtpType.email, ); } // ============================================================ // SENSOR DATA (sensor_log) // ============================================================ Future>> getSensorLogs() async { return await supabase .from('sensor_log') .select() .order('created_at', ascending: false) .limit(20); } Future?> getLatestLog() async { final List data = await supabase .from('sensor_log') .select() .order('created_at', ascending: false) .limit(1); return data.isNotEmpty ? data.first as Map : null; } Future logFanAction( String fan1, String fan2, double suhu, double hum, double lux) async { await supabase.from('sensor_log').insert({ 'kipas1': fan1, 'kipas2': fan2, 'suhu': suhu, 'kelembapan': hum, 'intensitas': lux, 'timestamp': DateTime.now().toString().substring(0, 19), }); } // ============================================================ // BATAS SENSOR (batas_sensor) // ============================================================ Future?> getBatasSensor() async { final data = await supabase .from('batas_sensor') .select() .limit(1) .single(); return data; } Future updateBatasSensor( double suhuMin, double suhuMax, double rhMin, double rhMax) async { await supabase.from('batas_sensor').update({ 'suhu_min': suhuMin, 'suhu_max': suhuMax, 'rh_min': rhMin, 'rh_max': rhMax, 'updated_at': DateTime.now().toIso8601String(), }).eq('id', 1); } // ============================================================ // INTERVAL SETTING (interval_setting) // ============================================================ Future getIntervalSetting() async { final data = await supabase .from('interval_setting') .select('durasi_menit') .limit(1) .single(); return data['durasi_menit'] as int; } Future updateIntervalSetting(int menit) async { await supabase.from('interval_setting').update({ 'durasi_menit': menit, 'update_at': DateTime.now().toIso8601String(), }).eq('id', 1); } // ============================================================ // GALLERY (foto_dataset) // ============================================================ Future>> getFotoDataset() async { final List data = await supabase .from('foto_dataset') .select() .order('created_at', ascending: true); return List>.from(data); } }