Perbarui model PenitipanBantuan untuk menggunakan stok_bantuan sebagai kategori bantuan. Tambahkan rute baru untuk Donatur dengan beberapa halaman terkait, termasuk donaturDashboard, donaturSkema, donaturJadwal, donaturPenitipan, dan donaturLaporan. Modifikasi rute dan tampilan untuk meningkatkan navigasi dan pengalaman pengguna.
This commit is contained in:
774
lib/app/modules/donatur/views/donatur_dashboard_view.dart
Normal file
774
lib/app/modules/donatur/views/donatur_dashboard_view.dart
Normal file
@ -0,0 +1,774 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:penyaluran_app/app/modules/donatur/controllers/donatur_dashboard_controller.dart';
|
||||
import 'package:penyaluran_app/app/routes/app_pages.dart';
|
||||
import 'package:penyaluran_app/app/widgets/section_header.dart';
|
||||
|
||||
class DonaturDashboardView extends GetView<DonaturDashboardController> {
|
||||
const DonaturDashboardView({super.key});
|
||||
|
||||
@override
|
||||
DonaturDashboardController get controller {
|
||||
if (!Get.isRegistered<DonaturDashboardController>(
|
||||
tag: 'donatur_dashboard')) {
|
||||
return Get.put(DonaturDashboardController(),
|
||||
tag: 'donatur_dashboard', permanent: true);
|
||||
}
|
||||
return Get.find<DonaturDashboardController>(tag: 'donatur_dashboard');
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Obx(() {
|
||||
if (controller.isLoading.value) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
controller.fetchData();
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildWelcomeSection(),
|
||||
const SizedBox(height: 24),
|
||||
_buildStatisticSection(),
|
||||
const SizedBox(height: 24),
|
||||
_buildUpcomingEvents(),
|
||||
const SizedBox(height: 24),
|
||||
_buildRecentPenitipan(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildWelcomeSection() {
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 8),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.blue.withOpacity(0.1),
|
||||
blurRadius: 15,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
gradient: LinearGradient(
|
||||
colors: [Colors.white, Colors.blue.shade50],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.blue.shade200, width: 2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.blue.withOpacity(0.2),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Hero(
|
||||
tag: 'donatur-profile',
|
||||
child: CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundColor: Colors.blue.shade100,
|
||||
backgroundImage: controller.profilePhotoUrl != null
|
||||
? NetworkImage(controller.profilePhotoUrl!)
|
||||
: null,
|
||||
child: controller.profilePhotoUrl == null
|
||||
? Icon(
|
||||
Icons.person,
|
||||
color: Colors.blue.shade700,
|
||||
size: 30,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Selamat Datang,',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.blue.shade700,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.nama,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue.shade900,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.blue.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildInfoRow(
|
||||
icon: Icons.home_rounded,
|
||||
iconColor: Colors.blue.shade300,
|
||||
label: 'Alamat',
|
||||
value: controller.alamat ?? 'Alamat tidak tersedia',
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
child: Divider(height: 1),
|
||||
),
|
||||
_buildInfoRow(
|
||||
icon: Icons.phone_rounded,
|
||||
iconColor: Colors.green.shade300,
|
||||
label: 'No. HP',
|
||||
value: controller.noHp ?? 'No. HP tidak tersedia',
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 8),
|
||||
child: Divider(height: 1),
|
||||
),
|
||||
_buildInfoRow(
|
||||
icon: Icons.category_rounded,
|
||||
iconColor: Colors.amber.shade300,
|
||||
label: 'Jenis Donatur',
|
||||
value: controller.jenis ?? 'Jenis tidak tersedia',
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildActionButton(
|
||||
icon: Icons.edit_rounded,
|
||||
label: 'Edit Profil',
|
||||
color: Colors.blue.shade700,
|
||||
onTap: () => Get.toNamed(Routes.profile),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: _buildActionButton(
|
||||
icon: Icons.add_box_rounded,
|
||||
label: 'Titip Bantuan',
|
||||
color: Colors.green.shade700,
|
||||
onTap: () {
|
||||
// Navigasi ke form penitipan bantuan
|
||||
controller.activeTabIndex.value = 3;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatisticSection() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SectionHeader(
|
||||
title: 'Statistik Kontribusi',
|
||||
),
|
||||
Text(
|
||||
'Ringkasan aktivitas anda sebagai donatur',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
title: 'Total Bantuan',
|
||||
value: '${controller.penitipanBantuan.length}',
|
||||
icon: Icons.card_giftcard,
|
||||
color: Colors.blue,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
title: 'Menunggu Verifikasi',
|
||||
value:
|
||||
'${controller.penitipanBantuan.where((p) => p.status == 'MENUNGGU').length}',
|
||||
icon: Icons.hourglass_empty,
|
||||
color: Colors.orange,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
title: 'Diterima',
|
||||
value:
|
||||
'${controller.penitipanBantuan.where((p) => p.status == 'DITERIMA').length}',
|
||||
icon: Icons.check_circle_outline,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: _buildStatCard(
|
||||
title: 'Ditolak',
|
||||
value:
|
||||
'${controller.penitipanBantuan.where((p) => p.status == 'DITOLAK').length}',
|
||||
icon: Icons.cancel_outlined,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildUpcomingEvents() {
|
||||
final upcomingEvents = controller.jadwalPenyaluran
|
||||
.where((event) =>
|
||||
event.tanggalPenyaluran != null &&
|
||||
event.tanggalPenyaluran!.isAfter(DateTime.now()))
|
||||
.take(3)
|
||||
.toList();
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SectionHeader(
|
||||
title: 'Jadwal Penyaluran',
|
||||
),
|
||||
Text(
|
||||
'Jadwal penyaluran bantuan terdekat',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigasi ke tab jadwal penyaluran
|
||||
controller.activeTabIndex.value = 2;
|
||||
},
|
||||
child: Text(
|
||||
'Lihat Semua',
|
||||
style: TextStyle(color: Colors.blue.shade700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (upcomingEvents.isEmpty)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'Tidak ada jadwal penyaluran dalam waktu dekat',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
...upcomingEvents.map((event) => _buildEventCard(event)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRecentPenitipan() {
|
||||
final recentPenitipan = controller.penitipanBantuan.take(3).toList();
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SectionHeader(
|
||||
title: 'Bantuan Terakhir',
|
||||
),
|
||||
Text(
|
||||
'Riwayat penitipan bantuan terakhir',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigasi ke tab riwayat penitipan
|
||||
controller.activeTabIndex.value = 3;
|
||||
},
|
||||
child: Text(
|
||||
'Lihat Semua',
|
||||
style: TextStyle(color: Colors.blue.shade700),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (recentPenitipan.isEmpty)
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade100,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'Belum ada riwayat penitipan bantuan',
|
||||
style: TextStyle(color: Colors.grey),
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
...recentPenitipan.map((penitipan) => _buildPenitipanCard(penitipan)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInfoRow({
|
||||
required IconData icon,
|
||||
required Color iconColor,
|
||||
required String label,
|
||||
required String value,
|
||||
}) {
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: iconColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
size: 16,
|
||||
color: iconColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade600,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildActionButton({
|
||||
required IconData icon,
|
||||
required String label,
|
||||
required Color color,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return ElevatedButton(
|
||||
onPressed: onTap,
|
||||
style: ElevatedButton.styleFrom(
|
||||
foregroundColor: Colors.white,
|
||||
backgroundColor: color,
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
elevation: 0,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(icon, size: 16),
|
||||
const SizedBox(width: 8),
|
||||
Text(label),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatCard({
|
||||
required String title,
|
||||
required String value,
|
||||
required IconData icon,
|
||||
required Color color,
|
||||
}) {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: color.withOpacity(0.1),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: color.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: color,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
value,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: color,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEventCard(dynamic event) {
|
||||
final formattedDate = event.tanggalPenyaluran != null
|
||||
? DateFormat('dd MMMM yyyy', 'id_ID').format(event.tanggalPenyaluran!)
|
||||
: 'Tanggal tidak tersedia';
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue.shade50,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.event,
|
||||
color: Colors.blue.shade700,
|
||||
size: 24,
|
||||
),
|
||||
Text(
|
||||
event.tanggalPenyaluran != null
|
||||
? DateFormat('dd').format(event.tanggalPenyaluran!)
|
||||
: '--',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.blue.shade700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
event.nama ?? 'Penyaluran Bantuan',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
formattedDate,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
event.deskripsi ?? 'Tidak ada deskripsi',
|
||||
style: const TextStyle(fontSize: 14),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPenitipanCard(dynamic penitipan) {
|
||||
final formattedDate = penitipan.tanggalPenitipan != null
|
||||
? DateFormat('dd MMMM yyyy', 'id_ID')
|
||||
.format(penitipan.tanggalPenitipan!)
|
||||
: 'Tanggal tidak tersedia';
|
||||
|
||||
Color statusColor;
|
||||
IconData statusIcon;
|
||||
|
||||
switch (penitipan.status) {
|
||||
case 'DITERIMA':
|
||||
statusColor = Colors.green;
|
||||
statusIcon = Icons.check_circle;
|
||||
break;
|
||||
case 'DITOLAK':
|
||||
statusColor = Colors.red;
|
||||
statusIcon = Icons.cancel;
|
||||
break;
|
||||
case 'MENUNGGU':
|
||||
default:
|
||||
statusColor = Colors.orange;
|
||||
statusIcon = Icons.hourglass_empty;
|
||||
break;
|
||||
}
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.05),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 5),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(12),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: statusColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Icon(
|
||||
statusIcon,
|
||||
color: statusColor,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
penitipan.kategoriBantuan?.nama ?? 'Bantuan',
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
maxLines: 1,
|
||||
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(
|
||||
penitipan.status ?? 'MENUNGGU',
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: statusColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
formattedDate,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.inventory_2_outlined,
|
||||
size: 14,
|
||||
color: Colors.grey.shade600,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'Jumlah: ${penitipan.jumlah ?? 0}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.grey.shade800,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user