|
|
|
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<AssetStatusPage> createState() => AssetStatusPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class AssetStatusPageState extends State<AssetStatusPage> {
|
|
|
|
String? token;
|
|
|
|
bool loading = true;
|
|
|
|
|
|
|
|
// Reinit atau Upload Only
|
|
|
|
WarehouseModel? warehouseSqfliteApi;
|
|
|
|
List<TypePetiModel>? typePetiSqfliteApi;
|
|
|
|
List<CustomerModel>? customerSqfliteApi;
|
|
|
|
PetiAssetModel? petiSqfliteApi;
|
|
|
|
DisposalPetiModel? disposalSqfliteApi;
|
|
|
|
|
|
|
|
List<PetiAssetModel>? _valpeti; // Change this line
|
|
|
|
List<WarehouseModel>? _valwarehouse;
|
|
|
|
List<DisposalPetiModel>? _valdisposal;
|
|
|
|
|
|
|
|
// Datatable
|
|
|
|
int _currentPage = 1;
|
|
|
|
int _pageSize = 10;
|
|
|
|
List<AssetStatusModel>? _data;
|
|
|
|
List<PetiAssetModel>? _petiData;
|
|
|
|
List<TypePetiModel>? _tipePetiData;
|
|
|
|
List<CustomerModel>? _customerData;
|
|
|
|
List<WarehouseModel>? _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 = <AssetStatusModel>[];
|
|
|
|
}
|
|
|
|
|
|
|
|
void _getUserToken() async {
|
|
|
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
|
|
|
if (mounted) {
|
|
|
|
setState(() {
|
|
|
|
token = prefs.getString('token');
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> _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<dynamic>)
|
|
|
|
.map((item) => WarehouseModel.fromJson(item))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future typePetiListAPI() async {
|
|
|
|
if (mounted) {
|
|
|
|
await ControllerApi().fetchTipePetiDataAPI().then((value) {
|
|
|
|
setState(() {
|
|
|
|
typePetiSqfliteApi = (value as List<dynamic>)
|
|
|
|
.map((item) => TypePetiModel.fromJson(item))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future customerListAPI() async {
|
|
|
|
if (mounted) {
|
|
|
|
await ControllerApi().fetchCustomerDataAPI().then((value) {
|
|
|
|
setState(() {
|
|
|
|
customerSqfliteApi = (value as List<dynamic>)
|
|
|
|
.map((item) => CustomerModel.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<void> reinitWarehouseApi() async {
|
|
|
|
EasyLoading.show(status: 'Mengambil data Warehouse...');
|
|
|
|
List<WarehouseModel> warehouseApiData =
|
|
|
|
await SyncronizationDataAPI().fetchWarehouseFromApi();
|
|
|
|
await ControllerApi()
|
|
|
|
.deleteAllWarehouseDataAPI(); // Clear existing data in SQLite
|
|
|
|
await ControllerApi()
|
|
|
|
.addAllWarehouseDataAPI(warehouseApiData); // Add new data to SQLite
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> reinitPetiApi() async {
|
|
|
|
EasyLoading.show(status: 'Mengambil data Peti...');
|
|
|
|
List<PetiAssetModel> 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<void> reinitCustomerApi() async {
|
|
|
|
EasyLoading.show(status: 'Mengambil data Customer...');
|
|
|
|
List<CustomerModel> customerApiData =
|
|
|
|
await SyncronizationDataAPI().fetchCustomerFromApi();
|
|
|
|
await ControllerApi()
|
|
|
|
.deleteAllCustomerDataAPI(); // Clear existing data in SQLite
|
|
|
|
await ControllerApi()
|
|
|
|
.addAllCustomerDataAPI(customerApiData); // Add new data to SQLite
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> reinitTypePetiApi() async {
|
|
|
|
EasyLoading.show(status: 'Mengambil data Type Peti...');
|
|
|
|
List<TypePetiModel> typePetiApiData =
|
|
|
|
await SyncronizationDataAPI().fetchTipePetiFromApi();
|
|
|
|
await ControllerApi()
|
|
|
|
.deleteAllTipePetiDataAPI(); // Clear existing data in SQLite
|
|
|
|
await ControllerApi()
|
|
|
|
.addAllTipePetiDataAPI(typePetiApiData); // Add new data to SQLite
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> reinitConditionPetiApi() async {
|
|
|
|
EasyLoading.show(status: 'Mengambil data Condition Peti...');
|
|
|
|
List<ConditionPetiModel> conditionPetiApiData =
|
|
|
|
await SyncronizationDataAPI().fetchKondisiPetiFromApi();
|
|
|
|
await ControllerApi()
|
|
|
|
.deleteAllKondisiPetiDataAPI(); // Clear existing data in SQLite
|
|
|
|
await ControllerApi().addAllKondisiPetiDataAPI(
|
|
|
|
conditionPetiApiData); // Add new data to SQLite
|
|
|
|
EasyLoading.dismiss();
|
|
|
|
}
|
|
|
|
|
|
|
|
Future<void> 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<void> 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<dynamic>)
|
|
|
|
.map((e) => AssetStatusModel.fromJson(e))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future datatablesPetiList() async {
|
|
|
|
if (mounted) {
|
|
|
|
await Controller().fetchPetiData().then((value) {
|
|
|
|
setState(() {
|
|
|
|
_petiData = (value as List<dynamic>)
|
|
|
|
.map((e) => PetiAssetModel.fromJson(e))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future datatablesTipePetiList() async {
|
|
|
|
if (mounted) {
|
|
|
|
await Controller().fetchTipePetiData().then((value) {
|
|
|
|
setState(() {
|
|
|
|
_tipePetiData = (value as List<dynamic>)
|
|
|
|
.map((e) => TypePetiModel.fromJson(e))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future datatablesCustomerList() async {
|
|
|
|
if (mounted) {
|
|
|
|
await Controller().fetchCustomerData().then((value) {
|
|
|
|
setState(() {
|
|
|
|
_customerData = (value as List<dynamic>)
|
|
|
|
.map((e) => CustomerModel.fromJson(e))
|
|
|
|
.toList();
|
|
|
|
loading = false;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Future datatablesWarehouseList() async {
|
|
|
|
if (mounted) {
|
|
|
|
await Controller().fetchWarehouseData().then((value) {
|
|
|
|
setState(() {
|
|
|
|
_warehouseData = (value as List<dynamic>)
|
|
|
|
.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<AssetStatusModel> 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: <Widget>[
|
|
|
|
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<int> 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<PetiAssetModel> petiData;
|
|
|
|
final List<TypePetiModel> tipePetiData;
|
|
|
|
final List<CustomerModel> customerData;
|
|
|
|
final List<WarehouseModel> 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<void> _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<void> _showDeleteConfirmationDialog() async {
|
|
|
|
return showDialog<void>(
|
|
|
|
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: <Widget>[
|
|
|
|
Text(
|
|
|
|
'Anda yakin ingin menghapus peminjaman ini? ${petiSqfliteApi!.fix_lot.toString()}',
|
|
|
|
style: TextStyle(
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
actions: <Widget>[
|
|
|
|
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
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|