Files
Eventify-frontend/lib/widgets/skeleton_loader.dart

135 lines
3.8 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';
/// Generic shimmer rectangle with configurable dimensions and border radius.
class SkeletonBox extends StatelessWidget {
final double width;
final double height;
final double borderRadius;
const SkeletonBox({
Key? key,
this.width = double.infinity,
required this.height,
this.borderRadius = 8,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return Shimmer.fromColors(
baseColor: isDark ? const Color(0xFF2D2D2D) : Colors.grey[300]!,
highlightColor: isDark ? const Color(0xFF3D3D3D) : Colors.grey[100]!,
child: Container(
width: width,
height: height,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(borderRadius),
),
),
);
}
}
/// Shimmer placeholder for a compact event card (used in horizontal lists).
class EventCardSkeleton extends StatelessWidget {
const EventCardSkeleton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: 200,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
SkeletonBox(height: 140, borderRadius: 12),
SizedBox(height: 8),
SkeletonBox(height: 14, width: 160),
SizedBox(height: 6),
SkeletonBox(height: 12, width: 100),
],
),
);
}
}
/// Shimmer placeholder for a full-width event list row.
class EventListSkeleton extends StatelessWidget {
const EventListSkeleton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6, horizontal: 16),
child: Row(
children: const [
SkeletonBox(width: 64, height: 64, borderRadius: 10),
SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SkeletonBox(height: 14),
SizedBox(height: 8),
SkeletonBox(height: 12, width: 140),
],
),
),
],
),
);
}
}
/// Shimmer placeholder for hero carousel area.
class HeroCarouselSkeleton extends StatelessWidget {
const HeroCarouselSkeleton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: SkeletonBox(height: 320, borderRadius: 24),
);
}
}
/// Shimmer grid for achievements tab.
class AchievementGridSkeleton extends StatelessWidget {
const AchievementGridSkeleton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 2,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
mainAxisSpacing: 12,
crossAxisSpacing: 12,
padding: const EdgeInsets.all(16),
children: List.generate(4, (_) => const SkeletonBox(height: 160, borderRadius: 16)),
);
}
}
/// Shimmer placeholder for profile stat cards row.
class ProfileStatsSkeleton extends StatelessWidget {
const ProfileStatsSkeleton({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
child: Row(
children: List.generate(3, (_) => const Expanded(
child: Padding(
padding: EdgeInsets.symmetric(horizontal: 4),
child: SkeletonBox(height: 80, borderRadius: 12),
),
)),
),
);
}
}