Tambahkan SVG ikon dan perbarui tampilan dashboard

- Integrasikan flutter_svg untuk ikon vektor
- Ganti ikon default dengan SVG dari aset
- Perbarui desain statistik dan daftar dengan tampilan baru
- Tambahkan daftar donasi dan donatur
- Modifikasi tata letak dan gaya komponen dashboard
This commit is contained in:
Khafidh Fuadi
2025-03-08 11:54:36 +07:00
parent b6b4d63802
commit eb80fb629a
3 changed files with 312 additions and 62 deletions

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart';
import 'package:google_fonts/google_fonts.dart'; import 'package:google_fonts/google_fonts.dart';
@ -10,12 +11,14 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final TextTheme textTheme = final TextTheme textTheme =
GoogleFonts.dmSansTextTheme(Theme.of(context).textTheme); GoogleFonts.dmSansTextTheme(Theme.of(context).textTheme);
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
return Theme( return Theme(
data: Theme.of(context).copyWith( data: Theme.of(context).copyWith(
textTheme: textTheme, textTheme: textTheme,
), ),
child: Scaffold( child: Scaffold(
key: _scaffoldKey,
drawer: Drawer( drawer: Drawer(
child: ListView( child: ListView(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
@ -60,7 +63,12 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
), ),
), ),
ListTile( ListTile(
leading: const Icon(Icons.home), leading: SvgPicture.asset(
'assets/icons/home-icon.svg',
width: 24,
height: 24,
color: Colors.grey[700],
),
title: const Text('Beranda'), title: const Text('Beranda'),
onTap: () { onTap: () {
Get.back(); Get.back();
@ -110,6 +118,11 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// add drawer button
IconButton(
onPressed: () => _scaffoldKey.currentState?.openDrawer(),
icon: const Icon(Icons.menu),
),
// Header dengan greeting // Header dengan greeting
_buildGreetingHeader(textTheme), _buildGreetingHeader(textTheme),
const SizedBox(height: 20), const SizedBox(height: 20),
@ -122,7 +135,7 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
dateTime: '15 April 2023, 13:00 - 14:00', dateTime: '15 April 2023, 13:00 - 14:00',
isToday: true, isToday: true,
), ),
const SizedBox(height: 10), const SizedBox(height: 20),
// Jadwal penyaluran mendatang // Jadwal penyaluran mendatang
_buildScheduleCard( _buildScheduleCard(
@ -144,6 +157,11 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
// Daftar penerima // Daftar penerima
_buildRecipientsList(textTheme), _buildRecipientsList(textTheme),
// Daftar Donasi
_buildDonationList(textTheme),
// Daftar Donatur
_buildDonorsList(textTheme),
], ],
); );
}), }),
@ -155,21 +173,37 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
selectedLabelStyle: textTheme.bodySmall, selectedLabelStyle: textTheme.bodySmall,
unselectedLabelStyle: textTheme.bodySmall, unselectedLabelStyle: textTheme.bodySmall,
items: const [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.home), icon: SvgPicture.asset(
'assets/icons/home-icon.svg',
width: 24,
height: 24,
),
label: 'Beranda', label: 'Beranda',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.calendar_today), icon: SvgPicture.asset(
'assets/icons/jadwal-icon.svg',
width: 24,
height: 24,
),
label: 'Jadwal', label: 'Jadwal',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.notifications), icon: SvgPicture.asset(
'assets/icons/notif-icon.svg',
width: 24,
height: 24,
),
label: 'Notifikasi', label: 'Notifikasi',
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.inventory), icon: SvgPicture.asset(
'assets/icons/inventory-icon.svg',
width: 24,
height: 24,
),
label: 'Inventaris', label: 'Inventaris',
), ),
], ],
@ -272,11 +306,11 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
return Row( return Row(
children: [ children: [
Expanded( Expanded(
child: _buildStatCard('Penerima', '3', 'Konfirmasi', textTheme), child: _buildStatCard('Penitipan', '3', 'Konfirmasi', textTheme),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
child: _buildStatCard('Pengajuan', '1', 'Pengajuan', textTheme), child: _buildStatCard('Penjadwalan', '1', 'Pengajuan', textTheme),
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Expanded( Expanded(
@ -303,6 +337,13 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(
title,
style: textTheme.bodyMedium?.copyWith(
fontSize: 14,
color: Colors.white.withOpacity(0.8),
),
),
Text( Text(
count, count,
style: textTheme.headlineSmall?.copyWith( style: textTheme.headlineSmall?.copyWith(
@ -325,48 +366,60 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
} }
Widget _buildProgressSection(TextTheme textTheme) { Widget _buildProgressSection(TextTheme textTheme) {
return Column( return Container(
crossAxisAlignment: CrossAxisAlignment.start, padding: const EdgeInsets.all(16),
children: [ decoration: BoxDecoration(
Text( gradient: const LinearGradient(
'Progress Penyaluran', begin: Alignment.topLeft,
style: textTheme.titleMedium?.copyWith( end: Alignment.bottomRight,
fontSize: 16, colors: [Color(0xFF2E5077), Color(0xFF5882B1)],
fontWeight: FontWeight.bold, transform: GradientRotation(96.93 * 3.14159 / 180),
),
), ),
const SizedBox(height: 10), borderRadius: BorderRadius.circular(12),
ClipRRect( ),
borderRadius: BorderRadius.circular(8), child: Column(
child: LinearProgressIndicator( crossAxisAlignment: CrossAxisAlignment.start,
value: 0.7, children: [
minHeight: 10, Text(
backgroundColor: Colors.grey[300], 'Progress Penyaluran',
valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFF2E5077)), style: textTheme.bodyMedium?.copyWith(
fontSize: 14,
color: Colors.white.withOpacity(0.8),
),
), ),
), const SizedBox(height: 10),
const SizedBox(height: 10), ClipRRect(
Text( borderRadius: BorderRadius.circular(8),
'70% Selesai', child: LinearProgressIndicator(
style: textTheme.bodyMedium?.copyWith( value: 0.7,
fontSize: 14, minHeight: 10,
fontWeight: FontWeight.bold, backgroundColor: Colors.white.withOpacity(0.3),
color: const Color(0xFF2E5077), valueColor: const AlwaysStoppedAnimation<Color>(Colors.white),
),
), ),
), const SizedBox(height: 10),
const SizedBox(height: 10), Text(
_buildProgressDetailRow('Telah Menerima', 70, textTheme), '70% Selesai',
_buildProgressDetailRow('Dijedwalkan', 20, textTheme), style: textTheme.bodyMedium?.copyWith(
_buildProgressDetailRow('Belum Dijadwalkan', 10, textTheme), fontSize: 16,
const SizedBox(height: 5), fontWeight: FontWeight.bold,
Text( color: Colors.white,
'Total : 100 Penerima, Telah Disalurkan : 70 Penerima, Belum Disalurkan : 30', ),
style: textTheme.bodySmall?.copyWith(
fontSize: 12,
color: Colors.grey[600],
), ),
), const SizedBox(height: 10),
], _buildProgressDetailRow('Telah Menerima', 70, textTheme),
_buildProgressDetailRow('Dijedwalkan', 20, textTheme),
_buildProgressDetailRow('Belum Dijadwalkan', 10, textTheme),
const SizedBox(height: 5),
Text(
'Total : 100 Penerima, Telah Disalurkan : 70 Penerima, Belum Disalurkan : 30',
style: textTheme.bodySmall?.copyWith(
fontSize: 12,
color: Colors.white.withOpacity(0.8),
),
),
],
),
); );
} }
@ -376,17 +429,17 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
child: Row( child: Row(
children: [ children: [
Expanded( Expanded(
flex: 3, flex: 5,
child: Text( child: Text(
label, label,
style: textTheme.bodyMedium?.copyWith( style: textTheme.bodyMedium?.copyWith(
fontSize: 14, fontSize: 14,
color: Colors.grey[700], color: Colors.white,
), ),
), ),
), ),
Expanded( Expanded(
flex: 7, flex: 5,
child: Stack( child: Stack(
children: [ children: [
Container( Container(
@ -402,7 +455,7 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
0.7 * 0.7 *
(value / 100), (value / 100),
decoration: BoxDecoration( decoration: BoxDecoration(
color: const Color(0xFF2E5077), color: const Color(0xFFE4F1AC),
borderRadius: BorderRadius.circular(4), borderRadius: BorderRadius.circular(4),
), ),
), ),
@ -411,10 +464,11 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Text( Text(
'$value', '$value%',
style: textTheme.bodyMedium?.copyWith( style: textTheme.bodyMedium?.copyWith(
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: Colors.white,
), ),
), ),
], ],
@ -423,6 +477,31 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
} }
Widget _buildRecipientsList(TextTheme textTheme) { Widget _buildRecipientsList(TextTheme textTheme) {
return _buildList(
textTheme: textTheme,
title: 'Daftar Penerima',
items: [
{
'title': 'Siti Rahayu',
'subtitle': '3201020107030010',
'status': 'Selesai'
},
{
'title': 'Siti Rahayu',
'subtitle': '3201020107030010',
'status': 'Selesai'
},
{
'title': 'Siti Rahayu',
'subtitle': '3201020107030010',
'status': 'Selesai'
},
],
idLabel: 'NIK',
);
}
Widget _buildDonorsList(TextTheme textTheme) {
return Column( return Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@ -430,7 +509,7 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'Daftar Penerima', 'Daftar Donatur',
style: textTheme.titleMedium?.copyWith( style: textTheme.titleMedium?.copyWith(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -457,18 +536,14 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
], ],
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
_buildRecipientItem( _buildDonorItem('PT Sejahtera', 'D-2023-001', textTheme),
'Siti Rahayu', '3201020107030010', 'Selesai', textTheme), _buildDonorItem('Yayasan Peduli', 'D-2023-002', textTheme),
_buildRecipientItem( _buildDonorItem('CV Makmur', 'D-2023-003', textTheme),
'Siti Rahayu', '3201020107030010', 'Selesai', textTheme),
_buildRecipientItem(
'Siti Rahayu', '3201020107030010', 'Selesai', textTheme),
], ],
); );
} }
Widget _buildRecipientItem( Widget _buildDonorItem(String name, String id, TextTheme textTheme) {
String name, String nik, String status, TextTheme textTheme) {
return Container( return Container(
width: double.infinity, width: double.infinity,
margin: const EdgeInsets.only(bottom: 10), margin: const EdgeInsets.only(bottom: 10),
@ -492,7 +567,117 @@ class PetugasDesaDashboardView extends GetView<DashboardController> {
), ),
), ),
subtitle: Text( subtitle: Text(
'NIK: $nik', id,
style: textTheme.bodyMedium,
),
trailing: IconButton(
icon: const Icon(
Icons.chevron_right,
color: Colors.grey,
),
onPressed: () {},
),
),
);
}
//daftar donasi
Widget _buildDonationList(TextTheme textTheme) {
return _buildList(
textTheme: textTheme,
title: 'Daftar Donasi',
items: [
{
'title': 'Rp 100.000',
'subtitle': 'Siti Rahayu',
'status': 'Selesai',
},
{
'title': 'Rp 100.000',
'subtitle': 'Siti Rahayu',
'status': 'Selesai',
},
],
idLabel: '',
);
}
Widget _buildList({
required TextTheme textTheme,
required String title,
required List<Map<String, String>> items,
required String idLabel,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: textTheme.titleMedium?.copyWith(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
TextButton(
onPressed: () {},
child: Row(
children: [
Text(
'Lihat Semua',
style: textTheme.bodyMedium?.copyWith(
color: const Color(0xFF2E5077),
),
),
Icon(
Icons.chevron_right,
size: 16,
color: const Color(0xFF2E5077),
),
],
),
),
],
),
const SizedBox(height: 10),
...items.map((item) => _buildItem(
item['title'] ?? '',
item['subtitle'] ?? '',
item['status'] ?? '',
textTheme,
)),
],
);
}
Widget _buildItem(
String title, String subtitle, String status, TextTheme textTheme) {
return Container(
width: double.infinity,
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.1),
spreadRadius: 1,
blurRadius: 3,
offset: const Offset(0, 1),
),
],
),
child: ListTile(
title: Text(
title,
style: textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
subtitle: Text(
subtitle,
style: textTheme.bodyMedium, style: textTheme.bodyMedium,
), ),
trailing: Row( trailing: Row(

View File

@ -33,6 +33,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.4" version: "1.0.4"
args:
dependency: transitive
description:
name: args
sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6
url: "https://pub.dev"
source: hosted
version: "2.6.0"
async: async:
dependency: transitive dependency: transitive
description: description:
@ -134,6 +142,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.2.1" version: "5.2.1"
flutter_svg:
dependency: "direct main"
description:
name: flutter_svg
sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b
url: "https://pub.dev"
source: hosted
version: "2.0.17"
flutter_test: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -296,6 +312,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" version: "1.9.0"
path_parsing:
dependency: transitive
description:
name: path_parsing
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
path_provider: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -344,6 +368,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.3.0" version: "2.3.0"
petitparser:
dependency: transitive
description:
name: petitparser
sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27
url: "https://pub.dev"
source: hosted
version: "6.0.2"
platform: platform:
dependency: transitive dependency: transitive
description: description:
@ -597,6 +629,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.4" version: "3.1.4"
vector_graphics:
dependency: transitive
description:
name: vector_graphics
sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de"
url: "https://pub.dev"
source: hosted
version: "1.1.18"
vector_graphics_codec:
dependency: transitive
description:
name: vector_graphics_codec
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
url: "https://pub.dev"
source: hosted
version: "1.1.13"
vector_graphics_compiler:
dependency: transitive
description:
name: vector_graphics_compiler
sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad"
url: "https://pub.dev"
source: hosted
version: "1.1.16"
vector_math: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -645,6 +701,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" version: "1.1.0"
xml:
dependency: transitive
description:
name: xml
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
url: "https://pub.dev"
source: hosted
version: "6.5.0"
yet_another_json_isolate: yet_another_json_isolate:
dependency: transitive dependency: transitive
description: description:

View File

@ -50,6 +50,7 @@ dependencies:
# Untuk tampilan loading # Untuk tampilan loading
flutter_spinkit: ^5.2.0 flutter_spinkit: ^5.2.0
google_fonts: ^6.2.1 google_fonts: ^6.2.1
flutter_svg: ^2.0.17
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: