From 201344790495be818a1c21f96c1274df2e9f9e98 Mon Sep 17 00:00:00 2001 From: Vaibhav Surve Date: Fri, 8 Aug 2025 15:33:25 +0530 Subject: [PATCH] removed the extra boz coming for the dashboard chart --- lib/view/dashboard/dashboard_chart.dart | 69 ++++---- lib/view/dashboard/dashboard_screen.dart | 202 +++++++++++------------ 2 files changed, 128 insertions(+), 143 deletions(-) diff --git a/lib/view/dashboard/dashboard_chart.dart b/lib/view/dashboard/dashboard_chart.dart index eaba8cc..edcd1ed 100644 --- a/lib/view/dashboard/dashboard_chart.dart +++ b/lib/view/dashboard/dashboard_chart.dart @@ -64,49 +64,36 @@ class AttendanceDashboardChart extends StatelessWidget { } @override - Widget build(BuildContext context) { - return Obx(() { - final isChartView = controller.isChartView.value; - final selectedRange = controller.selectedRange.value; - final isLoading = controller.isLoading.value; +Widget build(BuildContext context) { + return Obx(() { + final isChartView = controller.isChartView.value; + final selectedRange = controller.selectedRange.value; + final isLoading = controller.isLoading.value; - return Container( - decoration: const BoxDecoration( - gradient: LinearGradient( - colors: [Color(0xfff0f4f8), Color(0xffe2ebf0)], - begin: Alignment.topLeft, - end: Alignment.bottomRight, + return Container( + // flat white background + color: Colors.white, + padding: const EdgeInsets.all(10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildHeader(selectedRange, isChartView), + const SizedBox(height: 12), + AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: isLoading + ? SkeletonLoaders.buildLoadingSkeleton() + : filteredData.isEmpty + ? _buildNoDataMessage() + : isChartView + ? _buildChart() + : _buildTable(), ), - ), - child: Card( - color: Colors.white, - elevation: 6, - shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), - shadowColor: Colors.black12, - child: Padding( - padding: const EdgeInsets.all(10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _buildHeader(selectedRange, isChartView), - const SizedBox(height: 12), - AnimatedSwitcher( - duration: const Duration(milliseconds: 300), - child: isLoading - ? SkeletonLoaders.buildLoadingSkeleton() - : filteredData.isEmpty - ? _buildNoDataMessage() - : isChartView - ? _buildChart() - : _buildTable(), - ), - ], - ), - ), - ), - ); - }); - } + ], + ), + ); + }); +} Widget _buildHeader(String selectedRange, bool isChartView) { return Padding( diff --git a/lib/view/dashboard/dashboard_screen.dart b/lib/view/dashboard/dashboard_screen.dart index 32c1c18..80e2d79 100644 --- a/lib/view/dashboard/dashboard_screen.dart +++ b/lib/view/dashboard/dashboard_screen.dart @@ -5,14 +5,13 @@ import 'package:marco/controller/dashboard/dashboard_controller.dart'; import 'package:marco/controller/project_controller.dart'; import 'package:marco/helpers/services/storage/local_storage.dart'; import 'package:marco/helpers/utils/mixins/ui_mixin.dart'; -import 'package:marco/helpers/utils/my_shadow.dart'; import 'package:marco/helpers/widgets/my_card.dart'; import 'package:marco/helpers/widgets/my_container.dart'; import 'package:marco/helpers/widgets/my_spacing.dart'; import 'package:marco/helpers/widgets/my_text.dart'; import 'package:marco/view/dashboard/dashboard_chart.dart'; import 'package:marco/view/layouts/layout.dart'; - + class DashboardScreen extends StatefulWidget { const DashboardScreen({super.key}); @@ -26,14 +25,12 @@ class DashboardScreen extends StatefulWidget { static const String directoryMainPageRoute = "/dashboard/directory-main-page"; static const String expenseMainPageRoute = "/dashboard/expense-main-page"; - @override State createState() => _DashboardScreenState(); } class _DashboardScreenState extends State with UIMixin { - final DashboardController dashboardController = - Get.put(DashboardController()); + final DashboardController dashboardController = Get.put(DashboardController()); bool hasMpin = true; @override @@ -43,10 +40,8 @@ class _DashboardScreenState extends State with UIMixin { } Future _checkMpinStatus() async { - final bool mpinStatus = await LocalStorage.getIsMpin(); - setState(() { - hasMpin = mpinStatus; - }); + hasMpin = await LocalStorage.getIsMpin(); + if (mounted) setState(() {}); } @override @@ -57,107 +52,50 @@ class _DashboardScreenState extends State with UIMixin { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - _buildDashboardStats(), + _buildDashboardStats(context), MySpacing.height(24), - GetBuilder( - id: 'dashboard_controller', - builder: (projectController) { - final bool isProjectSelected = - projectController.selectedProject != null; - - return Opacity( - opacity: isProjectSelected ? 1.0 : 0.4, - child: IgnorePointer( - ignoring: !isProjectSelected, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AttendanceDashboardChart(), - ], - ), - ), - ); - }, - ), + _buildAttendanceChartSection(), ], ), ), ); } - Widget _buildDashboardStats() { + /// Dashboard Statistics Section with ProjectController + Widget _buildDashboardStats(BuildContext context) { final stats = [ - _StatItem(LucideIcons.scan_face, "Attendance", contentTheme.success, - DashboardScreen.attendanceRoute), - _StatItem(LucideIcons.users, "Employees", contentTheme.warning, - DashboardScreen.employeesRoute), - _StatItem(LucideIcons.logs, "Daily Task Planing", contentTheme.info, - DashboardScreen.dailyTasksRoute), - _StatItem(LucideIcons.list_todo, "Daily Task Progress", contentTheme.info, - DashboardScreen.dailyTasksProgressRoute), - _StatItem(LucideIcons.folder, "Directory", contentTheme.info, - DashboardScreen.directoryMainPageRoute), - _StatItem(LucideIcons.badge_dollar_sign, "Expense", contentTheme.info, - DashboardScreen.expenseMainPageRoute), + _StatItem(LucideIcons.scan_face, "Attendance", contentTheme.success, DashboardScreen.attendanceRoute), + _StatItem(LucideIcons.users, "Employees", contentTheme.warning, DashboardScreen.employeesRoute), + _StatItem(LucideIcons.logs, "Daily Task Planing", contentTheme.info, DashboardScreen.dailyTasksRoute), + _StatItem(LucideIcons.list_todo, "Daily Task Progress", contentTheme.info, DashboardScreen.dailyTasksProgressRoute), + _StatItem(LucideIcons.folder, "Directory", contentTheme.info, DashboardScreen.directoryMainPageRoute), + _StatItem(LucideIcons.badge_dollar_sign, "Expense", contentTheme.info, DashboardScreen.expenseMainPageRoute), ]; return GetBuilder( id: 'dashboard_controller', builder: (controller) { - final bool isLoading = controller.isLoading.value; - final bool isProjectSelected = controller.selectedProject != null; - - if (isLoading) { - return Wrap( - spacing: 10, - runSpacing: 10, - children: List.generate( - 4, - (index) => - _buildStatCardSkeleton(MediaQuery.of(context).size.width / 3), - ), - ); + if (controller.isLoading.value) { + return _buildLoadingSkeleton(context); } + final isProjectSelected = controller.selectedProject != null; + return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - if (!isProjectSelected) - Padding( - padding: const EdgeInsets.symmetric(vertical: 12), - child: MyCard( - color: Colors.orange.withOpacity(0.1), - paddingAll: 12, - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const Icon(Icons.info_outline, color: Colors.orange), - MySpacing.width(8), - Expanded( - child: MyText.bodySmall( - "No projects assigned yet. Please contact your manager to get started.", - color: Colors.orange.shade800, - maxLines: 3, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), - ), - ), + if (!isProjectSelected) _buildNoProjectMessage(), LayoutBuilder( builder: (context, constraints) { - double maxWidth = constraints.maxWidth; - int crossAxisCount = (maxWidth / 100).floor().clamp(2, 4); - double cardWidth = - (maxWidth - (crossAxisCount - 1) * 10) / crossAxisCount; + final maxWidth = constraints.maxWidth; + final crossAxisCount = (maxWidth / 100).floor().clamp(2, 4); + final cardWidth = (maxWidth - (crossAxisCount - 1) * 10) / crossAxisCount; return Wrap( spacing: 10, runSpacing: 10, children: stats - .map((stat) => - _buildStatCard(stat, cardWidth, isProjectSelected)) + .map((stat) => _buildStatCard(stat, cardWidth, isProjectSelected)) .toList(), ); }, @@ -168,6 +106,64 @@ class _DashboardScreenState extends State with UIMixin { ); } + /// Attendance Chart Section + Widget _buildAttendanceChartSection() { + return GetBuilder( + id: 'dashboard_controller', + builder: (projectController) { + final isProjectSelected = projectController.selectedProject != null; + return Opacity( + opacity: isProjectSelected ? 1.0 : 0.4, + child: IgnorePointer( + ignoring: !isProjectSelected, + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: AttendanceDashboardChart(), + ), + ), + ); + }, + ); + } + + /// No Project Assigned Message + Widget _buildNoProjectMessage() { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: MyCard( + color: Colors.orange.withOpacity(0.1), + paddingAll: 12, + child: Row( + children: [ + const Icon(Icons.info_outline, color: Colors.orange), + MySpacing.width(8), + Expanded( + child: MyText.bodySmall( + "No projects assigned yet. Please contact your manager to get started.", + color: Colors.orange.shade800, + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ); + } + + /// Loading Skeletons + Widget _buildLoadingSkeleton(BuildContext context) { + return Wrap( + spacing: 10, + runSpacing: 10, + children: List.generate( + 4, + (index) => _buildStatCardSkeleton(MediaQuery.of(context).size.width / 3), + ), + ); + } + + /// Skeleton Card Widget _buildStatCardSkeleton(double width) { return MyCard.bordered( width: width, @@ -175,7 +171,6 @@ class _DashboardScreenState extends State with UIMixin { paddingAll: 5, borderRadiusAll: 10, border: Border.all(color: Colors.grey.withOpacity(0.15)), - shadow: MyShadow(elevation: 1.5, position: MyShadowPosition.bottom), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -195,27 +190,14 @@ class _DashboardScreenState extends State with UIMixin { ); } + /// Stat Card Widget _buildStatCard(_StatItem statItem, double width, bool isEnabled) { return Opacity( opacity: isEnabled ? 1.0 : 0.4, child: IgnorePointer( ignoring: !isEnabled, child: InkWell( - onTap: () { - if (!isEnabled) { - Get.defaultDialog( - title: "No Project Selected", - middleText: - "You need to select a project before accessing this section.", - confirm: ElevatedButton( - onPressed: () => Get.back(), - child: const Text("OK"), - ), - ); - } else { - Get.toNamed(statItem.route); - } - }, + onTap: () => _handleStatCardTap(statItem, isEnabled), borderRadius: BorderRadius.circular(10), child: MyCard.bordered( width: width, @@ -223,7 +205,6 @@ class _DashboardScreenState extends State with UIMixin { paddingAll: 5, borderRadiusAll: 10, border: Border.all(color: Colors.grey.withOpacity(0.15)), - shadow: MyShadow(elevation: 1.5, position: MyShadowPosition.bottom), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ @@ -243,6 +224,23 @@ class _DashboardScreenState extends State with UIMixin { ); } + /// Handle Tap + void _handleStatCardTap(_StatItem statItem, bool isEnabled) { + if (!isEnabled) { + Get.defaultDialog( + title: "No Project Selected", + middleText: "You need to select a project before accessing this section.", + confirm: ElevatedButton( + onPressed: () => Get.back(), + child: const Text("OK"), + ), + ); + } else { + Get.toNamed(statItem.route); + } + } + + /// Stat Icon Widget _buildStatCardIcon(_StatItem statItem) { return MyContainer.rounded( paddingAll: 10,