diff --git a/lib/app/modules/petugas_desa/controllers/petugas_desa_controller.dart b/lib/app/modules/petugas_desa/controllers/petugas_desa_controller.dart index 829d6b1..49c3fcd 100644 --- a/lib/app/modules/petugas_desa/controllers/petugas_desa_controller.dart +++ b/lib/app/modules/petugas_desa/controllers/petugas_desa_controller.dart @@ -43,6 +43,13 @@ class PetugasDesaController extends GetxController { final RxDouble stokMasuk = 0.0.obs; final RxDouble stokKeluar = 0.0.obs; + // Data untuk penitipan + final RxList> daftarPenitipan = + >[].obs; + final RxInt jumlahMenunggu = 0.obs; + final RxInt jumlahTerverifikasi = 0.obs; + final RxInt jumlahDitolak = 0.obs; + // Controller untuk pencarian final TextEditingController searchController = TextEditingController(); @@ -58,6 +65,7 @@ class PetugasDesaController extends GetxController { loadJadwalData(); loadNotifikasiData(); loadInventarisData(); + loadPenitipanData(); } @override @@ -281,6 +289,65 @@ class PetugasDesaController extends GetxController { } } + Future loadPenitipanData() async { + try { + // Simulasi data untuk penitipan + await Future.delayed(const Duration(milliseconds: 600)); + + daftarPenitipan.value = [ + { + 'id': '1', + 'donatur': 'PT Sejahtera Abadi', + 'jenis_bantuan': 'Sembako', + 'jumlah': '500 kg', + 'tanggal_pengajuan': '15 April 2023', + 'status': 'Menunggu', + }, + { + 'id': '2', + 'donatur': 'Yayasan Peduli Sesama', + 'jenis_bantuan': 'Pakaian', + 'jumlah': '200 pcs', + 'tanggal_pengajuan': '14 April 2023', + 'status': 'Terverifikasi', + }, + { + 'id': '3', + 'donatur': 'Bank BRI', + 'jenis_bantuan': 'Beras', + 'jumlah': '300 kg', + 'tanggal_pengajuan': '13 April 2023', + 'status': 'Terverifikasi', + }, + { + 'id': '4', + 'donatur': 'Komunitas Peduli', + 'jenis_bantuan': 'Alat Tulis', + 'jumlah': '100 set', + 'tanggal_pengajuan': '12 April 2023', + 'status': 'Ditolak', + }, + ]; + + // Hitung jumlah penitipan berdasarkan status + jumlahMenunggu.value = + daftarPenitipan.where((p) => p['status'] == 'Menunggu').length; + jumlahTerverifikasi.value = + daftarPenitipan.where((p) => p['status'] == 'Terverifikasi').length; + jumlahDitolak.value = + daftarPenitipan.where((p) => p['status'] == 'Ditolak').length; + + // Di implementasi nyata, data akan diambil dari Supabase + // final result = await _supabaseService.getPenitipanData(); + // daftarPenitipan.value = result ?? []; + // jumlahMenunggu.value = daftarPenitipan.where((p) => p['status'] == 'Menunggu').length; + // jumlahTerverifikasi.value = daftarPenitipan.where((p) => p['status'] == 'Terverifikasi').length; + // jumlahDitolak.value = daftarPenitipan.where((p) => p['status'] == 'Ditolak').length; + } catch (e) { + print('Error loading penitipan data: $e'); + } + } + void tandaiNotifikasiDibaca(String id) { // Implementasi untuk menandai notifikasi sebagai dibaca // Di implementasi nyata, akan memanggil Supabase untuk memperbarui status notifikasi @@ -308,6 +375,25 @@ class PetugasDesaController extends GetxController { loadInventarisData(); } + void terimaPermohonanPenitipan(String id) { + // Implementasi untuk menerima permohonan penitipan + // Di implementasi nyata, akan memanggil Supabase untuk memperbarui status penitipan + // await _supabaseService.acceptDeposit(id); + + // Perbarui data lokal + loadPenitipanData(); + loadInventarisData(); // Perbarui inventaris karena ada penambahan stok + } + + void tolakPermohonanPenitipan(String id) { + // Implementasi untuk menolak permohonan penitipan + // Di implementasi nyata, akan memanggil Supabase untuk memperbarui status penitipan + // await _supabaseService.rejectDeposit(id); + + // Perbarui data lokal + loadPenitipanData(); + } + void logout() { _authController.logout(); } diff --git a/lib/app/modules/petugas_desa/views/inventaris_view.dart b/lib/app/modules/petugas_desa/views/inventaris_view.dart index 77a5a01..04b6e4b 100644 --- a/lib/app/modules/petugas_desa/views/inventaris_view.dart +++ b/lib/app/modules/petugas_desa/views/inventaris_view.dart @@ -8,8 +8,6 @@ class InventarisView extends GetView { @override Widget build(BuildContext context) { - final textTheme = Theme.of(context).textTheme; - return SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(16.0), @@ -39,7 +37,7 @@ class InventarisView extends GetView { width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration( - color: AppTheme.primaryColor.withOpacity(0.1), + gradient: AppTheme.primaryGradient, borderRadius: BorderRadius.circular(12), ), child: Column( @@ -49,6 +47,7 @@ class InventarisView extends GetView { 'Ringkasan Inventaris', style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, + color: Colors.white, ), ), const SizedBox(height: 16), @@ -60,7 +59,6 @@ class InventarisView extends GetView { icon: Icons.inventory_2_outlined, title: 'Total Stok', value: '1,250 kg', - color: Colors.blue, ), ), Expanded( @@ -69,7 +67,6 @@ class InventarisView extends GetView { icon: Icons.input, title: 'Masuk Bulan Ini', value: '500 kg', - color: Colors.green, ), ), Expanded( @@ -78,7 +75,6 @@ class InventarisView extends GetView { icon: Icons.output, title: 'Keluar Bulan Ini', value: '350 kg', - color: Colors.orange, ), ), ], @@ -93,19 +89,18 @@ class InventarisView extends GetView { required IconData icon, required String title, required String value, - required Color color, }) { return Column( children: [ Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( - color: color.withOpacity(0.2), + color: Colors.white.withOpacity(0.2), shape: BoxShape.circle, ), child: Icon( icon, - color: color, + color: Colors.white, size: 24, ), ), @@ -114,12 +109,15 @@ class InventarisView extends GetView { value, style: Theme.of(context).textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, + color: Colors.white, ), ), const SizedBox(height: 4), Text( title, - style: Theme.of(context).textTheme.bodySmall, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.white, + ), textAlign: TextAlign.center, ), ], diff --git a/lib/app/modules/petugas_desa/views/jadwal_view.dart b/lib/app/modules/petugas_desa/views/jadwal_view.dart index 643c07e..23efc41 100644 --- a/lib/app/modules/petugas_desa/views/jadwal_view.dart +++ b/lib/app/modules/petugas_desa/views/jadwal_view.dart @@ -16,6 +16,10 @@ class JadwalView extends GetView { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Ringkasan jadwal + _buildJadwalSummary(context), + + const SizedBox(height: 20), // Jadwal hari ini _buildJadwalSection( textTheme, @@ -84,6 +88,102 @@ class JadwalView extends GetView { ); } + Widget _buildJadwalSummary(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: AppTheme.primaryGradient, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Ringkasan Jadwal', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.pending_actions, + title: 'Terjadwal', + value: '5', + color: Colors.blue, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.event_available, + title: 'Aktif', + value: '1', + color: Colors.green, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.event_busy, + title: 'Selesai', + value: '12', + color: Colors.grey, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildSummaryItem( + BuildContext context, { + required IconData icon, + required String title, + required String value, + required Color color, + }) { + return Column( + children: [ + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.2), + shape: BoxShape.circle, + ), + child: Icon( + icon, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(height: 8), + Text( + value, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 4), + Text( + title, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ], + ); + } + Widget _buildJadwalSection( TextTheme textTheme, { required String title, diff --git a/lib/app/modules/petugas_desa/views/notifikasi_view.dart b/lib/app/modules/petugas_desa/views/notifikasi_view.dart index 0f5e065..ac2b6d8 100644 --- a/lib/app/modules/petugas_desa/views/notifikasi_view.dart +++ b/lib/app/modules/petugas_desa/views/notifikasi_view.dart @@ -10,83 +10,116 @@ class NotifikasiView extends GetView { Widget build(BuildContext context) { final textTheme = Theme.of(context).textTheme; - return SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Notifikasi hari ini - _buildNotifikasiSection( - textTheme, - title: 'Hari Ini', - notifikasiList: [ - { - 'judul': 'Jadwal Penyaluran Baru', - 'pesan': - 'Jadwal penyaluran beras telah ditambahkan untuk hari ini', - 'waktu': '08:30', - 'dibaca': false, - }, - { - 'judul': 'Pengajuan Bantuan Baru', - 'pesan': - 'Ada 3 pengajuan bantuan baru yang perlu diverifikasi', - 'waktu': '10:15', - 'dibaca': false, - }, - ], - ), - - const SizedBox(height: 20), - - // Notifikasi kemarin - _buildNotifikasiSection( - textTheme, - title: 'Kemarin', - notifikasiList: [ - { - 'judul': 'Laporan Penyaluran', - 'pesan': - 'Laporan penyaluran bantuan tanggal 14 April 2023 telah selesai', - 'waktu': '16:45', - 'dibaca': true, - }, - { - 'judul': 'Pengaduan Warga', - 'pesan': - 'Ada pengaduan baru dari warga yang perlu ditindaklanjuti', - 'waktu': '14:20', - 'dibaca': true, - }, - ], - ), - - const SizedBox(height: 20), - - // Notifikasi minggu ini - _buildNotifikasiSection( - textTheme, - title: 'Minggu Ini', - notifikasiList: [ - { - 'judul': 'Perubahan Jadwal', - 'pesan': - 'Jadwal penyaluran bantuan di Balai Desa A diubah menjadi tanggal 17 April 2023', - 'waktu': 'Sen, 13:00', - 'dibaca': true, - }, - { - 'judul': 'Donasi Baru', - 'pesan': - 'PT Sejahtera telah mengirimkan donasi baru berupa sembako', - 'waktu': 'Sen, 09:30', - 'dibaca': true, - }, - ], - ), - ], + return Scaffold( + appBar: AppBar( + title: const Text('Notifikasi'), + leading: IconButton( + icon: const Icon(Icons.arrow_back), + onPressed: () => Get.back(), ), + actions: [ + IconButton( + icon: const Icon(Icons.check_circle_outline), + tooltip: 'Tandai Semua Dibaca', + onPressed: () { + // Implementasi untuk menandai semua notifikasi sebagai dibaca + }, + ), + ], + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Notifikasi hari ini + _buildNotifikasiSection( + textTheme, + title: 'Hari Ini', + notifikasiList: [ + { + 'judul': 'Jadwal Penyaluran Baru', + 'pesan': + 'Jadwal penyaluran beras telah ditambahkan untuk hari ini', + 'waktu': '08:30', + 'dibaca': false, + }, + { + 'judul': 'Pengajuan Bantuan Baru', + 'pesan': + 'Ada 3 pengajuan bantuan baru yang perlu diverifikasi', + 'waktu': '10:15', + 'dibaca': false, + }, + ], + ), + + const SizedBox(height: 20), + + // Notifikasi kemarin + _buildNotifikasiSection( + textTheme, + title: 'Kemarin', + notifikasiList: [ + { + 'judul': 'Laporan Penyaluran', + 'pesan': + 'Laporan penyaluran bantuan tanggal 14 April 2023 telah selesai', + 'waktu': '16:45', + 'dibaca': true, + }, + { + 'judul': 'Pengaduan Warga', + 'pesan': + 'Ada pengaduan baru dari warga yang perlu ditindaklanjuti', + 'waktu': '14:20', + 'dibaca': true, + }, + ], + ), + + const SizedBox(height: 20), + + // Notifikasi minggu ini + _buildNotifikasiSection( + textTheme, + title: 'Minggu Ini', + notifikasiList: [ + { + 'judul': 'Perubahan Jadwal', + 'pesan': + 'Jadwal penyaluran bantuan di Balai Desa A diubah menjadi tanggal 17 April 2023', + 'waktu': 'Sen, 13:00', + 'dibaca': true, + }, + { + 'judul': 'Donasi Baru', + 'pesan': + 'PT Sejahtera telah mengirimkan donasi baru berupa sembako', + 'waktu': 'Sen, 09:30', + 'dibaca': true, + }, + ], + ), + ], + ), + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () { + // Implementasi untuk menandai semua notifikasi sebagai dibaca + Get.snackbar( + 'Notifikasi', + 'Semua notifikasi telah ditandai sebagai dibaca', + snackPosition: SnackPosition.BOTTOM, + backgroundColor: AppTheme.primaryColor, + colorText: Colors.white, + ); + }, + backgroundColor: AppTheme.primaryColor, + child: const Icon(Icons.done_all), + tooltip: 'Tandai Semua Dibaca', ), ); } @@ -131,51 +164,66 @@ class NotifikasiView extends GetView { ), ], ), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - if (!dibaca) - Container( - width: 10, - height: 10, - margin: const EdgeInsets.only(top: 5, right: 10), - decoration: const BoxDecoration( - color: AppTheme.primaryColor, - shape: BoxShape.circle, + child: InkWell( + onTap: () { + // Implementasi untuk menandai notifikasi sebagai dibaca + if (!dibaca) { + Get.snackbar( + 'Notifikasi', + 'Notifikasi ditandai sebagai dibaca', + snackPosition: SnackPosition.BOTTOM, + backgroundColor: AppTheme.primaryColor, + colorText: Colors.white, + ); + } + }, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (!dibaca) + Container( + width: 10, + height: 10, + margin: const EdgeInsets.only(top: 5, right: 10), + decoration: const BoxDecoration( + color: AppTheme.primaryColor, + shape: BoxShape.circle, + ), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + notifikasi['judul'] ?? '', + style: textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Text( + notifikasi['waktu'] ?? '', + style: textTheme.bodySmall?.copyWith( + color: Colors.grey, + ), + ), + ], + ), + const SizedBox(height: 8), + Text( + notifikasi['pesan'] ?? '', + style: textTheme.bodyMedium, + ), + ], ), ), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - notifikasi['judul'] ?? '', - style: textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - Text( - notifikasi['waktu'] ?? '', - style: textTheme.bodySmall?.copyWith( - color: Colors.grey, - ), - ), - ], - ), - const SizedBox(height: 8), - Text( - notifikasi['pesan'] ?? '', - style: textTheme.bodyMedium, - ), - ], - ), - ), - ], + ], + ), ), ), ); diff --git a/lib/app/modules/petugas_desa/views/penitipan_view.dart b/lib/app/modules/petugas_desa/views/penitipan_view.dart new file mode 100644 index 0000000..64baed9 --- /dev/null +++ b/lib/app/modules/petugas_desa/views/penitipan_view.dart @@ -0,0 +1,428 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:penyaluran_app/app/modules/petugas_desa/controllers/petugas_desa_controller.dart'; +import 'package:penyaluran_app/app/theme/app_theme.dart'; + +class PenitipanView extends GetView { + const PenitipanView({super.key}); + + @override + Widget build(BuildContext context) { + final textTheme = Theme.of(context).textTheme; + + return SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Ringkasan penitipan + _buildPenitipanSummary(context), + + const SizedBox(height: 24), + + // Filter dan pencarian + _buildFilterSearch(context), + + const SizedBox(height: 20), + + // Daftar penitipan + _buildPenitipanList(context), + ], + ), + ), + ); + } + + Widget _buildPenitipanSummary(BuildContext context) { + return Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: AppTheme.primaryGradient, + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Ringkasan Penitipan', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.pending_actions, + title: 'Menunggu', + value: '5', + color: Colors.orange, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.check_circle, + title: 'Terverifikasi', + value: '12', + color: Colors.green, + ), + ), + Expanded( + child: _buildSummaryItem( + context, + icon: Icons.cancel, + title: 'Ditolak', + value: '2', + color: Colors.red, + ), + ), + ], + ), + ], + ), + ); + } + + Widget _buildSummaryItem( + BuildContext context, { + required IconData icon, + required String title, + required String value, + required Color color, + }) { + return Column( + children: [ + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.2), + shape: BoxShape.circle, + ), + child: Icon( + icon, + color: Colors.white, + size: 24, + ), + ), + const SizedBox(height: 8), + Text( + value, + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 4), + Text( + title, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.white, + ), + textAlign: TextAlign.center, + ), + ], + ); + } + + Widget _buildFilterSearch(BuildContext context) { + return Row( + children: [ + Expanded( + child: TextField( + decoration: InputDecoration( + hintText: 'Cari penitipan...', + prefixIcon: const Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide.none, + ), + filled: true, + fillColor: Colors.grey.shade100, + contentPadding: const EdgeInsets.symmetric(vertical: 0), + ), + ), + ), + const SizedBox(width: 12), + Container( + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(12), + ), + child: IconButton( + onPressed: () { + // Tampilkan dialog filter + }, + icon: const Icon(Icons.filter_list), + tooltip: 'Filter', + ), + ), + ], + ); + } + + Widget _buildPenitipanList(BuildContext context) { + final List> penitipanList = [ + { + 'id': '1', + 'donatur': 'PT Sejahtera Abadi', + 'jenis_bantuan': 'Sembako', + 'jumlah': '500 kg', + 'tanggal_pengajuan': '15 April 2023', + 'status': 'Menunggu', + }, + { + 'id': '2', + 'donatur': 'Yayasan Peduli Sesama', + 'jenis_bantuan': 'Pakaian', + 'jumlah': '200 pcs', + 'tanggal_pengajuan': '14 April 2023', + 'status': 'Terverifikasi', + }, + { + 'id': '3', + 'donatur': 'Bank BRI', + 'jenis_bantuan': 'Beras', + 'jumlah': '300 kg', + 'tanggal_pengajuan': '13 April 2023', + 'status': 'Terverifikasi', + }, + { + 'id': '4', + 'donatur': 'Komunitas Peduli', + 'jenis_bantuan': 'Alat Tulis', + 'jumlah': '100 set', + 'tanggal_pengajuan': '12 April 2023', + 'status': 'Ditolak', + }, + ]; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Daftar Penitipan', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 12), + ...penitipanList.map((item) => _buildPenitipanItem(context, item)), + ], + ); + } + + Widget _buildPenitipanItem(BuildContext context, Map item) { + Color statusColor; + IconData statusIcon; + + switch (item['status']) { + case 'Menunggu': + statusColor = Colors.orange; + statusIcon = Icons.pending_actions; + break; + case 'Terverifikasi': + statusColor = Colors.green; + statusIcon = Icons.check_circle; + break; + case 'Ditolak': + statusColor = Colors.red; + statusIcon = Icons.cancel; + break; + default: + statusColor = Colors.grey; + statusIcon = Icons.help_outline; + } + + return Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + boxShadow: [ + BoxShadow( + color: Colors.grey.withAlpha(26), + spreadRadius: 1, + blurRadius: 3, + offset: const Offset(0, 1), + ), + ], + ), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + item['donatur'] ?? '', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + overflow: TextOverflow.ellipsis, + ), + ), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: statusColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + statusIcon, + size: 16, + color: statusColor, + ), + const SizedBox(width: 4), + Text( + item['status'] ?? '', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: statusColor, + fontWeight: FontWeight.bold, + ), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: _buildItemDetail( + context, + icon: Icons.category, + label: 'Jenis Bantuan', + value: item['jenis_bantuan'] ?? '', + ), + ), + Expanded( + child: _buildItemDetail( + context, + icon: Icons.inventory, + label: 'Jumlah', + value: item['jumlah'] ?? '', + ), + ), + ], + ), + const SizedBox(height: 8), + _buildItemDetail( + context, + icon: Icons.calendar_today, + label: 'Tanggal Pengajuan', + value: item['tanggal_pengajuan'] ?? '', + ), + const SizedBox(height: 12), + if (item['status'] == 'Menunggu') + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton.icon( + onPressed: () { + // Implementasi untuk menerima penitipan + }, + icon: const Icon(Icons.check, size: 18), + label: const Text('Terima'), + style: TextButton.styleFrom( + foregroundColor: Colors.green, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + TextButton.icon( + onPressed: () { + // Implementasi untuk menolak penitipan + }, + icon: const Icon(Icons.close, size: 18), + label: const Text('Tolak'), + style: TextButton.styleFrom( + foregroundColor: Colors.red, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + TextButton.icon( + onPressed: () { + // Implementasi untuk melihat detail penitipan + }, + icon: const Icon(Icons.info_outline, size: 18), + label: const Text('Detail'), + style: TextButton.styleFrom( + foregroundColor: Colors.blue, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + ], + ) + else + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton.icon( + onPressed: () { + // Implementasi untuk melihat detail penitipan + }, + icon: const Icon(Icons.info_outline, size: 18), + label: const Text('Detail'), + style: TextButton.styleFrom( + foregroundColor: Colors.blue, + padding: const EdgeInsets.symmetric(horizontal: 8), + ), + ), + ], + ), + ], + ), + ), + ); + } + + Widget _buildItemDetail( + BuildContext context, { + required IconData icon, + required String label, + required String value, + }) { + return Row( + children: [ + Icon( + icon, + size: 16, + color: Colors.grey, + ), + const SizedBox(width: 4), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + label, + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: Colors.grey, + ), + ), + Text( + value, + style: Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ); + } +} diff --git a/lib/app/modules/petugas_desa/views/petugas_desa_view.dart b/lib/app/modules/petugas_desa/views/petugas_desa_view.dart index 41e107e..e1e1f0e 100644 --- a/lib/app/modules/petugas_desa/views/petugas_desa_view.dart +++ b/lib/app/modules/petugas_desa/views/petugas_desa_view.dart @@ -5,6 +5,7 @@ import 'package:penyaluran_app/app/modules/petugas_desa/views/dashboard_view.dar import 'package:penyaluran_app/app/modules/petugas_desa/views/jadwal_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/notifikasi_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/inventaris_view.dart'; +import 'package:penyaluran_app/app/modules/petugas_desa/views/penitipan_view.dart'; import 'package:penyaluran_app/app/theme/app_theme.dart'; class PetugasDesaView extends GetView { @@ -24,9 +25,9 @@ class PetugasDesaView extends GetView { case 1: return const Text('Jadwal Penyaluran'); case 2: - return const Text('Notifikasi'); - case 3: return const Text('Inventaris'); + case 3: + return const Text('Penitipan'); default: return const Text('Petugas Desa'); } @@ -49,7 +50,13 @@ class PetugasDesaView extends GetView { IconButton( icon: const Icon(Icons.notifications_outlined), onPressed: () { - controller.changeTab(2); // Pindah ke tab notifikasi + // Navigasi ke halaman notifikasi + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const NotifikasiView(), + ), + ); }, ), if (controller.jumlahNotifikasiBelumDibaca.value > 0) @@ -95,14 +102,6 @@ class PetugasDesaView extends GetView { ], ); } else if (activeTab == 2) { - return IconButton( - icon: const Icon(Icons.check_circle_outline), - tooltip: 'Tandai Semua Dibaca', - onPressed: () { - // Implementasi untuk menandai semua notifikasi sebagai dibaca - }, - ); - } else if (activeTab == 3) { return Row( mainAxisSize: MainAxisSize.min, children: [ @@ -130,9 +129,9 @@ class PetugasDesaView extends GetView { case 1: return const JadwalView(); case 2: - return const NotifikasiView(); - case 3: return const InventarisView(); + case 3: + return const PenitipanView(); default: return const DashboardView(); } @@ -182,26 +181,76 @@ class PetugasDesaView extends GetView { ], ), ), - ListTile( - leading: const Icon(Icons.dashboard_outlined), - title: const Text('Dashboard'), - selected: controller.activeTabIndex.value == 0, - selectedColor: AppTheme.primaryColor, - onTap: () { - controller.changeTab(0); - Get.back(); - }, - ), - ListTile( - leading: const Icon(Icons.calendar_today_outlined), - title: const Text('Jadwal Penyaluran'), - selected: controller.activeTabIndex.value == 1, - selectedColor: AppTheme.primaryColor, - onTap: () { - controller.changeTab(1); - Get.back(); - }, - ), + Obx(() => ListTile( + leading: const Icon(Icons.dashboard_outlined), + title: const Text('Dashboard'), + selected: controller.activeTabIndex.value == 0, + selectedColor: AppTheme.primaryColor, + onTap: () { + controller.changeTab(0); + Navigator.pop(context); + }, + )), + Obx(() => ListTile( + leading: const Icon(Icons.calendar_today_outlined), + title: const Text('Jadwal Penyaluran'), + selected: controller.activeTabIndex.value == 1, + selectedColor: AppTheme.primaryColor, + onTap: () { + controller.changeTab(1); + Navigator.pop(context); + }, + )), + Obx(() => ListTile( + leading: const Icon(Icons.inventory_2_outlined), + title: const Text('Inventaris'), + selected: controller.activeTabIndex.value == 2, + selectedColor: AppTheme.primaryColor, + onTap: () { + controller.changeTab(2); + Navigator.pop(context); + }, + )), + Obx(() => ListTile( + leading: Stack( + alignment: Alignment.center, + children: [ + const Icon(Icons.handshake_outlined), + if (controller.jumlahMenunggu.value > 0) + Positioned( + top: 0, + right: 0, + child: Container( + padding: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: Colors.orange, + borderRadius: BorderRadius.circular(10), + ), + constraints: const BoxConstraints( + minWidth: 12, + minHeight: 12, + ), + child: Text( + controller.jumlahMenunggu.value.toString(), + style: const TextStyle( + color: Colors.white, + fontSize: 8, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + title: const Text('Penitipan'), + selected: controller.activeTabIndex.value == 3, + selectedColor: AppTheme.primaryColor, + onTap: () { + controller.changeTab(3); + Navigator.pop(context); + }, + )), + const Divider(), ListTile( leading: Stack( alignment: Alignment.center, @@ -234,30 +283,22 @@ class PetugasDesaView extends GetView { ], ), title: const Text('Notifikasi'), - selected: controller.activeTabIndex.value == 2, - selectedColor: AppTheme.primaryColor, onTap: () { - controller.changeTab(2); - Get.back(); + Navigator.pop(context); // Tutup drawer terlebih dahulu + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const NotifikasiView(), + ), + ); }, ), - ListTile( - leading: const Icon(Icons.inventory_2_outlined), - title: const Text('Inventaris'), - selected: controller.activeTabIndex.value == 3, - selectedColor: AppTheme.primaryColor, - onTap: () { - controller.changeTab(3); - Get.back(); - }, - ), - const Divider(), ListTile( leading: const Icon(Icons.person_outline), title: const Text('Profil'), onTap: () { // Navigasi ke halaman profil - Get.back(); + Navigator.pop(context); }, ), ListTile( @@ -265,14 +306,14 @@ class PetugasDesaView extends GetView { title: const Text('Pengaturan'), onTap: () { // Navigasi ke halaman pengaturan - Get.back(); + Navigator.pop(context); }, ), ListTile( leading: const Icon(Icons.logout), title: const Text('Keluar'), onTap: () { - Get.back(); + Navigator.pop(context); controller.logout(); }, ), @@ -288,27 +329,143 @@ class PetugasDesaView extends GetView { type: BottomNavigationBarType.fixed, selectedItemColor: AppTheme.primaryColor, unselectedItemColor: Colors.grey, - items: const [ - BottomNavigationBarItem( + items: [ + const BottomNavigationBarItem( icon: Icon(Icons.dashboard_outlined), activeIcon: Icon(Icons.dashboard), label: 'Dashboard', ), BottomNavigationBarItem( - icon: Icon(Icons.calendar_today_outlined), - activeIcon: Icon(Icons.calendar_today), + icon: Stack( + alignment: Alignment.center, + children: [ + const Icon(Icons.calendar_today_outlined), + if (controller.jadwalHariIni.isNotEmpty) + Positioned( + top: 0, + right: 0, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + color: Colors.blue, + shape: BoxShape.circle, + ), + constraints: const BoxConstraints( + minWidth: 12, + minHeight: 12, + ), + child: Text( + controller.jadwalHariIni.length.toString(), + style: const TextStyle( + color: Colors.white, + fontSize: 8, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + activeIcon: Stack( + alignment: Alignment.center, + children: [ + const Icon(Icons.calendar_today), + if (controller.jadwalHariIni.isNotEmpty) + Positioned( + top: 0, + right: 0, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + color: Colors.blue, + shape: BoxShape.circle, + ), + constraints: const BoxConstraints( + minWidth: 12, + minHeight: 12, + ), + child: Text( + controller.jadwalHariIni.length.toString(), + style: const TextStyle( + color: Colors.white, + fontSize: 8, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), label: 'Jadwal', ), - BottomNavigationBarItem( - icon: Icon(Icons.notifications_outlined), - activeIcon: Icon(Icons.notifications), - label: 'Notifikasi', - ), - BottomNavigationBarItem( + const BottomNavigationBarItem( icon: Icon(Icons.inventory_2_outlined), activeIcon: Icon(Icons.inventory_2), label: 'Inventaris', ), + BottomNavigationBarItem( + icon: Stack( + alignment: Alignment.center, + children: [ + const Icon(Icons.handshake_outlined), + if (controller.jumlahMenunggu.value > 0) + Positioned( + top: 0, + right: 0, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + color: Colors.orange, + shape: BoxShape.circle, + ), + constraints: const BoxConstraints( + minWidth: 12, + minHeight: 12, + ), + child: Text( + controller.jumlahMenunggu.value.toString(), + style: const TextStyle( + color: Colors.white, + fontSize: 8, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + activeIcon: Stack( + alignment: Alignment.center, + children: [ + const Icon(Icons.handshake), + if (controller.jumlahMenunggu.value > 0) + Positioned( + top: 0, + right: 0, + child: Container( + padding: const EdgeInsets.all(2), + decoration: const BoxDecoration( + color: Colors.orange, + shape: BoxShape.circle, + ), + constraints: const BoxConstraints( + minWidth: 12, + minHeight: 12, + ), + child: Text( + controller.jumlahMenunggu.value.toString(), + style: const TextStyle( + color: Colors.white, + fontSize: 8, + ), + textAlign: TextAlign.center, + ), + ), + ), + ], + ), + label: 'Penitipan', + ), ], )); }