Hapus modul dashboard dan home yang tidak digunakan

- Hapus file-file terkait dashboard untuk warga, donatur, dan petugas verifikasi
- Hapus modul home yang sudah tidak diperlukan
- Perbarui app_pages.dart untuk menghapus rute dashboard dan home
- Bersihkan impor dan binding yang tidak digunakan
This commit is contained in:
Khafidh Fuadi
2025-03-09 10:45:13 +07:00
parent c54c0a27d9
commit c8f529bd1a
12 changed files with 527 additions and 968 deletions

View File

@ -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>(
() => DashboardController(),
);
}
}

View File

@ -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<AuthController>();
final SupabaseService _supabaseService = SupabaseService.to;
final RxBool isLoading = false.obs;
final Rx<Map<String, dynamic>?> roleData = Rx<Map<String, dynamic>?>(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<void> 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();
}
}

View File

@ -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<DashboardController> {
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),
],
),
),
),
);
}
}

View File

@ -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<DashboardController> {
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),
],
),
),
),
);
}
}

View File

@ -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<DashboardController> {
const WargaDashboardView({super.key});
@override
Widget build(BuildContext context) {
final authController = Get.find<AuthController>();
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),
],
),
),
),
);
}
}

View File

@ -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>(
() => HomeController(),
);
}
}

View File

@ -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<AuthController>();
// Getter untuk mendapatkan user dari auth controller
get user => _authController.user;
// Metode untuk logout
void logout() {
_authController.logout();
}
}

View File

@ -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<HomeController> {
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,
),
),
),
),
],
),
),
),
);
}
}

View File

@ -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,7 +91,12 @@ class JadwalSectionWidget extends StatelessWidget {
statusColor = Colors.orange;
}
return Container(
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(
@ -158,8 +164,28 @@ class JadwalSectionWidget extends StatelessWidget {
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,
),
],
),
],
),
),
),
);
}

View File

@ -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<PetugasDesaController> {
const PelaksanaanPenyaluranView({super.key});
@override
Widget build(BuildContext context) {
// Ambil data jadwal dari parameter
final jadwal = Get.arguments as Map<String, dynamic>;
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<String, dynamic> 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<String, dynamic> jadwal) {
// Simulasi data penerima bantuan
final List<Map<String, dynamic>> 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<String, dynamic> 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<String, dynamic> 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<String, dynamic> 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'),
),
],
),
);
}
}

View File

@ -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(),
),
];
}

View File

@ -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';
}