import 'dart:convert'; import 'package:dropdown_search/dropdown_search.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:intl/intl.dart'; import 'package:loading_animation_widget/loading_animation_widget.dart'; import 'package:provider/provider.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:intl/date_symbol_data_local.dart'; import 'package:collection/collection.dart'; import 'package:uuid/uuid.dart'; import '../../models/asset_status_model.dart'; import '../../models/customer_model.dart'; import '../../models/disposal_model.dart'; import '../../models/m_asset_status_model.dart'; import '../../models/type_peti_model.dart'; import '../../models/user_model.dart'; import '../../models/warehouse_mode.dart'; import '../../providers/auth_provider.dart'; import '../../services/controllerApi.dart'; import 'conn/syncronize.dart'; import 'controller/peminjaman_controller.dart'; class CreateFinishPeminjaman extends StatefulWidget { final List temporaryDataList; CreateFinishPeminjaman({required this.temporaryDataList}); @override _CreateFinishPeminjamanState createState() => _CreateFinishPeminjamanState(); } class _CreateFinishPeminjamanState extends State { String? token; // List? customerSqfliteApi; PetiAssetModel? petiSqfliteApi; WarehouseModel? warehouseSqfliteApi; WarehouseModel? warehouseTujuanSqfliteApi; DisposalPetiModel? disposalSqfliteApi; CustomerModel? customerSqfliteApi; List? _valpeti; // Change this line List? _valwarehouse; List? _valwarehouseTujuan; List? _valcustomer; List? _valdisposal; List _allPetiList = []; List _unrestrictedPetiList = []; List _filteredPetiList = []; bool isQRCodeScanned = false; String searchText = ''; PetiAssetModel? selectedPeti; TextEditingController searchBoxController = TextEditingController(); TextEditingController _exit_atController = TextEditingController(); TextEditingController _est_pengembalianController = TextEditingController(); TextEditingController _penanggungJawabController = TextEditingController(); TextEditingController _warehouseController = TextEditingController(); List selectedPetiList = []; List? _data; List temporaryDataList = []; final _formKey = GlobalKey(); bool loading = true; late Future _dataFuture; // bool _isLoading = false; @override void initState() { super.initState(); // Set loading ke true pada awalnya if (mounted) { if (mounted) { setState(() { loading = false; }); } } _dataFuture = fetchData(); } Future fetchData() async { await _getUserToken(); await warehouseListAPI(); await petiListAPI(); await disposalListAPI(); await customerListAPI(); initializeDateFormatting('id_ID', null); // Tandai bahwa proses loading telah selesai if (mounted) { setState(() { loading = false; }); } } Future _getUserToken() async { SharedPreferences prefs = await SharedPreferences.getInstance(); if (mounted) { setState(() { token = prefs.getString('token'); loading = false; }); } } void addDataToDropdown(PetiAssetModel peti) { if (mounted) { setState(() { selectedPetiList.add(peti); }); } } Future disposalListAPI() async { if (mounted) { await ControllerApi().fetchDisposalDataAPI().then((value) { setState(() { _valdisposal = (value as List) .map((item) => DisposalPetiModel.fromJson(item)) .toList(); loading = false; }); }); } } Future customerListAPI() async { if (mounted) { await ControllerApi().fetchCustomerDataAPI().then((value) { setState(() { _valcustomer = (value as List) .map((item) => CustomerModel.fromJson(item)) .toList(); loading = false; }); }); } } Future warehouseListAPI() async { if (mounted) { await ControllerApi().fetchWarehouseDataAPI().then((value) { setState(() { _valwarehouse = (value as List) .map((item) => WarehouseModel.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 isInteret() async { await SyncronizationPeminjamanData.isInternet().then((connection) { if (connection) { print("Internet connection available"); } else { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("No Internet"))); } }); } @override Widget build(BuildContext context) { AuthProvider authProvider = Provider.of(context, listen: false); UserModel user = authProvider.user; // WarehouseModel? warehouseSqfliteApi = _valwarehouse?.firstWhereOrNull( // (warehouse) => warehouse.id == _valwarehouse?.first.id, // ); var uuid = Uuid(); DateTime? parseDateTime(String? dateTimeString) { if (dateTimeString == null || dateTimeString.isEmpty) { return null; } try { return DateTime.parse(dateTimeString); } catch (e) { print('Error parsing DateTime: $e'); return null; } } Future removePetiFromSharedPreferences( PetiAssetModel removedPeti) async { SharedPreferences prefs = await SharedPreferences.getInstance(); // Retrieve existing data from SharedPreferences List? petiListJson = prefs.getStringList('selectedPetiList'); if (petiListJson != null) { // Convert JSON strings to PetiAssetModel objects List existingPetiList = petiListJson .map((petiJson) => PetiAssetModel.fromJson(json.decode(petiJson))) .toList(); // Remove the specified peti from the list existingPetiList.removeWhere((peti) => peti.id == removedPeti.id); // Save the updated list back to SharedPreferences List updatedPetiListJson = existingPetiList.map((peti) => json.encode(peti.toJson())).toList(); prefs.setStringList('selectedPetiList', updatedPetiListJson); } } void removePeti(int index) async { PetiAssetModel? selectedPeti = selectedPetiList != null ? selectedPetiList[index] : null; print('Before Remove: ${selectedPeti?.fix_lot}'); if (index >= 0 && index < selectedPetiList.length) { if (mounted) { PetiAssetModel removedPeti = selectedPetiList[index]; // Remove the data with the specified peti_id from temporaryDataList temporaryDataList .removeWhere((data) => data.peti_id == removedPeti.id); selectedPetiList.removeAt(index); await removePetiFromSharedPreferences(removedPeti); print('After Remove: ${selectedPeti?.fix_lot}'); } } else { print('Invalid index: $index. No removal performed.'); } } List selectedPetis = widget.temporaryDataList .map((data) { PetiAssetModel? peti = _valpeti?.firstWhereOrNull((peti) => peti.id == data.peti_id); // print("Checking conditions for Peti ID: ${data.peti_id}"); // print("Exit_atController: ${_exit_atController.text.isNotEmpty}"); // print("petiSqfliteApi: ${peti != null}"); // print("warehouseSqfliteApi: ${warehouseSqfliteApi != null}"); if (peti != null) { return peti; } else { print("Peti not found for ID: ${data.peti_id}"); return PetiAssetModel( id: -1, fix_lot: '', /* other default values */ ); } }) .where((peti) => peti != null && peti.id != -1) .cast() .toList(); Future saveAssetData(List selectedPetis) async { DateTime now = DateTime.now().toLocal(); String formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(now); List savedPetiIds = []; List assetAddModels = []; for (PetiAssetModel selectedPeti in selectedPetis) { print("Checking conditions for Peti ID: ${selectedPeti.id}"); print("Exit_atController: ${_exit_atController.text.isNotEmpty}"); print("warehouseSqfliteApi: ${warehouseSqfliteApi != null}"); if (selectedPeti == null) { print("Selected Peti is null"); continue; } PetiAssetModel? peti = _valpeti?.firstWhereOrNull((peti) => peti.id == selectedPeti.id); if (peti != null) { if (_exit_atController.text.isNotEmpty && warehouseSqfliteApi != null) { print("All conditions met. Preparing data..."); AssetStatusModel assetAddModel = AssetStatusModel( id: null, peti_id: selectedPeti.id, customer_id: customerSqfliteApi?.id, warehouse_id: warehouseSqfliteApi?.id, exit_at: parseDateTime(_exit_atController.text), exit_pic: _penanggungJawabController.text, est_pengembalian: parseDateTime(_est_pengembalianController.text), created_by: user.fullname, created_at: parseDateTime(formattedDate), mobile_id: uuid.v4(), ); assetAddModels.add(assetAddModel); savedPetiIds.add(selectedPeti.id!); } else { print("Conditions not met. Unable to save data."); if (_exit_atController.text.isEmpty) { print("Exit_atController is empty"); } if (warehouseSqfliteApi == null) { print("warehouseSqfliteApi is null"); } } } else { print("Peti not found for ID: ${selectedPeti.id}"); } } // Save all AssetStatusModels for (AssetStatusModel assetAddModel in assetAddModels) { int result = await Controller().addPeminjamanData(assetAddModel); if (result <= 0) { print("Failed untuk Peti ID: ${assetAddModel.peti_id}"); } } // Clear controllers and make fields nullable if (mounted) { setState(() { _exit_atController.text = ''; _penanggungJawabController.text = ''; _est_pengembalianController.text = ''; warehouseSqfliteApi?.id = null; customerSqfliteApi?.id = null; }); } // Hapus peti-peti yang baru saja disimpan dari SharedPreferences for (PetiAssetModel selectedPeti in selectedPetis) { if (selectedPeti != null) { await removePetiFromSharedPreferences(selectedPeti); } } // Jika Anda ingin pindah ke halaman setelah menyimpan data untuk semua peti Navigator.pushNamed(context, '/peminjaman-barang'); } return WillPopScope( onWillPop: () async { // Mencegah kembali ke halaman sebelumnya return true; }, child: Scaffold( appBar: AppBar( automaticallyImplyLeading: true, backgroundColor: Colors.indigo[700], elevation: 0, title: Text('Isikan Data Peti Out', style: TextStyle( fontSize: 16, )), ), body: Form( key: _formKey, child: FutureBuilder( future: _dataFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return Center( child: LoadingAnimationWidget.staggeredDotsWave( color: Colors.indigo, size: 40, ), ); } else if (snapshot.hasError) { return Text('Error: ${snapshot.error}'); } else { return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 8), Text( 'List Peti:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 8), Container( height: 250, decoration: BoxDecoration( border: Border.all( color: Colors.grey.withOpacity(0.5), width: 1, ), borderRadius: BorderRadius.circular(8), color: Colors.grey[100], ), padding: EdgeInsets.all(8), child: Expanded( child: ListView.builder( itemCount: widget.temporaryDataList.length, itemBuilder: (context, index) { int? petiId = widget.temporaryDataList[index].peti_id; PetiAssetModel? petiSqfliteApi = _valpeti?.firstWhereOrNull( (peti) => peti.id == petiId, ); return ConstrainedBox( constraints: BoxConstraints( maxHeight: 100, // Set your desired height here ), child: Card( elevation: 1, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), side: BorderSide( color: Colors.grey.withOpacity(0.5), width: 1, ), ), margin: EdgeInsets.symmetric(vertical: 4), child: Padding( padding: const EdgeInsets.all(16.0), child: SingleChildScrollView( child: Row( children: [ Text( '${index + 1}.', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, ), ), SizedBox(width: 16), Text( ' ${petiSqfliteApi?.fix_lot ?? ''}', style: TextStyle(fontSize: 13), ), // Tambahkan properti lainnya sesuai kebutuhan ], ), ), ), ), ); }, ), ), ), SizedBox(height: 16), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Pilih Customer:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 8), DropdownSearch( dropdownDecoratorProps: DropDownDecoratorProps( dropdownSearchDecoration: InputDecoration( hintText: 'Pilih Customer', border: OutlineInputBorder( borderRadius: BorderRadius.all( Radius.circular(5.0), ), ), ), ), popupProps: PopupProps.bottomSheet( showSearchBox: true, itemBuilder: (context, CustomerModel? customer, bool? isSelected) { if (customer == null) { return SizedBox.shrink(); } return Container( child: Column( children: [ ListTile( title: Text( customer.name.toString(), style: TextStyle( fontSize: 16, fontFamily: 'OpenSansCondensed', ), ), leading: Icon( Icons.person_pin, size: 24, color: customer.id == customerSqfliteApi?.id ? Colors.indigo[700] : Colors.grey, ), ), Divider( height: 1, color: Colors .grey, // Warna pembatas (divider) ), ], ), color: customer.id == customerSqfliteApi?.id ? Colors.grey.withOpacity(0.7) : Colors.white, ); }, fit: FlexFit.loose, title: Padding( padding: EdgeInsets.all(8.0), child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( 'Pilih Customer', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold), ), IconButton( icon: Icon( Icons.close, color: Colors.red, ), onPressed: () { Navigator.pop(context); }, ), ], ), Divider(), ], ), ), ), items: (_valcustomer ?? []) .where((customer) => customer.deleted_at != true) .where((customer) => customer.name! .toLowerCase() .contains(searchBoxController.text .toLowerCase())) .toList() ?? [], itemAsString: (CustomerModel customer) => customer.name ?? "", // Ganti dengan properti yang sesuai selectedItem: customerSqfliteApi, onChanged: (CustomerModel? value) { setState(() { customerSqfliteApi = value; }); }, validator: (CustomerModel? value) { if (value == null) { return 'Harus diisi'; } return null; }, ), ], ), ), SizedBox(height: 16), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Tanggal Peminjaman:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 8), FormBuilderDateTimePicker( validator: (value) { if (_exit_atController.text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: Colors.redAccent[700], content: Row( children: [ Icon( Icons.error_outline, color: Colors.white, ), SizedBox(width: 5), Text( 'Tanggal Peminjaman harus diisi'), ], ), duration: Duration(seconds: 2), ), ); return null; // Return null jika ada kesalahan } return null; // Return null jika tidak ada kesalahan }, controller: _exit_atController, name: 'tanggal_peminjaman', inputType: InputType.date, format: DateFormat('yyyy-MM-dd', 'id_ID'), decoration: InputDecoration( hintText: 'Tanggal Peminjaman', border: OutlineInputBorder(), suffixIcon: Icon(Icons.calendar_today), ), onChanged: (DateTime? selectedDate) { if (selectedDate != null) { // Mengisi tanggal estimasi 7 hari ke depan DateTime estimasiPengembalian = selectedDate.add(Duration(days: 7)); _est_pengembalianController.text = DateFormat('yyyy-MM-dd') .format(estimasiPengembalian); } }, ), ], ), ), SizedBox(height: 16), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Estimasi Pengembalian:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 4), Text( '* Terisi otomatis 7 hari setelah tanggal peminjaman', style: TextStyle( fontSize: 12, color: Colors.red, fontStyle: FontStyle.italic), ), SizedBox(height: 8), FormBuilderDateTimePicker( validator: (value) { if (_est_pengembalianController .text.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: Colors.redAccent[700], content: Row( children: [ Icon( Icons.error_outline, color: Colors.white, ), SizedBox(width: 5), Text( 'Tanggal Estimasi Pengembalian'), ], ), duration: Duration(seconds: 2), ), ); return null; // Return null jika ada kesalahan } return null; // Return null jika tidak ada kesalahan }, controller: _est_pengembalianController, name: 'estimasi_pengembalian', inputType: InputType.date, format: DateFormat('yyyy-MM-dd', 'id_ID'), decoration: InputDecoration( hintText: 'Estimasi Tanggal Pengembalian', border: OutlineInputBorder(), suffixIcon: Icon(Icons.calendar_today), ), ), ], ), ), SizedBox(height: 16), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Gudang:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 8), DropdownButtonFormField( validator: (value) { if (value == null) { return 'Harus diisi'; } return null; }, decoration: InputDecoration( hintText: 'Gudang', border: OutlineInputBorder(), ), hint: Text("Gudang"), value: warehouseSqfliteApi, items: (_valwarehouse ?? []) .where((warehouse) => warehouse.deleted_at != true) .map((WarehouseModel warehouse) // _valwarehouse?.map((WarehouseModel warehouse) { return DropdownMenuItem( child: Row( children: [ Icon( Icons.warehouse, color: warehouseSqfliteApi?.id == warehouse.id ? Colors.indigo[700] : Colors.grey, ), SizedBox( width: 8), // Jarak antara ikon dan teks Text( '${warehouse.name}', style: TextStyle( fontSize: 16, fontFamily: 'OpenSansCondensed', ), ), ], ), value: warehouse, ); }).toList() ?? [], onChanged: (value) { setState(() { warehouseSqfliteApi = value; }); }, ), ], ), ), SizedBox(height: 16), Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Penanggung Jawab:', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold), ), SizedBox(height: 8), TextFormField( controller: _penanggungJawabController = TextEditingController(text: user.fullname), decoration: InputDecoration( border: OutlineInputBorder(), hintText: 'Penanggung Jawab', ), validator: (value) { if (value == null || value.isEmpty) { return 'Harus diisi'; } return null; // Return null jika tidak ada kesalahan }, ), ], ), ), ], ), ), ); } }, ), ), bottomNavigationBar: BottomAppBar( height: MediaQuery.of(context).size.height / 10, color: Color.fromARGB(255, 5, 28, 158), // Warna latar belakang child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( width: MediaQuery.of(context).size.width / 3, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Container( height: 50, // Lebar dan tinggi sesuai kebutuhan width: 50, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.green, // Warna hijau untuk save ), child: IconButton( onPressed: () async { if (_formKey.currentState!.validate()) { try { if (_exit_atController.text.isNotEmpty && warehouseSqfliteApi != null) { await saveAssetData(selectedPetis); // Menampilkan Snackbar dengan pesan sukses ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Row( children: [ Icon( Icons.check, color: Colors.white, ), SizedBox(width: 5), Text('Data berhasil disimpan'), ], ), backgroundColor: Colors.greenAccent[700], duration: Duration(seconds: 2), ), ); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( backgroundColor: Colors.redAccent[700], content: Row( children: [ Icon( Icons.error_outline, color: Colors.white, ), SizedBox(width: 5), Text('Data belum lengkap'), ], ), duration: Duration(seconds: 2), ), ); } } catch (e) { print('Error storing data: $e'); } } }, icon: Icon(Icons.check, color: Colors.white), ), ), ], ), ), ], ), ), ), ); } }