172 lines
4.9 KiB
Dart
172 lines
4.9 KiB
Dart
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<AuthResponse> 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<AuthResponse> signIn(String email, String password) async {
|
|
return await supabase.auth.signInWithPassword(
|
|
email: email,
|
|
password: password,
|
|
);
|
|
}
|
|
|
|
Future<void> signOut() async {
|
|
await supabase.auth.signOut();
|
|
}
|
|
|
|
User? get currentUser => supabase.auth.currentUser;
|
|
|
|
// ============================================================
|
|
// PROFILE
|
|
// ============================================================
|
|
|
|
// Ambil profil dari tabel profiles berdasarkan user yang login
|
|
Future<Map<String, dynamic>?> 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<void> updatePassword(String passwordBaru) async {
|
|
await supabase.auth.updateUser(
|
|
UserAttributes(password: passwordBaru),
|
|
);
|
|
}
|
|
|
|
// Kirim OTP ke email
|
|
Future<void> resetPassword(String email) async {
|
|
await supabase.auth.signInWithOtp(
|
|
email: email,
|
|
shouldCreateUser: false, // jangan buat user baru
|
|
);
|
|
}
|
|
|
|
// Verifikasi OTP yang diinput user
|
|
Future<void> verifyOTP(String email, String token) async {
|
|
await supabase.auth.verifyOTP(
|
|
email: email,
|
|
token: token,
|
|
type: OtpType.email,
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// SENSOR DATA (sensor_log)
|
|
// ============================================================
|
|
|
|
Future<List<Map<String, dynamic>>> getSensorLogs() async {
|
|
return await supabase
|
|
.from('sensor_log')
|
|
.select()
|
|
.order('created_at', ascending: false)
|
|
.limit(20);
|
|
}
|
|
|
|
Future<Map<String, dynamic>?> getLatestLog() async {
|
|
final List<dynamic> data = await supabase
|
|
.from('sensor_log')
|
|
.select()
|
|
.order('created_at', ascending: false)
|
|
.limit(1);
|
|
return data.isNotEmpty ? data.first as Map<String, dynamic> : null;
|
|
}
|
|
|
|
Future<void> 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<Map<String, dynamic>?> getBatasSensor() async {
|
|
final data = await supabase
|
|
.from('batas_sensor')
|
|
.select()
|
|
.limit(1)
|
|
.single();
|
|
return data;
|
|
}
|
|
|
|
Future<void> 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<int> getIntervalSetting() async {
|
|
final data = await supabase
|
|
.from('interval_setting')
|
|
.select('durasi_menit')
|
|
.limit(1)
|
|
.single();
|
|
return data['durasi_menit'] as int;
|
|
}
|
|
|
|
Future<void> 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<List<Map<String, dynamic>>> getFotoDataset() async {
|
|
final List<dynamic> data = await supabase
|
|
.from('foto_dataset')
|
|
.select()
|
|
.order('created_at', ascending: true);
|
|
return List<Map<String, dynamic>>.from(data);
|
|
}
|
|
} |