From eb80fb629a4ceba93297e1a7ca0f7c6a5784971b Mon Sep 17 00:00:00 2001 From: Khafidh Fuadi Date: Sat, 8 Mar 2025 11:54:36 +0700 Subject: [PATCH] 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 --- .../views/petugas_desa_dashboard_view.dart | 309 ++++++++++++++---- pubspec.lock | 64 ++++ pubspec.yaml | 1 + 3 files changed, 312 insertions(+), 62 deletions(-) diff --git a/lib/app/modules/dashboard/views/petugas_desa_dashboard_view.dart b/lib/app/modules/dashboard/views/petugas_desa_dashboard_view.dart index 590dffc..27ca8e8 100644 --- a/lib/app/modules/dashboard/views/petugas_desa_dashboard_view.dart +++ b/lib/app/modules/dashboard/views/petugas_desa_dashboard_view.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:get/get.dart'; import 'package:penyaluran_app/app/modules/dashboard/controllers/dashboard_controller.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -10,12 +11,14 @@ class PetugasDesaDashboardView extends GetView { Widget build(BuildContext context) { final TextTheme textTheme = GoogleFonts.dmSansTextTheme(Theme.of(context).textTheme); + final GlobalKey _scaffoldKey = GlobalKey(); return Theme( data: Theme.of(context).copyWith( textTheme: textTheme, ), child: Scaffold( + key: _scaffoldKey, drawer: Drawer( child: ListView( padding: EdgeInsets.zero, @@ -60,7 +63,12 @@ class PetugasDesaDashboardView extends GetView { ), ), 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'), onTap: () { Get.back(); @@ -110,6 +118,11 @@ class PetugasDesaDashboardView extends GetView { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + // add drawer button + IconButton( + onPressed: () => _scaffoldKey.currentState?.openDrawer(), + icon: const Icon(Icons.menu), + ), // Header dengan greeting _buildGreetingHeader(textTheme), const SizedBox(height: 20), @@ -122,7 +135,7 @@ class PetugasDesaDashboardView extends GetView { dateTime: '15 April 2023, 13:00 - 14:00', isToday: true, ), - const SizedBox(height: 10), + const SizedBox(height: 20), // Jadwal penyaluran mendatang _buildScheduleCard( @@ -144,6 +157,11 @@ class PetugasDesaDashboardView extends GetView { // Daftar penerima _buildRecipientsList(textTheme), + + // Daftar Donasi + _buildDonationList(textTheme), + // Daftar Donatur + _buildDonorsList(textTheme), ], ); }), @@ -155,21 +173,37 @@ class PetugasDesaDashboardView extends GetView { type: BottomNavigationBarType.fixed, selectedLabelStyle: textTheme.bodySmall, unselectedLabelStyle: textTheme.bodySmall, - items: const [ + items: [ BottomNavigationBarItem( - icon: Icon(Icons.home), + icon: SvgPicture.asset( + 'assets/icons/home-icon.svg', + width: 24, + height: 24, + ), label: 'Beranda', ), BottomNavigationBarItem( - icon: Icon(Icons.calendar_today), + icon: SvgPicture.asset( + 'assets/icons/jadwal-icon.svg', + width: 24, + height: 24, + ), label: 'Jadwal', ), BottomNavigationBarItem( - icon: Icon(Icons.notifications), + icon: SvgPicture.asset( + 'assets/icons/notif-icon.svg', + width: 24, + height: 24, + ), label: 'Notifikasi', ), BottomNavigationBarItem( - icon: Icon(Icons.inventory), + icon: SvgPicture.asset( + 'assets/icons/inventory-icon.svg', + width: 24, + height: 24, + ), label: 'Inventaris', ), ], @@ -272,11 +306,11 @@ class PetugasDesaDashboardView extends GetView { return Row( children: [ Expanded( - child: _buildStatCard('Penerima', '3', 'Konfirmasi', textTheme), + child: _buildStatCard('Penitipan', '3', 'Konfirmasi', textTheme), ), const SizedBox(width: 10), Expanded( - child: _buildStatCard('Pengajuan', '1', 'Pengajuan', textTheme), + child: _buildStatCard('Penjadwalan', '1', 'Pengajuan', textTheme), ), const SizedBox(width: 10), Expanded( @@ -303,6 +337,13 @@ class PetugasDesaDashboardView extends GetView { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text( + title, + style: textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: Colors.white.withOpacity(0.8), + ), + ), Text( count, style: textTheme.headlineSmall?.copyWith( @@ -325,48 +366,60 @@ class PetugasDesaDashboardView extends GetView { } Widget _buildProgressSection(TextTheme textTheme) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - 'Progress Penyaluran', - style: textTheme.titleMedium?.copyWith( - fontSize: 16, - fontWeight: FontWeight.bold, - ), + return Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Color(0xFF2E5077), Color(0xFF5882B1)], + transform: GradientRotation(96.93 * 3.14159 / 180), ), - const SizedBox(height: 10), - ClipRRect( - borderRadius: BorderRadius.circular(8), - child: LinearProgressIndicator( - value: 0.7, - minHeight: 10, - backgroundColor: Colors.grey[300], - valueColor: const AlwaysStoppedAnimation(Color(0xFF2E5077)), + borderRadius: BorderRadius.circular(12), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Progress Penyaluran', + style: textTheme.bodyMedium?.copyWith( + fontSize: 14, + color: Colors.white.withOpacity(0.8), + ), ), - ), - const SizedBox(height: 10), - Text( - '70% Selesai', - style: textTheme.bodyMedium?.copyWith( - fontSize: 14, - fontWeight: FontWeight.bold, - color: const Color(0xFF2E5077), + const SizedBox(height: 10), + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: LinearProgressIndicator( + value: 0.7, + minHeight: 10, + backgroundColor: Colors.white.withOpacity(0.3), + valueColor: const AlwaysStoppedAnimation(Colors.white), + ), ), - ), - 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.grey[600], + const SizedBox(height: 10), + Text( + '70% Selesai', + style: textTheme.bodyMedium?.copyWith( + fontSize: 16, + fontWeight: FontWeight.bold, + color: Colors.white, + ), ), - ), - ], + 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 { child: Row( children: [ Expanded( - flex: 3, + flex: 5, child: Text( label, style: textTheme.bodyMedium?.copyWith( fontSize: 14, - color: Colors.grey[700], + color: Colors.white, ), ), ), Expanded( - flex: 7, + flex: 5, child: Stack( children: [ Container( @@ -402,7 +455,7 @@ class PetugasDesaDashboardView extends GetView { 0.7 * (value / 100), decoration: BoxDecoration( - color: const Color(0xFF2E5077), + color: const Color(0xFFE4F1AC), borderRadius: BorderRadius.circular(4), ), ), @@ -411,10 +464,11 @@ class PetugasDesaDashboardView extends GetView { ), const SizedBox(width: 10), Text( - '$value', + '$value%', style: textTheme.bodyMedium?.copyWith( fontSize: 14, fontWeight: FontWeight.bold, + color: Colors.white, ), ), ], @@ -423,6 +477,31 @@ class PetugasDesaDashboardView extends GetView { } 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( crossAxisAlignment: CrossAxisAlignment.start, children: [ @@ -430,7 +509,7 @@ class PetugasDesaDashboardView extends GetView { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - 'Daftar Penerima', + 'Daftar Donatur', style: textTheme.titleMedium?.copyWith( fontSize: 16, fontWeight: FontWeight.bold, @@ -457,18 +536,14 @@ class PetugasDesaDashboardView extends GetView { ], ), const SizedBox(height: 10), - _buildRecipientItem( - 'Siti Rahayu', '3201020107030010', 'Selesai', textTheme), - _buildRecipientItem( - 'Siti Rahayu', '3201020107030010', 'Selesai', textTheme), - _buildRecipientItem( - 'Siti Rahayu', '3201020107030010', 'Selesai', textTheme), + _buildDonorItem('PT Sejahtera', 'D-2023-001', textTheme), + _buildDonorItem('Yayasan Peduli', 'D-2023-002', textTheme), + _buildDonorItem('CV Makmur', 'D-2023-003', textTheme), ], ); } - Widget _buildRecipientItem( - String name, String nik, String status, TextTheme textTheme) { + Widget _buildDonorItem(String name, String id, TextTheme textTheme) { return Container( width: double.infinity, margin: const EdgeInsets.only(bottom: 10), @@ -492,7 +567,117 @@ class PetugasDesaDashboardView extends GetView { ), ), 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> 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, ), trailing: Row( diff --git a/pubspec.lock b/pubspec.lock index c364ca4..1b7a6ea 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -33,6 +33,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" async: dependency: transitive description: @@ -134,6 +142,14 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: "direct dev" description: flutter @@ -296,6 +312,14 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: transitive description: @@ -344,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" platform: dependency: transitive description: @@ -597,6 +629,30 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: transitive description: @@ -645,6 +701,14 @@ packages: url: "https://pub.dev" source: hosted 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: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5d35d38..45b14cd 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: # Untuk tampilan loading flutter_spinkit: ^5.2.0 google_fonts: ^6.2.1 + flutter_svg: ^2.0.17 dev_dependencies: flutter_test: