feat: Add chart skeleton loader to enhance loading experience in dashboard

This commit is contained in:
Vaibhav Surve 2025-08-28 16:28:54 +05:30
parent 80d5fc5f21
commit d62f8aa9ef
2 changed files with 78 additions and 2 deletions

View File

@ -45,6 +45,74 @@ class SkeletonLoaders {
);
}
// Chart Skeleton Loader
static Widget chartSkeletonLoader() {
return MyCard.bordered(
margin: MySpacing.only(bottom: 12),
paddingAll: 16,
borderRadiusAll: 16,
shadow: MyShadow(
elevation: 1.5,
position: MyShadowPosition.bottom,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Chart Title Placeholder
Container(
height: 14,
width: 120,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(6),
),
),
MySpacing.height(20),
// Chart Bars (variable height for realism)
SizedBox(
height: 180,
child: Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: List.generate(6, (index) {
return Expanded(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 4),
child: Container(
height:
(60 + (index * 20)).toDouble(), // fake chart shape
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(6),
),
),
),
);
}),
),
),
MySpacing.height(16),
// X-Axis Labels
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(6, (index) {
return Container(
height: 10,
width: 30,
decoration: BoxDecoration(
color: Colors.grey.shade300,
borderRadius: BorderRadius.circular(4),
),
);
}),
),
],
),
);
}
// Employee List - Card Style
static Widget employeeListSkeletonLoader() {
return Column(

View File

@ -12,6 +12,7 @@ import 'package:marco/helpers/widgets/my_text.dart';
import 'package:marco/view/dashboard/dashboard_chart.dart';
import 'package:marco/view/layouts/layout.dart';
import 'package:marco/controller/dynamicMenu/dynamic_menu_controller.dart';
import 'package:marco/helpers/widgets/my_custom_skeleton.dart';
// import 'package:marco/helpers/services/firebase/firebase_messaging_service.dart'; // Commented out
@ -94,7 +95,7 @@ class _DashboardScreenState extends State<DashboardScreen> with UIMixin {
padding: const EdgeInsets.all(16),
child: Center(
child: MyText.bodySmall(
menuController.errorMessage.value,
"Failed to load menus. Please try again later.",
color: Colors.red,
),
),
@ -155,10 +156,17 @@ class _DashboardScreenState extends State<DashboardScreen> with UIMixin {
});
}
/// Attendance Chart Section
/// Attendance Chart Section
Widget _buildAttendanceChartSection() {
return Obx(() {
if (menuController.isLoading.value) {
// Show Skeleton Loader Instead of CircularProgressIndicator
return Padding(
padding: const EdgeInsets.all(8.0),
child: SkeletonLoaders.chartSkeletonLoader(), // <-- using the skeleton we built
);
}
final isAttendanceAllowed = menuController.isMenuAllowed("Attendance");
if (!isAttendanceAllowed) {