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