Perbarui model Pengaduan dengan menambahkan getter isUang untuk memeriksa jenis bantuan. Modifikasi tampilan dan controller di modul donatur dan petugas desa untuk meningkatkan pengalaman pengguna, termasuk penggantian ikon dan penyesuaian format tampilan jumlah bantuan. Hapus kode yang tidak diperlukan untuk menjaga kebersihan kode.
This commit is contained in:
@ -10,6 +10,12 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
final JadwalPenyaluranController controller;
|
||||
final CalendarController _calendarController = CalendarController();
|
||||
|
||||
// Tambahkan variabel untuk status filter
|
||||
final RxBool _showAllSchedules = true.obs;
|
||||
|
||||
// Tambahkan variabel untuk mode tampilan kalender
|
||||
final Rx<CalendarView> _calendarView = CalendarView.month.obs;
|
||||
|
||||
CalendarViewWidget({
|
||||
super.key,
|
||||
required this.controller,
|
||||
@ -47,20 +53,135 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
topRight: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.calendar_month_rounded,
|
||||
color: Colors.white,
|
||||
size: 28,
|
||||
// Title pada baris pertama
|
||||
Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.calendar_month_rounded,
|
||||
color: Colors.white,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
'Kalender Penyaluran',
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
'Kalender Penyaluran',
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Tombol filter pada baris kedua
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
// Tombol mode tampilan
|
||||
Obx(() => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Tooltip(
|
||||
message: _calendarView.value == CalendarView.month
|
||||
? 'Beralih ke tampilan agenda'
|
||||
: 'Beralih ke tampilan kalender',
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_calendarView.value =
|
||||
_calendarView.value == CalendarView.month
|
||||
? CalendarView.schedule
|
||||
: CalendarView.month;
|
||||
|
||||
// Update calendar controller dengan tampilan baru
|
||||
_calendarController.view = _calendarView.value;
|
||||
},
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 6),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
_calendarView.value == CalendarView.month
|
||||
? Icons.view_agenda
|
||||
: Icons.calendar_month,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_calendarView.value == CalendarView.month
|
||||
? 'Agenda'
|
||||
: 'Bulan',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
|
||||
const SizedBox(width: 8),
|
||||
|
||||
// Tombol filter
|
||||
Obx(() => Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Tooltip(
|
||||
message: _showAllSchedules.value
|
||||
? 'Tampilkan hanya jadwal bulan ini'
|
||||
: 'Tampilkan semua jadwal',
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
_showAllSchedules.value =
|
||||
!_showAllSchedules.value;
|
||||
},
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 6),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
_showAllSchedules.value
|
||||
? Icons.filter_list
|
||||
: Icons.filter_alt,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_showAllSchedules.value
|
||||
? 'Semua'
|
||||
: 'Bulan Ini',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -71,7 +192,7 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
height: MediaQuery.of(context).size.height * 0.65,
|
||||
child: Obx(() {
|
||||
return SfCalendar(
|
||||
view: CalendarView.month,
|
||||
view: _calendarView.value,
|
||||
controller: _calendarController,
|
||||
initialSelectedDate: DateTime.now(),
|
||||
initialDisplayDate: DateTime.now(),
|
||||
@ -119,6 +240,42 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
scheduleViewSettings: ScheduleViewSettings(
|
||||
appointmentItemHeight: 70,
|
||||
monthHeaderSettings: MonthHeaderSettings(
|
||||
height: 50,
|
||||
backgroundColor: AppTheme.primaryColor,
|
||||
monthTextStyle: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
weekHeaderSettings: WeekHeaderSettings(
|
||||
height: 40,
|
||||
textAlign: TextAlign.center,
|
||||
backgroundColor: Colors.grey.shade100,
|
||||
weekTextStyle: TextStyle(
|
||||
color: AppTheme.primaryColor,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
dayHeaderSettings: DayHeaderSettings(
|
||||
dayFormat: 'EEEE',
|
||||
width: 70,
|
||||
dayTextStyle: const TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: AppTheme.primaryColor,
|
||||
),
|
||||
dateTextStyle: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppTheme.primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
cellBorderColor: Colors.grey.withOpacity(0.2),
|
||||
todayHighlightColor: AppTheme.primaryColor,
|
||||
selectionDecoration: BoxDecoration(
|
||||
@ -291,6 +448,7 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
...controller.jadwalTerlaksana,
|
||||
];
|
||||
|
||||
// Tambahkan filter berdasarkan _showAllSchedules
|
||||
DateTime now = DateTime.now();
|
||||
DateTime firstDayOfMonth = DateTime(now.year, now.month, 1);
|
||||
DateTime lastDayOfMonth = DateTime(now.year, now.month + 1, 0);
|
||||
@ -300,9 +458,14 @@ class CalendarViewWidget extends StatelessWidget {
|
||||
DateTime jadwalDate =
|
||||
FormatHelper.toLocalDateTime(jadwal.tanggalPenyaluran!);
|
||||
|
||||
if (jadwalDate
|
||||
.isAfter(firstDayOfMonth.subtract(const Duration(days: 1))) &&
|
||||
jadwalDate.isBefore(lastDayOfMonth.add(const Duration(days: 1)))) {
|
||||
// Filter berdasarkan bulan saat ini jika _showAllSchedules.value = false
|
||||
bool shouldShow = _showAllSchedules.value ||
|
||||
(jadwalDate.isAfter(
|
||||
firstDayOfMonth.subtract(const Duration(days: 1))) &&
|
||||
jadwalDate
|
||||
.isBefore(lastDayOfMonth.add(const Duration(days: 1))));
|
||||
|
||||
if (shouldShow) {
|
||||
Color appointmentColor;
|
||||
|
||||
// Periksa status jadwal menggunakan switch-case untuk konsistensi
|
||||
|
@ -1,55 +1,223 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class GreetingHeader extends StatelessWidget {
|
||||
final String name;
|
||||
final String role;
|
||||
final String? desa;
|
||||
final String? nip;
|
||||
final String? profileImageUrl;
|
||||
|
||||
const GreetingHeader({
|
||||
super.key,
|
||||
required this.name,
|
||||
required this.role,
|
||||
this.desa,
|
||||
this.nip,
|
||||
this.profileImageUrl,
|
||||
});
|
||||
|
||||
String _getGreeting() {
|
||||
final hour = DateTime.now().hour;
|
||||
if (hour < 12) {
|
||||
return 'Selamat Pagi';
|
||||
} else if (hour < 15) {
|
||||
return 'Selamat Siang';
|
||||
} else if (hour < 19) {
|
||||
return 'Selamat Sore';
|
||||
} else {
|
||||
return 'Selamat Malam';
|
||||
}
|
||||
}
|
||||
|
||||
String _getCurrentDate() {
|
||||
final now = DateTime.now();
|
||||
return DateFormat('EEEE, d MMMM yyyy', 'id_ID').format(now);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textTheme = Theme.of(context).textTheme;
|
||||
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
gradient: LinearGradient(
|
||||
colors: [
|
||||
Colors.blue.shade800,
|
||||
Colors.blue.shade600,
|
||||
],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withAlpha(26), // 0.1 * 255 ≈ 26
|
||||
color: Colors.blue.withOpacity(0.3),
|
||||
spreadRadius: 1,
|
||||
blurRadius: 3,
|
||||
offset: const Offset(0, 1),
|
||||
blurRadius: 15,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Selamat Datang, $name!',
|
||||
style: textTheme.headlineSmall?.copyWith(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
_getGreeting(),
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
name,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(
|
||||
color: Colors.white.withOpacity(0.3),
|
||||
width: 2,
|
||||
),
|
||||
image: profileImageUrl != null && profileImageUrl!.isNotEmpty
|
||||
? DecorationImage(
|
||||
image: NetworkImage(profileImageUrl!),
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
child: profileImageUrl == null || profileImageUrl!.isEmpty
|
||||
? const Icon(
|
||||
Icons.person,
|
||||
size: 30,
|
||||
color: Colors.white,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
desa != null && desa!.isNotEmpty
|
||||
? 'Kamu Login Sebagai $role $desa.'
|
||||
: 'Kamu Login Sebagai $role.',
|
||||
style: textTheme.bodyMedium?.copyWith(
|
||||
fontSize: 14,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.location_on,
|
||||
size: 14,
|
||||
color: Colors.white70,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Flexible(
|
||||
child: Text(
|
||||
desa != null && desa!.isNotEmpty
|
||||
? '$role - Desa $desa'
|
||||
: role,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.white70,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (nip != null && nip!.isNotEmpty)
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.badge,
|
||||
size: 14,
|
||||
color: Colors.white70,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'NIP: $nip',
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.white70,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.15),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.calendar_today,
|
||||
size: 14,
|
||||
color: Colors.white70,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
_getCurrentDate(),
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.white70,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -57,6 +57,15 @@ class PetugasDesaDashboardController extends GetxController {
|
||||
userProfile['desa']?['nama'] ??
|
||||
(userProfile['desa_id'] != null ? 'Desa' : 'Desa');
|
||||
|
||||
// Getter untuk NIP dari profil pengguna
|
||||
String? get nip =>
|
||||
userProfile['role_data']?['nip'] ?? _authController.roleData?.nip;
|
||||
|
||||
// Getter untuk foto profil dari profil pengguna
|
||||
String? get profileImageUrl =>
|
||||
userProfile['role_data']?['foto_profil'] ??
|
||||
_authController.roleData?.fotoProfil;
|
||||
|
||||
// Getter untuk counter dari CounterService
|
||||
RxInt get jumlahMenunggu => _counterService.jumlahMenunggu;
|
||||
RxInt get jumlahDiproses => _counterService.jumlahDiproses;
|
||||
|
@ -263,7 +263,7 @@ class DaftarDonaturView extends GetView<DonaturController> {
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Icons.attach_money,
|
||||
Icons.payment_rounded,
|
||||
size: 14,
|
||||
color: Colors.green,
|
||||
),
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -277,7 +277,7 @@ class DetailDonaturView extends GetView<DonaturController> {
|
||||
child: _buildSummaryCard(
|
||||
title: 'Donasi Uang',
|
||||
value: jumlahDonasiUang.toString(),
|
||||
icon: Icons.attach_money,
|
||||
icon: Icons.payment_rounded,
|
||||
color: jenisColor,
|
||||
),
|
||||
),
|
||||
|
@ -5,14 +5,10 @@ import 'package:penyaluran_app/app/data/models/tindakan_pengaduan_model.dart';
|
||||
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/pengaduan_controller.dart';
|
||||
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
||||
import 'package:penyaluran_app/app/utils/format_helper.dart';
|
||||
import 'package:penyaluran_app/app/widgets/cards/info_card.dart';
|
||||
import 'package:penyaluran_app/app/widgets/indicators/status_pill.dart';
|
||||
import 'package:penyaluran_app/app/services/supabase_service.dart';
|
||||
import 'package:timeline_tile/timeline_tile.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'dart:io';
|
||||
import 'package:penyaluran_app/app/widgets/inputs/dropdown_input.dart';
|
||||
import 'package:penyaluran_app/app/widgets/inputs/text_input.dart';
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:penyaluran_app/app/widgets/widgets.dart';
|
||||
|
||||
@ -1391,61 +1387,9 @@ class DetailPengaduanView extends GetView<PengaduanController> {
|
||||
? List<String>.from(tindakan.buktiTindakan!)
|
||||
: [];
|
||||
|
||||
// Fungsi untuk memilih bukti tindakan
|
||||
Future<void> pickBuktiTindakan(
|
||||
BuildContext dialogContext, bool fromCamera) async {
|
||||
try {
|
||||
final ImagePicker picker = ImagePicker();
|
||||
final XFile? pickedFile = await picker.pickImage(
|
||||
source: fromCamera ? ImageSource.camera : ImageSource.gallery,
|
||||
imageQuality: 80,
|
||||
maxWidth: 1200,
|
||||
maxHeight: 1200,
|
||||
preferredCameraDevice:
|
||||
fromCamera ? CameraDevice.rear : CameraDevice.front,
|
||||
);
|
||||
|
||||
if (pickedFile != null) {
|
||||
// Tampilkan loading dialog
|
||||
showDialog(
|
||||
context: dialogContext,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
// Tambahkan gambar ke daftar
|
||||
buktiTindakanPaths.add(pickedFile.path);
|
||||
|
||||
// Tutup loading dialog
|
||||
Navigator.of(dialogContext, rootNavigator: true).pop();
|
||||
|
||||
// Tutup dialog pilih sumber foto
|
||||
Navigator.of(dialogContext).pop();
|
||||
} catch (e) {
|
||||
// Tutup loading dialog jika terjadi error
|
||||
Navigator.of(dialogContext, rootNavigator: true).pop();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error picking image: $e');
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengambil gambar: ${e.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Fungsi untuk menampilkan dialog pilih sumber foto
|
||||
void showPilihSumberFoto(BuildContext dialogContext) {
|
||||
void showPilihSumberFoto(
|
||||
BuildContext dialogContext, Function(BuildContext, bool) pickFunction) {
|
||||
showDialog(
|
||||
context: dialogContext,
|
||||
builder: (innerContext) => AlertDialog(
|
||||
@ -1456,12 +1400,12 @@ class DetailPengaduanView extends GetView<PengaduanController> {
|
||||
ListTile(
|
||||
leading: const Icon(Icons.camera_alt),
|
||||
title: const Text('Kamera'),
|
||||
onTap: () => pickBuktiTindakan(innerContext, true),
|
||||
onTap: () => pickFunction(innerContext, true),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.photo_library),
|
||||
title: const Text('Galeri'),
|
||||
onTap: () => pickBuktiTindakan(innerContext, false),
|
||||
onTap: () => pickFunction(innerContext, false),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -1473,6 +1417,61 @@ class DetailPengaduanView extends GetView<PengaduanController> {
|
||||
context: context,
|
||||
builder: (dialogContext) =>
|
||||
StatefulBuilder(builder: (stateContext, setState) {
|
||||
// Fungsi untuk memilih bukti tindakan dipindahkan ke dalam StatefulBuilder
|
||||
Future<void> pickBuktiTindakan(
|
||||
BuildContext innerContext, bool fromCamera) async {
|
||||
try {
|
||||
final ImagePicker picker = ImagePicker();
|
||||
final XFile? pickedFile = await picker.pickImage(
|
||||
source: fromCamera ? ImageSource.camera : ImageSource.gallery,
|
||||
imageQuality: 80,
|
||||
maxWidth: 1200,
|
||||
maxHeight: 1200,
|
||||
preferredCameraDevice:
|
||||
fromCamera ? CameraDevice.rear : CameraDevice.front,
|
||||
);
|
||||
|
||||
if (pickedFile != null) {
|
||||
// Tampilkan loading dialog
|
||||
showDialog(
|
||||
context: innerContext,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return const Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
try {
|
||||
// Tambahkan gambar ke daftar dan update state
|
||||
setState(() {
|
||||
buktiTindakanPaths.add(pickedFile.path);
|
||||
});
|
||||
|
||||
// Tutup loading dialog
|
||||
Navigator.of(innerContext, rootNavigator: true).pop();
|
||||
|
||||
// Tutup dialog pilih sumber foto
|
||||
Navigator.of(innerContext).pop();
|
||||
} catch (e) {
|
||||
// Tutup loading dialog jika terjadi error
|
||||
Navigator.of(innerContext, rootNavigator: true).pop();
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error picking image: $e');
|
||||
Get.snackbar(
|
||||
'Error',
|
||||
'Gagal mengambil gambar: ${e.toString()}',
|
||||
snackPosition: SnackPosition.TOP,
|
||||
backgroundColor: Colors.red,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return AlertDialog(
|
||||
title: Row(
|
||||
children: [
|
||||
@ -1581,7 +1580,8 @@ class DetailPengaduanView extends GetView<PengaduanController> {
|
||||
children: [
|
||||
if (buktiTindakanPaths.isEmpty)
|
||||
InkWell(
|
||||
onTap: () => showPilihSumberFoto(stateContext),
|
||||
onTap: () => showPilihSumberFoto(
|
||||
stateContext, pickBuktiTindakan),
|
||||
child: Container(
|
||||
height: 150,
|
||||
width: double.infinity,
|
||||
@ -1619,15 +1619,16 @@ class DetailPengaduanView extends GetView<PengaduanController> {
|
||||
height: 100,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: buktiTindakanPaths
|
||||
.length, //tombol tambah jika tidak selesai
|
||||
itemCount: buktiTindakanPaths.length +
|
||||
1, // Tambah 1 untuk tombol tambah
|
||||
itemBuilder: (context, index) {
|
||||
if (index ==
|
||||
buktiTindakanPaths.length) {
|
||||
// Tombol tambah foto
|
||||
return InkWell(
|
||||
onTap: () => showPilihSumberFoto(
|
||||
stateContext),
|
||||
stateContext,
|
||||
pickBuktiTindakan),
|
||||
child: Container(
|
||||
width: 100,
|
||||
margin: const EdgeInsets.only(
|
||||
|
@ -675,7 +675,7 @@ class _KonfirmasiPenerimaPageState extends State<KonfirmasiPenerimaPage> {
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Icon(
|
||||
isUang ? Icons.attach_money : Icons.scale_outlined,
|
||||
isUang ? Icons.payment_rounded : Icons.scale_outlined,
|
||||
color: Colors.green,
|
||||
size: 20,
|
||||
),
|
||||
|
@ -521,7 +521,15 @@ class PengaduanView extends GetView<PengaduanController> {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${item.jumlahBantuan} ${item.stokBantuan?['satuan'] ?? ''}',
|
||||
item.stokBantuan?['is_uang'] == true
|
||||
? FormatHelper.formatRupiah(
|
||||
item.jumlahBantuan is num
|
||||
? item.jumlahBantuan
|
||||
: double.tryParse(item
|
||||
.jumlahBantuan
|
||||
.toString()) ??
|
||||
0)
|
||||
: '${item.jumlahBantuan} ${item.stokBantuan?['satuan'] ?? ''}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.grey.shade800,
|
||||
|
@ -10,6 +10,7 @@ import 'package:penyaluran_app/app/modules/petugas_desa/views/penitipan_view.dar
|
||||
import 'package:penyaluran_app/app/modules/petugas_desa/views/pengaduan_view.dart';
|
||||
import 'package:penyaluran_app/app/theme/app_theme.dart';
|
||||
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/riwayat_stok_controller.dart';
|
||||
import 'package:penyaluran_app/app/widgets/app_drawer.dart';
|
||||
|
||||
class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
const PetugasDesaView({super.key});
|
||||
@ -190,360 +191,119 @@ class PetugasDesaView extends GetView<PetugasDesaController> {
|
||||
}
|
||||
|
||||
Widget _buildDrawer(BuildContext context) {
|
||||
return Drawer(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
gradient: AppTheme.primaryGradient,
|
||||
),
|
||||
padding: EdgeInsets.only(
|
||||
top: MediaQuery.of(context).padding.top + 16,
|
||||
bottom: 24,
|
||||
left: 16,
|
||||
right: 16),
|
||||
width: double.infinity,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Hero(
|
||||
tag: 'profile-photo',
|
||||
child: CircleAvatar(
|
||||
radius: 40,
|
||||
backgroundColor: Colors.white70,
|
||||
backgroundImage: controller.profilePhotoUrl != null &&
|
||||
controller.profilePhotoUrl!.isNotEmpty
|
||||
? NetworkImage(controller.profilePhotoUrl!)
|
||||
: null,
|
||||
child: (controller.profilePhotoUrl == null ||
|
||||
controller.profilePhotoUrl!.isEmpty)
|
||||
? Text(
|
||||
controller.nama.isNotEmpty
|
||||
? controller.nama
|
||||
.substring(0, 1)
|
||||
.toUpperCase()
|
||||
: '?',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: AppTheme.primaryColor,
|
||||
fontSize: 30,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
'Halo,',
|
||||
style: TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.nama,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 22,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 2,
|
||||
),
|
||||
SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Text(
|
||||
controller.formattedRole,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.location_on,
|
||||
color: Colors.white,
|
||||
size: 14,
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
controller.desa,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
return Obx(() {
|
||||
Map<String, List<DrawerMenuItem>> menuCategories = {
|
||||
'Menu Utama': [
|
||||
DrawerMenuItem(
|
||||
icon: Icons.dashboard_outlined,
|
||||
activeIcon: Icons.dashboard,
|
||||
title: 'Dashboard',
|
||||
isSelected: controller.activeTabIndex.value == 0,
|
||||
onTap: () {
|
||||
controller.activeTabIndex.value = 0;
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: ListView(
|
||||
padding: EdgeInsets.zero,
|
||||
children: [
|
||||
_buildMenuCategory('Menu Utama'),
|
||||
Obx(() => _buildMenuItem(
|
||||
icon: Icons.dashboard_outlined,
|
||||
activeIcon: Icons.dashboard,
|
||||
title: 'Dashboard',
|
||||
isSelected: controller.activeTabIndex.value == 0,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.changeTab(0);
|
||||
},
|
||||
)),
|
||||
Obx(() => _buildMenuItem(
|
||||
icon: Icons.handshake_outlined,
|
||||
activeIcon: Icons.handshake,
|
||||
title: 'Penyaluran',
|
||||
isSelected: controller.activeTabIndex.value == 1,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.changeTab(1);
|
||||
},
|
||||
)),
|
||||
Obx(() => _buildMenuItem(
|
||||
icon: Icons.inventory_2_outlined,
|
||||
activeIcon: Icons.inventory_2,
|
||||
title: 'Penitipan',
|
||||
isSelected: controller.activeTabIndex.value == 2,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.changeTab(2);
|
||||
},
|
||||
)),
|
||||
Obx(() => _buildMenuItem(
|
||||
icon: Icons.warning_amber_outlined,
|
||||
activeIcon: Icons.warning_amber,
|
||||
title: 'Pengaduan',
|
||||
isSelected: controller.activeTabIndex.value == 3,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.changeTab(3);
|
||||
},
|
||||
)),
|
||||
Obx(() => _buildMenuItem(
|
||||
icon: Icons.inventory_outlined,
|
||||
activeIcon: Icons.inventory,
|
||||
title: 'Stok Bantuan',
|
||||
isSelected: controller.activeTabIndex.value == 4,
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.changeTab(4);
|
||||
},
|
||||
)),
|
||||
_buildMenuCategory('Kelola Data'),
|
||||
_buildMenuItem(
|
||||
icon: Icons.person_add_outlined,
|
||||
activeIcon: Icons.person_add,
|
||||
title: 'Kelola Penerima',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/daftar-penerima');
|
||||
},
|
||||
),
|
||||
_buildMenuItem(
|
||||
icon: Icons.people_outlined,
|
||||
activeIcon: Icons.people,
|
||||
title: 'Kelola Donatur',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/daftar-donatur');
|
||||
},
|
||||
),
|
||||
_buildMenuItem(
|
||||
icon: Icons.location_on_outlined,
|
||||
activeIcon: Icons.location_on,
|
||||
title: 'Lokasi Penyaluran',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/lokasi-penyaluran');
|
||||
},
|
||||
),
|
||||
_buildMenuItem(
|
||||
icon: Icons.description_outlined,
|
||||
activeIcon: Icons.description,
|
||||
title: 'Laporan Penyaluran',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/laporan-penyaluran');
|
||||
},
|
||||
),
|
||||
_buildMenuCategory('Pengaturan'),
|
||||
_buildMenuItem(
|
||||
icon: Icons.person_outline,
|
||||
activeIcon: Icons.person,
|
||||
title: 'Profil',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/profile');
|
||||
},
|
||||
),
|
||||
const Divider(),
|
||||
_buildMenuItem(
|
||||
icon: Icons.info_outline,
|
||||
activeIcon: Icons.info,
|
||||
title: 'Tentang Kami',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Get.toNamed('/about');
|
||||
},
|
||||
),
|
||||
_buildMenuItem(
|
||||
icon: Icons.logout,
|
||||
title: 'Keluar',
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
controller.logout();
|
||||
},
|
||||
isLogout: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.volunteer_activism_outlined,
|
||||
activeIcon: Icons.volunteer_activism,
|
||||
title: 'Penyaluran',
|
||||
isSelected: controller.activeTabIndex.value == 1,
|
||||
badgeCount: controller.jumlahMenunggu.value > 0
|
||||
? controller.jumlahMenunggu.value
|
||||
: null,
|
||||
badgeColor: Colors.green,
|
||||
onTap: () {
|
||||
controller.activeTabIndex.value = 1;
|
||||
},
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
'© ${DateTime.now().year} DisalurKita',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.inbox_outlined,
|
||||
activeIcon: Icons.inbox,
|
||||
title: 'Penitipan',
|
||||
isSelected: controller.activeTabIndex.value == 2,
|
||||
onTap: () {
|
||||
controller.activeTabIndex.value = 2;
|
||||
},
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.report_problem_outlined,
|
||||
activeIcon: Icons.report_problem,
|
||||
title: 'Pengaduan',
|
||||
isSelected: controller.activeTabIndex.value == 3,
|
||||
badgeCount: controller.jumlahDiproses.value > 0
|
||||
? controller.jumlahDiproses.value
|
||||
: null,
|
||||
badgeColor: Colors.orange,
|
||||
onTap: () {
|
||||
controller.activeTabIndex.value = 3;
|
||||
},
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.inventory_outlined,
|
||||
activeIcon: Icons.inventory,
|
||||
title: 'Stok Bantuan',
|
||||
isSelected: controller.activeTabIndex.value == 4,
|
||||
onTap: () {
|
||||
controller.activeTabIndex.value = 4;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMenuCategory(String title) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildMenuItem({
|
||||
required IconData icon,
|
||||
IconData? activeIcon,
|
||||
required String title,
|
||||
bool isSelected = false,
|
||||
String? badge,
|
||||
required Function() onTap,
|
||||
bool isLogout = false,
|
||||
}) {
|
||||
return AnimatedContainer(
|
||||
duration: Duration(milliseconds: 200),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected
|
||||
? AppTheme.primaryColor.withOpacity(0.1)
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 2),
|
||||
child: ListTile(
|
||||
leading: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
isSelected ? (activeIcon ?? icon) : icon,
|
||||
color: isSelected
|
||||
? AppTheme.primaryColor
|
||||
: isLogout
|
||||
? Colors.red
|
||||
: Colors.grey[700],
|
||||
size: 24,
|
||||
),
|
||||
if (badge != null)
|
||||
Positioned(
|
||||
top: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
padding: EdgeInsets.all(2),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
constraints: BoxConstraints(
|
||||
minWidth: 16,
|
||||
minHeight: 16,
|
||||
),
|
||||
child: Text(
|
||||
badge,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.white,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
'Pengaturan': [
|
||||
DrawerMenuItem(
|
||||
icon: Icons.notifications_outlined,
|
||||
activeIcon: Icons.notifications,
|
||||
title: 'Notifikasi',
|
||||
badgeCount: controller.jumlahNotifikasiBelumDibaca.value > 0
|
||||
? controller.jumlahNotifikasiBelumDibaca.value
|
||||
: null,
|
||||
badgeColor: Colors.red,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const NotifikasiView(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
title: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||
color: isSelected
|
||||
? AppTheme.primaryColor
|
||||
: isLogout
|
||||
? Colors.red
|
||||
: Colors.grey[800],
|
||||
fontSize: 14,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
onTap: onTap,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
visualDensity: VisualDensity.compact,
|
||||
selectedTileColor: AppTheme.primaryColor.withOpacity(0.1),
|
||||
selected: isSelected,
|
||||
),
|
||||
);
|
||||
DrawerMenuItem(
|
||||
icon: Icons.person_outline,
|
||||
activeIcon: Icons.person,
|
||||
title: 'Profil',
|
||||
onTap: () {
|
||||
Get.toNamed('/profile');
|
||||
},
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.info_outline,
|
||||
activeIcon: Icons.info,
|
||||
title: 'Tentang Kami',
|
||||
onTap: () {
|
||||
Get.toNamed('/about');
|
||||
},
|
||||
),
|
||||
DrawerMenuItem(
|
||||
icon: Icons.logout,
|
||||
title: 'Keluar',
|
||||
isLogout: true,
|
||||
onTap: () {
|
||||
controller.logout();
|
||||
},
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
return AppDrawer(
|
||||
nama: controller.namaLengkap,
|
||||
role: 'Petugas Desa',
|
||||
desa: controller.desa,
|
||||
avatar: controller.profilePhotoUrl,
|
||||
menuItems: const [], // Tidak digunakan karena menggunakan menuCategories
|
||||
menuCategories: menuCategories,
|
||||
onLogout: controller.logout,
|
||||
footerText: '© ${DateTime.now().year} DisalurKita',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildBottomNavigationBar() {
|
||||
|
@ -347,10 +347,16 @@ class RiwayatStokView extends GetView<RiwayatStokController> {
|
||||
),
|
||||
),
|
||||
...controller.daftarStokBantuan.map((stok) {
|
||||
final bool isUang = stok.isUang ?? false;
|
||||
final String formattedJumlah = isUang
|
||||
? FormatHelper.formatRupiah(
|
||||
stok.totalStok ?? 0)
|
||||
: '${stok.totalStok} ${stok.satuan}';
|
||||
|
||||
return DropdownMenuItem(
|
||||
value: stok.id,
|
||||
child: Text(
|
||||
stok.nama ?? '-',
|
||||
'${stok.nama ?? '-'} ($formattedJumlah)',
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
);
|
||||
@ -380,6 +386,9 @@ class RiwayatStokView extends GetView<RiwayatStokController> {
|
||||
: 'Tidak diketahui';
|
||||
final stokBantuanSatuan =
|
||||
riwayat.stokBantuan != null ? riwayat.stokBantuan!['satuan'] ?? '' : '';
|
||||
final bool isUang = riwayat.stokBantuan != null
|
||||
? riwayat.stokBantuan!['is_uang'] ?? false
|
||||
: false;
|
||||
final sumberLabels = {
|
||||
'penitipan': 'Penitipan',
|
||||
'penerimaan': 'Penerimaan',
|
||||
@ -464,7 +473,9 @@ class RiwayatStokView extends GetView<RiwayatStokController> {
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'${riwayat.jumlah?.toStringAsFixed(0) ?? '0'} $stokBantuanSatuan',
|
||||
isUang
|
||||
? FormatHelper.formatRupiah(riwayat.jumlah ?? 0)
|
||||
: '${riwayat.jumlah?.toStringAsFixed(0) ?? '0'} $stokBantuanSatuan',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
color: isPenambahan ? Colors.green : Colors.red,
|
||||
@ -761,10 +772,13 @@ class RiwayatStokView extends GetView<RiwayatStokController> {
|
||||
value: controller.selectedStokBantuan.value,
|
||||
items: controller.daftarStokBantuan
|
||||
.map((StokBantuanModel stok) {
|
||||
final bool isUang = stok.isUang ?? false;
|
||||
final String formattedStok = isUang
|
||||
? FormatHelper.formatRupiah(stok.totalStok ?? 0)
|
||||
: '${stok.totalStok} ${stok.satuan}';
|
||||
return DropdownMenuItem<StokBantuanModel>(
|
||||
value: stok,
|
||||
child: Text(
|
||||
'${stok.nama} (${stok.totalStok} ${stok.satuan})'),
|
||||
child: Text('${stok.nama} ($formattedStok)'),
|
||||
);
|
||||
}).toList(),
|
||||
onChanged: (StokBantuanModel? value) {
|
||||
|
@ -24,7 +24,8 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
||||
},
|
||||
backgroundColor: AppTheme.primaryColor,
|
||||
icon: const Icon(Icons.add, color: Colors.white),
|
||||
label: const Text('Tambah Stok', style: TextStyle(color: Colors.white)),
|
||||
label: const Text('Tambah Jenis Stok',
|
||||
style: TextStyle(color: Colors.white)),
|
||||
elevation: 2,
|
||||
),
|
||||
);
|
||||
@ -636,7 +637,7 @@ class StokBantuanView extends GetView<StokBantuanController> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Tambah Stok Bantuan',
|
||||
'Tambah Jenis Stok Bantuan',
|
||||
style: Theme.of(context).textTheme.titleLarge?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
|
@ -363,7 +363,7 @@ class TambahPenyaluranView extends GetView<JadwalPenyaluranController> {
|
||||
child: Row(
|
||||
children: [
|
||||
isUang.value
|
||||
? const Icon(Icons.attach_money)
|
||||
? const Icon(Icons.payment_rounded)
|
||||
: const Icon(Icons.inventory_2),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
|
Reference in New Issue
Block a user