Hapus tampilan dashboard Petugas Desa dan perbarui routing

- Hapus file petugas_desa_dashboard_view.dart
- Perbarui app_pages.dart untuk menggunakan PetugasDesaView dan PetugasDesaBinding
- Pindahkan logika dashboard ke modul petugas_desa yang baru
- Sesuaikan routing untuk dashboard Petugas Desa
This commit is contained in:
Khafidh Fuadi
2025-03-08 16:39:48 +07:00
parent 539fad3cda
commit 10ed95b3ac
12 changed files with 1850 additions and 635 deletions

View File

@ -0,0 +1,187 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:penyaluran_app/app/modules/petugas_desa/components/greeting_header.dart';
import 'package:penyaluran_app/app/modules/petugas_desa/components/progress_section.dart';
import 'package:penyaluran_app/app/modules/petugas_desa/components/schedule_card.dart';
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/petugas_desa_controller.dart';
import 'package:penyaluran_app/app/theme/app_theme.dart';
import 'package:penyaluran_app/app/widgets/statistic_card.dart';
class DashboardView extends GetView<PetugasDesaController> {
const DashboardView({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: [
// Header dengan greeting
GreetingHeader(
name: controller.roleData.value?['namaLengkap'] ?? 'Ahmad',
role: 'Petugas Desa',
desa: controller.roleData.value?['Desa'] ?? 'Jatihurip',
),
const SizedBox(height: 20),
// Jadwal penyaluran hari ini
ScheduleCard(
title: 'Jadwal Penyaluran Hari ini',
location: 'Kantor Kepala Desa (Beras)',
dateTime: '15 April 2023, 13:00 - 14:00',
isToday: true,
onTap: () => Get.toNamed('/petugas-desa/jadwal'),
),
const SizedBox(height: 20),
// Jadwal penyaluran mendatang
ScheduleCard(
title: 'Jadwal Penyaluran Mendatang',
location: 'Balai Desa A (Sembako)',
dateTime: '17 April 2023, 13:00 - 14:00',
isToday: false,
onTap: () => Get.toNamed('/petugas-desa/jadwal'),
),
const SizedBox(height: 20),
// Statistik penyaluran
Row(
children: [
Expanded(
child: StatisticCard(
title: 'Penitipan',
count: '3',
subtitle: 'Perlu Konfirmasi',
height: 120,
),
),
const SizedBox(width: 10),
Expanded(
child: StatisticCard(
title: 'Penjadwalan',
count: '1',
subtitle: 'Perlu Konfirmasi',
height: 120,
),
),
const SizedBox(width: 10),
Expanded(
child: StatisticCard(
title: 'Pengaduan',
count: '1',
subtitle: 'Perlu Tindakan',
height: 120,
),
),
],
),
const SizedBox(height: 20),
// Progress penyaluran
ProgressSection(
progressValue: 0.7,
total: 100,
distributed: 70,
scheduled: 20,
unscheduled: 10,
),
const SizedBox(height: 20),
// Daftar penerima
_buildRecipientsList(textTheme),
],
),
),
);
}
Widget _buildRecipientsList(TextTheme textTheme) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Daftar Penerima',
style: textTheme.titleMedium?.copyWith(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
TextButton(
onPressed: () {},
child: Row(
children: [
Text(
'Lihat Semua',
style: textTheme.bodyMedium?.copyWith(
color: AppTheme.primaryColor,
),
),
Icon(
Icons.chevron_right,
size: 16,
color: AppTheme.primaryColor,
),
],
),
),
],
),
const SizedBox(height: 10),
_buildRecipientItem(
'Siti Rahayu', '3201020107030010', 'Selesai', textTheme),
_buildRecipientItem(
'Budi Santoso', '3201020107030011', 'Selesai', textTheme),
_buildRecipientItem(
'Dewi Lestari', '3201020107030012', 'Selesai', textTheme),
],
);
}
Widget _buildRecipientItem(
String name, String nik, String status, TextTheme textTheme) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
gradient: AppTheme.primaryGradient,
borderRadius: BorderRadius.circular(12),
),
child: ListTile(
title: Text(
name,
style: textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
subtitle: Text(
'NIK: $nik',
style: textTheme.bodyMedium?.copyWith(
color: Colors.white,
),
),
trailing: Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Text(
status,
style: textTheme.bodySmall?.copyWith(
color: Colors.white,
fontSize: 12,
),
),
),
),
);
}
}

View File

@ -0,0 +1,389 @@
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 InventarisView extends GetView<PetugasDesaController> {
const InventarisView({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 inventaris
_buildInventarisSummary(context),
const SizedBox(height: 24),
// Filter dan pencarian
_buildFilterSearch(context),
const SizedBox(height: 20),
// Daftar inventaris
_buildInventarisList(context),
],
),
),
);
}
Widget _buildInventarisSummary(BuildContext context) {
return Container(
width: double.infinity,
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: AppTheme.primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Ringkasan Inventaris',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
Row(
children: [
Expanded(
child: _buildSummaryItem(
context,
icon: Icons.inventory_2_outlined,
title: 'Total Stok',
value: '1,250 kg',
color: Colors.blue,
),
),
Expanded(
child: _buildSummaryItem(
context,
icon: Icons.input,
title: 'Masuk Bulan Ini',
value: '500 kg',
color: Colors.green,
),
),
Expanded(
child: _buildSummaryItem(
context,
icon: Icons.output,
title: 'Keluar Bulan Ini',
value: '350 kg',
color: Colors.orange,
),
),
],
),
],
),
);
}
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: color.withOpacity(0.2),
shape: BoxShape.circle,
),
child: Icon(
icon,
color: color,
size: 24,
),
),
const SizedBox(height: 8),
Text(
value,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
title,
style: Theme.of(context).textTheme.bodySmall,
textAlign: TextAlign.center,
),
],
);
}
Widget _buildFilterSearch(BuildContext context) {
return Row(
children: [
Expanded(
child: TextField(
decoration: InputDecoration(
hintText: 'Cari bantuan...',
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 _buildInventarisList(BuildContext context) {
final List<Map<String, dynamic>> inventarisList = [
{
'nama': 'Beras',
'jenis': 'Sembako',
'stok': '750 kg',
'lokasi': 'Gudang Utama',
'tanggal_masuk': '10 April 2023',
'kadaluarsa': '10 April 2024',
},
{
'nama': 'Minyak Goreng',
'jenis': 'Sembako',
'stok': '250 liter',
'lokasi': 'Gudang Utama',
'tanggal_masuk': '12 April 2023',
'kadaluarsa': '12 Oktober 2023',
},
{
'nama': 'Paket Sembako',
'jenis': 'Paket Bantuan',
'stok': '100 paket',
'lokasi': 'Gudang Cabang',
'tanggal_masuk': '15 April 2023',
'kadaluarsa': '15 Juli 2023',
},
{
'nama': 'Selimut',
'jenis': 'Non-Pangan',
'stok': '150 buah',
'lokasi': 'Gudang Cabang',
'tanggal_masuk': '5 April 2023',
'kadaluarsa': '-',
},
];
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Daftar Inventaris',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
TextButton.icon(
onPressed: () {
// Navigasi ke halaman tambah inventaris
},
icon: const Icon(Icons.add),
label: const Text('Tambah'),
style: TextButton.styleFrom(
foregroundColor: AppTheme.primaryColor,
),
),
],
),
const SizedBox(height: 12),
...inventarisList.map((item) => _buildInventarisItem(context, item)),
],
);
}
Widget _buildInventarisItem(BuildContext context, Map<String, dynamic> item) {
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: [
Text(
item['nama'] ?? '',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
Container(
padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: AppTheme.primaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(8),
),
child: Text(
item['jenis'] ?? '',
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: AppTheme.primaryColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 12),
Row(
children: [
Expanded(
child: _buildItemDetail(
context,
icon: Icons.inventory,
label: 'Stok',
value: item['stok'] ?? '',
),
),
Expanded(
child: _buildItemDetail(
context,
icon: Icons.location_on_outlined,
label: 'Lokasi',
value: item['lokasi'] ?? '',
),
),
],
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: _buildItemDetail(
context,
icon: Icons.calendar_today,
label: 'Tanggal Masuk',
value: item['tanggal_masuk'] ?? '',
),
),
Expanded(
child: _buildItemDetail(
context,
icon: Icons.timelapse,
label: 'Kadaluarsa',
value: item['kadaluarsa'] ?? '',
),
),
],
),
const SizedBox(height: 12),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton.icon(
onPressed: () {
// Tampilkan detail inventaris
},
icon: const Icon(Icons.edit_outlined, size: 18),
label: const Text('Edit'),
style: TextButton.styleFrom(
foregroundColor: Colors.blue,
padding: const EdgeInsets.symmetric(horizontal: 8),
),
),
TextButton.icon(
onPressed: () {
// Tampilkan dialog konfirmasi hapus
},
icon: const Icon(Icons.delete_outline, size: 18),
label: const Text('Hapus'),
style: TextButton.styleFrom(
foregroundColor: Colors.red,
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,
),
],
),
),
],
);
}
}

View File

@ -0,0 +1,189 @@
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 JadwalView extends GetView<PetugasDesaController> {
const JadwalView({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: [
// Jadwal hari ini
_buildJadwalSection(
textTheme,
title: 'Hari Ini',
jadwalList: [
{
'lokasi': 'Kantor Kepala Desa',
'jenisBantuan': 'Beras',
'tanggal': '15 April 2023',
'waktu': '13:00 - 14:00',
'status': 'Aktif',
},
],
),
const SizedBox(height: 20),
// Jadwal mendatang
_buildJadwalSection(
textTheme,
title: 'Mendatang',
jadwalList: [
{
'lokasi': 'Balai Desa A',
'jenisBantuan': 'Sembako',
'tanggal': '17 April 2023',
'waktu': '13:00 - 14:00',
'status': 'Terjadwal',
},
{
'lokasi': 'Balai Desa B',
'jenisBantuan': 'Uang Tunai',
'tanggal': '20 April 2023',
'waktu': '10:00 - 12:00',
'status': 'Terjadwal',
},
],
),
const SizedBox(height: 20),
// Jadwal selesai
_buildJadwalSection(
textTheme,
title: 'Selesai',
jadwalList: [
{
'lokasi': 'Kantor Kepala Desa',
'jenisBantuan': 'Beras',
'tanggal': '10 April 2023',
'waktu': '13:00 - 14:00',
'status': 'Selesai',
},
{
'lokasi': 'Balai Desa C',
'jenisBantuan': 'Sembako',
'tanggal': '5 April 2023',
'waktu': '09:00 - 11:00',
'status': 'Selesai',
},
],
),
],
),
),
);
}
Widget _buildJadwalSection(
TextTheme textTheme, {
required String title,
required List<Map<String, String>> jadwalList,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
...jadwalList.map((jadwal) => _buildJadwalItem(textTheme, jadwal)),
],
);
}
Widget _buildJadwalItem(TextTheme textTheme, Map<String, String> jadwal) {
Color statusColor;
switch (jadwal['status']) {
case 'Aktif':
statusColor = Colors.green;
break;
case 'Terjadwal':
statusColor = Colors.blue;
break;
case 'Selesai':
statusColor = Colors.grey;
break;
default:
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(
jadwal['status'] ?? '',
style: textTheme.bodySmall?.copyWith(
color: statusColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
const SizedBox(height: 8),
Text(
'Jenis Bantuan: ${jadwal['jenisBantuan'] ?? ''}',
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,
),
],
),
),
);
}
}

View File

@ -0,0 +1,183 @@
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 NotifikasiView extends GetView<PetugasDesaController> {
const NotifikasiView({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: [
// 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,
},
],
),
],
),
),
);
}
Widget _buildNotifikasiSection(
TextTheme textTheme, {
required String title,
required List<Map<String, dynamic>> notifikasiList,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 10),
...notifikasiList
.map((notifikasi) => _buildNotifikasiItem(textTheme, notifikasi)),
],
);
}
Widget _buildNotifikasiItem(
TextTheme textTheme, Map<String, dynamic> notifikasi) {
final bool dibaca = notifikasi['dibaca'] as bool;
return Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
color: dibaca ? Colors.white : Colors.blue.shade50,
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: 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,
),
],
),
),
],
),
),
);
}
}

View File

@ -0,0 +1,315 @@
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/modules/petugas_desa/views/dashboard_view.dart';
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/theme/app_theme.dart';
class PetugasDesaView extends GetView<PetugasDesaController> {
const PetugasDesaView({super.key});
@override
Widget build(BuildContext context) {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: Obx(() {
switch (controller.activeTabIndex.value) {
case 0:
return const Text('Dashboard');
case 1:
return const Text('Jadwal Penyaluran');
case 2:
return const Text('Notifikasi');
case 3:
return const Text('Inventaris');
default:
return const Text('Petugas Desa');
}
}),
leading: IconButton(
icon: const Icon(Icons.menu),
onPressed: () {
scaffoldKey.currentState?.openDrawer();
},
),
actions: [
// Tombol aksi berdasarkan tab yang aktif
Obx(() {
final activeTab = controller.activeTabIndex.value;
// Tombol notifikasi selalu ditampilkan
final notificationButton = Stack(
alignment: Alignment.center,
children: [
IconButton(
icon: const Icon(Icons.notifications_outlined),
onPressed: () {
controller.changeTab(2); // Pindah ke tab notifikasi
},
),
if (controller.jumlahNotifikasiBelumDibaca.value > 0)
Positioned(
top: 8,
right: 8,
child: Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
constraints: const BoxConstraints(
minWidth: 16,
minHeight: 16,
),
child: Text(
controller.jumlahNotifikasiBelumDibaca.value.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 10,
),
textAlign: TextAlign.center,
),
),
),
],
);
// Tombol tambah untuk jadwal dan inventaris
if (activeTab == 1) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: const Icon(Icons.add),
tooltip: 'Tambah Jadwal',
onPressed: () {
// Implementasi untuk menambah jadwal baru
},
),
notificationButton,
],
);
} 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: [
IconButton(
icon: const Icon(Icons.add),
tooltip: 'Tambah Inventaris',
onPressed: () {
// Implementasi untuk menambah inventaris baru
},
),
notificationButton,
],
);
} else {
return notificationButton;
}
}),
],
),
drawer: _buildDrawer(context),
body: Obx(() {
switch (controller.activeTabIndex.value) {
case 0:
return const DashboardView();
case 1:
return const JadwalView();
case 2:
return const NotifikasiView();
case 3:
return const InventarisView();
default:
return const DashboardView();
}
}),
bottomNavigationBar: _buildBottomNavigationBar(),
);
}
Widget _buildDrawer(BuildContext context) {
return Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
DrawerHeader(
decoration: BoxDecoration(
gradient: AppTheme.primaryGradient,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.end,
children: [
const CircleAvatar(
radius: 30,
backgroundColor: Colors.white,
child: Icon(
Icons.person,
size: 40,
color: AppTheme.primaryColor,
),
),
const SizedBox(height: 10),
Text(
controller.nama,
style: const TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
'Petugas Desa',
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 14,
),
),
],
),
),
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();
},
),
ListTile(
leading: Stack(
alignment: Alignment.center,
children: [
const Icon(Icons.notifications_outlined),
if (controller.jumlahNotifikasiBelumDibaca.value > 0)
Positioned(
top: 0,
right: 0,
child: Container(
padding: const EdgeInsets.all(2),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10),
),
constraints: const BoxConstraints(
minWidth: 12,
minHeight: 12,
),
child: Text(
controller.jumlahNotifikasiBelumDibaca.value.toString(),
style: const TextStyle(
color: Colors.white,
fontSize: 8,
),
textAlign: TextAlign.center,
),
),
),
],
),
title: const Text('Notifikasi'),
selected: controller.activeTabIndex.value == 2,
selectedColor: AppTheme.primaryColor,
onTap: () {
controller.changeTab(2);
Get.back();
},
),
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();
},
),
ListTile(
leading: const Icon(Icons.settings_outlined),
title: const Text('Pengaturan'),
onTap: () {
// Navigasi ke halaman pengaturan
Get.back();
},
),
ListTile(
leading: const Icon(Icons.logout),
title: const Text('Keluar'),
onTap: () {
Get.back();
controller.logout();
},
),
],
),
);
}
Widget _buildBottomNavigationBar() {
return Obx(() => BottomNavigationBar(
currentIndex: controller.activeTabIndex.value,
onTap: controller.changeTab,
type: BottomNavigationBarType.fixed,
selectedItemColor: AppTheme.primaryColor,
unselectedItemColor: Colors.grey,
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),
label: 'Jadwal',
),
BottomNavigationBarItem(
icon: Icon(Icons.notifications_outlined),
activeIcon: Icon(Icons.notifications),
label: 'Notifikasi',
),
BottomNavigationBarItem(
icon: Icon(Icons.inventory_2_outlined),
activeIcon: Icon(Icons.inventory_2),
label: 'Inventaris',
),
],
));
}
}