feat(statistics): implement shimmer loading placeholders in statistics view
This commit is contained in:
parent
b54c204963
commit
8bafa19e31
|
@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:get/get.dart';
|
||||
import 'package:sigap/src/features/panic/presentation/controllers/main_safety_indicator_controller.dart';
|
||||
import 'package:sigap/src/features/panic/presentation/controllers/statistics_view_controller.dart';
|
||||
import 'package:sigap/src/shared/widgets/loaders/custom_circular_loader.dart';
|
||||
import 'package:sigap/src/utils/constants/colors.dart';
|
||||
import 'package:sigap/src/utils/loaders/shimmer.dart';
|
||||
|
||||
import 'crime_stats_header.dart';
|
||||
import 'main_safety_indicator.dart';
|
||||
|
@ -24,7 +23,10 @@ class StatisticsView extends StatelessWidget {
|
|||
// Main content
|
||||
SingleChildScrollView(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||
child: Column(
|
||||
child:
|
||||
statsController.isLoading.value
|
||||
? _buildShimmerLoading(context)
|
||||
: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// District and date information
|
||||
|
@ -49,7 +51,9 @@ class StatisticsView extends StatelessWidget {
|
|||
progress: safetyController.progress.value,
|
||||
title: safetyController.title.value,
|
||||
label: safetyController.label.value,
|
||||
color: _getSafetyColor(safetyController.progress.value),
|
||||
color: _getSafetyColor(
|
||||
safetyController.progress.value,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 15),
|
||||
|
@ -94,11 +98,6 @@ class StatisticsView extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
|
||||
// Loading indicator
|
||||
if (statsController.isLoading.value)
|
||||
Center(child: TLoader.centeredLoader(color: TColors.primary),
|
||||
),
|
||||
|
||||
// Error message
|
||||
if (statsController.errorMessage.value.isNotEmpty)
|
||||
Positioned(
|
||||
|
@ -124,6 +123,168 @@ class StatisticsView extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
|
||||
// Build shimmer loading placeholders
|
||||
Widget _buildShimmerLoading(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
// Header shimmer
|
||||
_buildHeaderShimmer(),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
// Main indicator shimmer
|
||||
_buildMainIndicatorShimmer(),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
// Stats cards shimmer
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildStatCardShimmer()),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _buildStatCardShimmer()),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _buildStatCardShimmer()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
|
||||
// Recovery indicator shimmer
|
||||
_buildRecoveryShimmer(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
// Header shimmer placeholder
|
||||
Widget _buildHeaderShimmer() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
blurRadius: 5,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const TShimmerEffect(width: 150, height: 20, radius: 4),
|
||||
Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.withOpacity(0.2),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Row(
|
||||
children: const [
|
||||
TShimmerEffect(width: 120, height: 30, radius: 5),
|
||||
SizedBox(width: 10),
|
||||
TShimmerEffect(width: 80, height: 30, radius: 5),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Main safety indicator shimmer
|
||||
Widget _buildMainIndicatorShimmer() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
blurRadius: 5,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
const TShimmerEffect(width: 120, height: 120, radius: 60), // Circle
|
||||
const SizedBox(height: 15),
|
||||
const TShimmerEffect(width: 100, height: 20, radius: 4), // Text
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Stat card shimmer
|
||||
Widget _buildStatCardShimmer() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
blurRadius: 5,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: const [
|
||||
TShimmerEffect(width: 60, height: 60, radius: 30), // Circle
|
||||
SizedBox(height: 10),
|
||||
TShimmerEffect(width: 40, height: 18, radius: 4), // Value
|
||||
SizedBox(height: 5),
|
||||
TShimmerEffect(width: 60, height: 14, radius: 4), // Label
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Recovery indicator shimmer
|
||||
Widget _buildRecoveryShimmer() {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.1),
|
||||
blurRadius: 5,
|
||||
spreadRadius: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
TShimmerEffect(width: 140, height: 20, radius: 4), // Title
|
||||
SizedBox(height: 15),
|
||||
TShimmerEffect(
|
||||
width: double.infinity,
|
||||
height: 12,
|
||||
radius: 6,
|
||||
), // Progress bar
|
||||
SizedBox(height: 10),
|
||||
TShimmerEffect(width: 80, height: 16, radius: 4), // Status text
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Helper to get district name from district ID
|
||||
String _getDistrictName(String districtId) {
|
||||
final statsController = Get.find<StatisticsViewController>();
|
||||
|
|
Loading…
Reference in New Issue