import 'dart:async'; import 'dart:convert'; import 'dart:developer'; import 'package:flutter/material.dart'; import 'package:data_table_2/data_table_2.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:shimmer/shimmer.dart'; import 'package:siopas/models/customer_model.dart'; import 'package:siopas/models/disposal_model.dart'; import 'package:siopas/models/m_asset_status_model.dart'; import 'package:siopas/models/type_peti_model.dart'; import 'package:siopas/models/warehouse_mode.dart'; import 'package:siopas/pages/peminjaman_barang/conn/syncronize.dart'; import 'package:siopas/services/syncronizeAPI.dart'; import 'package:siopas/services/controllerApi.dart'; import 'package:siopas/pages/peminjaman_barang/controller/peminjaman_controller.dart'; import 'package:intl/intl.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:siopas/models/asset_status_model.dart'; import 'package:siopas/providers/asset_status_provider.dart'; import 'package:collection/collection.dart'; import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:flutter_slidable/flutter_slidable.dart'; import '../../models/condition_peti_model.dart'; import '../../widget/loading_shimmer_show.dart'; import '../home/controller/home_controller.dart'; import 'show.dart'; class AssetStatusPage extends StatefulWidget { AssetStatusPage({super.key}); final ControllerHome controllerHome = ControllerHome(); // Declare here @override State createState() => AssetStatusPageState(); } class AssetStatusPageState extends State { String? token; bool loading = true; // Reinit atau Upload Only WarehouseModel? warehouseSqfliteApi; List? typePetiSqfliteApi; List? customerSqfliteApi; PetiAssetModel? petiSqfliteApi; DisposalPetiModel? disposalSqfliteApi; List? _valpeti; // Change this line List? _valwarehouse; List? _valdisposal; // Datatable int _currentPage = 1; int _pageSize = 10; List? _data; List? _petiData; List? _tipePetiData; List? _customerData; List? _warehouseData; Timer? _timer; String _searchQuery = ''; int _peminjamanCount = 0; bool _isLoading = false; @override void initState() { super.initState(); _getUserToken(); // Mengatur _isLoading ke true sebelum tugas dimulai if (mounted) { setState(() { _isLoading = true; }); } Future.wait([ warehouseListAPI(), typePetiListAPI(), customerListAPI(), petiListAPI(), datatablesAssetStatusList(), datatablesPetiList(), datatablesTipePetiList(), datatablesCustomerList(), datatablesWarehouseList(), _initData(), initializeDateFormatting('id_ID', null), ]).then((_) { // Mengatur _isLoading ke false setelah semua tugas selesai if (mounted) { setState(() { _isLoading = false; }); } }); // Inisialisasi _data di sini jika diperlukan _data = []; } void _getUserToken() async { SharedPreferences prefs = await SharedPreferences.getInstance(); if (mounted) { setState(() { token = prefs.getString('token'); }); } } Future _initData() async { try { _peminjamanCount = await widget.controllerHome.getPeminjamanCount(); } catch (error) { print('Error fetching peminjamanCount: $error'); } // ... tambahkan inisialisasi lainnya } // Reinit atau Upload Only ------------------------------------------------------------------------ Future warehouseListAPI() async { if (mounted) { await ControllerApi().fetchWarehouseDataAPI().then((value) { setState(() { _valwarehouse = (value as List) .map((item) => WarehouseModel.fromJson(item)) .toList(); loading = false; }); }); } } Future typePetiListAPI() async { if (mounted) { await ControllerApi().fetchTipePetiDataAPI().then((value) { setState(() { typePetiSqfliteApi = (value as List) .map((item) => TypePetiModel.fromJson(item)) .toList(); loading = false; }); }); } } Future customerListAPI() async { if (mounted) { await ControllerApi().fetchCustomerDataAPI().then((value) { setState(() { customerSqfliteApi = (value as List) .map((item) => CustomerModel.fromJson(item)) .toList(); loading = false; }); }); } } Future petiListAPI() async { if (mounted) { await ControllerApi().fetchPetiDataAPI().then((value) { setState(() { _valpeti = (value as List) .map((item) => PetiAssetModel.fromJson(item)) .toList(); loading = false; }); }); } } Future reinitWarehouseApi() async { EasyLoading.show(status: 'Mengambil data Warehouse...'); List warehouseApiData = await SyncronizationDataAPI().fetchWarehouseFromApi(); await ControllerApi() .deleteAllWarehouseDataAPI(); // Clear existing data in SQLite await ControllerApi() .addAllWarehouseDataAPI(warehouseApiData); // Add new data to SQLite EasyLoading.dismiss(); } Future reinitPetiApi() async { EasyLoading.show(status: 'Mengambil data Peti...'); List petiApiData = await SyncronizationDataAPI().fetchPetiFromApi(); await ControllerApi() .deleteAllPetiDataAPI(); // Clear existing data in SQLite // Menentukan ukuran chunk, misalnya 100 int chunkSize = 100; // Memasukkan data ke SQLite dengan menggunakan chunk await ControllerApi().addAllPetiDataAPI(petiApiData, chunkSize); EasyLoading.dismiss(); } Future reinitCustomerApi() async { EasyLoading.show(status: 'Mengambil data Customer...'); List customerApiData = await SyncronizationDataAPI().fetchCustomerFromApi(); await ControllerApi() .deleteAllCustomerDataAPI(); // Clear existing data in SQLite await ControllerApi() .addAllCustomerDataAPI(customerApiData); // Add new data to SQLite EasyLoading.dismiss(); } Future reinitTypePetiApi() async { EasyLoading.show(status: 'Mengambil data Type Peti...'); List typePetiApiData = await SyncronizationDataAPI().fetchTipePetiFromApi(); await ControllerApi() .deleteAllTipePetiDataAPI(); // Clear existing data in SQLite await ControllerApi() .addAllTipePetiDataAPI(typePetiApiData); // Add new data to SQLite EasyLoading.dismiss(); } Future reinitConditionPetiApi() async { EasyLoading.show(status: 'Mengambil data Condition Peti...'); List conditionPetiApiData = await SyncronizationDataAPI().fetchKondisiPetiFromApi(); await ControllerApi() .deleteAllKondisiPetiDataAPI(); // Clear existing data in SQLite await ControllerApi().addAllKondisiPetiDataAPI( conditionPetiApiData); // Add new data to SQLite EasyLoading.dismiss(); } Future fetchDataFromApiAndSync() async { EasyLoading.show(status: 'Mengambil data dari Server...'); await Future.delayed(Duration(seconds: 3)); try { await syncToMysql(); await reinitWarehouseApi(); await reinitPetiApi(); await reinitCustomerApi(); await reinitConditionPetiApi(); await datatablesAssetStatusList(); EasyLoading.showSuccess('Data berhasil diperbarui'); } catch (e) { EasyLoading.showError('Gagal memperbarui data: $e'); } finally { EasyLoading.dismiss(); } } Future syncToMysql() async { await SyncronizationPeminjamanData() .fetchAllInfo() .then((peminjamanList) async { EasyLoading.show( status: 'Jangan tutup aplikasi. Kami sedang menyinkronkan...'); await Future.delayed(Duration(seconds: 2)); // Tambahkan penanganan pengunggahan bool uploadSuccess = await SyncronizationPeminjamanData() .saveToPeminjamanWith(peminjamanList); // Jika pengunggahan berhasil, hapus data lokal if (uploadSuccess) { await SyncronizationPeminjamanData().deleteAllAssetStatusData(); // Setelah selesai, tampilkan pesan sukses EasyLoading.showSuccess('Berhasil disinkronkan dengan Server'); await datatablesAssetStatusList(); } else { // Tampilkan pesan gagal jika pengunggahan tidak berhasil EasyLoading.showError('Gagal disinkronkan dengan Server'); } }); } // Future syncToMysql() async { // await SyncronizationData().fetchAllInfo().then((assetList) async { // EasyLoading.show(status: 'Don\'t close app. We are syncing...'); // await SyncronizationData().saveToMysqlWith(assetList); // await SyncronizationData().deleteAllAssetStatusData(); // // EasyLoading.showSuccess('Successfully saved to MySQL'); // }); // } Future isInteret() async { await SyncronizationPeminjamanData.isInternet().then((connection) { if (connection) { print("Internet connection available"); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text("Tidak ada koneksi internet"))); } }); } // Datatables ------------------------------------------------------------------------ Future datatablesAssetStatusList() async { if (mounted) { await Controller().fetchAssetStatusLocalController().then((value) { setState(() { _data = (value as List) .map((e) => AssetStatusModel.fromJson(e)) .toList(); loading = false; }); }); } } Future datatablesPetiList() async { if (mounted) { await Controller().fetchPetiData().then((value) { setState(() { _petiData = (value as List) .map((e) => PetiAssetModel.fromJson(e)) .toList(); loading = false; }); }); } } Future datatablesTipePetiList() async { if (mounted) { await Controller().fetchTipePetiData().then((value) { setState(() { _tipePetiData = (value as List) .map((e) => TypePetiModel.fromJson(e)) .toList(); loading = false; }); }); } } Future datatablesCustomerList() async { if (mounted) { await Controller().fetchCustomerData().then((value) { setState(() { _customerData = (value as List) .map((e) => CustomerModel.fromJson(e)) .toList(); loading = false; }); }); } } Future datatablesWarehouseList() async { if (mounted) { await Controller().fetchWarehouseData().then((value) { setState(() { _warehouseData = (value as List) .map((e) => WarehouseModel.fromJson(e)) .toList(); loading = false; }); }); } } String _formatDate(String? date) { if (date != null) { DateTime parsedDate = DateTime.parse(date); String formattedDate = DateFormat('EEEE, dd MMMM yyyy', 'id_ID').format(parsedDate); return formattedDate; } else { return ''; } } List get _filteredData { return _data != null ? _data!.where((item) { // Sesuaikan dengan properti yang ingin Anda cari return item.exit_pic! .toLowerCase() .contains(_searchQuery.toLowerCase()) || _formatDate(item.exit_at.toString()) .toLowerCase() .contains(_searchQuery.toLowerCase()) || _formatDate(item.est_pengembalian.toString()) .toLowerCase() .contains(_searchQuery.toLowerCase()) || (_petiData?.firstWhere((peti) => peti.id == item.peti_id, orElse: () => PetiAssetModel(fix_lot: ''))?.fix_lot ?? '') .toLowerCase() .contains(_searchQuery.toLowerCase()) || (_customerData ?.firstWhere( (customer) => customer.id == item.customer_id, orElse: () => CustomerModel(name: '')) ?.name ?? '') .toLowerCase() .contains(_searchQuery.toLowerCase()) || (_warehouseData ?.firstWhere( (warehouse) => warehouse.id == item.warehouse_id, orElse: () => WarehouseModel(name: '')) ?.name ?? '') .toLowerCase() .contains(_searchQuery.toLowerCase()); }).toList() : []; } @override Widget build(BuildContext context) { // Add this function outside the build method // void showSyncDialog(BuildContext context) { // showDialog( // context: context, // builder: (BuildContext context) { // return Dialog( // // Dialog shape and style // shape: RoundedRectangleBorder( // borderRadius: BorderRadius.circular(16), // ), // backgroundColor: Colors.grey[100], // elevation: 0, // // Dialog content // child: Column( // mainAxisSize: MainAxisSize.min, // children: [ // // Dialog title with close button // Container( // width: double.infinity, // color: Colors.indigo[700], // Indigo background // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Padding( // padding: const EdgeInsets.all(16.0), // child: Text( // "Sync Server Peminjaman", // style: TextStyle( // color: Colors.white, // fontWeight: FontWeight.bold, // fontSize: 16.0, // ), // ), // ), // IconButton( // icon: Icon( // Icons.close, // color: Colors.white, // ), // onPressed: () { // Navigator.pop(context); // Close dialog // }, // ), // ], // ), // ), // // Divider // Divider( // height: 1, // thickness: 1, // color: Colors.black, // Black divider // ), // // Re-init Button // Container( // width: double.infinity, // child: TextButton( // onPressed: () { // Navigator.pop(context); // Close dialog // fetchDataFromApiAndSync(); // }, // child: Text( // "Upload + Download", // style: TextStyle( // color: Colors.black, // fontSize: 16.0, // fontFamily: 'Poppins', // ), // ), // ), // ), // ], // ), // ); // }, // ); // } return WillPopScope( onWillPop: () async { // Mencegah kembali ke halaman sebelumnya return false; }, child: DefaultTabController( length: 1, child: Scaffold( appBar: appBarPeminjaman(context), body: _isLoading ? Column( children: [ // shimmerSearch(), Expanded( child: ListView.builder( itemCount: 4, // Set the number of shimmer cards based on your data count itemBuilder: (context, index) { return ShimmerLoadingAssetStatusCard(); }, ), ), ], ) : bodyPeminjaman(), bottomNavigationBar: bottomAppBar(context), ), ), ); } BottomAppBar bottomAppBar(BuildContext context) { return BottomAppBar( color: Color.fromARGB(255, 5, 28, 158), // Warna latar belakang child: Container( height: 65.0, child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ InkWell( customBorder: CircleBorder(), onTap: () { // Aksi ketika ikon diklik Navigator.pushNamed(context, '/peminjaman-barang/create'); }, child: Container( width: 45, height: 45, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.greenAccent[700], ), child: Icon( Icons.add, size: 30, color: Colors.white, ), ), ), ], ), ), ); } Column bodyPeminjaman() { return Column( children: [ Expanded( child: TabBarView( children: [ SingleChildScrollView( child: Column( children: _filteredData.isNotEmpty ? _filteredData.asMap().entries.map((entry) { final index = entry.key + 1; final item = entry.value; return AssetStatusCard( assetStatus: item, petiData: _petiData ?? [], tipePetiData: _tipePetiData ?? [], customerData: _customerData ?? [], warehouseData: _warehouseData ?? [], index: index, ); }).toList() // : [Text('No results')], : [ Center( child: Column( children: [ Image.asset( 'assets/item/empty.png', width: 250, // Set the width as needed height: 250, // Set the height as needed ), Text( 'Tidak ada data ditemukan', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, ), ), ], ), ), ], ), ), ], ), ), ], ); } AppBar appBarPeminjaman(BuildContext context) { Future peminjamanCount = widget.controllerHome.getPeminjamanCount(); return AppBar( backgroundColor: Colors.indigo[700], elevation: 0, title: Text('Data Peti Out', style: TextStyle( fontSize: 16, )), leading: IconButton( icon: Icon(Icons.arrow_back, color: Colors.white), onPressed: () { Navigator.pushNamed(context, '/home'); }, ), bottom: TabBar( indicator: BoxDecoration( color: Color.fromARGB(255, 255, 165, 9), ), tabs: [ Tab( height: 65, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(0), border: Border.all(color: Colors.grey, width: 1.0), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: TextField( style: TextStyle(fontSize: 18), decoration: InputDecoration( hintText: 'Masukkan data pencarian...', prefixIcon: Icon(Icons.search), border: InputBorder.none, contentPadding: EdgeInsets.all(10), labelStyle: TextStyle( color: Colors.grey, fontSize: 12, ), hintStyle: TextStyle( color: Colors.grey, fontSize: 12, ), ), onChanged: (value) { setState(() { _searchQuery = value.isNotEmpty ? value : ''; // Memperbarui dengan null jika value kosong }); }, ), ), Text( 'Total: $_peminjamanCount', style: TextStyle(color: Colors.black), ), ], ), ), ), ], ), ); } } class AssetStatusCard extends StatelessWidget { final AssetStatusModel assetStatus; final List petiData; final List tipePetiData; final List customerData; final List warehouseData; final int index; // Tambahkan parameter nomor urutan AssetStatusCard({ required this.assetStatus, required this.petiData, required this.tipePetiData, required this.customerData, required this.warehouseData, required this.index, // Inisialisasi parameter nomor urutan }); @override Widget build(BuildContext context) { PetiAssetModel? petiSqfliteApi = petiData.firstWhereOrNull( (peti) => peti.id == assetStatus.peti_id, ); TypePetiModel? tipePetiSqfliteApi = tipePetiData.firstWhereOrNull( (tipePeti) => tipePeti.id == petiSqfliteApi?.tipe_peti_id, ); CustomerModel? customerSqfliteApi = customerData.firstWhereOrNull( (customer) => customer.id == assetStatus.customer_id, ); WarehouseModel? warehouseSqfliteApi = warehouseData.firstWhereOrNull( (warehouse) => warehouse.id == assetStatus.warehouse_id, ); // WarehouseModel? warehouseTujuanSqfliteApi = warehouseData.firstWhereOrNull( // (warehouse) => warehouse.id == assetStatus.exit_warehouse, // ); String _formatDate(String? date) { if (date != null) { DateTime parsedDate = DateTime.parse(date); String formattedDate = DateFormat('EEEE, dd MMMM yyyy', 'id_ID').format(parsedDate); return formattedDate; } else { return ''; } } Future _deletePeminjaman() async { try { // Panggil fungsi untuk menghapus peminjaman berdasarkan ID await Controller().deletePeminjamanById(assetStatus.id.toString()); // Navigasi kembali ke halaman sebelumnya atau halaman yang sesuai Navigator.pushReplacementNamed(context, '/peminjaman-barang'); } catch (e) { // Tangani kesalahan jika terjadi print('Gagal menghapus peminjaman: $e'); } } Future _showDeleteConfirmationDialog() async { return showDialog( context: context, builder: (BuildContext context) { return AlertDialog( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16.0), ), title: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon( Icons.info, color: Colors.blue, ), SizedBox(width: 8), Text( 'Konfirmasi Hapus', style: TextStyle( fontSize: 18, ), ), ], ), IconButton( icon: Icon( Icons.close, color: Colors.black54, ), onPressed: () { Navigator.of(context).pop(); }, ), ], ), content: SingleChildScrollView( child: ListBody( children: [ Text( 'Anda yakin ingin menghapus peminjaman ini? ${petiSqfliteApi!.fix_lot.toString()}', style: TextStyle( fontSize: 16, ), ), ], ), ), actions: [ Container( margin: EdgeInsets.only(right: 3.0), child: ElevatedButton( child: Text('Hapus'), onPressed: () { // Panggil fungsi untuk menghapus peminjaman berdasarkan ID _deletePeminjaman(); // Navigator.pushNamed(context, '/peminjaman-barang'); EasyLoading.showSuccess( 'Berhasil menghapus data peminjaman'); }, style: ElevatedButton.styleFrom( primary: Colors.red, ), ), ), ], ); }, ); } return Slidable( key: Key(assetStatus.id.toString()), endActionPane: ActionPane( motion: ScrollMotion(), children: [ SlidableAction( onPressed: (context) { _showDeleteConfirmationDialog(); }, backgroundColor: Color(0xFFFE4A49), foregroundColor: Colors.white, icon: Icons.delete, label: 'Hapus', ), ], ), child: GestureDetector( onTap: () { // Tindakan yang dilakukan saat card diklik if (assetStatus != null) { Navigator.push( context, MaterialPageRoute( builder: (context) => DetailPeminjamanBarangPage( peminjamanId: assetStatus.id.toString(), ), ), ); } }, child: Card( color: Colors.white60, elevation: 0.0, shape: RoundedRectangleBorder( side: BorderSide(color: Colors.grey, width: 1.0), ), child: Padding( padding: const EdgeInsets.only( top: 8.0, bottom: 8.0, left: 16.0, right: 16.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildAvatarAndIndex(index), Divider(), _buildInfoRow( 'Nama Customer:', '${customerSqfliteApi?.name ?? '-'}', 'PIC/PJ:', '${assetStatus.exit_pic ?? '-'}', 13), _buildInfoRow( 'Tanggal Peminjaman:', '${_formatDate(assetStatus.exit_at.toString())}', 'Estimasi Pengembalian:', '${_formatDate(assetStatus.est_pengembalian.toString())}', 13), _buildInfoRow('Gudang:', '${warehouseSqfliteApi?.name ?? '-'}', '', '', 13), ], ), ), ), ), ); } Widget _buildAvatarAndIndex(int index) { PetiAssetModel? petiSqfliteApi = petiData.firstWhereOrNull( (peti) => peti.id == assetStatus.peti_id, ); return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildAvatar(index), Expanded( child: Padding( padding: const EdgeInsets.only( left: 8.0, top: 8.0, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '${petiSqfliteApi?.fix_lot ?? '-'}', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 14.5, ), ), ], ), ), ), ], ); } Widget _buildAvatar(int index) { return Container( child: CircleAvatar( radius: 11, backgroundColor: Colors.indigo[700], child: Text( '$index', style: TextStyle( fontWeight: FontWeight.bold, fontSize: 13, color: Colors.white, ), ), ), ); } Widget _buildInfoRow(String title1, String content1, String title2, String content2, double fontSize) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title1, style: TextStyle( fontWeight: FontWeight.bold, fontSize: fontSize, ), ), SizedBox(height: 3), Text( content1, style: TextStyle( fontSize: fontSize - 0.5, // Mengurangkan ukuran font agar cocok dengan judul ), ), ], ), ), SizedBox(width: 10), // Memberi jarak antara dua kolom Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( title2, style: TextStyle( fontWeight: FontWeight.bold, fontSize: fontSize, ), ), SizedBox(height: 3), Text( content2, style: TextStyle( fontSize: fontSize - 0.5, // Mengurangkan ukuran font agar cocok dengan judul ), ), ], ), ), ], ); } }