unknown
11 months ago
19 changed files with 6070 additions and 4370 deletions
@ -0,0 +1,21 @@
|
||||
class UserRoleModel { |
||||
int? id; |
||||
String? name; |
||||
|
||||
UserRoleModel({ |
||||
this.id, |
||||
this.name, |
||||
}); |
||||
|
||||
UserRoleModel.fromJson(Map<String, dynamic> json) { |
||||
id = json['id']; |
||||
name = json['name'] != null ? json['name'] : null; |
||||
} |
||||
|
||||
Map<String, dynamic> toJson() { |
||||
return { |
||||
'id': id, |
||||
'name': name, |
||||
}; |
||||
} |
||||
} |
@ -0,0 +1,761 @@
|
||||
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:siopas/pages/pengembalian_barang/controller/pengembalian_controller.dart'; |
||||
import 'package:uuid/uuid.dart'; |
||||
|
||||
import '../../models/asset_status_model.dart'; |
||||
import '../../models/condition_peti_model.dart'; |
||||
import '../../models/disposal_model.dart'; |
||||
import '../../models/m_asset_status_model.dart'; |
||||
import '../../models/user_model.dart'; |
||||
import '../../models/warehouse_mode.dart'; |
||||
import '../../providers/auth_provider.dart'; |
||||
import '../../services/controllerApi.dart'; |
||||
|
||||
class EditFinishPengembalian extends StatefulWidget { |
||||
final List<AssetStatusModel> temporaryDataList; |
||||
|
||||
EditFinishPengembalian({required this.temporaryDataList}); |
||||
|
||||
@override |
||||
_EditFinishPengembalianState createState() => _EditFinishPengembalianState(); |
||||
} |
||||
|
||||
class _EditFinishPengembalianState extends State<EditFinishPengembalian> { |
||||
String? token; |
||||
// List<CustomerModel>? customerSqfliteApi; |
||||
PetiAssetModel? petiSqfliteApi; |
||||
WarehouseModel? warehouseSqfliteApi; |
||||
ConditionPetiModel? conditionSqfliteApi; |
||||
DisposalPetiModel? disposalSqfliteApi; |
||||
|
||||
List<PetiAssetModel>? _valpeti; // Change this line |
||||
List<WarehouseModel>? _valwarehouse; |
||||
List<ConditionPetiModel>? _valcondition; |
||||
List<DisposalPetiModel>? _valdisposal; |
||||
List<PetiAssetModel> _allPetiList = []; |
||||
List<PetiAssetModel> _unrestrictedPetiList = []; |
||||
List<PetiAssetModel> _filteredPetiList = []; |
||||
bool isQRCodeScanned = false; |
||||
String searchText = ''; |
||||
PetiAssetModel? selectedPeti; |
||||
TextEditingController searchBoxController = TextEditingController(); |
||||
TextEditingController _enter_atController = TextEditingController(); |
||||
TextEditingController _penanggungJawabController = TextEditingController(); |
||||
TextEditingController _warehouseController = TextEditingController(); |
||||
|
||||
List<PetiAssetModel> selectedPetiList = []; |
||||
List<AssetStatusModel>? _data; |
||||
List<AssetStatusModel> temporaryDataList = []; |
||||
|
||||
final _formKey = GlobalKey<FormState>(); |
||||
|
||||
bool loading = true; |
||||
late Future<void> _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<void> fetchData() async { |
||||
await _getUserToken(); |
||||
await warehouseListAPI(); |
||||
await petiListAPI(); |
||||
await disposalListAPI(); |
||||
await kondisiPetiListAPI(); |
||||
initializeDateFormatting('id_ID', null); |
||||
|
||||
// Tandai bahwa proses loading telah selesai |
||||
if (mounted) { |
||||
setState(() { |
||||
loading = false; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future<void> _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<dynamic>) |
||||
.map((item) => DisposalPetiModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future warehouseListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchWarehouseDataAPI().then((value) { |
||||
setState(() { |
||||
_valwarehouse = (value as List<dynamic>) |
||||
.map((item) => WarehouseModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future petiListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchPetiDataAPI().then((value) { |
||||
setState(() { |
||||
_valpeti = (value as List<dynamic>) |
||||
.map((item) => PetiAssetModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future kondisiPetiListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchKondisiPetiDataAPI().then((value) { |
||||
setState(() { |
||||
_valcondition = (value as List<dynamic>) |
||||
.map((item) => ConditionPetiModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
AuthProvider authProvider = |
||||
Provider.of<AuthProvider>(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<void> removePetiFromSharedPreferences( |
||||
PetiAssetModel removedPeti) async { |
||||
SharedPreferences prefs = await SharedPreferences.getInstance(); |
||||
|
||||
// Retrieve existing data from SharedPreferences |
||||
List<String>? petiListJson = prefs.getStringList('petiListPengembalian'); |
||||
|
||||
if (petiListJson != null) { |
||||
// Convert JSON strings to PetiAssetModel objects |
||||
List<PetiAssetModel> 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<String> updatedPetiListJson = |
||||
existingPetiList.map((peti) => json.encode(peti.toJson())).toList(); |
||||
|
||||
prefs.setStringList('petiListPengembalian', 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<PetiAssetModel> 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: ${_enter_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<PetiAssetModel>() |
||||
.toList(); |
||||
|
||||
Future<void> saveAssetData(List<PetiAssetModel> selectedPetis) async { |
||||
DateTime now = DateTime.now().toLocal(); |
||||
String formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(now); |
||||
|
||||
List<int?> savedPetiIds = []; |
||||
List<AssetStatusModel> assetAddModels = []; |
||||
|
||||
for (PetiAssetModel selectedPeti in selectedPetis) { |
||||
// print("Checking conditions for Peti ID: ${selectedPeti.id}"); |
||||
// print("Enter_atController: ${_enter_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 (_enter_atController.text.isNotEmpty && |
||||
warehouseSqfliteApi != null) { |
||||
print("All conditions met. Preparing data..."); |
||||
|
||||
AssetStatusModel assetAddModel = AssetStatusModel( |
||||
id: null, |
||||
peti_id: selectedPeti.id, |
||||
enter_warehouse: warehouseSqfliteApi?.id, |
||||
enter_at: parseDateTime(_enter_atController.text), |
||||
enter_pic: _penanggungJawabController.text, |
||||
kondisi_peti_id: conditionSqfliteApi?.id, |
||||
updated_by: user.fullname, |
||||
updated_at: parseDateTime(formattedDate), |
||||
mobile_id: uuid.v4(), |
||||
); |
||||
|
||||
assetAddModels.add(assetAddModel); |
||||
savedPetiIds.add(selectedPeti.id!); |
||||
} else { |
||||
print("Conditions not met. Unable to save data."); |
||||
if (_enter_atController.text.isEmpty) { |
||||
print("Enter_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 ControllerPengembalian().addPengembalianData(assetAddModel); |
||||
|
||||
if (result <= 0) { |
||||
print("Failed untuk Peti ID: ${assetAddModel.peti_id}"); |
||||
} |
||||
} |
||||
|
||||
// Clear controllers and make fields nullable |
||||
if (mounted) { |
||||
setState(() { |
||||
_enter_atController.text = ''; |
||||
_penanggungJawabController.text = ''; |
||||
warehouseSqfliteApi?.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, '/pengembalian-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 In', |
||||
style: TextStyle( |
||||
fontSize: 16, |
||||
)), |
||||
), |
||||
body: Form( |
||||
key: _formKey, |
||||
child: FutureBuilder<void>( |
||||
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( |
||||
'Tanggal Pengembalian:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
FormBuilderDateTimePicker( |
||||
validator: (value) { |
||||
if (_enter_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 pengembalian harus diisi'), |
||||
], |
||||
), |
||||
duration: Duration(seconds: 2), |
||||
), |
||||
); |
||||
return null; // Return null jika ada kesalahan |
||||
} |
||||
return null; // Return null jika tidak ada kesalahan |
||||
}, |
||||
controller: _enter_atController, |
||||
name: 'tanggal_pengembalian', |
||||
inputType: InputType.date, |
||||
format: DateFormat('yyyy-MM-dd', 'id_ID'), |
||||
decoration: InputDecoration( |
||||
hintText: 'Tanggal Pengembalian', |
||||
border: OutlineInputBorder(), |
||||
suffixIcon: Icon(Icons.calendar_today), |
||||
), |
||||
onChanged: (DateTime? selectedDate) { |
||||
if (selectedDate != null) { |
||||
// Mengisi tanggal estimasi 7 hari ke depan |
||||
DateTime tanggalPengembalian = |
||||
selectedDate.add(Duration(days: 7)); |
||||
_enter_atController.text = |
||||
DateFormat('yyyy-MM-dd') |
||||
.format(tanggalPengembalian); |
||||
} |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
SizedBox(height: 16), |
||||
Container( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
'Gudang:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
DropdownButtonFormField<WarehouseModel>( |
||||
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<WarehouseModel>( |
||||
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( |
||||
'Kondisi Barang:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
DropdownButtonFormField<ConditionPetiModel>( |
||||
validator: (value) { |
||||
if (value == null) { |
||||
return 'Harus diisi'; |
||||
} |
||||
return null; |
||||
}, |
||||
decoration: InputDecoration( |
||||
hintText: 'Pilih Kondisi Peti', |
||||
border: OutlineInputBorder(), |
||||
), |
||||
hint: Text("Pilih Kondisi Peti"), |
||||
value: conditionSqfliteApi, |
||||
items: (_valcondition ?? []) |
||||
.where((kondisi) => |
||||
kondisi.deleted_at != true) |
||||
.map((ConditionPetiModel kondisi) { |
||||
return DropdownMenuItem< |
||||
ConditionPetiModel>( |
||||
child: Row( |
||||
children: [ |
||||
Icon( |
||||
kondisi.id == |
||||
conditionSqfliteApi?.id |
||||
? Icons.check_box |
||||
: Icons |
||||
.check_box_outline_blank, |
||||
color: kondisi.id == |
||||
conditionSqfliteApi?.id |
||||
? Colors.teal[700] |
||||
: Colors.grey, |
||||
), |
||||
SizedBox( |
||||
width: 8, |
||||
), |
||||
Text( |
||||
'${kondisi.nama_kondisi}', |
||||
style: TextStyle( |
||||
fontSize: 16, |
||||
fontFamily: 'OpenSansCondensed', |
||||
), |
||||
), |
||||
], |
||||
), |
||||
value: kondisi, |
||||
); |
||||
}).toList() ?? |
||||
[], |
||||
onChanged: (ConditionPetiModel? value) { |
||||
if (mounted) { |
||||
setState(() { |
||||
conditionSqfliteApi = 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 (_enter_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), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,899 @@
|
||||
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:siopas/models/customer_model.dart'; |
||||
import 'package:siopas/pages/transfer_peti/controller/transfer_peti_controller.dart'; |
||||
import 'package:uuid/uuid.dart'; |
||||
|
||||
import '../../models/condition_peti_model.dart'; |
||||
import '../../models/disposal_model.dart'; |
||||
import '../../models/m_asset_status_model.dart'; |
||||
import '../../models/transfer_peti_model.dart'; |
||||
import '../../models/user_model.dart'; |
||||
import '../../models/warehouse_mode.dart'; |
||||
import '../../providers/auth_provider.dart'; |
||||
import '../../services/controllerApi.dart'; |
||||
|
||||
class EditFinishTransferPeti extends StatefulWidget { |
||||
final List<TransferPetiModel> temporaryDataList; |
||||
|
||||
EditFinishTransferPeti({required this.temporaryDataList}); |
||||
|
||||
@override |
||||
_EditFinishTransferPetiState createState() => _EditFinishTransferPetiState(); |
||||
} |
||||
|
||||
class _EditFinishTransferPetiState extends State<EditFinishTransferPeti> { |
||||
String? token; |
||||
// List<CustomerModel>? customerSqfliteApi; |
||||
PetiAssetModel? petiSqfliteApi; |
||||
WarehouseModel? warehouseSqfliteApi; |
||||
WarehouseModel? warehouseTujuanSqfliteApi; |
||||
ConditionPetiModel? conditionSqfliteApi; |
||||
CustomerModel? customerSqfliteApi; |
||||
DisposalPetiModel? disposalSqfliteApi; |
||||
|
||||
List<PetiAssetModel>? _valpeti; // Change this line |
||||
List<WarehouseModel>? _valwarehouse; |
||||
List<WarehouseModel>? _valTujuanwarehouse; |
||||
List<ConditionPetiModel>? _valcondition; |
||||
List<DisposalPetiModel>? _valdisposal; |
||||
List<CustomerModel>? _valcustomer; |
||||
List<PetiAssetModel> _allPetiList = []; |
||||
List<PetiAssetModel> _unrestrictedPetiList = []; |
||||
List<PetiAssetModel> _filteredPetiList = []; |
||||
bool isQRCodeScanned = false; |
||||
String searchText = ''; |
||||
PetiAssetModel? selectedPeti; |
||||
TextEditingController searchBoxController = TextEditingController(); |
||||
TextEditingController _date_atController = TextEditingController(); |
||||
TextEditingController _penanggungJawabController = TextEditingController(); |
||||
|
||||
List<PetiAssetModel> selectedPetiList = []; |
||||
List<TransferPetiModel>? _data; |
||||
List<TransferPetiModel> temporaryDataList = []; |
||||
|
||||
final _formKey = GlobalKey<FormState>(); |
||||
|
||||
bool loading = true; |
||||
late Future<void> _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<void> fetchData() async { |
||||
await _getUserToken(); |
||||
await warehouseListAPI(); |
||||
await petiListAPI(); |
||||
await disposalListAPI(); |
||||
await kondisiPetiListAPI(); |
||||
await customerListAPI(); |
||||
initializeDateFormatting('id_ID', null); |
||||
|
||||
// Tandai bahwa proses loading telah selesai |
||||
if (mounted) { |
||||
setState(() { |
||||
loading = false; |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future<void> _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 customerListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchCustomerDataAPI().then((value) { |
||||
setState(() { |
||||
_valcustomer = (value as List<dynamic>) |
||||
.map((item) => CustomerModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future disposalListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchDisposalDataAPI().then((value) { |
||||
setState(() { |
||||
_valdisposal = (value as List<dynamic>) |
||||
.map((item) => DisposalPetiModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future warehouseListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchWarehouseDataAPI().then((value) { |
||||
setState(() { |
||||
_valwarehouse = (value as List<dynamic>) |
||||
.map((item) => WarehouseModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future petiListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchPetiDataAPI().then((value) { |
||||
setState(() { |
||||
_valpeti = (value as List<dynamic>) |
||||
.map((item) => PetiAssetModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
Future kondisiPetiListAPI() async { |
||||
if (mounted) { |
||||
await ControllerApi().fetchKondisiPetiDataAPI().then((value) { |
||||
setState(() { |
||||
_valcondition = (value as List<dynamic>) |
||||
.map((item) => ConditionPetiModel.fromJson(item)) |
||||
.toList(); |
||||
loading = false; |
||||
}); |
||||
}); |
||||
} |
||||
} |
||||
|
||||
@override |
||||
Widget build(BuildContext context) { |
||||
AuthProvider authProvider = |
||||
Provider.of<AuthProvider>(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<void> removePetiFromSharedPreferences( |
||||
PetiAssetModel removedPeti) async { |
||||
SharedPreferences prefs = await SharedPreferences.getInstance(); |
||||
|
||||
// Retrieve existing data from SharedPreferences |
||||
List<String>? petiListJson = |
||||
prefs.getStringList('menu2_transferPetiList'); |
||||
|
||||
if (petiListJson != null) { |
||||
// Convert JSON strings to PetiAssetModel objects |
||||
List<PetiAssetModel> 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<String> updatedPetiListJson = |
||||
existingPetiList.map((peti) => json.encode(peti.toJson())).toList(); |
||||
|
||||
prefs.setStringList('menu2_transferPetiList', 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<PetiAssetModel> 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: ${_date_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<PetiAssetModel>() |
||||
.toList(); |
||||
|
||||
Future<void> saveAssetData(List<PetiAssetModel> selectedPetis) async { |
||||
DateTime now = DateTime.now().toLocal(); |
||||
String formattedDate = DateFormat('yyyy-MM-dd HH:mm:ss.SSS').format(now); |
||||
|
||||
List<int?> savedPetiIds = []; |
||||
List<TransferPetiModel> assetAddModels = []; |
||||
|
||||
for (PetiAssetModel selectedPeti in selectedPetis) { |
||||
print("Checking conditions for Peti ID: ${selectedPeti.id}"); |
||||
print("Enter_atController: ${_date_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 (_date_atController.text.isNotEmpty && |
||||
warehouseSqfliteApi != null) { |
||||
print("All conditions met. Preparing data..."); |
||||
|
||||
TransferPetiModel assetAddModel = TransferPetiModel( |
||||
id: null, |
||||
peti_id: selectedPeti.id, |
||||
name_customer: customerSqfliteApi?.id, |
||||
source_warehouse: warehouseSqfliteApi?.id, |
||||
destination_warehouse: warehouseTujuanSqfliteApi?.id, |
||||
date: parseDateTime(_date_atController.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 (_date_atController.text.isEmpty) { |
||||
print("Enter_atController is empty"); |
||||
} |
||||
if (warehouseSqfliteApi == null) { |
||||
print("warehouseSqfliteApi is null"); |
||||
} |
||||
} |
||||
} else { |
||||
print("Peti not found for ID: ${selectedPeti.id}"); |
||||
} |
||||
} |
||||
|
||||
// Save all TransferPetiModels |
||||
for (TransferPetiModel assetAddModel in assetAddModels) { |
||||
int result = await ControllerTransferPeti().addData(assetAddModel); |
||||
|
||||
if (result <= 0) { |
||||
print("Failed untuk Peti ID: ${assetAddModel.peti_id}"); |
||||
} |
||||
} |
||||
|
||||
// Clear controllers and make fields nullable |
||||
if (mounted) { |
||||
setState(() { |
||||
_date_atController.text = ''; |
||||
_penanggungJawabController.text = ''; |
||||
warehouseSqfliteApi?.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, '/transfer-peti'); |
||||
} |
||||
|
||||
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 Transfer Peti', |
||||
style: TextStyle( |
||||
fontSize: 16, |
||||
)), |
||||
), |
||||
body: Form( |
||||
key: _formKey, |
||||
child: FutureBuilder<void>( |
||||
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( |
||||
'Tanggal Transfer Peti:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
FormBuilderDateTimePicker( |
||||
validator: (value) { |
||||
if (_date_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 transfer peti harus diisi'), |
||||
], |
||||
), |
||||
duration: Duration(seconds: 2), |
||||
), |
||||
); |
||||
return null; // Return null jika ada kesalahan |
||||
} |
||||
return null; // Return null jika tidak ada kesalahan |
||||
}, |
||||
controller: _date_atController, |
||||
name: 'tanggal_transfer_peti', |
||||
inputType: InputType.date, |
||||
format: DateFormat('yyyy-MM-dd', 'id_ID'), |
||||
decoration: InputDecoration( |
||||
hintText: 'Tanggal Transfer Peti', |
||||
border: OutlineInputBorder(), |
||||
suffixIcon: Icon(Icons.calendar_today), |
||||
), |
||||
onChanged: (DateTime? selectedDate) { |
||||
if (selectedDate != null) { |
||||
// Mengisi tanggal estimasi 7 hari ke depan |
||||
DateTime tanggalTransferPeti = |
||||
selectedDate.add(Duration(days: 7)); |
||||
_date_atController.text = |
||||
DateFormat('yyyy-MM-dd') |
||||
.format(tanggalTransferPeti); |
||||
} |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
), |
||||
SizedBox(height: 16), |
||||
Container( |
||||
child: Column( |
||||
crossAxisAlignment: CrossAxisAlignment.start, |
||||
children: [ |
||||
Text( |
||||
'Pilih Customer:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
DropdownSearch<CustomerModel>( |
||||
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( |
||||
'Asal Gudang:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
DropdownButtonFormField<WarehouseModel>( |
||||
validator: (value) { |
||||
if (value == null) { |
||||
return 'Harus diisi'; |
||||
} |
||||
return null; |
||||
}, |
||||
decoration: InputDecoration( |
||||
hintText: 'Asal Gudang', |
||||
border: OutlineInputBorder(), |
||||
), |
||||
hint: Text("Asal Gudang"), |
||||
value: warehouseSqfliteApi, |
||||
items: (_valwarehouse ?? []) |
||||
.where((warehouse) => |
||||
warehouse.deleted_at != true) |
||||
.map((WarehouseModel warehouse) |
||||
// _valwarehouse?.map((WarehouseModel warehouse) |
||||
{ |
||||
return DropdownMenuItem<WarehouseModel>( |
||||
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( |
||||
'Tujuan Gudang:', |
||||
style: TextStyle( |
||||
fontSize: 14, fontWeight: FontWeight.bold), |
||||
), |
||||
SizedBox(height: 8), |
||||
DropdownButtonFormField<WarehouseModel>( |
||||
validator: (value) { |
||||
if (value == null) { |
||||
return 'Harus diisi'; |
||||
} |
||||
return null; |
||||
}, |
||||
decoration: InputDecoration( |
||||
hintText: 'Tujuan Gudang', |
||||
border: OutlineInputBorder(), |
||||
), |
||||
hint: Text("Tujuan Gudang"), |
||||
value: warehouseTujuanSqfliteApi, |
||||
items: (_valwarehouse ?? []) |
||||
.where((warehouse) => |
||||
warehouse.deleted_at != true) |
||||
.map((WarehouseModel warehouse) |
||||
// _valwarehouse?.map((WarehouseModel warehouse) |
||||
{ |
||||
return DropdownMenuItem<WarehouseModel>( |
||||
child: Row( |
||||
children: [ |
||||
Icon( |
||||
Icons.local_shipping, |
||||
color: warehouseTujuanSqfliteApi |
||||
?.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(() { |
||||
warehouseTujuanSqfliteApi = 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 (_date_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), |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
], |
||||
), |
||||
), |
||||
), |
||||
); |
||||
} |
||||
} |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,13 +0,0 @@
|
||||
import 'package:intl/intl.dart'; |
||||
import 'package:flutter/material.dart'; |
||||
|
||||
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 ''; |
||||
} |
||||
} |
Loading…
Reference in new issue