// lib/screens/transaction_screen.dart import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../models/firefly_account.dart'; import '../services/firefly_api_service.dart'; import '../services/account_mirror_service.dart'; import '../services/account_cache_service.dart'; class TransactionScreen extends StatefulWidget { const TransactionScreen({super.key}); @override State createState() => _TransactionScreenState(); } class _TransactionScreenState extends State { List _revenueAccounts = []; List _assetAccounts = []; FireflyAccount? _selectedSourceAccount; FireflyAccount? _selectedDestinationAccount; bool _isLoading = false; String _message = ''; String? _fireflyUrl; String? _accessToken; @override void initState() { super.initState(); _loadCredentialsAndAccounts(); } /// Memuat kredensial dari shared preferences dan kemudian memuat akun. Future _loadCredentialsAndAccounts() async { final prefs = await SharedPreferences.getInstance(); final url = prefs.getString('firefly_url'); final token = prefs.getString('firefly_token'); if (url == null || token == null || url.isEmpty || token.isEmpty) { setState(() { _message = 'Kredensial Firefly III belum dikonfigurasi. Silakan atur di menu konfigurasi.'; }); return; } setState(() { _fireflyUrl = url; _accessToken = token; }); // Jika kredensial ada, lanjutkan untuk memuat akun dengan fallback mekanisme _loadAccountsWithFallback(); } /// Memuat daftar akun sumber (revenue) dan tujuan (asset) dari API dengan fallback. Future _loadAccountsWithFallback() async { if (_fireflyUrl == null || _accessToken == null) { return; } setState(() { _isLoading = true; _message = 'Memuat daftar akun...'; }); try { // Mengambil akun revenue dengan fallback final revenueAccounts = await FireflyApiService.fetchAccounts( baseUrl: _fireflyUrl!, accessToken: _accessToken!, type: 'revenue', ); // Simpan ke cache await AccountCacheService.updateAccountsFromServer( revenueAccounts.map((account) => account.toJson()).toList()); // Mengambil akun asset dengan fallback final assetAccounts = await FireflyApiService.fetchAccounts( baseUrl: _fireflyUrl!, accessToken: _accessToken!, type: 'asset', ); // Simpan ke cache await AccountCacheService.updateAccountsFromServer( assetAccounts.map((account) => account.toJson()).toList()); setState(() { _revenueAccounts = revenueAccounts; _assetAccounts = assetAccounts; // Tidak lagi menggunakan default account mapping _message = 'Daftar akun berhasil dimuat.'; }); } catch (error) { // Jika gagal dari server, coba load dari cache try { final cachedRevenueAccounts = await AccountCacheService.getLastKnownGoodAccounts().then( (cached) => cached .where((json) => (json['attributes'] as Map)['type'] == 'revenue') .map((json) => FireflyAccount.fromJson(json)) .toList()); final cachedAssetAccounts = await AccountCacheService .getLastKnownGoodAccounts() .then((cached) => cached .where((json) => (json['attributes'] as Map)['type'] == 'asset') .map((json) => FireflyAccount.fromJson(json)) .toList()); setState(() { _revenueAccounts = cachedRevenueAccounts; _assetAccounts = cachedAssetAccounts; // Coba set default account jika tersedia _setDefaultAccounts(); _message = 'Akun dimuat dari cache offline.'; }); } catch (cacheError) { setState(() { _message = 'Gagal memuat akun: $error, dan cache juga tidak tersedia: $cacheError'; }); } } finally { setState(() { _isLoading = false; }); } } /// Tidak lagi menggunakan default account mapping Future _setDefaultAccounts() async { // Fitur default account mapping telah dihapus } /// Tidak lagi menyimpan default account mapping Future _saveAccountMapping() async { // Fitur default account mapping telah dihapus } /// Mengirim transaksi dummy menggunakan akun yang dipilih. Future _submitTransaction() async { if (_fireflyUrl == null || _accessToken == null) { setState(() { _message = 'Kredensial tidak lengkap.'; return; }); } if (_selectedSourceAccount == null || _selectedDestinationAccount == null) { setState(() { _message = 'Silakan pilih akun sumber dan tujuan.'; }); return; } setState(() { _isLoading = true; _message = 'Mengirim transaksi...'; }); try { final success = await FireflyApiService.submitDummyTransaction( baseUrl: _fireflyUrl!, accessToken: _accessToken!, sourceId: _selectedSourceAccount!.id, destinationId: _selectedDestinationAccount!.id, type: 'deposit', // Sesuaikan dengan logika bisnis description: 'Transaksi Dummy dari Aplikasi Flutter', ); // Simpan mapping akun jika transaksi berhasil if (success != null) { await _saveAccountMapping(); } setState(() { _message = success != null ? 'Transaksi berhasil dikirim!' : 'Gagal mengirim transaksi. Periksa log.'; }); } catch (error) { setState(() { _message = 'Terjadi kesalahan: $error'; }); } finally { setState(() { _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Kirim Transaksi ke Firefly III'), actions: [ IconButton( icon: const Icon(Icons.settings), onPressed: () { // Navigasi ke ConfigScreen Navigator.pushNamed(context, '/config'); }, ), ], ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Pesan status if (_message.isNotEmpty) Text(_message, style: TextStyle( color: _message.contains('berhasil') ? Colors.green : (_message.contains('belum') || _message.contains('tidak')) ? Colors.orange : Colors.red)), const SizedBox(height: 10), if (_fireflyUrl != null && _accessToken != null) ...[ // Dropdown untuk Akun Sumber (Revenue) const Text('Pilih Akun Sumber (Revenue):', style: TextStyle(fontWeight: FontWeight.bold)), DropdownButton( isExpanded: true, hint: const Text('Pilih akun sumber'), value: _selectedSourceAccount, items: _revenueAccounts.map((account) { return DropdownMenuItem( value: account, child: Text(account.name), ); }).toList(), onChanged: (account) { setState(() { _selectedSourceAccount = account; // Simpan mapping ketika user memilih akun if (account != null) { _saveAccountMapping(); } }); }, ), const SizedBox(height: 20), // Dropdown untuk Akun Tujuan (Asset) const Text('Pilih Akun Tujuan (Asset):', style: TextStyle(fontWeight: FontWeight.bold)), DropdownButton( isExpanded: true, hint: const Text('Pilih akun tujuan'), value: _selectedDestinationAccount, items: _assetAccounts.map((account) { return DropdownMenuItem( value: account, child: Text(account.name), ); }).toList(), onChanged: (account) { setState(() { _selectedDestinationAccount = account; // Simpan mapping ketika user memilih akun if (account != null) { _saveAccountMapping(); } }); }, ), const SizedBox(height: 20), // Tombol untuk memuat ulang akun ElevatedButton.icon( onPressed: _isLoading ? null : _loadAccountsWithFallback, icon: const Icon(Icons.refresh), label: const Text('Muat Ulang Akun'), ), const SizedBox(height: 10), // Tombol untuk mengirim transaksi ElevatedButton.icon( onPressed: _isLoading ? null : _submitTransaction, icon: const Icon(Icons.send), label: const Text('Kirim Transaksi Dummy'), ), const SizedBox(height: 20), ], // Status dan pesan loading if (_isLoading) const Row( mainAxisAlignment: MainAxisAlignment.center, children: [ CircularProgressIndicator(), SizedBox(width: 10), Text('Sedang diproses...'), ], ), ], ), ), ); } }