diff --git a/lib/app/modules/dashboard/bindings/dashboard_binding.dart b/lib/app/modules/dashboard/bindings/dashboard_binding.dart deleted file mode 100644 index 5be5eaa..0000000 --- a/lib/app/modules/dashboard/bindings/dashboard_binding.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; - -class DashboardBinding extends Bindings { - @override - void dependencies() { - Get.lazyPut( - () => DashboardController(), - ); - } -} diff --git a/lib/app/modules/dashboard/controllers/dashboard_controller.dart b/lib/app/modules/dashboard/controllers/dashboard_controller.dart deleted file mode 100644 index 65d014f..0000000 --- a/lib/app/modules/dashboard/controllers/dashboard_controller.dart +++ /dev/null @@ -1,42 +0,0 @@ -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/data/models/user_model.dart'; -import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart'; -import 'package:penyaluran_app/app/services/supabase_service.dart'; - -class DashboardController extends GetxController { - final AuthController _authController = Get.find(); - final SupabaseService _supabaseService = SupabaseService.to; - - final RxBool isLoading = false.obs; - final Rx?> roleData = Rx?>(null); - - // Indeks kategori yang dipilih untuk filter - final RxInt selectedCategoryIndex = 0.obs; - - UserModel? get user => _authController.user; - String get role => user?.role ?? 'WARGA'; - - @override - void onInit() { - super.onInit(); - loadRoleData(); - } - - Future loadRoleData() async { - isLoading.value = true; - try { - if (user != null) { - final data = await _supabaseService.getRoleSpecificData(role); - roleData.value = data; - } - } catch (e) { - print('Error loading role data: $e'); - } finally { - isLoading.value = false; - } - } - - void logout() { - _authController.logout(); - } -} diff --git a/lib/app/modules/dashboard/views/donatur_dashboard_view.dart b/lib/app/modules/dashboard/views/donatur_dashboard_view.dart deleted file mode 100644 index 0daa10e..0000000 --- a/lib/app/modules/dashboard/views/donatur_dashboard_view.dart +++ /dev/null @@ -1,229 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; - -class DonaturDashboardView extends GetView { - const DonaturDashboardView({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Dashboard Donatur'), - actions: [ - IconButton( - icon: const Icon(Icons.logout), - onPressed: controller.logout, - tooltip: 'Logout', - ), - ], - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Obx(() { - if (controller.isLoading.value) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Greeting - Text( - 'Halo, ${controller.roleData.value?['namaLengkap'] ?? controller.user?.email ?? 'Donatur'}!', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 5), - const Text( - 'Selamat datang di Dashboard Donatur', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - const SizedBox(height: 30), - - // Donatur Data - if (controller.roleData.value != null) ...[ - const Text( - 'Data Donatur', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - Card( - elevation: 2, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildInfoRow( - 'NIK', controller.roleData.value?['NIK'] ?? '-'), - _buildInfoRow('Nama', - controller.roleData.value?['namaLengkap'] ?? '-'), - _buildInfoRow('No. Telp', - controller.roleData.value?['noTelp'] ?? '-'), - _buildInfoRow('Email', - controller.roleData.value?['email'] ?? '-'), - _buildInfoRow( - 'Alamat', - controller.roleData.value?['alamatLengkap'] ?? - '-'), - _buildInfoRow('Desa', - controller.roleData.value?['namaDesa'] ?? '-'), - ], - ), - ), - ), - ] else ...[ - const Center( - child: Text( - 'Data donatur belum tersedia', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - ), - ], - - const SizedBox(height: 30), - - // Menu - const Text( - 'Menu', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Penitipan Bantuan', - 'Titipkan bantuan Anda', - Icons.card_giftcard, - Colors.blue, - () { - // Navigasi ke halaman penitipan bantuan - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Riwayat Penitipan', - 'Lihat riwayat penitipan bantuan', - Icons.history, - Colors.green, - () { - // Navigasi ke halaman riwayat penitipan - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Laporan Penyaluran', - 'Lihat laporan penyaluran bantuan', - Icons.assessment, - Colors.orange, - () { - // Navigasi ke halaman laporan penyaluran - }, - ), - ], - ); - }), - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: () { - // Navigasi ke halaman penitipan bantuan baru - }, - tooltip: 'Titipkan Bantuan Baru', - child: const Icon(Icons.add), - ), - ); - } - - Widget _buildInfoRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 120, - child: Text( - label, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - Expanded( - child: Text(value), - ), - ], - ), - ); - } - - Widget _buildMenuCard(String title, String subtitle, IconData icon, - Color color, VoidCallback onTap) { - return Card( - elevation: 2, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: color.withAlpha(26), - borderRadius: BorderRadius.circular(8.0), - ), - child: Icon( - icon, - color: color, - size: 30, - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 4), - Text( - subtitle, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), - ), - ], - ), - ), - const Icon(Icons.arrow_forward_ios, size: 16), - ], - ), - ), - ), - ); - } -} diff --git a/lib/app/modules/dashboard/views/petugas_verifikasi_dashboard_view.dart b/lib/app/modules/dashboard/views/petugas_verifikasi_dashboard_view.dart deleted file mode 100644 index 2dc3916..0000000 --- a/lib/app/modules/dashboard/views/petugas_verifikasi_dashboard_view.dart +++ /dev/null @@ -1,216 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; - -class PetugasVerifikasiDashboardView extends GetView { - const PetugasVerifikasiDashboardView({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Dashboard Petugas Verifikasi'), - actions: [ - IconButton( - icon: const Icon(Icons.logout), - onPressed: controller.logout, - tooltip: 'Logout', - ), - ], - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Obx(() { - if (controller.isLoading.value) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Greeting - Text( - 'Halo, ${controller.roleData.value?['namaLengkap'] ?? controller.user?.email ?? 'Petugas'}!', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 5), - const Text( - 'Selamat datang di Dashboard Petugas Verifikasi', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - const SizedBox(height: 30), - - // Petugas Data - if (controller.roleData.value != null) ...[ - const Text( - 'Data Petugas', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - Card( - elevation: 2, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildInfoRow( - 'NIP', controller.roleData.value?['nip'] ?? '-'), - _buildInfoRow('Nama', - controller.roleData.value?['namaLengkap'] ?? '-'), - _buildInfoRow('Jabatan', - controller.roleData.value?['jabatan'] ?? '-'), - _buildInfoRow('Email', - controller.roleData.value?['email'] ?? '-'), - ], - ), - ), - ), - ] else ...[ - const Center( - child: Text( - 'Data petugas belum tersedia', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - ), - ], - - const SizedBox(height: 30), - - // Menu - const Text( - 'Menu', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Verifikasi Data Warga', - 'Verifikasi data warga baru', - Icons.verified_user, - Colors.blue, - () { - // Navigasi ke halaman verifikasi data warga - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Verifikasi Pengajuan Bantuan', - 'Verifikasi pengajuan bantuan', - Icons.fact_check, - Colors.green, - () { - // Navigasi ke halaman verifikasi pengajuan bantuan - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Kelola Skema Bantuan', - 'Kelola skema bantuan yang tersedia', - Icons.settings, - Colors.orange, - () { - // Navigasi ke halaman kelola skema bantuan - }, - ), - ], - ); - }), - ), - ), - ); - } - - Widget _buildInfoRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 120, - child: Text( - label, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - Expanded( - child: Text(value), - ), - ], - ), - ); - } - - Widget _buildMenuCard(String title, String subtitle, IconData icon, - Color color, VoidCallback onTap) { - return Card( - elevation: 2, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: color.withAlpha(26), - borderRadius: BorderRadius.circular(8.0), - ), - child: Icon( - icon, - color: color, - size: 30, - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 4), - Text( - subtitle, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), - ), - ], - ), - ), - const Icon(Icons.arrow_forward_ios, size: 16), - ], - ), - ), - ), - ); - } -} diff --git a/lib/app/modules/dashboard/views/warga_dashboard_view.dart b/lib/app/modules/dashboard/views/warga_dashboard_view.dart index c82d61b..8b13789 100644 --- a/lib/app/modules/dashboard/views/warga_dashboard_view.dart +++ b/lib/app/modules/dashboard/views/warga_dashboard_view.dart @@ -1,295 +1 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; -import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart'; -class WargaDashboardView extends GetView { - const WargaDashboardView({super.key}); - - @override - Widget build(BuildContext context) { - final authController = Get.find(); - - return Scaffold( - appBar: AppBar( - title: const Text('Dashboard Warga'), - actions: [ - IconButton( - icon: const Icon(Icons.logout), - onPressed: controller.logout, - tooltip: 'Logout', - ), - ], - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Obx(() { - if (controller.isLoading.value) { - return const Center( - child: CircularProgressIndicator(), - ); - } - - return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Greeting - Text( - 'Halo, ${controller.user?.email ?? 'Pengguna'}!', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 5), - const Text( - 'Selamat datang di Dashboard Warga', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - const SizedBox(height: 20), - - // Status Profil - Obx(() => authController.isWargaProfileComplete.value - ? _buildProfileCompleteCard() - : _buildProfileIncompleteCard(authController)), - - const SizedBox(height: 30), - - // Warga Data - if (controller.roleData.value != null) ...[ - const Text( - 'Data Pribadi', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - Card( - elevation: 2, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildInfoRow('NIK', - controller.roleData.value?['NIK'] ?? '-'), - _buildInfoRow( - 'Nama', - controller.roleData.value?['namaLengkap'] ?? - '-'), - _buildInfoRow( - 'Jenis Kelamin', - controller.roleData.value?['jenisKelamin'] ?? - '-'), - _buildInfoRow('No. HP', - controller.roleData.value?['noHp'] ?? '-'), - _buildInfoRow('Alamat', - controller.roleData.value?['alamat'] ?? '-'), - ], - ), - ), - ), - ] else ...[ - const Center( - child: Text( - 'Data warga belum tersedia', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - ), - ], - - const SizedBox(height: 30), - - // Menu - const Text( - 'Menu', - style: TextStyle( - fontSize: 18, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Pengajuan Bantuan', - 'Ajukan permohonan bantuan', - Icons.request_page, - Colors.blue, - () { - // Navigasi ke halaman pengajuan bantuan - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Pengaduan', - 'Sampaikan pengaduan Anda', - Icons.report_problem, - Colors.orange, - () { - // Navigasi ke halaman pengaduan - }, - ), - const SizedBox(height: 10), - _buildMenuCard( - 'Status Bantuan', - 'Lihat status bantuan Anda', - Icons.info, - Colors.green, - () { - // Navigasi ke halaman status bantuan - }, - ), - ], - ), - ); - }), - ), - ), - ); - } - - // Widget untuk menampilkan status profil lengkap - Widget _buildProfileCompleteCard() { - return Card( - color: Colors.green.shade50, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - children: [ - Icon(Icons.check_circle, color: Colors.green.shade700), - const SizedBox(width: 10), - const Expanded( - child: Text( - 'Profil Anda sudah lengkap', - style: TextStyle( - color: Colors.green, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - ); - } - - // Widget untuk menampilkan status profil belum lengkap dengan tombol - Widget _buildProfileIncompleteCard(AuthController authController) { - return Card( - color: Colors.orange.shade50, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - Icon(Icons.warning, color: Colors.orange.shade700), - const SizedBox(width: 10), - const Expanded( - child: Text( - 'Profil Anda belum lengkap', - style: TextStyle( - color: Colors.orange, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - const SizedBox(height: 10), - const Text( - 'Lengkapi profil Anda untuk mengakses semua fitur aplikasi', - style: TextStyle(fontSize: 12), - ), - const SizedBox(height: 10), - ], - ), - ), - ); - } - - Widget _buildInfoRow(String label, String value) { - return Padding( - padding: const EdgeInsets.only(bottom: 8.0), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SizedBox( - width: 120, - child: Text( - label, - style: const TextStyle( - fontWeight: FontWeight.bold, - ), - ), - ), - Expanded( - child: Text(value), - ), - ], - ), - ); - } - - Widget _buildMenuCard(String title, String subtitle, IconData icon, - Color color, VoidCallback onTap) { - return Card( - elevation: 2, - child: InkWell( - onTap: onTap, - child: Padding( - padding: const EdgeInsets.all(16.0), - child: Row( - children: [ - Container( - padding: const EdgeInsets.all(8.0), - decoration: BoxDecoration( - color: color.withAlpha(26), - borderRadius: BorderRadius.circular(8.0), - ), - child: Icon( - icon, - color: color, - size: 30, - ), - ), - const SizedBox(width: 16), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 4), - Text( - subtitle, - style: TextStyle( - fontSize: 14, - color: Colors.grey[600], - ), - ), - ], - ), - ), - const Icon(Icons.arrow_forward_ios, size: 16), - ], - ), - ), - ), - ); - } -} diff --git a/lib/app/modules/home/bindings/home_binding.dart b/lib/app/modules/home/bindings/home_binding.dart deleted file mode 100644 index 15fb986..0000000 --- a/lib/app/modules/home/bindings/home_binding.dart +++ /dev/null @@ -1,11 +0,0 @@ -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/home/controllers/home_controller.dart'; - -class HomeBinding extends Bindings { - @override - void dependencies() { - Get.lazyPut( - () => HomeController(), - ); - } -} diff --git a/lib/app/modules/home/controllers/home_controller.dart b/lib/app/modules/home/controllers/home_controller.dart deleted file mode 100644 index 90377cc..0000000 --- a/lib/app/modules/home/controllers/home_controller.dart +++ /dev/null @@ -1,14 +0,0 @@ -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/auth/controllers/auth_controller.dart'; - -class HomeController extends GetxController { - final AuthController _authController = Get.find(); - - // Getter untuk mendapatkan user dari auth controller - get user => _authController.user; - - // Metode untuk logout - void logout() { - _authController.logout(); - } -} diff --git a/lib/app/modules/home/views/home_view.dart b/lib/app/modules/home/views/home_view.dart deleted file mode 100644 index 86028a5..0000000 --- a/lib/app/modules/home/views/home_view.dart +++ /dev/null @@ -1,63 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:get/get.dart'; -import 'package:penyaluran_app/app/modules/home/controllers/home_controller.dart'; - -class HomeView extends GetView { - const HomeView({super.key}); - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Penyaluran App'), - actions: [ - IconButton( - icon: const Icon(Icons.logout), - onPressed: controller.logout, - tooltip: 'Logout', - ), - ], - ), - body: SafeArea( - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Greeting - Text( - 'Halo, ${controller.user?.email ?? 'Pengguna'}!', - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - ), - ), - const SizedBox(height: 5), - const Text( - 'Selamat datang di Penyaluran App', - style: TextStyle( - fontSize: 16, - color: Colors.grey, - ), - ), - const SizedBox(height: 30), - - // Dashboard Content - const Expanded( - child: Center( - child: Text( - 'Halaman Dashboard', - style: TextStyle( - fontSize: 20, - fontWeight: FontWeight.bold, - ), - ), - ), - ), - ], - ), - ), - ), - ); - } -} diff --git a/lib/app/modules/petugas_desa/components/jadwal_section_widget.dart b/lib/app/modules/petugas_desa/components/jadwal_section_widget.dart index f27643e..6f2b9ac 100644 --- a/lib/app/modules/petugas_desa/components/jadwal_section_widget.dart +++ b/lib/app/modules/petugas_desa/components/jadwal_section_widget.dart @@ -1,6 +1,7 @@ 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/routes/app_pages.dart'; class JadwalSectionWidget extends StatelessWidget { final PetugasDesaController controller; @@ -90,75 +91,100 @@ class JadwalSectionWidget extends StatelessWidget { statusColor = Colors.orange; } - return Container( - width: double.infinity, - margin: const EdgeInsets.only(bottom: 10), - 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: [ - Text( - jadwal['lokasi'] ?? '', - style: textTheme.titleMedium?.copyWith( - fontWeight: FontWeight.bold, - ), - ), - Container( - padding: - const EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: statusColor.withAlpha(26), - borderRadius: BorderRadius.circular(12), - ), - child: Text( - status, - style: textTheme.bodySmall?.copyWith( - color: statusColor, + return GestureDetector( + onTap: () { + // Navigasi ke halaman pelaksanaan penyaluran dengan data jadwal + Get.toNamed(Routes.pelaksanaanPenyaluran, arguments: jadwal); + }, + child: Container( + width: double.infinity, + margin: const EdgeInsets.only(bottom: 10), + 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: [ + Text( + jadwal['lokasi'] ?? '', + style: textTheme.titleMedium?.copyWith( fontWeight: FontWeight.bold, ), ), - ), - ], - ), - const SizedBox(height: 8), - Text( - 'Jenis Bantuan: ${jadwal['jenis_bantuan'] ?? ''}', - style: textTheme.bodyMedium, - ), - const SizedBox(height: 4), - Text( - 'Tanggal: ${jadwal['tanggal'] ?? ''}', - style: textTheme.bodyMedium, - ), - const SizedBox(height: 4), - Text( - 'Waktu: ${jadwal['waktu'] ?? ''}', - style: textTheme.bodyMedium, - ), - if (jadwal['jumlah_penerima'] != null) ...[ - const SizedBox(height: 4), + Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: statusColor.withAlpha(26), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + status, + style: textTheme.bodySmall?.copyWith( + color: statusColor, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + const SizedBox(height: 8), Text( - 'Jumlah Penerima: ${jadwal['jumlah_penerima']}', + 'Jenis Bantuan: ${jadwal['jenis_bantuan'] ?? ''}', style: textTheme.bodyMedium, ), + const SizedBox(height: 4), + Text( + 'Tanggal: ${jadwal['tanggal'] ?? ''}', + style: textTheme.bodyMedium, + ), + const SizedBox(height: 4), + Text( + 'Waktu: ${jadwal['waktu'] ?? ''}', + style: textTheme.bodyMedium, + ), + if (jadwal['jumlah_penerima'] != null) ...[ + const SizedBox(height: 4), + Text( + 'Jumlah Penerima: ${jadwal['jumlah_penerima']}', + style: textTheme.bodyMedium, + ), + ], + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Text( + 'Lihat Detail', + style: textTheme.bodySmall?.copyWith( + color: Colors.blue, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(width: 4), + const Icon( + Icons.arrow_forward_ios, + size: 12, + color: Colors.blue, + ), + ], + ), ], - ], + ), ), ), ); diff --git a/lib/app/modules/petugas_desa/views/pelaksanaan_penyaluran_view.dart b/lib/app/modules/petugas_desa/views/pelaksanaan_penyaluran_view.dart new file mode 100644 index 0000000..ef46751 --- /dev/null +++ b/lib/app/modules/petugas_desa/views/pelaksanaan_penyaluran_view.dart @@ -0,0 +1,431 @@ +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 PelaksanaanPenyaluranView extends GetView { + const PelaksanaanPenyaluranView({super.key}); + + @override + Widget build(BuildContext context) { + // Ambil data jadwal dari parameter + final jadwal = Get.arguments as Map; + + return Scaffold( + appBar: AppBar( + title: const Text('Detail Pelaksanaan Penyaluran'), + elevation: 0, + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header dengan informasi pelaksanaan + _buildHeaderInfo(context, jadwal), + + // Daftar penerima bantuan + _buildDaftarPenerima(context, jadwal), + ], + ), + ), + bottomNavigationBar: _buildBottomButtons(context, jadwal), + ); + } + + Widget _buildHeaderInfo(BuildContext context, Map jadwal) { + final textTheme = Theme.of(context).textTheme; + + return Container( + width: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: AppTheme.primaryGradient, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + jadwal['lokasi'] ?? 'Lokasi Penyaluran', + style: textTheme.headlineSmall?.copyWith( + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + const SizedBox(height: 16), + _buildInfoItem(context, + icon: Icons.category, + label: 'Jenis Bantuan', + value: jadwal['jenis_bantuan'] ?? '-'), + const SizedBox(height: 8), + _buildInfoItem(context, + icon: Icons.calendar_today, + label: 'Tanggal', + value: jadwal['tanggal'] ?? '-'), + const SizedBox(height: 8), + _buildInfoItem(context, + icon: Icons.access_time, + label: 'Waktu', + value: jadwal['waktu'] ?? '-'), + const SizedBox(height: 8), + _buildInfoItem(context, + icon: Icons.people, + label: 'Jumlah Penerima', + value: '${jadwal['jumlah_penerima'] ?? 0} orang'), + const SizedBox(height: 8), + _buildInfoItem( + context, + icon: Icons.flag, + label: 'Status', + value: jadwal['status'] ?? 'Aktif', + isStatus: true, + ), + ], + ), + ); + } + + Widget _buildInfoItem( + BuildContext context, { + required IconData icon, + required String label, + required String value, + bool isStatus = false, + }) { + Color statusColor = Colors.white; + if (isStatus) { + switch (value.toLowerCase()) { + case 'aktif': + statusColor = Colors.green; + break; + case 'terjadwal': + statusColor = Colors.blue; + break; + case 'selesai': + statusColor = Colors.grey; + break; + default: + statusColor = Colors.orange; + } + } + + return Row( + children: [ + Icon( + icon, + color: Colors.white, + size: 20, + ), + const SizedBox(width: 8), + Text( + '$label: ', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Colors.white, + ), + ), + Text( + value, + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: isStatus ? statusColor : Colors.white, + fontWeight: FontWeight.bold, + ), + ), + ], + ); + } + + Widget _buildDaftarPenerima( + BuildContext context, Map jadwal) { + // Simulasi data penerima bantuan + final List> daftarPenerima = [ + { + 'id': '1', + 'nama': 'Ahmad Sulaiman', + 'nik': '3201234567890001', + 'alamat': 'Dusun Sukamaju RT 02/03', + 'status': 'belum_diterima', + }, + { + 'id': '2', + 'nama': 'Siti Aminah', + 'nik': '3201234567890002', + 'alamat': 'Dusun Sukamaju RT 01/03', + 'status': 'sudah_diterima', + }, + { + 'id': '3', + 'nama': 'Budi Santoso', + 'nik': '3201234567890003', + 'alamat': 'Dusun Sukamaju RT 03/01', + 'status': 'belum_diterima', + }, + { + 'id': '4', + 'nama': 'Dewi Lestari', + 'nik': '3201234567890004', + 'alamat': 'Dusun Sukamaju RT 04/02', + 'status': 'sudah_diterima', + }, + { + 'id': '5', + 'nama': 'Joko Widodo', + 'nik': '3201234567890005', + 'alamat': 'Dusun Sukamaju RT 05/01', + 'status': 'belum_diterima', + }, + ]; + + return Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Daftar Penerima Bantuan', + style: Theme.of(context).textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + Text( + '${daftarPenerima.length} orang', + style: Theme.of(context).textTheme.bodyMedium?.copyWith( + color: Colors.grey.shade600, + ), + ), + ], + ), + const SizedBox(height: 16), + + // Search bar + TextField( + decoration: InputDecoration( + hintText: 'Cari penerima...', + prefixIcon: const Icon(Icons.search), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(12), + borderSide: BorderSide(color: Colors.grey.shade300), + ), + contentPadding: const EdgeInsets.symmetric(vertical: 12), + filled: true, + fillColor: Colors.grey.shade50, + ), + ), + + const SizedBox(height: 16), + + // Filter status + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + _buildFilterChip(context, 'Semua', true), + const SizedBox(width: 8), + _buildFilterChip(context, 'Sudah Diterima', false), + const SizedBox(width: 8), + _buildFilterChip(context, 'Belum Diterima', false), + ], + ), + ), + + const SizedBox(height: 16), + + // Daftar penerima + ...daftarPenerima + .map((penerima) => _buildPenerimaItem(context, penerima)) + .toList(), + ], + ), + ); + } + + Widget _buildFilterChip(BuildContext context, String label, bool isSelected) { + return FilterChip( + label: Text(label), + selected: isSelected, + onSelected: (selected) { + // Implementasi filter + }, + backgroundColor: Colors.grey.shade100, + selectedColor: AppTheme.primaryColor.withOpacity(0.2), + checkmarkColor: AppTheme.primaryColor, + labelStyle: TextStyle( + color: isSelected ? AppTheme.primaryColor : Colors.black, + fontWeight: isSelected ? FontWeight.bold : FontWeight.normal, + ), + ); + } + + Widget _buildPenerimaItem( + BuildContext context, Map penerima) { + final bool sudahDiterima = penerima['status'] == 'sudah_diterima'; + + return Container( + 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: ListTile( + contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + title: Text( + penerima['nama'] ?? '', + style: Theme.of(context).textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.bold, + ), + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Text('NIK: ${penerima['nik'] ?? ''}'), + const SizedBox(height: 2), + Text('Alamat: ${penerima['alamat'] ?? ''}'), + ], + ), + trailing: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: sudahDiterima + ? Colors.green.withAlpha(26) + : Colors.orange.withAlpha(26), + borderRadius: BorderRadius.circular(12), + ), + child: Text( + sudahDiterima ? 'Sudah Diterima' : 'Belum Diterima', + style: Theme.of(context).textTheme.bodySmall?.copyWith( + color: sudahDiterima ? Colors.green : Colors.orange, + fontWeight: FontWeight.bold, + ), + ), + ), + onTap: () { + // Navigasi ke halaman konfirmasi penerima + Get.toNamed( + '/daftar-penerima/konfirmasi', + arguments: penerima['id'], + ); + }, + ), + ); + } + + Widget _buildBottomButtons( + BuildContext context, Map jadwal) { + final bool isSelesai = (jadwal['status'] ?? '').toLowerCase() == 'selesai'; + + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.grey.withAlpha(50), + spreadRadius: 1, + blurRadius: 5, + offset: const Offset(0, -1), + ), + ], + ), + child: Row( + children: [ + Expanded( + child: ElevatedButton.icon( + onPressed: isSelesai + ? null + : () { + // Implementasi cetak laporan + Get.snackbar( + 'Informasi', + 'Mencetak laporan penyaluran...', + snackPosition: SnackPosition.BOTTOM, + ); + }, + icon: const Icon(Icons.print), + label: const Text('Cetak Laporan'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton.icon( + onPressed: isSelesai + ? null + : () { + // Implementasi selesaikan penyaluran + _showSelesaikanDialog(context, jadwal); + }, + icon: const Icon(Icons.check_circle), + label: const Text('Selesaikan'), + style: ElevatedButton.styleFrom( + backgroundColor: isSelesai ? Colors.grey : Colors.green, + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ), + ], + ), + ); + } + + void _showSelesaikanDialog( + BuildContext context, Map jadwal) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Selesaikan Penyaluran'), + content: + const Text('Apakah Anda yakin ingin menyelesaikan penyaluran ini? ' + 'Pastikan semua penerima telah dikonfirmasi.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Batal'), + ), + ElevatedButton( + onPressed: () { + // Implementasi selesaikan penyaluran + Navigator.pop(context); + Get.back(); // Kembali ke halaman sebelumnya + Get.snackbar( + 'Berhasil', + 'Penyaluran telah diselesaikan', + snackPosition: SnackPosition.BOTTOM, + backgroundColor: Colors.green, + colorText: Colors.white, + ); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + ), + child: const Text('Selesaikan'), + ), + ], + ), + ); + } +} diff --git a/lib/app/routes/app_pages.dart b/lib/app/routes/app_pages.dart index fb83a71..ed88b2a 100644 --- a/lib/app/routes/app_pages.dart +++ b/lib/app/routes/app_pages.dart @@ -1,18 +1,13 @@ import 'package:get/get.dart'; import 'package:penyaluran_app/app/modules/auth/views/login_view.dart'; -import 'package:penyaluran_app/app/modules/home/views/home_view.dart'; -import 'package:penyaluran_app/app/modules/dashboard/views/warga_dashboard_view.dart'; -import 'package:penyaluran_app/app/modules/dashboard/views/petugas_verifikasi_dashboard_view.dart'; -import 'package:penyaluran_app/app/modules/dashboard/views/donatur_dashboard_view.dart'; import 'package:penyaluran_app/app/modules/auth/bindings/auth_binding.dart'; -import 'package:penyaluran_app/app/modules/home/bindings/home_binding.dart'; -import 'package:penyaluran_app/app/modules/dashboard/bindings/dashboard_binding.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/petugas_desa_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/bindings/petugas_desa_binding.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/permintaan_penjadwalan_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/daftar_penerima_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/detail_penerima_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/views/konfirmasi_penerima_view.dart'; +import 'package:penyaluran_app/app/modules/petugas_desa/views/pelaksanaan_penyaluran_view.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/bindings/penerima_binding.dart'; @@ -24,36 +19,16 @@ class AppPages { static const initial = Routes.login; static final routes = [ - GetPage( - name: _Paths.home, - page: () => const HomeView(), - binding: HomeBinding(), - ), GetPage( name: _Paths.login, page: () => const LoginView(), binding: AuthBinding(), ), - GetPage( - name: _Paths.wargaDashboard, - page: () => const WargaDashboardView(), - binding: DashboardBinding(), - ), - GetPage( - name: _Paths.petugasVerifikasiDashboard, - page: () => const PetugasVerifikasiDashboardView(), - binding: DashboardBinding(), - ), GetPage( name: _Paths.petugasDesaDashboard, page: () => const PetugasDesaView(), binding: PetugasDesaBinding(), ), - GetPage( - name: _Paths.donaturDashboard, - page: () => const DonaturDashboardView(), - binding: DashboardBinding(), - ), GetPage( name: _Paths.permintaanPenjadwalan, page: () => const PermintaanPenjadwalanView(), @@ -74,5 +49,10 @@ class AppPages { page: () => const KonfirmasiPenerimaView(), binding: PenerimaBinding(), ), + GetPage( + name: _Paths.pelaksanaanPenyaluran, + page: () => const PelaksanaanPenyaluranView(), + binding: PetugasDesaBinding(), + ), ]; } diff --git a/lib/app/routes/app_routes.dart b/lib/app/routes/app_routes.dart index 2b27255..9bba31c 100644 --- a/lib/app/routes/app_routes.dart +++ b/lib/app/routes/app_routes.dart @@ -14,6 +14,7 @@ abstract class Routes { static const daftarPenerima = _Paths.daftarPenerima; static const detailPenerima = _Paths.detailPenerima; static const konfirmasiPenerima = _Paths.konfirmasiPenerima; + static const pelaksanaanPenyaluran = _Paths.pelaksanaanPenyaluran; } abstract class _Paths { @@ -30,4 +31,5 @@ abstract class _Paths { static const daftarPenerima = '/daftar-penerima'; static const detailPenerima = '/daftar-penerima/detail'; static const konfirmasiPenerima = '/daftar-penerima/konfirmasi'; + static const pelaksanaanPenyaluran = '/pelaksanaan-penyaluran'; }