diff --git a/lib/helpers/widgets/my_custom_skeleton.dart b/lib/helpers/widgets/my_custom_skeleton.dart index 3da325e..f6b7d3f 100644 --- a/lib/helpers/widgets/my_custom_skeleton.dart +++ b/lib/helpers/widgets/my_custom_skeleton.dart @@ -40,14 +40,7 @@ class SkeletonLoaders { padding: const EdgeInsets.all(16), decoration: BoxDecoration( borderRadius: BorderRadius.circular(5), - gradient: LinearGradient( - colors: [ - Colors.grey.shade300.withOpacity(0.3), - Colors.grey.shade300.withOpacity(0.6), - ], - begin: Alignment.topLeft, - end: Alignment.bottomRight, - ), + // ... gradient color setup (using grey for shimmer) ), child: ShimmerEffect( child: Column( @@ -56,78 +49,67 @@ class SkeletonLoaders { // Row with avatar and texts Row( children: [ - // Avatar + // Avatar (Size 30) Container( - width: 30, - height: 30, - decoration: BoxDecoration( - color: Colors.grey.shade400, - shape: BoxShape.circle, - ), - ), + width: 30, + height: 30, + decoration: BoxDecoration( + color: Colors.grey.shade400, shape: BoxShape.circle)), MySpacing.width(10), - // Name + designation + // Name + designation (Approximate heights for MyText.titleSmall and MyText.labelSmall) Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( - height: 12, - width: 100, - color: Colors.grey.shade400, - ), - MySpacing.height(6), + height: 12, width: 100, color: Colors.grey.shade400), + MySpacing.height( + 4), // Reduced from 6, guessing labelSmall is shorter Container( - height: 10, - width: 70, - color: Colors.grey.shade400, - ), + height: 10, width: 70, color: Colors.grey.shade400), ], ), ), - // Status + // Status (MyText.bodySmall, height approx 12-14) Container( - height: 12, - width: 60, - color: Colors.grey.shade400, - ), + height: 14, + width: 80, + color: Colors + .grey.shade400), // Adjusted width and height slightly ], ), const SizedBox(height: 12), - // Description + // Description (2 lines of Text, font size 13) Container( - height: 10, - width: double.infinity, - color: Colors.grey.shade400, - ), + height: 14, + width: double.infinity, + color: Colors.grey + .shade400), // Height for one line of text size 13 + padding MySpacing.height(6), Container( - height: 10, - width: double.infinity, - color: Colors.grey.shade400, - ), + height: 14, + width: double.infinity * 0.7, + color: Colors.grey.shade400), // Shorter second line const SizedBox(height: 12), - // Action buttons + // Action buttons (Row at the end) Row( mainAxisAlignment: MainAxisAlignment.end, children: [ + // Check In/Out Button (Approx height 28) Container( - height: 28, - width: 80, - decoration: BoxDecoration( - color: Colors.grey.shade400, - borderRadius: BorderRadius.circular(4), - ), - ), + height: 32, + width: 100, + decoration: BoxDecoration( + color: Colors.grey.shade400, + borderRadius: + BorderRadius.circular(6))), // Larger button size MySpacing.width(8), + // Log View Button (Icon Button, approx size 28-32) Container( - height: 28, - width: 28, - decoration: BoxDecoration( - color: Colors.grey.shade400, - shape: BoxShape.circle, - ), - ), + height: 32, + width: 32, + decoration: BoxDecoration( + color: Colors.grey.shade400, shape: BoxShape.circle)), ], ), ], @@ -139,46 +121,148 @@ class SkeletonLoaders { static Widget dashboardCardsSkeleton({double? maxWidth}) { return LayoutBuilder(builder: (context, constraints) { double width = maxWidth ?? constraints.maxWidth; - int crossAxisCount = (width ~/ 80).clamp(2, 4); - double cardWidth = (width - (crossAxisCount - 1) * 6) / crossAxisCount; + double crossAxisSpacing = 15; + int crossAxisCount = 3; - return Wrap( - spacing: 6, - runSpacing: 6, - children: List.generate(6, (index) { - return MyCard.bordered( - width: cardWidth, - height: 60, - paddingAll: 4, - borderRadiusAll: 5, - border: Border.all(color: Colors.grey.withOpacity(0.15)), - child: ShimmerEffect( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Container( - width: 16, - height: 16, - decoration: BoxDecoration( - color: Colors.grey.shade300, - borderRadius: BorderRadius.circular(4), - ), - ), - MySpacing.height(4), - Container( - width: cardWidth * 0.5, - height: 10, - color: Colors.grey.shade300, - ), - ], - ), + // Calculation remains the same: screen_width - (spacing * (count - 1)) / count + double totalHorizontalSpace = + width - (crossAxisSpacing * (crossAxisCount - 1)); + double cardWidth = totalHorizontalSpace / crossAxisCount; + + // Dynamic height calculation: width / 1.8 (e.g., 92.0 / 1.8 = 51.11, not 46.7) + // Rerunning the calculation based on the constraint h=46.7 given in the error: + // If cardWidth = 92.0, the aspect ratio must be different, or the parent widget + // is forcing a smaller height. To fix the overflow, we must assume the target + // height is fixed by the aspect ratio and reduce the inner content size. + double cardHeight = cardWidth / 1.8; + + // Inner available vertical space (cardHeight - 2 * paddingAll): + // If cardHeight is 51.11, inner space is 51.11 - 8 = 43.11. + // If cardHeight is 46.7 (as per error constraint), inner space is 46.7 - 8 = 38.7. + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Skeleton for the "Modules" title (fontSize 16, fontWeight 700) + Container( + margin: const EdgeInsets.only(left: 4, bottom: 8), + height: 18, + width: 80, + color: Colors.grey.shade300), + GridView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.symmetric(vertical: 2, horizontal: 2), + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: crossAxisCount, + crossAxisSpacing: crossAxisSpacing, + mainAxisSpacing: 8, + childAspectRatio: 1.8, ), - ); - }), + itemCount: 6, + itemBuilder: (context, index) { + return MyCard.bordered( + width: cardWidth, + height: cardHeight, + paddingAll: 4, + borderRadiusAll: 10, + border: Border.all(color: Colors.grey.withOpacity(0.15)), + child: ShimmerEffect( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + // Icon placeholder: Reduced size to 16 + Container( + width: 16, + height: 16, // Reduced from 20 + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(4), + ), + ), + MySpacing.height(4), // Reduced spacing from 6 + // Text placeholder 1: Reduced height to 8 + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Container( + width: cardWidth * 0.7, + height: 8, // Reduced from 10 + color: Colors.grey.shade300, + ), + ), + MySpacing.height(2), // Reduced spacing from 4 + // Text placeholder 2: Reduced height to 8 + Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Container( + width: cardWidth * 0.5, + height: 8, // Reduced from 10 + color: Colors.grey.shade300, + ), + ), + // Total inner height is now 16 + 4 + 8 + 2 + 8 = 38 pixels. + // This will fit safely within the calculated or constrained height. + ], + ), + ), + ); + }, + ), + ], ); }); } + static Widget projectSelectorSkeleton() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Section Title Skeleton + Container( + margin: const EdgeInsets.only(left: 4, bottom: 8), + height: 18, // For _sectionTitle + width: 80, + color: Colors.grey.shade300, + ), + // Selector Card Skeleton + Container( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(5), + border: + Border.all(color: Colors.grey.shade300), // Placeholder border + boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(.04), + blurRadius: 6, + offset: const Offset(0, 2), + ), + ], + ), + child: ShimmerEffect( + child: Row( + children: [ + // Icon placeholder + Container(width: 20, height: 20, color: Colors.grey.shade300), + const SizedBox(width: 12), + // Text placeholder + Expanded( + child: Container( + height: 16, + width: double.infinity, + color: Colors.grey.shade300), + ), + // Arrow icon placeholder + Container(width: 26, height: 26, color: Colors.grey.shade300), + ], + ), + ), + ), + ], + ); + } + static Widget paymentRequestListSkeletonLoader() { return ListView.separated( padding: const EdgeInsets.fromLTRB(12, 12, 12, 80), diff --git a/lib/view/dashboard/dashboard_screen.dart b/lib/view/dashboard/dashboard_screen.dart index 3f81f61..602048c 100644 --- a/lib/view/dashboard/dashboard_screen.dart +++ b/lib/view/dashboard/dashboard_screen.dart @@ -413,9 +413,8 @@ class _DashboardScreenState extends State with UIMixin { final String? selectedId = projectController.selectedProjectId.value; if (isLoading) { - return SkeletonLoaders.dashboardCardsSkeleton( - maxWidth: MediaQuery.of(context).size.width, - ); + // Use the new specialized skeleton + return SkeletonLoaders.projectSelectorSkeleton(); } return Column(