kelola penyewa dan beberapa error fix
This commit is contained in:
@ -476,7 +476,7 @@ class ListPetugasMitraView extends GetView<ListPetugasMitraController> {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Harap isi semua data',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
@ -600,7 +600,7 @@ class ListPetugasMitraView extends GetView<ListPetugasMitraController> {
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Harap isi semua data',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
|
@ -203,7 +203,7 @@ class ListTagihanPeriodeView extends GetView<ListTagihanPeriodeController> {
|
||||
backgroundColor: Colors.orange.withOpacity(0.1),
|
||||
colorText: Colors.orange.shade800,
|
||||
duration: const Duration(seconds: 3),
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
margin: const EdgeInsets.all(8),
|
||||
);
|
||||
},
|
||||
|
@ -81,11 +81,15 @@ class _PetugasAsetViewState extends State<PetugasAsetView>
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
// Navigate to PetugasTambahAsetView in add mode
|
||||
// Navigate to PetugasTambahAsetView in add mode and refresh data when returning
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_ASET,
|
||||
arguments: {'isEditing': false, 'assetData': null},
|
||||
);
|
||||
)?.then((_) {
|
||||
// Refresh data when returning from tambah_aset page
|
||||
debugPrint('Returning from tambah aset page, refreshing data...');
|
||||
controller.loadAsetData();
|
||||
});
|
||||
},
|
||||
backgroundColor: AppColorsPetugas.babyBlueBright,
|
||||
icon: Icon(Icons.add, color: AppColorsPetugas.blueGrotto),
|
||||
@ -456,7 +460,7 @@ class _PetugasAsetViewState extends State<PetugasAsetView>
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'ID Aset tidak valid',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -467,7 +471,13 @@ class _PetugasAsetViewState extends State<PetugasAsetView>
|
||||
'isEditing': true,
|
||||
'assetId': assetId,
|
||||
},
|
||||
);
|
||||
)?.then((_) {
|
||||
// Refresh data when returning from edit page
|
||||
debugPrint(
|
||||
'Returning from edit aset page, refreshing data...',
|
||||
);
|
||||
controller.loadAsetData();
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
@ -670,235 +680,16 @@ class _PetugasAsetViewState extends State<PetugasAsetView>
|
||||
}
|
||||
}
|
||||
|
||||
void _showAddEditAssetDialog(
|
||||
BuildContext context, {
|
||||
Map<String, dynamic>? aset,
|
||||
}) {
|
||||
final isEditing = aset != null;
|
||||
|
||||
// In a real app, this would have proper form handling with controllers
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Dialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlue,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
isEditing ? Icons.edit : Icons.add,
|
||||
color: AppColorsPetugas.navyBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
isEditing ? 'Edit Aset' : 'Tambah Aset Baru',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorsPetugas.navyBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Silakan lengkapi form di bawah ini',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColorsPetugas.textSecondary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Mock form - In a real app this would have actual form fields
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlueBright,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: AppColorsPetugas.babyBlue),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Form pengelolaan aset akan ditampilkan di sini dengan field untuk:',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildMockFormField('Nama Aset', 'Contoh: Meja Rapat'),
|
||||
_buildMockFormField('Kategori', 'Pilih kategori aset'),
|
||||
_buildMockFormField(
|
||||
'Harga',
|
||||
'Masukkan harga per unit/periode',
|
||||
),
|
||||
_buildMockFormField(
|
||||
'Satuan',
|
||||
'Contoh: per hari, per bulan',
|
||||
),
|
||||
_buildMockFormField('Stok', 'Jumlah unit tersedia'),
|
||||
_buildMockFormField(
|
||||
'Deskripsi',
|
||||
'Keterangan lengkap aset',
|
||||
),
|
||||
_buildMockToggle(
|
||||
'Status Ketersediaan',
|
||||
isEditing && aset?['tersedia'] == true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Action buttons
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: Text(
|
||||
'Batal',
|
||||
style: TextStyle(
|
||||
color: AppColorsPetugas.textSecondary,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
// In a real app, we would save the form data
|
||||
Get.snackbar(
|
||||
isEditing ? 'Aset Diperbarui' : 'Aset Ditambahkan',
|
||||
isEditing
|
||||
? 'Aset berhasil diperbarui'
|
||||
: 'Aset baru berhasil ditambahkan',
|
||||
backgroundColor: AppColorsPetugas.success,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
margin: const EdgeInsets.all(16),
|
||||
borderRadius: 10,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 24,
|
||||
vertical: 12,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
child: Text(isEditing ? 'Simpan' : 'Tambah'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMockFormField(String label, String hint) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: AppColorsPetugas.babyBlue),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
hint,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColorsPetugas.textLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
Icons.keyboard_arrow_down,
|
||||
color: AppColorsPetugas.textSecondary,
|
||||
size: 20,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMockToggle(String label, bool value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: (_) {},
|
||||
activeColor: AppColorsPetugas.blueGrotto,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
void _showAddEditAssetDialog(BuildContext context) {
|
||||
// Navigate to PetugasTambahAsetView in add mode and refresh data when returning
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_ASET,
|
||||
arguments: {'isEditing': false, 'assetData': null},
|
||||
)?.then((_) {
|
||||
// Refresh data when returning from tambah_aset page
|
||||
debugPrint('Returning from tambah aset page, refreshing data...');
|
||||
controller.loadAsetData();
|
||||
});
|
||||
}
|
||||
|
||||
void _showDeleteConfirmation(
|
||||
|
@ -1023,7 +1023,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status sewa telah diubah menjadi SELESAI',
|
||||
backgroundColor: Colors.green,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -1054,7 +1054,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status sewa telah diubah menjadi DIKEMBALIKAN',
|
||||
backgroundColor: Colors.teal,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -1127,7 +1127,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status sewa telah diubah menjadi DIBATALKAN',
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -1381,7 +1381,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status pengajuan diubah menjadi Periksa Pembayaran',
|
||||
backgroundColor: Colors.amber.shade700,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -1394,7 +1394,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Pengajuan sewa aset telah disetujui',
|
||||
backgroundColor: Colors.green.shade600,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -1407,7 +1407,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Permintaan pembayaran denda telah dikirim',
|
||||
backgroundColor: Colors.deepOrange,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -1420,7 +1420,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status pengajuan diubah menjadi Periksa Denda',
|
||||
backgroundColor: Colors.red.shade600,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -1433,7 +1433,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Aset telah dikembalikan dan sewa telah selesai',
|
||||
backgroundColor: Colors.green.shade600,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
break;
|
||||
|
||||
@ -1476,7 +1476,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status sewa telah diubah menjadi DIBATALKAN',
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -1595,7 +1595,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Status sewa diubah menjadi Dikembalikan',
|
||||
backgroundColor: Colors.teal,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1628,7 +1628,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Permintaan pembayaran denda telah dikirim',
|
||||
backgroundColor: Colors.deepOrange,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1661,7 +1661,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Sewa aset telah selesai',
|
||||
backgroundColor: Colors.purple,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
};
|
||||
} else if (status == 'Dikembalikan') {
|
||||
@ -1709,7 +1709,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Sewa aset telah selesai',
|
||||
backgroundColor: Colors.purple,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.task_alt_outlined),
|
||||
@ -1817,7 +1817,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Bukti sewa dalam format PDF sedang diunduh',
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1837,7 +1837,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Bukti sewa dalam format JPG sedang diunduh',
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1857,7 +1857,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Data sewa dalam format XLSX sedang diunduh',
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1963,7 +1963,8 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
width: double.infinity,
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: () {
|
||||
nominalController.text = sewa.totalTagihan.toString();
|
||||
nominalController.text =
|
||||
sewa.totalTagihan.toInt().toString();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.payments_outlined,
|
||||
@ -2456,7 +2457,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Nominal denda harus diisi',
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@ -2501,7 +2502,7 @@ class _PetugasDetailSewaViewState extends State<PetugasDetailSewaView> {
|
||||
'Permintaan pembayaran denda telah dikirim',
|
||||
backgroundColor: Colors.deepOrange,
|
||||
colorText: Colors.white,
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.check_circle),
|
||||
|
@ -567,7 +567,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur tambah rekening bank sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -639,7 +639,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur edit rekening bank sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -689,7 +689,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur hapus rekening bank sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -765,7 +765,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur tambah mitra sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -845,7 +845,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur edit mitra sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -895,7 +895,7 @@ class PetugasManajemenBumdesView
|
||||
Get.snackbar(
|
||||
'Info',
|
||||
'Fitur hapus mitra sedang dalam pengembangan',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
snackPosition: SnackPosition.TOP,
|
||||
);
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
|
@ -55,11 +55,17 @@ class PetugasPaketView extends GetView<PetugasPaketController> {
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed:
|
||||
() => Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_PAKET,
|
||||
arguments: {'isEditing': false},
|
||||
),
|
||||
onPressed: () async {
|
||||
final result = await Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_PAKET,
|
||||
arguments: {'isEditing': false},
|
||||
);
|
||||
|
||||
// Refresh the package list if a package was added
|
||||
if (result == true) {
|
||||
controller.loadPaketData();
|
||||
}
|
||||
},
|
||||
label: Text(
|
||||
'Tambah Paket',
|
||||
style: TextStyle(
|
||||
@ -142,11 +148,17 @@ class PetugasPaketView extends GetView<PetugasPaketController> {
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed:
|
||||
() => Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_PAKET,
|
||||
arguments: {'isEditing': false},
|
||||
),
|
||||
onPressed: () async {
|
||||
final result = await Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_PAKET,
|
||||
arguments: {'isEditing': false},
|
||||
);
|
||||
|
||||
// Refresh the package list if a package was added
|
||||
if (result == true) {
|
||||
controller.loadPaketData();
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Tambah Paket'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
@ -376,6 +388,21 @@ class PetugasPaketView extends GetView<PetugasPaketController> {
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
final result = await Get.toNamed(
|
||||
Routes.PETUGAS_TAMBAH_PAKET,
|
||||
arguments: {
|
||||
'isEditing': false,
|
||||
'isViewing': true,
|
||||
'paket': paket,
|
||||
},
|
||||
);
|
||||
|
||||
// Refresh the package list if data was modified
|
||||
if (result == true) {
|
||||
controller.loadPaketData();
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
// Paket image or icon
|
||||
|
@ -111,6 +111,27 @@ class _PetugasPenyewaViewState extends State<PetugasPenyewaView>
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
// Tambahkan indikator refresh
|
||||
Obx(
|
||||
() =>
|
||||
controller.isRefreshing.value
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(right: 16.0),
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: CircularProgressIndicator(
|
||||
color: Colors.white,
|
||||
strokeWidth: 2,
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
: SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
),
|
||||
drawer: PetugasSideNavbar(controller: dashboardController),
|
||||
drawerEdgeDragWidth: 60,
|
||||
@ -148,7 +169,13 @@ class _PetugasPenyewaViewState extends State<PetugasPenyewaView>
|
||||
}
|
||||
|
||||
if (controller.filteredPenyewaList.isEmpty) {
|
||||
return _buildEmptyState();
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.refreshPenyewaList();
|
||||
},
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
child: _buildEmptyStateWithScrollView(),
|
||||
);
|
||||
}
|
||||
|
||||
return _buildPenyewaList();
|
||||
@ -282,208 +309,234 @@ class _PetugasPenyewaViewState extends State<PetugasPenyewaView>
|
||||
);
|
||||
}
|
||||
|
||||
// Widget untuk menampilkan empty state dengan ScrollView untuk mendukung RefreshIndicator
|
||||
Widget _buildEmptyStateWithScrollView() {
|
||||
return ListView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
children: [
|
||||
SizedBox(
|
||||
height: MediaQuery.of(Get.context!).size.height * 0.7,
|
||||
child: _buildEmptyState(),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPenyewaList() {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: controller.filteredPenyewaList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final penyewa = controller.filteredPenyewaList[index];
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: InkWell(
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await controller.refreshPenyewaList();
|
||||
},
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(16),
|
||||
itemCount: controller.filteredPenyewaList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final penyewa = controller.filteredPenyewaList[index];
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header with avatar and badge
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlueLight.withOpacity(0.2),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Material(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header with avatar and badge
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlueLight.withOpacity(
|
||||
0.2,
|
||||
),
|
||||
borderRadius: const BorderRadius.only(
|
||||
topLeft: Radius.circular(16),
|
||||
topRight: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Avatar with border
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: Colors.white,
|
||||
width: 2,
|
||||
),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CircleAvatar(
|
||||
radius: 24,
|
||||
backgroundColor: AppColorsPetugas.babyBlueLight,
|
||||
backgroundImage:
|
||||
penyewa['avatar'] != null &&
|
||||
penyewa['avatar']
|
||||
.toString()
|
||||
.isNotEmpty
|
||||
? NetworkImage(penyewa['avatar'])
|
||||
: null,
|
||||
child:
|
||||
penyewa['avatar'] == null ||
|
||||
penyewa['avatar'].toString().isEmpty
|
||||
? const Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
// Name and email
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
penyewa['nama_lengkap'] ??
|
||||
'Nama tidak tersedia',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorsPetugas.navyBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.email_outlined,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(
|
||||
child: Text(
|
||||
penyewa['email'] ??
|
||||
'Email tidak tersedia',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_buildStatusBadge(penyewa['status']),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Avatar with border
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CircleAvatar(
|
||||
radius: 24,
|
||||
backgroundColor: AppColorsPetugas.babyBlueLight,
|
||||
backgroundImage:
|
||||
penyewa['avatar'] != null &&
|
||||
penyewa['avatar']
|
||||
.toString()
|
||||
.isNotEmpty
|
||||
? NetworkImage(penyewa['avatar'])
|
||||
: null,
|
||||
child:
|
||||
penyewa['avatar'] == null ||
|
||||
penyewa['avatar'].toString().isEmpty
|
||||
? const Icon(
|
||||
Icons.person,
|
||||
color: Colors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
// Name and email
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
penyewa['nama_lengkap'] ??
|
||||
'Nama tidak tersedia',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppColorsPetugas.navyBlue,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.email_outlined,
|
||||
size: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(
|
||||
child: Text(
|
||||
penyewa['email'] ??
|
||||
'Email tidak tersedia',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
_buildStatusBadge(penyewa['status']),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Content section
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Show additional info only for Aktif and Ditangguhkan tabs
|
||||
if (controller.currentTabIndex.value != 0) ...[
|
||||
Row(
|
||||
children: [
|
||||
_buildInfoChip(
|
||||
Icons.credit_card_outlined,
|
||||
'NIK: ${penyewa['nik'] ?? 'Tidak tersedia'}',
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
_buildInfoChip(
|
||||
Icons.phone_outlined,
|
||||
penyewa['no_hp'] ?? 'No. HP tidak tersedia',
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_buildInfoTile(
|
||||
'Total Sewa',
|
||||
penyewa['total_sewa']?.toString() ?? '0',
|
||||
Icons.shopping_bag_outlined,
|
||||
AppColorsPetugas.blueGrotto,
|
||||
),
|
||||
if (controller.currentTabIndex.value == 1 ||
|
||||
controller.currentTabIndex.value == 2)
|
||||
_buildActionChip(
|
||||
label: 'Lihat Detail',
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
icon: Icons.visibility,
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_DETAIL_PENYEWA,
|
||||
arguments: {
|
||||
'userId': penyewa['user_id'],
|
||||
},
|
||||
);
|
||||
},
|
||||
// Content section
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Show additional info only for Aktif and Ditangguhkan tabs
|
||||
if (controller.currentTabIndex.value != 0) ...[
|
||||
Row(
|
||||
children: [
|
||||
_buildInfoChip(
|
||||
Icons.credit_card_outlined,
|
||||
'NIK: ${penyewa['nik'] ?? 'Tidak tersedia'}',
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 8),
|
||||
_buildInfoChip(
|
||||
Icons.phone_outlined,
|
||||
penyewa['no_hp'] ?? 'No. HP tidak tersedia',
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
_buildInfoTile(
|
||||
'Total Sewa',
|
||||
penyewa['total_sewa']?.toString() ?? '0',
|
||||
Icons.shopping_bag_outlined,
|
||||
AppColorsPetugas.blueGrotto,
|
||||
),
|
||||
if (controller.currentTabIndex.value == 1 ||
|
||||
controller.currentTabIndex.value == 2)
|
||||
_buildActionChip(
|
||||
label: 'Lihat Detail',
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
icon: Icons.visibility,
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_DETAIL_PENYEWA,
|
||||
arguments: {
|
||||
'userId': penyewa['user_id'],
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
// Add "Detail" button for Verifikasi tab
|
||||
if (controller.currentTabIndex.value == 0) ...[
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildActionChip(
|
||||
label: 'Lihat Detail & Verifikasi',
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
icon: Icons.visibility,
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_DETAIL_PENYEWA,
|
||||
arguments: {
|
||||
'userId': penyewa['user_id'],
|
||||
},
|
||||
);
|
||||
},
|
||||
// Add "Detail" button for Verifikasi tab
|
||||
if (controller.currentTabIndex.value == 0) ...[
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildActionChip(
|
||||
label: 'Lihat Detail & Verifikasi',
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
icon: Icons.visibility,
|
||||
onTap: () {
|
||||
Get.toNamed(
|
||||
Routes.PETUGAS_DETAIL_PENYEWA,
|
||||
arguments: {
|
||||
'userId': penyewa['user_id'],
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,9 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
appBar: AppBar(
|
||||
title: Obx(
|
||||
() => Text(
|
||||
controller.isEditing.value ? 'Edit Paket' : 'Tambah Paket',
|
||||
controller.isViewing.value
|
||||
? 'Detail Paket'
|
||||
: (controller.isEditing.value ? 'Edit Paket' : 'Tambah Paket'),
|
||||
style: const TextStyle(fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
@ -168,15 +170,16 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
'Item Paket',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _showAddItemDialog(),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Tambah Item'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.babyBlueLight,
|
||||
foregroundColor: AppColorsPetugas.blueGrotto,
|
||||
if (!controller.isViewing.value)
|
||||
ElevatedButton.icon(
|
||||
onPressed: () => _showAddItemDialog(),
|
||||
icon: const Icon(Icons.add),
|
||||
label: const Text('Tambah Item'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.babyBlueLight,
|
||||
foregroundColor: AppColorsPetugas.blueGrotto,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
@ -208,26 +211,33 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
Text('Stok tersedia: ${item['stok']}'),
|
||||
],
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.edit,
|
||||
color: Colors.blue,
|
||||
),
|
||||
onPressed: () => _showEditItemDialog(index),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.delete,
|
||||
color: Colors.red,
|
||||
),
|
||||
onPressed:
|
||||
() => controller.removeItem(index),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing:
|
||||
controller.isViewing.value
|
||||
? null
|
||||
: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.edit,
|
||||
color: Colors.blue,
|
||||
),
|
||||
onPressed:
|
||||
() =>
|
||||
_showEditItemDialog(index),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(
|
||||
Icons.delete,
|
||||
color: Colors.red,
|
||||
),
|
||||
onPressed:
|
||||
() => controller.removeItem(
|
||||
index,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -526,6 +536,9 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
String? prefixText,
|
||||
IconData? prefixIcon,
|
||||
}) {
|
||||
final petugasController =
|
||||
this.controller; // Reference to PetugasTambahPaketController
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
@ -539,7 +552,7 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
color: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
),
|
||||
if (isRequired) ...[
|
||||
if (isRequired && !petugasController.isViewing.value) ...[
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'*',
|
||||
@ -553,43 +566,55 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextFormField(
|
||||
controller: controller,
|
||||
maxLines: maxLines,
|
||||
keyboardType: keyboardType,
|
||||
inputFormatters: inputFormatters,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: TextStyle(color: AppColorsPetugas.textLight),
|
||||
filled: true,
|
||||
fillColor: AppColorsPetugas.babyBlueBright,
|
||||
prefixText: prefixText,
|
||||
prefixIcon:
|
||||
prefixIcon != null
|
||||
? Icon(
|
||||
prefixIcon,
|
||||
size: 20,
|
||||
color: AppColorsPetugas.textSecondary,
|
||||
)
|
||||
: null,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide.none,
|
||||
Obx(
|
||||
() => TextFormField(
|
||||
controller: controller,
|
||||
maxLines: maxLines,
|
||||
keyboardType: keyboardType,
|
||||
inputFormatters: inputFormatters,
|
||||
readOnly: petugasController.isViewing.value,
|
||||
style: TextStyle(
|
||||
color:
|
||||
petugasController.isViewing.value
|
||||
? AppColorsPetugas.textSecondary
|
||||
: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide(
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
width: 1.5,
|
||||
decoration: InputDecoration(
|
||||
hintText: hint,
|
||||
hintStyle: TextStyle(color: AppColorsPetugas.textLight),
|
||||
filled: true,
|
||||
fillColor:
|
||||
petugasController.isViewing.value
|
||||
? AppColorsPetugas.babyBlueLight
|
||||
: AppColorsPetugas.babyBlueBright,
|
||||
prefixText: prefixText,
|
||||
prefixIcon:
|
||||
prefixIcon != null
|
||||
? Icon(
|
||||
prefixIcon,
|
||||
size: 20,
|
||||
color: AppColorsPetugas.textSecondary,
|
||||
)
|
||||
: null,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide(
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
width: 1.5,
|
||||
),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -646,7 +671,10 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
vertical: 12,
|
||||
),
|
||||
filled: true,
|
||||
fillColor: AppColorsPetugas.babyBlueBright,
|
||||
fillColor:
|
||||
controller.isViewing.value
|
||||
? AppColorsPetugas.babyBlueLight
|
||||
: AppColorsPetugas.babyBlueBright,
|
||||
),
|
||||
items:
|
||||
options.map((option) {
|
||||
@ -661,9 +689,12 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (value) {
|
||||
if (value != null) onChanged(value);
|
||||
},
|
||||
onChanged:
|
||||
controller.isViewing.value
|
||||
? null // Disable in view-only mode
|
||||
: (value) {
|
||||
if (value != null) onChanged(value);
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.keyboard_arrow_down_rounded,
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
@ -717,41 +748,42 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
runSpacing: 12,
|
||||
children: [
|
||||
// Add button
|
||||
GestureDetector(
|
||||
onTap: _showImageSourceOptions,
|
||||
child: Container(
|
||||
width: 100,
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlueBright,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: AppColorsPetugas.babyBlue,
|
||||
width: 1,
|
||||
style: BorderStyle.solid,
|
||||
if (!controller.isViewing.value)
|
||||
GestureDetector(
|
||||
onTap: _showImageSourceOptions,
|
||||
child: Container(
|
||||
width: 100,
|
||||
height: 100,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColorsPetugas.babyBlueBright,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: AppColorsPetugas.babyBlue,
|
||||
width: 1,
|
||||
style: BorderStyle.solid,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_photo_alternate_outlined,
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
size: 32,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Tambah Foto',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_photo_alternate_outlined,
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
size: 32,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Tambah Foto',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: AppColorsPetugas.blueGrotto,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// Image previews
|
||||
...List<Widget>.generate(controller.selectedImages.length, (
|
||||
index,
|
||||
@ -811,21 +843,24 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
Positioned(
|
||||
top: 4,
|
||||
right: 4,
|
||||
child: InkWell(
|
||||
onTap: () => controller.removeImage(index),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
child:
|
||||
!controller.isViewing.value
|
||||
? InkWell(
|
||||
onTap: () => controller.removeImage(index),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.white,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.close,
|
||||
size: 18,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -949,67 +984,97 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
label: const Text('Batal'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColorsPetugas.textSecondary,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
|
||||
side: BorderSide(color: AppColorsPetugas.divider),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Obx(() {
|
||||
// In view-only mode, just show a back button
|
||||
if (controller.isViewing.value) {
|
||||
return SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
label: const Text('Kembali'),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
textStyle: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final isValid = controller.isFormValid.value;
|
||||
final isSubmitting = controller.isSubmitting.value;
|
||||
return ElevatedButton.icon(
|
||||
onPressed:
|
||||
controller.isFormChanged.value && !isSubmitting
|
||||
? controller.savePaket
|
||||
: null,
|
||||
icon:
|
||||
);
|
||||
}
|
||||
|
||||
// For edit/add mode, show cancel and save buttons
|
||||
return Row(
|
||||
children: [
|
||||
OutlinedButton.icon(
|
||||
onPressed: () => Get.back(),
|
||||
icon: const Icon(Icons.arrow_back),
|
||||
label: const Text('Batal'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: AppColorsPetugas.textSecondary,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12,
|
||||
horizontal: 16,
|
||||
),
|
||||
side: BorderSide(color: AppColorsPetugas.divider),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Obx(() {
|
||||
final isValid = controller.isFormValid.value;
|
||||
final isSubmitting = controller.isSubmitting.value;
|
||||
return ElevatedButton.icon(
|
||||
onPressed:
|
||||
controller.isFormChanged.value && !isSubmitting
|
||||
? controller.savePaket
|
||||
: null,
|
||||
icon:
|
||||
isSubmitting
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.save),
|
||||
label: Text(
|
||||
isSubmitting
|
||||
? const SizedBox(
|
||||
width: 24,
|
||||
height: 24,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: Colors.white,
|
||||
),
|
||||
)
|
||||
: const Icon(Icons.save),
|
||||
label: Text(
|
||||
isSubmitting
|
||||
? 'Menyimpan...'
|
||||
: (controller.isEditing.value
|
||||
? 'Simpan Paket'
|
||||
: 'Tambah Paket'),
|
||||
),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
textStyle: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
? 'Menyimpan...'
|
||||
: (controller.isEditing.value
|
||||
? 'Simpan Paket'
|
||||
: 'Tambah Paket'),
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: AppColorsPetugas.blueGrotto,
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
textStyle: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
disabledBackgroundColor: AppColorsPetugas.textLight,
|
||||
),
|
||||
disabledBackgroundColor: AppColorsPetugas.textLight,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@ -1035,7 +1100,10 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
() => Material(
|
||||
color: Colors.transparent,
|
||||
child: InkWell(
|
||||
onTap: () => controller.toggleTimeOption(option),
|
||||
onTap:
|
||||
controller.isViewing.value
|
||||
? null
|
||||
: () => controller.toggleTimeOption(option),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
@ -1173,12 +1241,22 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
controller: priceController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
readOnly: controller.isViewing.value,
|
||||
style: TextStyle(
|
||||
color:
|
||||
controller.isViewing.value
|
||||
? AppColorsPetugas.textSecondary
|
||||
: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Masukkan harga',
|
||||
hintStyle: TextStyle(color: AppColorsPetugas.textLight),
|
||||
prefixText: 'Rp ',
|
||||
filled: true,
|
||||
fillColor: AppColorsPetugas.babyBlueBright,
|
||||
fillColor:
|
||||
controller.isViewing.value
|
||||
? AppColorsPetugas.babyBlueLight
|
||||
: AppColorsPetugas.babyBlueBright,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
@ -1210,11 +1288,21 @@ class PetugasTambahPaketView extends GetView<PetugasTambahPaketController> {
|
||||
controller: maxController,
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
readOnly: controller.isViewing.value,
|
||||
style: TextStyle(
|
||||
color:
|
||||
controller.isViewing.value
|
||||
? AppColorsPetugas.textSecondary
|
||||
: AppColorsPetugas.textPrimary,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
hintText: 'Opsional',
|
||||
hintStyle: TextStyle(color: AppColorsPetugas.textLight),
|
||||
filled: true,
|
||||
fillColor: AppColorsPetugas.babyBlueBright,
|
||||
fillColor:
|
||||
controller.isViewing.value
|
||||
? AppColorsPetugas.babyBlueLight
|
||||
: AppColorsPetugas.babyBlueBright,
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 12,
|
||||
vertical: 12,
|
||||
|
Reference in New Issue
Block a user