Perbarui JadwalSectionWidget untuk menambahkan ikon status dan informasi tambahan

- Tambahkan ikon status dan warna berdasarkan status penyaluran
- Perbarui tampilan untuk menampilkan informasi lokasi, kategori, dan jumlah penerima
- Modifikasi format tanggal dan waktu untuk tampilan yang lebih informatif
- Ganti beberapa elemen UI untuk meningkatkan pengalaman pengguna
This commit is contained in:
Khafidh Fuadi
2025-03-13 20:05:58 +07:00
parent 0223d457a5
commit b0310103fe

View File

@ -4,6 +4,7 @@ import 'package:intl/intl.dart';
import 'package:penyaluran_app/app/data/models/penyaluran_bantuan_model.dart'; import 'package:penyaluran_app/app/data/models/penyaluran_bantuan_model.dart';
import 'package:penyaluran_app/app/modules/petugas_desa/controllers/jadwal_penyaluran_controller.dart'; import 'package:penyaluran_app/app/modules/petugas_desa/controllers/jadwal_penyaluran_controller.dart';
import 'package:penyaluran_app/app/routes/app_pages.dart'; import 'package:penyaluran_app/app/routes/app_pages.dart';
import 'package:penyaluran_app/app/theme/app_theme.dart';
class JadwalSectionWidget extends StatelessWidget { class JadwalSectionWidget extends StatelessWidget {
final JadwalPenyaluranController controller; final JadwalPenyaluranController controller;
@ -26,13 +27,23 @@ class JadwalSectionWidget extends StatelessWidget {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Row(
title, children: [
style: textTheme.titleLarge?.copyWith( Icon(
fontWeight: FontWeight.bold, _getStatusIcon(),
), color: _getStatusColor(),
size: 24,
),
const SizedBox(width: 8),
Text(
title,
style: textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
), ),
const SizedBox(height: 10), const SizedBox(height: 12),
Obx(() { Obx(() {
final currentJadwalList = _getCurrentJadwalList(); final currentJadwalList = _getCurrentJadwalList();
@ -44,11 +55,21 @@ class JadwalSectionWidget extends StatelessWidget {
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
child: Center( child: Center(
child: Text( child: Column(
'Tidak ada jadwal $title', children: [
style: textTheme.titleMedium?.copyWith( Icon(
color: Colors.grey.shade600, _getEmptyIcon(),
), size: 40,
color: Colors.grey.shade400,
),
const SizedBox(height: 8),
Text(
'Tidak ada jadwal $title',
style: textTheme.titleMedium?.copyWith(
color: Colors.grey.shade600,
),
),
],
), ),
), ),
); );
@ -64,6 +85,45 @@ class JadwalSectionWidget extends StatelessWidget {
); );
} }
IconData _getStatusIcon() {
switch (status) {
case 'Aktif':
return Icons.event_available;
case 'Terjadwal':
return Icons.pending_actions;
case 'Selesai':
return Icons.event_busy;
default:
return Icons.event_note;
}
}
IconData _getEmptyIcon() {
switch (status) {
case 'Aktif':
return Icons.calendar_today;
case 'Terjadwal':
return Icons.schedule;
case 'Selesai':
return Icons.task_alt;
default:
return Icons.event_note;
}
}
Color _getStatusColor() {
switch (status) {
case 'Aktif':
return Colors.green;
case 'Terjadwal':
return Colors.blue;
case 'Selesai':
return Colors.grey;
default:
return Colors.orange;
}
}
List<PenyaluranBantuanModel> _getCurrentJadwalList() { List<PenyaluranBantuanModel> _getCurrentJadwalList() {
switch (title) { switch (title) {
case 'Hari Ini': case 'Hari Ini':
@ -78,150 +138,201 @@ class JadwalSectionWidget extends StatelessWidget {
} }
Widget _buildJadwalItem(TextTheme textTheme, PenyaluranBantuanModel jadwal) { Widget _buildJadwalItem(TextTheme textTheme, PenyaluranBantuanModel jadwal) {
Color statusColor; Color statusColor = _getStatusColor();
switch (status) {
case 'Aktif':
statusColor = Colors.green;
break;
case 'Terjadwal':
statusColor = Colors.blue;
break;
case 'Selesai':
statusColor = Colors.grey;
break;
default:
statusColor = Colors.orange;
}
// Format tanggal // Format tanggal dan waktu
String formattedDate = jadwal.tanggalPenyaluran != null String formattedDateTime = jadwal.tanggalPenyaluran != null
? DateFormat('dd MMMM yyyy').format(jadwal.tanggalPenyaluran!) ? "${DateFormat('dd MMM yyyy').format(jadwal.tanggalPenyaluran!)} ${DateFormat('HH:mm').format(jadwal.tanggalPenyaluran!)}"
: 'Belum ditentukan'; : 'Belum ditentukan';
// Format waktu
String formattedTime = jadwal.tanggalPenyaluran != null
? DateFormat('HH:mm').format(jadwal.tanggalPenyaluran!)
: '-';
// Dapatkan nama lokasi dan kategori // Dapatkan nama lokasi dan kategori
String lokasiName = String lokasiName =
controller.getLokasiPenyaluranName(jadwal.lokasiPenyaluranId); controller.getLokasiPenyaluranName(jadwal.lokasiPenyaluranId);
String kategoriName = String kategoriName =
controller.getKategoriBantuanName(jadwal.kategoriBantuanId); controller.getKategoriBantuanName(jadwal.kategoriBantuanId);
return GestureDetector( return Card(
onTap: () { margin: const EdgeInsets.only(bottom: 12),
// Navigasi ke halaman pelaksanaan penyaluran dengan data jadwal elevation: 2,
Get.toNamed(Routes.pelaksanaanPenyaluran, arguments: jadwal); shape: RoundedRectangleBorder(
}, borderRadius: BorderRadius.circular(12),
child: Container( side: BorderSide(
width: double.infinity, color: statusColor.withOpacity(0.3),
margin: const EdgeInsets.only(bottom: 10), width: 1,
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: InkWell(
borderRadius: BorderRadius.circular(12),
onTap: () {
Get.toNamed(Routes.pelaksanaanPenyaluran, arguments: jadwal);
},
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// Container(
// padding: const EdgeInsets.all(10),
// decoration: BoxDecoration(
// color: statusColor.withOpacity(0.1),
// borderRadius: BorderRadius.circular(10),
// ),
// child: Icon(
// _getStatusIcon(),
// color: statusColor,
// size: 24,
// ),
// ),
// const SizedBox(width: 12),
Expanded( Expanded(
child: Text( child: Column(
jadwal.nama ?? 'Tanpa Nama', crossAxisAlignment: CrossAxisAlignment.start,
style: textTheme.titleMedium?.copyWith( children: [
fontWeight: FontWeight.bold, Row(
), mainAxisAlignment: MainAxisAlignment.spaceBetween,
overflow: TextOverflow.ellipsis, children: [
), Expanded(
), child: Text(
Container( jadwal.nama ?? 'Tanpa Nama',
padding: style: textTheme.titleMedium?.copyWith(
const EdgeInsets.symmetric(horizontal: 8, vertical: 4), fontWeight: FontWeight.bold,
decoration: BoxDecoration( ),
color: statusColor.withAlpha(26), overflow: TextOverflow.ellipsis,
borderRadius: BorderRadius.circular(12), ),
), ),
child: Text( Container(
status, padding: const EdgeInsets.symmetric(
style: textTheme.bodySmall?.copyWith( horizontal: 8,
color: statusColor, vertical: 4,
fontWeight: FontWeight.bold, ),
), decoration: BoxDecoration(
color: statusColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Text(
status,
style: textTheme.bodySmall?.copyWith(
color: statusColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
if (jadwal.deskripsi != null &&
jadwal.deskripsi!.isNotEmpty) ...[
const SizedBox(height: 4),
Text(
jadwal.deskripsi!,
style: textTheme.bodyMedium,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
],
), ),
), ),
], ],
), ),
const SizedBox(height: 8), const Divider(height: 24),
if (jadwal.deskripsi != null && jadwal.deskripsi!.isNotEmpty) ...[ _buildInfoItem(
Text( Icons.location_on_outlined,
jadwal.deskripsi!, 'Lokasi',
style: textTheme.bodyMedium, lokasiName,
maxLines: 2, textTheme,
overflow: TextOverflow.ellipsis,
),
const SizedBox(height: 8),
],
Text(
'Lokasi: $lokasiName',
style: textTheme.bodyMedium,
), ),
const SizedBox(height: 4),
Text(
'Kategori: $kategoriName',
style: textTheme.bodyMedium,
),
const SizedBox(height: 4),
Text(
'Tanggal: $formattedDate',
style: textTheme.bodyMedium,
),
const SizedBox(height: 4),
Text(
'Waktu: $formattedTime',
style: textTheme.bodyMedium,
),
if (jadwal.jumlahPenerima != null) ...[
const SizedBox(height: 4),
Text(
'Jumlah Penerima: ${jadwal.jumlahPenerima}',
style: textTheme.bodyMedium,
),
],
const SizedBox(height: 8), const SizedBox(height: 8),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [ children: [
Text( Expanded(
'Lihat Detail', child: _buildInfoItem(
style: textTheme.bodySmall?.copyWith( Icons.category_outlined,
color: Colors.blue, 'Kategori',
fontWeight: FontWeight.bold, kategoriName,
textTheme,
), ),
), ),
const SizedBox(width: 4), Expanded(
const Icon( child: _buildInfoItem(
Icons.arrow_forward_ios, Icons.event,
size: 12, 'Jadwal',
color: Colors.blue, formattedDateTime,
textTheme,
),
), ),
], ],
), ),
if (jadwal.jumlahPenerima != null) ...[
const SizedBox(height: 8),
_buildInfoItem(
Icons.people_outline,
'Jumlah Penerima',
'${jadwal.jumlahPenerima}',
textTheme,
),
],
const SizedBox(height: 8),
Align(
alignment: Alignment.centerRight,
child: TextButton.icon(
onPressed: () {
Get.toNamed(Routes.pelaksanaanPenyaluran,
arguments: jadwal);
},
icon: const Icon(Icons.info_outline, size: 16),
label: const Text('Lihat Detail'),
style: TextButton.styleFrom(
foregroundColor: AppTheme.primaryColor,
padding: const EdgeInsets.symmetric(horizontal: 8),
visualDensity: VisualDensity.compact,
),
),
),
], ],
), ),
), ),
), ),
); );
} }
Widget _buildInfoItem(
IconData icon,
String label,
String value,
TextTheme textTheme,
) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Icon(
icon,
size: 16,
color: Colors.grey.shade600,
),
const SizedBox(width: 4),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: textTheme.bodySmall?.copyWith(
color: Colors.grey.shade600,
),
),
Text(
value,
style: textTheme.bodyMedium,
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
],
),
),
],
);
}
} }