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.

1072 lines
34 KiB

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:siopas/migrations/databasehelper.dart';
import 'package:siopas/models/transfer_peti_model.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../models/asset_status_model.dart';
import '../../models/condition_peti_model.dart';
import '../../models/customer_model.dart';
import '../../models/m_asset_status_model.dart';
import '../../models/type_peti_model.dart';
import '../../models/user_model.dart';
import '../../models/warehouse_mode.dart';
import '../../providers/auth_provider.dart';
import 'package:intl/intl.dart';
import 'package:intl/date_symbol_data_local.dart';
import '../../services/controllerApi.dart';
import '../../services/syncronizeAPI.dart';
import '../../theme.dart';
import '../../widget/loading_shimmer_show.dart';
import '../peminjaman_barang/conn/syncronize.dart';
import '../peminjaman_barang/controller/peminjaman_controller.dart';
import '../pengembalian_barang/conn/syncronize.dart';
import '../transfer_peti/conn/syncronize.dart';
import 'conn_home_page.dart/syncronize.dart';
import 'controller/home_controller.dart';
class HomePage extends StatefulWidget {
final ControllerHome controllerHome = ControllerHome(); // Declare here
final VoidCallback? onReinitStarted;
final VoidCallback? onReinitFinished;
HomePage({
Key? key,
this.onReinitStarted,
this.onReinitFinished,
}) : super(key: key);
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String? token;
bool loading = true;
// Reinit atau Upload Only
WarehouseModel? warehouseSqfliteApi;
List<TypePetiModel>? typePetiSqfliteApi;
List<CustomerModel>? customerSqfliteApi;
PetiAssetModel? petiSqfliteApi;
List<PetiAssetModel>? _valpeti; // Change this line
List<WarehouseModel>? _valwarehouse;
List<ConditionPetiModel>? _valcondition;
// Datatable
int _currentPage = 1;
int _pageSize = 10;
List<AssetStatusModel>? _data;
List<PetiAssetModel>? _petiData;
List<TypePetiModel>? _tipePetiData;
List<CustomerModel>? _customerData;
List<WarehouseModel>? _warehouseData;
Timer? _timer;
int _peminjamanCount = 0;
int _pengembalianCount = 0;
int _transferCount = 0;
bool _isLoading = false;
bool _isFetchingData = false;
@override
void initState() {
super.initState();
_getUserToken();
// Mengatur _isLoading dan _isFetchingData ke true sebelum tugas dimulai
if (mounted) {
setState(() {
_isLoading = true;
_isFetchingData = true;
});
}
// Memanggil _refreshPage untuk menginisialisasi dan memuat data
_refreshPage();
_data = <AssetStatusModel>[];
}
Future<void> _refreshPage() async {
// Menggunakan Future.wait untuk menunggu hasil dari semua tugas selesai
await Future.wait([
_initData(),
warehouseListAPI(),
typePetiListAPI(),
customerListAPI(),
petiListAPI(),
datatablesAssetStatusList(),
datatablesPetiList(),
datatablesTipePetiList(),
datatablesCustomerList(),
datatablesWarehouseList(),
initializeDateFormatting('id_ID', null),
]);
// Mengatur _isLoading dan _isFetchingData ke false setelah semua tugas selesai
if (mounted) {
setState(() {
_isLoading = false;
_isFetchingData = false;
});
}
}
@override
void setState(fn) {
if (mounted) {
super.setState(fn);
}
}
Future<void> _initData() async {
try {
_peminjamanCount = await widget.controllerHome.getPeminjamanCount();
_pengembalianCount = await widget.controllerHome.getPengembalianCount();
_transferCount = await widget.controllerHome.getTransferCount();
} catch (error) {
print(error);
}
// ... tambahkan inisialisasi lainnya
}
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 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 kondisiPetiListAPI() async {
if (mounted) {
await ControllerApi().fetchKondisiPetiDataAPI().then((value) {
setState(() {
_valcondition = (value as List<dynamic>)
.map((item) => ConditionPetiModel.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> 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 {
if (_isFetchingData) {
// Data is already being fetched, don't start another process
return;
}
// Set _isFetchingData to true to disable the button
setState(() {
_isFetchingData = true;
});
// Callback to inform that Reinit process has started
widget.onReinitStarted?.call();
EasyLoading.show(status: 'Mengambil data dari Server...');
try {
// Cek koneksi internet
bool hasInternet = await SyncronizationGlobalData.isInternet();
if (!hasInternet) {
EasyLoading.showError('Tidak ada koneksi internet');
return;
}
// Lanjutkan sinkronisasi jika ada koneksi
await syncToGlobal('Peminjaman');
await syncToGlobal('Pengembalian');
await syncToGlobal('Transfer');
// await reinitAssetStatusApi();
await reinitWarehouseApi();
await reinitPetiApi();
await reinitCustomerApi();
// await reinitTypePetiApi();
await reinitConditionPetiApi();
await datatablesAssetStatusList();
Navigator.pushNamed(context, '/home');
EasyLoading.showSuccess('Data berhasil diperbarui');
} catch (e) {
EasyLoading.showError('Gagal memperbarui data: $e');
} finally {
// Set _isFetchingData back to false when the process finishes
if (mounted) {
setState(() {
_isFetchingData = false;
});
EasyLoading.dismiss();
// Callback to inform that Reinit process has finished
widget.onReinitFinished?.call();
}
}
}
// Future<void> fetchDataFromApiAndSync() async {
// if (_isFetchingData) {
// // Data is already being fetched, don't start another process
// return;
// }
// // Set _isFetchingData to true to disable the button
// setState(() {
// _isFetchingData = true;
// });
// EasyLoading.show(status: 'Mengambil data dari Server...');
// try {
// // Cek koneksi internet
// bool hasInternet = await SyncronizationGlobalData.isInternet();
// if (!hasInternet) {
// EasyLoading.showError('Tidak ada koneksi internet');
// return;
// }
// // Lanjutkan sinkronisasi jika ada koneksi
// await syncToGlobal('Peminjaman');
// await syncToGlobal('Pengembalian');
// await syncToGlobal('Transfer');
// // await reinitAssetStatusApi();
// await reinitWarehouseApi();
// await reinitPetiApi();
// await reinitCustomerApi();
// // await reinitTypePetiApi();
// await reinitConditionPetiApi();
// await datatablesAssetStatusList();
// Navigator.pushNamed(context, '/home');
// EasyLoading.showSuccess('Data berhasil diperbarui');
// } catch (e) {
// EasyLoading.showError('Gagal memperbarui data: $e');
// } finally {
// // Set _isFetchingData back to false when the process finishes
// if (mounted) {
// setState(() {
// _isFetchingData = false;
// });
// EasyLoading.dismiss();
// }
// }
// }
Future syncToGlobal(String type) async {
try {
EasyLoading.show(
status: 'Jangan tutup aplikasi. Kami sedang menyinkronkan...');
await Future.delayed(Duration(seconds: 3));
// Tambahkan penanganan pengunggahan
bool uploadSuccess = false; // Berikan nilai awal false
if (type == 'Peminjaman') {
List<AssetStatusModel> peminjamanList =
await SyncronizationGlobalData().fetchAllPeminjamanInfo();
uploadSuccess = await SyncronizationPeminjamanData()
.saveToPeminjamanWith(peminjamanList);
// Jika pengunggahan berhasil, hapus data lokal Peminjaman
if (uploadSuccess) {
await SyncronizationGlobalData().deleteAllPeminjamanData();
}
} else if (type == 'Pengembalian') {
List<AssetStatusModel> pengembalianList =
await SyncronizationGlobalData().fetchAllPengembalianInfo();
uploadSuccess = await SyncronizationPengembalianData()
.savePengembalianToServerWith(pengembalianList);
// Jika pengunggahan berhasil, hapus data lokal Pengembalian
if (uploadSuccess) {
await SyncronizationGlobalData().deleteAllPengembalianData();
}
} else if (type == 'Transfer') {
List<TransferPetiModel> transferPetiList =
await SyncronizationGlobalData().fetchAllTransferInfo();
uploadSuccess = await SyncronizationTransferPetiData()
.saveTransferPetiServerWith(transferPetiList);
// Jika pengunggahan berhasil, hapus data lokal Pengembalian
if (uploadSuccess) {
await SyncronizationGlobalData().deleteAllTransferData();
}
}
// Setelah selesai, tampilkan pesan sukses atau gagal
if (uploadSuccess) {
EasyLoading.showSuccess('Berhasil disinkronkan dengan Server');
} else {
EasyLoading.showError('Gagal disinkronkan dengan Server');
}
} catch (error) {
// Handle error jika terjadi
EasyLoading.showError('Terjadi kesalahan: $error');
}
}
Future<void> isInteret() async {
await SyncronizationGlobalData.isInternet().then((connection) {
if (connection) {
print("Internet connection available");
} else {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text("No 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;
});
});
}
}
@override
void dispose() {
_timer?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
AuthProvider authProvider = Provider.of<AuthProvider>(context);
UserModel user = authProvider.user;
// String? token = authProvider.token;
Widget cardMenuPeminjaman() {
return Container(
height: 125,
margin: EdgeInsets.only(left: 10),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 3,
child: InkWell(
onTap: () {
// Aksi ketika card diklik
Navigator.pushNamed(context, '/peminjaman-barang');
},
child: Container(
// padding: EdgeInsets.only(top: 8.0, bottom: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.vertical_align_top,
size: 30,
color: Colors.greenAccent[700],
),
SizedBox(height: 5),
Text(
'Peminjaman (Peti Out)',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
],
),
),
),
),
);
}
Widget cardMenuPengembalian() {
return Container(
height: 125,
margin: EdgeInsets.only(right: 10),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 3,
child: InkWell(
onTap: () {
// Aksi ketika card diklik
Navigator.pushNamed(context, '/pengembalian-barang');
},
child: Container(
// padding: EdgeInsets.all(8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.vertical_align_bottom,
size: 30,
color: Colors.blueAccent[700],
),
SizedBox(height: 5),
Text(
'Pengembalian (Peti In)',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
],
),
),
),
),
);
}
Widget cardMenuTransfer() {
return Container(
height: 125,
margin: EdgeInsets.only(left: 10),
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
elevation: 3,
child: InkWell(
onTap: () {
// Aksi ketika card diklik
Navigator.pushNamed(context, '/transfer-peti');
},
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.input_outlined,
size: 30,
color: Colors.yellow[700],
),
SizedBox(height: 5),
Text(
'Transfer Peti',
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
],
),
),
),
),
);
}
Widget cardTotal(String title, int total, IconData icon) {
return Expanded(
child: Card(
margin: EdgeInsets.all(5),
child: Container(
padding: EdgeInsets.all(5),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(
icon,
size: 20,
color: Colors.blue[700],
),
SizedBox(height: 2),
Text(
title,
style: TextStyle(
fontSize: 8,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
SizedBox(height: 2),
Text(
total.toString(),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.blue[700],
),
),
],
),
),
),
);
}
Widget _buildCountTile(IconData icon, int count, Color color, String text) {
return Column(
children: [
CircleAvatar(
backgroundColor: color,
radius: 12,
child: Icon(icon, size: 12, color: Colors.white),
),
SizedBox(height: 4),
Text(
text,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
Text(
'$count',
style: TextStyle(fontSize: 12),
),
],
);
}
Future<void> showSyncDialog(BuildContext context) async {
// Create an instance of ControllerHome
ControllerHome controllerHome = ControllerHome();
// Fetch counts from the ControllerHome
int peminjamanCount = await controllerHome.getPeminjamanCount();
int pengembalianCount = await controllerHome.getPengembalianCount();
int transferCount = await controllerHome.getTransferCount();
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 Global",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
),
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
),
onPressed: () {
Navigator.pop(context); // Close dialog
},
),
],
),
),
Divider(
height: 1,
thickness: 1,
color: Colors.black, // Black divider
),
// Display counts for each table
SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildCountTile(Icons.vertical_align_top, peminjamanCount,
Colors.green[700]!, 'Peminjaman (Peti Out)'),
_buildCountTile(
Icons.vertical_align_bottom,
pengembalianCount,
Colors.blue[700]!,
'Pengembalian (Peti In)'),
_buildCountTile(Icons.input_outlined, transferCount,
Colors.yellow[700]!, 'Transfer'),
],
),
SizedBox(height: 10),
// Divider
Divider(
height: 1,
thickness: 1,
color: Colors.black, // Black divider
),
// Re-init Button
Container(
width: double.infinity,
child: TextButton(
onPressed: _isFetchingData
? null
: () {
fetchDataFromApiAndSync();
},
child: Text(
"Upload + Download",
style: TextStyle(
color: Colors.black,
fontSize: 16.0,
fontFamily: 'Poppins',
),
),
),
),
],
),
);
},
);
}
Widget cardMenuSync() {
return Card(
elevation: 3,
margin: EdgeInsets.all(10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Container(
color: Color.fromARGB(255, 50, 39, 122),
padding: EdgeInsets.all(16.0),
child: Text(
"Sync Data Global",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 20.0,
),
),
),
SizedBox(height: 10),
// Display counts for each table
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_isLoading
? ShimmerLoadingReinit()
: _buildCountTile(
Icons.vertical_align_top,
_peminjamanCount,
Colors.green[700]!,
'Peti Out',
),
_isLoading
? ShimmerLoadingReinit()
: _buildCountTile(
Icons.vertical_align_bottom,
_pengembalianCount,
Colors.blue[700]!,
'Peti In',
),
_isLoading
? ShimmerLoadingReinit()
: _buildCountTile(
Icons.input_outlined,
_transferCount,
Colors.yellow[700]!,
'Transfer Peti',
),
],
),
SizedBox(height: 10),
// Re-init Button
ElevatedButton(
onPressed: () async {
bool hasInternet = await ControllerApi.isInternetApi();
if (hasInternet) {
showDialog(
context: context,
builder: (BuildContext context) {
return Dialog(
backgroundColor:
Colors.grey[100], // Set the background color
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
),
elevation: 0,
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(
"Konfirmasi Sync",
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
),
// Description text
Container(
padding: EdgeInsets.all(16.0),
child: Text(
"Apakah Anda yakin ingin mengunggah dan mengunduh data?",
style: TextStyle(
fontSize: 16.0,
),
),
),
// Re-init Button with blue background
ElevatedButton(
onPressed: () {
if (hasInternet) {
Navigator.pop(context); // Close dialog
fetchDataFromApiAndSync();
} else {
EasyLoading.showError(
"Tidak ada koneksi internet");
}
},
style: TextButton.styleFrom(
backgroundColor: Colors.blue[700],
),
child: Text(
"Upload + Download",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
fontFamily: 'Poppins',
),
),
),
],
),
);
},
);
} else {
EasyLoading.showError("Tidak ada koneksi internet");
}
},
style: ElevatedButton.styleFrom(
primary: Colors.blue[700],
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"Upload + Download",
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
fontFamily: 'Poppins',
),
),
Icon(
Icons.cloud_upload,
color: Colors.white,
),
],
),
),
)
],
),
);
}
return WillPopScope(
onWillPop: () async {
// Mencegah kembali ke halaman sebelumnya
return false;
},
child: AbsorbPointer(
absorbing: _isFetchingData,
child: Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
elevation: 0,
automaticallyImplyLeading: false,
backgroundColor: Colors.indigo[700],
centerTitle: true,
title: Row(
children: [
SizedBox(width: 10),
Expanded(
child: Center(
child: Column(
children: [
Text(
'SIOPAS-ISTW',
textAlign: TextAlign.center,
),
Text(
'${user.fullname}',
style: TextStyle(
fontSize: 10,
),
),
],
),
),
),
],
),
),
body: RefreshIndicator(
color: Colors.white,
backgroundColor: Colors.indigo[700],
onRefresh: () async {
// Tampilkan Shimmer loading selama proses refresh
setState(() {
_isLoading = true;
});
// Selesaikan proses refresh
await _refreshPage();
// Sembunyikan Shimmer loading setelah selesai
setState(() {
_isLoading = false;
});
},
child: ListView(
children: [
cardMenuSync(),
SizedBox(height: 10),
Container(
padding: EdgeInsets.all(10),
child: Text(
'Menu Aplikasi',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: cardMenuPeminjaman(),
),
Expanded(
child: cardMenuPengembalian(),
),
],
),
SizedBox(height: 10), // Add some space between rows
Row(
children: [
Expanded(
child: cardMenuTransfer(),
),
Expanded(
child: Container(),
// child: cardMenuPengembalian(),
),
],
),
],
),
),
),
),
);
}
}