155 lines
5.0 KiB
Dart
155 lines
5.0 KiB
Dart
import 'package:shared_preferences/shared_preferences.dart';
|
|
import 'dart:convert';
|
|
import '../models/firefly_account.dart';
|
|
|
|
class AccountMirrorService {
|
|
static const String _accountsKey = 'mirrored_accounts';
|
|
static const String _lastSyncKey = 'accounts_last_sync';
|
|
static const String _lastSyncTimeKey = 'accounts_last_sync_time';
|
|
|
|
/// Simpan semua akun ke local storage untuk offline usage
|
|
static Future<void> mirrorAccounts(List<FireflyAccount> accounts) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
|
|
// Konversi akun ke JSON string
|
|
final accountsJson = accounts.map((account) => account.toJson()).toList();
|
|
|
|
await prefs.setStringList(
|
|
_accountsKey, accountsJson.map((json) => jsonEncode(json)).toList());
|
|
await prefs.setInt(_lastSyncTimeKey, DateTime.now().millisecondsSinceEpoch);
|
|
await prefs.setBool(
|
|
_lastSyncKey, true); // Menandakan bahwa akun pernah di-sync
|
|
}
|
|
|
|
/// Ambil semua akun yang telah di-mirror dari local storage
|
|
static Future<List<FireflyAccount>> getMirroredAccounts() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final accountsJsonList = prefs.getStringList(_accountsKey) ?? [];
|
|
|
|
if (accountsJsonList.isEmpty) {
|
|
return [];
|
|
}
|
|
|
|
return accountsJsonList
|
|
.map((jsonString) => FireflyAccount.fromJson(json.decode(jsonString)))
|
|
.toList();
|
|
}
|
|
|
|
/// Ambil akun berdasarkan tipe (revenue, asset, dll)
|
|
static Future<List<FireflyAccount>> getMirroredAccountsByType(
|
|
String type) async {
|
|
final allAccounts = await getMirroredAccounts();
|
|
return allAccounts.where((account) => account.type == type).toList();
|
|
}
|
|
|
|
/// Ambil akun berdasarkan ID
|
|
static Future<FireflyAccount?> getAccountById(String id) async {
|
|
final allAccounts = await getMirroredAccounts();
|
|
return allAccounts.firstWhere(
|
|
(account) => account.id == id,
|
|
orElse: () => FireflyAccount(id: '', name: '', type: ''),
|
|
);
|
|
}
|
|
|
|
/// Periksa apakah akun sudah pernah di-mirror
|
|
static Future<bool> hasMirroredAccounts() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return prefs.containsKey(_accountsKey);
|
|
}
|
|
|
|
/// Ambil waktu terakhir sync
|
|
static Future<DateTime?> getLastSyncTime() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final timestamp = prefs.getInt(_lastSyncTimeKey);
|
|
return timestamp != null
|
|
? DateTime.fromMillisecondsSinceEpoch(timestamp)
|
|
: null;
|
|
}
|
|
|
|
/// Ambil status sync terakhir
|
|
static Future<bool> getLastSyncStatus() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
return prefs.getBool(_lastSyncKey) ?? false;
|
|
}
|
|
|
|
/// Hapus semua data mirror (untuk testing atau reset)
|
|
static Future<void> clearMirror() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.remove(_accountsKey);
|
|
await prefs.remove(_lastSyncTimeKey);
|
|
await prefs.remove(_lastSyncKey);
|
|
}
|
|
|
|
/// Update mirror dari server dan simpan ke local storage
|
|
static Future<void> updateMirrorFromServer(
|
|
List<FireflyAccount> accounts) async {
|
|
await mirrorAccounts(accounts);
|
|
}
|
|
|
|
/// Dapatkan akun dengan prioritas: mirror terbaru > empty list
|
|
static Future<List<FireflyAccount>> getAccountsWithFallback(
|
|
Future<List<FireflyAccount>> Function() serverFetchFunction,
|
|
) async {
|
|
// Coba ambil dari mirror terlebih dahulu
|
|
final mirroredAccounts = await getMirroredAccounts();
|
|
if (mirroredAccounts.isNotEmpty) {
|
|
return mirroredAccounts;
|
|
}
|
|
|
|
// Jika mirror kosong, coba ambil dari server dan mirror
|
|
try {
|
|
final serverAccounts = await serverFetchFunction();
|
|
if (serverAccounts.isNotEmpty) {
|
|
// Simpan ke mirror jika berhasil ambil dari server
|
|
await updateMirrorFromServer(serverAccounts);
|
|
return serverAccounts;
|
|
}
|
|
} catch (e) {
|
|
print('Gagal mengambil akun dari server: $e');
|
|
}
|
|
|
|
// Jika semua gagal, kembalikan empty list
|
|
return [];
|
|
}
|
|
|
|
/// Format waktu sync untuk display
|
|
static String formatSyncTime(DateTime? syncTime) {
|
|
if (syncTime == null) {
|
|
return 'Belum pernah disinkronisasi';
|
|
}
|
|
|
|
final now = DateTime.now();
|
|
final difference = now.difference(syncTime);
|
|
|
|
if (difference.inMinutes < 1) {
|
|
return 'Baru saja';
|
|
} else if (difference.inHours < 1) {
|
|
final minutes = difference.inMinutes;
|
|
return '$minutes menit yang lalu';
|
|
} else if (difference.inDays < 1) {
|
|
final hours = difference.inHours;
|
|
return '$hours jam yang lalu';
|
|
} else {
|
|
final days = difference.inDays;
|
|
return '$days hari yang lalu';
|
|
}
|
|
}
|
|
|
|
/// Sinkronisasi otomatis jika server tersedia
|
|
static Future<bool> autoSyncIfNeeded(
|
|
Future<List<FireflyAccount>> Function() serverFetchFunction,
|
|
) async {
|
|
try {
|
|
final serverAccounts = await serverFetchFunction();
|
|
if (serverAccounts.isNotEmpty) {
|
|
await updateMirrorFromServer(serverAccounts);
|
|
return true;
|
|
}
|
|
} catch (e) {
|
|
print('Auto sync gagal: $e');
|
|
return false;
|
|
}
|
|
return false;
|
|
}
|
|
}
|