Siopas Inventory PETI for ISTW Mobile
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

811 lines
25 KiB

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: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 '../../models/condition_peti_model.dart';
import 'show.dart';
class AssetStatusPage extends StatefulWidget {
const AssetStatusPage({super.key});
@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;
bool _isLoading = false;
@override
void initState() {
super.initState();
_getUserToken();
// Mengatur _isLoading ke true sebelum tugas dimulai
setState(() {
_isLoading = true;
});
Future.wait([
warehouseListAPI(),
typePetiListAPI(),
customerListAPI(),
petiListAPI(),
datatablesAssetStatusList(),
datatablesPetiList(),
datatablesTipePetiList(),
datatablesCustomerList(),
datatablesWarehouseList(),
]).then((_) {
// Mengatur _isLoading ke false setelah semua tugas selesai
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');
});
}
}
// 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 disposalListAPI() async {
// if (mounted) {
// await ControllerApi().fetchDisposalDataAPI().then((value) {
// setState(() {
// _valdisposal = (value as List<dynamic>)
// .map((item) => DisposalPetiModel.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> reinitAssetStatusApi() async {
// EasyLoading.show(status: 'Mengambil data Asset Status...');
// List<AssetStatusModel> assetStatusApiData =
// await SyncronizationDataAPI().fetchAssetStatusFromApi();
// await ControllerApi()
// .deleteAllAssetStatusDataAPI(); // Clear existing data in SQLite
// await ControllerApi()
// .addAllAssetStatusDataAPI(assetStatusApiData); // Add new data to SQLite
// EasyLoading.dismiss();
// }
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> reinitDisposalApi() async {
// List<DisposalPetiModel> disposalApiData =
// await SyncronizationDataAPI().fetchDisposalFromApi();
// await ControllerApi()
// .deleteAllDisposalDataAPI(); // Clear existing data in SQLite
// await ControllerApi()
// .addAllDisposalDataAPI(disposalApiData); // Add new data to SQLite
// }
Future<void> fetchDataFromApiAndSync() async {
EasyLoading.show(status: 'Mengambil data dari Server...');
await Future.delayed(Duration(seconds: 3));
try {
await syncToMysql();
// await reinitAssetStatusApi();
await reinitWarehouseApi();
await reinitPetiApi();
await reinitCustomerApi();
// await reinitTypePetiApi();
await reinitConditionPetiApi();
// await reinitDisposalApi();
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("No Internet")));
}
});
}
// Datatables ------------------------------------------------------------------------
Future datatablesAssetStatusList() async {
await Controller().fetchAssetStatusLocalController().then((value) {
setState(() {
_data = (value as List<dynamic>)
.map((e) => AssetStatusModel.fromJson(e))
.toList();
loading = false;
});
});
}
Future datatablesPetiList() async {
await Controller().fetchPetiData().then((value) {
setState(() {
_petiData = (value as List<dynamic>)
.map((e) => PetiAssetModel.fromJson(e))
.toList();
loading = false;
});
});
}
Future datatablesTipePetiList() async {
await Controller().fetchTipePetiData().then((value) {
setState(() {
_tipePetiData = (value as List<dynamic>)
.map((e) => TypePetiModel.fromJson(e))
.toList();
loading = false;
});
});
}
Future datatablesCustomerList() async {
await Controller().fetchCustomerData().then((value) {
setState(() {
_customerData = (value as List<dynamic>)
.map((e) => CustomerModel.fromJson(e))
.toList();
loading = false;
});
});
}
Future datatablesWarehouseList() async {
await Controller().fetchWarehouseData().then((value) {
setState(() {
_warehouseData = (value as List<dynamic>)
.map((e) => WarehouseModel.fromJson(e))
.toList();
loading = false;
});
});
}
void _loadMoreData() {
if (mounted && !_isLoading) {
setState(() {
_currentPage++;
});
datatablesAssetStatusList();
}
}
@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',
),
),
),
),
// Divider
// Divider(
// height: 1,
// thickness: 1,
// color: Colors.black, // Black divider
// ),
// Upload Only Button
// Container(
// width: double.infinity,
// child: TextButton(
// onPressed: () {
// Navigator.pop(context); // Close dialog
// syncToMysql();
// },
// child: Text(
// "Upload Only",
// style: TextStyle(
// color: Colors.black,
// fontSize: 16.0,
// fontFamily: 'Poppins',
// ),
// ),
// ),
// ),
],
),
);
},
);
}
return DefaultTabController(
length: 1,
child: Scaffold(
appBar: AppBar(
backgroundColor: Colors.indigo[700],
elevation: 0,
title: Text('Data Peminjaman Peti',
style: TextStyle(
fontSize: 16,
)),
actions: [
IconButton(
icon: Icon(Icons.backup),
onPressed: () async {
if (await SyncronizationPeminjamanData.isInternet()) {
// Display custom dialog when the IconButton is pressed
showSyncDialog(context);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("No internet connection")),
);
}
},
),
],
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: () {
Navigator.pushNamed(context, '/home');
},
),
bottom: TabBar(
indicator: BoxDecoration(color: Color.fromARGB(255, 50, 39, 122)),
tabs: [
Tab(text: 'Peminjaman Hari ini'),
],
),
),
body: _isLoading
? Center(
child: LoadingAnimationWidget.staggeredDotsWave(
color: Colors.indigo,
size: 40,
),
)
: TabBarView(
children: [
SingleChildScrollView(
child: Column(
children: [
SizedBox(
width: double.infinity,
child: PaginatedDataTable(
// header: Text('Searching'), // Removed const
rowsPerPage: _pageSize,
availableRowsPerPage: [10, 25, 50], // Removed const
onRowsPerPageChanged: (value) {
setState(() {
_pageSize = value!;
});
},
columns: [
DataColumn(label: Text('No')),
DataColumn(label: Text('')),
DataColumn(label: Text('Kode Peti')),
DataColumn(label: Text('Nama Customer')),
DataColumn(label: Text('Tgl Peminjaman')),
DataColumn(label: Text('Est Peminjaman')),
DataColumn(label: Text('PJ Peminjaman')),
DataColumn(label: Text('Asal Gudang')),
DataColumn(label: Text('Tujuan Gudang')),
],
source: _DataSourceLokal(
data: _data!,
context: context,
petiData: _petiData != null ? _petiData : [],
tipePetiData:
_tipePetiData != null ? _tipePetiData : [],
customerData:
_customerData != null ? _customerData : [],
warehouseData:
_warehouseData != null ? _warehouseData : [],
),
),
),
],
),
),
],
),
bottomNavigationBar: 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,
),
),
),
],
),
),
),
),
);
}
}
class _DataSourceLokal extends DataTableSource {
final List<AssetStatusModel> data;
List<PetiAssetModel>? petiData;
List<TypePetiModel>? tipePetiData;
List<CustomerModel>? customerData;
List<WarehouseModel>? warehouseData;
final BuildContext context;
_DataSourceLokal({
required this.data,
required this.petiData,
required this.tipePetiData,
required this.customerData,
required this.warehouseData,
required this.context,
});
@override
DataRow? getRow(int index) {
if (index >= data.length) {
return null;
}
data.sort((a, b) {
if (a.created_at == null && b.created_at == null) {
return 0; // Both dates are null, consider them equal
} else if (a.created_at == null) {
return 1; // Null is considered greater than non-null
} else if (b.created_at == null) {
return -1; // Non-null is considered smaller than null
} else {
return b.created_at!.compareTo(a.created_at!); // Compare non-null dates
}
});
final item = data[index];
// Menemukan data peti yang sesuai dengan asset
PetiAssetModel? petiSqfliteApi;
if (item.peti_id != null) {
petiSqfliteApi = petiData!.firstWhere(
(peti) => peti.id == item.peti_id,
orElse: () => PetiAssetModel(
id: null,
tipe_peti_id: null,
warna: 'null',
packing_no: null,
customer_id: null,
warehouse_id: null,
kondisipeti_id: null,
jumlah: null,
date_pembuatan: DateTime.now(),
created_by: 'null',
updated_by: 'null',
fix_lot: '',
),
);
}
TypePetiModel? tipePetiSqfliteApi;
if (petiSqfliteApi != null && petiSqfliteApi.tipe_peti_id != null) {
tipePetiSqfliteApi = tipePetiData?.firstWhere(
(tipePeti) => tipePeti.id == petiSqfliteApi?.tipe_peti_id,
orElse: () => TypePetiModel(
id: null,
type: 'null',
size_peti: 'null',
description: 'null',
created_by: 'null',
updated_by: 'null',
),
);
}
CustomerModel? customerSqfliteApi;
if (petiSqfliteApi != null && petiSqfliteApi.customer_id != null) {
customerSqfliteApi = customerData?.firstWhere(
(customer) => customer.id == item.customer_id,
orElse: () => CustomerModel(
id: null,
name: 'null',
code_customer: 'null',
lot_no: 'null',
created_by: 'null',
updated_by: 'null',
),
);
}
WarehouseModel? warehouseSqfliteApi;
if (item.warehouse_id != null) {
warehouseSqfliteApi = warehouseData?.firstWhere(
(warehouse) => warehouse.id == item.warehouse_id,
orElse: () => WarehouseModel(
id: null,
name: 'null',
created_by: 'null',
updated_by: 'null',
),
);
}
WarehouseModel? warehouseTujuanSqfliteApi;
warehouseTujuanSqfliteApi = warehouseData?.firstWhereOrNull(
(warehouse) => warehouse.id == item.exit_warehouse,
);
return DataRow(cells: [
DataCell(
Text(
(index + 1).toString(),
),
),
DataCell(
GestureDetector(
onTap: () {
if (item.id != null) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DetailPeminjamanBarangPage(
peminjamanId: item.id.toString(),
),
),
);
print('asset id: ${item.id}');
}
},
child: Icon(Icons.article,
size: 40,
color: Colors.indigo[700]), // Ganti ikon sesuai kebutuhan
),
),
DataCell(
Text(
petiSqfliteApi != null && petiSqfliteApi.fix_lot != null
? petiSqfliteApi!.fix_lot.toString()
: '-',
),
),
DataCell(
Text(
customerSqfliteApi != null && customerSqfliteApi.name != null
? customerSqfliteApi!.name.toString()
: '-',
),
),
DataCell(
Text(
item.exit_at != null
? DateFormat('dd-MM-yyyy').format(item.exit_at!)
: '-',
),
),
DataCell(
Text(
item.est_pengembalian != null
? DateFormat('dd-MM-yyyy').format(item.est_pengembalian!)
: '-',
),
),
DataCell(
Text(
item.exit_pic != null ? item.exit_pic.toString() : '-',
),
),
DataCell(
Text(
warehouseSqfliteApi != null && warehouseSqfliteApi.name != null
? warehouseSqfliteApi.name.toString()
: '-',
),
),
DataCell(
Text(
warehouseTujuanSqfliteApi != null &&
warehouseTujuanSqfliteApi.name != null
? warehouseTujuanSqfliteApi.name.toString()
: '-',
),
),
]);
}
@override
bool get isRowCountApproximate => false;
@override
int get rowCount => data.length;
@override
int get selectedRowCount => 0;
}