Perbarui model dan tampilan untuk menambahkan properti fotoProfil di DonaturModel, PetugasDesaModel, dan WargaModel. Modifikasi controller dan tampilan untuk mendukung pengambilan dan penampilan foto profil pengguna. Tambahkan fungsionalitas baru untuk menampilkan foto profil di berbagai tampilan, termasuk detail penerima dan dashboard warga. Perbarui rute aplikasi untuk mencakup halaman profil pengguna.

This commit is contained in:
Khafidh Fuadi
2025-03-25 12:21:37 +07:00
parent 8e9553d1fc
commit 32736be867
19 changed files with 2138 additions and 752 deletions

View File

@ -41,111 +41,256 @@ class WargaDashboardView extends GetView<WargaDashboardController> {
}
Widget _buildWelcomeSection() {
return Card(
elevation: 2,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
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: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
CircleAvatar(
radius: 24,
backgroundColor: Colors.blue.shade100,
child: Icon(
Icons.person,
color: Colors.blue.shade700,
size: 28,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Selamat Datang,',
style: TextStyle(
fontSize: 14,
color: Colors.grey.shade600,
),
),
Text(
controller.nama,
style: const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
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,
),
const SizedBox(height: 16),
const Divider(),
const SizedBox(height: 16),
Row(
children: [
Icon(
Icons.home,
size: 16,
color: Colors.grey.shade600,
),
const SizedBox(width: 8),
Expanded(
child: Text(
'Alamat tidak tersedia',
style: TextStyle(
color: Colors.grey.shade700,
),
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: 'warga-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,
),
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
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),
),
],
),
],
),
const SizedBox(height: 8),
Row(
children: [
Icon(
Icons.phone,
size: 16,
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.location_city_rounded,
iconColor: Colors.amber.shade300,
label: 'Desa',
value: controller.desa ?? 'Desa 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.notifications_rounded,
label: 'Notifikasi',
color: Colors.amber.shade700,
onTap: () => Get.toNamed(Routes.NOTIFIKASI),
),
),
],
),
],
),
),
),
);
}
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(width: 8),
Text(
'No. HP tidak tersedia',
style: TextStyle(
color: Colors.grey.shade700,
),
),
const SizedBox(height: 2),
Text(
value,
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
),
],
),
const SizedBox(height: 8),
Row(
children: [
Icon(
Icons.location_city,
size: 16,
color: Colors.grey.shade600,
maxLines: 2,
overflow: TextOverflow.ellipsis,
),
],
),
),
],
);
}
Widget _buildActionButton({
required IconData icon,
required String label,
required Color color,
required VoidCallback onTap,
}) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(12),
child: Ink(
padding: const EdgeInsets.symmetric(vertical: 10),
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
size: 18,
color: color,
),
const SizedBox(width: 8),
Text(
label,
style: TextStyle(
color: color,
fontWeight: FontWeight.w600,
),
const SizedBox(width: 8),
Text(
controller.desa ?? 'Desa tidak tersedia',
style: TextStyle(
color: Colors.grey.shade700,
),
),
],
),
],
),
],
),
),
),
);