diff --git a/.gitignore b/.gitignore index 29a3a50..3c1b3ac 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,6 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +# Deprecated files +/deprecated/ diff --git a/INSTRUCTIONS_LOGO.md b/INSTRUCTIONS_LOGO.md deleted file mode 100644 index 92459e7..0000000 --- a/INSTRUCTIONS_LOGO.md +++ /dev/null @@ -1,23 +0,0 @@ -# Instruksi untuk menambahkan logo toko ke aplikasi: - -1. Tambahkan file gambar logo ke folder `assets/images/` dengan nama `store_logo.png` - -2. Tambahkan path ke file `pubspec.yaml` agar file gambar tersebut tersedia di aplikasi: - ```yaml - flutter: - assets: - - assets/images/ - ``` - -3. Untuk menyimpan path logo ke shared preferences, panggil fungsi: - ```dart - import 'package:cashumit/utils/store_logo_utils.dart'; - - // Simpan path logo - await saveStoreLogoPath('assets/images/store_logo.png'); - - // Hapus path logo jika diperlukan - await removeStoreLogoPath(); - ``` - -4. Untuk menguji pencetakan logo, pastikan printer thermal mendukung pencetakan gambar. \ No newline at end of file diff --git a/assets/images/store_logo.png b/assets/images/store_logo.png index 5371d4a..5d2ef65 100644 Binary files a/assets/images/store_logo.png and b/assets/images/store_logo.png differ diff --git a/lib/main.dart b/lib/main.dart index 6a56ea0..6545acb 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,8 @@ import 'package:cashumit/screens/transaction_screen.dart'; import 'package:flutter/material.dart'; import 'package:cashumit/screens/receipt_screen.dart'; import 'package:cashumit/utils/store_logo_utils.dart'; +import 'package:provider/provider.dart'; +import 'package:cashumit/providers/receipt_provider.dart'; void main() async { // Ensure WidgetsFlutterBinding is initialized for async operations @@ -11,7 +13,14 @@ void main() async { // Initialize the store logo from asset await copyAndSaveStoreLogoFromAsset('assets/images/store_logo.png'); - runApp(const MyApp()); + runApp( + MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => ReceiptProvider()), + ], + child: const MyApp(), + ), + ); } class MyApp extends StatelessWidget { diff --git a/lib/widgets/store_disclaimer.dart b/lib/widgets/store_disclaimer.dart index 85ac1d7..273cf3f 100644 --- a/lib/widgets/store_disclaimer.dart +++ b/lib/widgets/store_disclaimer.dart @@ -22,6 +22,13 @@ class _StoreDisclaimerState extends State { _loadDisclaimerText(); } + @override + void didUpdateWidget(covariant StoreDisclaimer oldWidget) { + super.didUpdateWidget(oldWidget); + // Memuat ulang teks ketika widget diupdate + _loadDisclaimerText(); + } + /// Memuat teks disclaimer dari shared preferences Future _loadDisclaimerText() async { final prefs = await SharedPreferences.getInstance(); diff --git a/lib/widgets/thank_you_pantun.dart b/lib/widgets/thank_you_pantun.dart index 7204498..2cb951a 100644 --- a/lib/widgets/thank_you_pantun.dart +++ b/lib/widgets/thank_you_pantun.dart @@ -14,9 +14,9 @@ class ThankYouPantun extends StatefulWidget { class _ThankYouPantunState extends State { String _thankYouText = '*** TERIMA KASIH ***'; - String _pantunText = 'Belanja di toko kami, hemat dan nyaman,\n' - 'Dengan penuh semangat, kami siap melayani,\n' - 'Harapan kami, Anda selalu puas,\n' + String _pantunText = 'Belanja di toko kami, hemat dan nyaman,\\n' + 'Dengan penuh semangat, kami siap melayani,\\n' + 'Harapan kami, Anda selalu puas,\\n' 'Sampai jumpa lagi, selamat tinggal.'; @override @@ -25,6 +25,13 @@ class _ThankYouPantunState extends State { _loadThankYouText(); } + @override + void didUpdateWidget(covariant ThankYouPantun oldWidget) { + super.didUpdateWidget(oldWidget); + // Memuat ulang teks ketika widget diupdate + _loadThankYouText(); + } + /// Memuat teks terima kasih dan pantun dari shared preferences Future _loadThankYouText() async { final prefs = await SharedPreferences.getInstance(); @@ -34,9 +41,9 @@ class _ThankYouPantunState extends State { if (mounted) { setState(() { _thankYouText = savedThankYou ?? '*** TERIMA KASIH ***'; - _pantunText = savedPantun ?? 'Belanja di toko kami, hemat dan nyaman,\n' - 'Dengan penuh semangat, kami siap melayani,\n' - 'Harapan kami, Anda selalu puas,\n' + _pantunText = savedPantun ?? 'Belanja di toko kami, hemat dan nyaman,\\n' + 'Dengan penuh semangat, kami siap melayani,\\n' + 'Harapan kami, Anda selalu puas,\\n' 'Sampai jumpa lagi, selamat tinggal.'; }); } diff --git a/pubspec.lock b/pubspec.lock index ce4af8b..ff4392e 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: archive - sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d url: "https://pub.dev" source: hosted - version: "4.0.7" + version: "3.6.1" async: dependency: transitive description: @@ -25,14 +25,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.9" - bidi: - dependency: transitive - description: - name: bidi - sha256: "77f475165e94b261745cf1032c751e2032b8ed92ccb2bf5716036db79320637d" - url: "https://pub.dev" - source: hosted - version: "2.0.13" bluetooth_print: dependency: "direct main" description: @@ -96,6 +88,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.6" + csslib: + dependency: transitive + description: + name: csslib + sha256: "09bad715f418841f976c77db72d5398dc1253c21fb9c0c7f0b0b985860b2d58e" + url: "https://pub.dev" + source: hosted + version: "1.0.2" cupertino_icons: dependency: "direct main" description: @@ -165,6 +165,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_esc_pos_utils: + dependency: "direct main" + description: + name: flutter_esc_pos_utils + sha256: dd0dbd9738c07ea9a6b078f5db18feb2d5d970b4de0ce34427d66665f639eaec + url: "https://pub.dev" + source: hosted + version: "0.0.5" flutter_lints: dependency: "direct dev" description: @@ -199,6 +207,14 @@ packages: description: flutter source: sdk version: "0.0.0" + gbk_codec: + dependency: transitive + description: + name: gbk_codec + sha256: "3af5311fc9393115e3650ae6023862adf998051a804a08fb804f042724999f61" + url: "https://pub.dev" + source: hosted + version: "0.4.0" google_fonts: dependency: "direct main" description: @@ -207,6 +223,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.3.0" + hex: + dependency: transitive + description: + name: hex + sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + html: + dependency: transitive + description: + name: html + sha256: "6d1264f2dffa1b1101c25a91dff0dc2daee4c18e87cd8538729773c073dbf602" + url: "https://pub.dev" + source: hosted + version: "0.15.6" http: dependency: "direct main" description: @@ -232,13 +264,13 @@ packages: source: hosted version: "4.0.2" image: - dependency: transitive + dependency: "direct main" description: name: image - sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + sha256: "8e9d133755c3e84c73288363e6343157c383a0c6c56fc51afcc5d4d7180306d6" url: "https://pub.dev" source: hosted - version: "4.5.4" + version: "3.3.0" image_picker: dependency: "direct main" description: @@ -383,6 +415,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" open_file: dependency: "direct main" description: @@ -515,10 +555,10 @@ packages: dependency: "direct main" description: name: pdf - sha256: "28eacad99bffcce2e05bba24e50153890ad0255294f4dd78a17075a2ba5c8416" + sha256: "10659b915e65832b106f6d1d213e09b789cc1f24bf282ee911e49db35b96be4d" url: "https://pub.dev" source: hosted - version: "3.11.3" + version: "3.8.4" petitparser: dependency: transitive description: @@ -543,14 +583,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.8" - posix: - dependency: transitive + provider: + dependency: "direct main" description: - name: posix - sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" url: "https://pub.dev" source: hosted - version: "6.0.3" + version: "6.1.5+1" qr: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index d98d103..b11744b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -49,6 +49,7 @@ dependencies: flutter_speed_dial: ^7.0.0 image_picker: ^1.0.0 webview_flutter: ^4.10.0 + provider: ^6.1.1 dev_dependencies: flutter_test: diff --git a/test_firefly_integration.dart b/test_firefly_integration.dart deleted file mode 100644 index 3f461c9..0000000 --- a/test_firefly_integration.dart +++ /dev/null @@ -1,158 +0,0 @@ -import 'dart:io'; -import 'dart:convert'; -import 'package:http/http.dart' as http; - -/// Script untuk menguji integrasi dengan Firefly III API -/// Menjalankan beberapa operasi dasar: -/// 1. Menguji koneksi ke instance Firefly III -/// 2. Menguji autentikasi dengan token -/// 3. Mengambil daftar akun -/// 4. Mengirim transaksi dummy - -void main() async { - // Konfigurasi - Ganti dengan nilai yang sesuai untuk instance Firefly III Anda - const String baseUrl = 'http://192.168.1.100:8080'; // Contoh URL - const String accessToken = 'your_access_token_here'; // Contoh token - const String sourceAccountId = '1'; // ID akun sumber (revenue) - const String destinationAccountId = '2'; // ID akun tujuan (asset) - - print('=== MENGUJI INTEGRASI FIREFLY III ===\n'); - - // 1. Menguji koneksi - print('1. Menguji koneksi ke Firefly III...'); - try { - final connectivityResponse = await http.get(Uri.parse('$baseUrl/api/v1/about')); - if (connectivityResponse.statusCode == 200) { - print(' ✓ Koneksi berhasil'); - } else { - print(' ✗ Koneksi gagal (Status code: ${connectivityResponse.statusCode})'); - return; - } - } catch (e) { - print(' ✗ Koneksi gagal dengan error: $e'); - return; - } - - // 2. Menguji autentikasi - print('\n2. Menguji autentikasi dengan token...'); - try { - final authResponse = await http.get( - Uri.parse('$baseUrl/api/v1/about/user'), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Accept': 'application/json', - }, - ); - if (authResponse.statusCode == 200) { - print(' ✓ Autentikasi berhasil'); - } else { - print(' ✗ Autentikasi gagal (Status code: ${authResponse.statusCode})'); - print(' Response body: ${authResponse.body}'); - return; - } - } catch (e) { - print(' ✗ Autentikasi gagal dengan error: $e'); - return; - } - - // 3. Mengambil daftar akun - print('\n3. Mengambil daftar akun...'); - try { - final accountsResponse = await http.get( - Uri.parse('$baseUrl/api/v1/accounts'), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Accept': 'application/json', - }, - ); - if (accountsResponse.statusCode == 200) { - final accountsData = json.decode(accountsResponse.body); - if (accountsData is Map && accountsData.containsKey('data')) { - final accounts = accountsData['data'] as List; - print(' ✓ Berhasil mengambil ${accounts.length} akun'); - - // Tampilkan 3 akun pertama - print(' Contoh akun:'); - for (int i = 0; i < accounts.length && i < 3; i++) { - final account = accounts[i]; - if (account is Map && account.containsKey('id') && account.containsKey('attributes')) { - final attributes = account['attributes']; - if (attributes is Map && attributes.containsKey('name') && attributes.containsKey('type')) { - print(' - ID: ${account['id']}, Nama: ${attributes['name']}, Tipe: ${attributes['type']}'); - } - } - } - } else { - print(' ✗ Format respons akun tidak sesuai harapan'); - return; - } - } else { - print(' ✗ Gagal mengambil akun (Status code: ${accountsResponse.statusCode})'); - print(' Response body: ${accountsResponse.body}'); - return; - } - } catch (e) { - print(' ✗ Gagal mengambil akun dengan error: $e'); - return; - } - - // 4. Mengirim transaksi dummy - print('\n4. Mengirim transaksi dummy...'); - try { - final transactionPayload = jsonEncode({ - "transactions": [ - { - "type": "deposit", - "date": "2025-08-21", - "amount": "50.00", - "description": "Transaksi Dummy via Test Script", - "source_id": sourceAccountId, - "destination_id": destinationAccountId, - } - ] - }); - - final transactionResponse = await http.post( - Uri.parse('$baseUrl/api/v1/transactions'), - headers: { - 'Authorization': 'Bearer $accessToken', - 'Accept': 'application/json', - 'Content-Type': 'application/json', - }, - body: transactionPayload, - ); - - if (transactionResponse.statusCode == 200 || transactionResponse.statusCode == 201) { - print(' ✓ Transaksi berhasil dikirim'); - - // Coba parse transaction ID - try { - final transactionData = json.decode(transactionResponse.body); - if (transactionData is Map && - transactionData.containsKey('data') && - transactionData['data'] is List && - transactionData['data'].isNotEmpty) { - - final firstTransaction = transactionData['data'][0]; - if (firstTransaction is Map && firstTransaction.containsKey('transaction_id')) { - print(' Transaction ID: ${firstTransaction['transaction_id']}'); - } else if (firstTransaction is Map && firstTransaction.containsKey('id')) { - print(' Transaction ID: ${firstTransaction['id']}'); - } - } - } catch (e) { - print(' Tidak dapat mem-parsing transaction ID: $e'); - } - } else { - print(' ✗ Gagal mengirim transaksi (Status code: ${transactionResponse.statusCode})'); - print(' Response body: ${transactionResponse.body}'); - return; - } - } catch (e) { - print(' ✗ Gagal mengirim transaksi dengan error: $e'); - return; - } - - print('\n=== PENGUJIAN SELESAI ==='); - print('Semua pengujian berhasil! Integrasi dengan Firefly III berfungsi dengan baik.'); -} \ No newline at end of file