import 'package:flutter/material.dart'; import 'package:tm_app/core/theme/colors.dart'; import 'package:tm_app/core/utils/size_config.dart'; class TenderCardShimmer extends StatelessWidget { const TenderCardShimmer({super.key, this.isDesktop = false}); final bool isDesktop; @override Widget build(BuildContext context) { return _Shimmer( child: Container( width: double.infinity, margin: EdgeInsets.symmetric(horizontal: 16.0.w()), height: isDesktop ? 350.0.h() : 587.0.h(), padding: EdgeInsets.all(16.0.w()), decoration: BoxDecoration( color: AppColors.grey0, borderRadius: BorderRadius.circular(12), border: Border.all(color: AppColors.grey30), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _bar(width: isDesktop ? 120.0.w() : 140.0.w(), height: 14.0.h()), SizedBox(height: 16.0.h()), _block(height: isDesktop ? 58.0.h() : 70.0.h()), SizedBox(height: isDesktop ? 12.0.h() : 20.0.h()), _bar(width: double.infinity, height: 18.0.h()), SizedBox(height: 8.0.h()), _fractionBar(widthFactor: 0.72, height: 18.0.h()), SizedBox(height: 16.0.h()), _bar(width: double.infinity, height: 14.0.h()), SizedBox(height: 8.0.h()), _bar(width: double.infinity, height: 14.0.h()), SizedBox(height: 8.0.h()), _fractionBar(widthFactor: 0.55, height: 14.0.h()), const Spacer(), Row( children: [ _circle(size: 24.0.h()), SizedBox(width: 8.0.w()), _bar(width: 60.0.w(), height: 14.0.h()), const Spacer(), _pill(width: 108.0.w(), height: 40.0.h()), ], ), ], ), ), ); } Widget _bar({required double width, required double height}) { return Container( width: width, height: height, decoration: BoxDecoration( color: AppColors.grey20, borderRadius: BorderRadius.circular(6), ), ); } Widget _fractionBar({required double widthFactor, required double height}) { return FractionallySizedBox( widthFactor: widthFactor, alignment: AlignmentDirectional.centerStart, child: _bar(width: double.infinity, height: height), ); } Widget _block({required double height}) { return Container( width: double.infinity, height: height, decoration: BoxDecoration( color: AppColors.grey20, borderRadius: BorderRadius.circular(4), ), ); } Widget _pill({required double width, required double height}) { return Container( width: width, height: height, decoration: BoxDecoration( color: AppColors.grey20, borderRadius: BorderRadius.circular(100), ), ); } Widget _circle({required double size}) { return Container( width: size, height: size, decoration: BoxDecoration( color: AppColors.grey20, shape: BoxShape.circle, ), ); } } class _Shimmer extends StatefulWidget { const _Shimmer({required this.child}); final Widget child; @override State<_Shimmer> createState() => _ShimmerState(); } class _ShimmerState extends State<_Shimmer> with SingleTickerProviderStateMixin { late final AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 1400), )..repeat(); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return AnimatedBuilder( animation: _controller, child: widget.child, builder: (context, child) { return ShaderMask( blendMode: BlendMode.srcATop, shaderCallback: (bounds) { final shimmerWidth = bounds.width * 0.8; final offset = (bounds.width + shimmerWidth) * _controller.value; return LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, colors: [AppColors.grey20, AppColors.grey10, AppColors.grey20], stops: const [0.25, 0.5, 0.75], transform: _SlidingGradientTransform( slidePercent: (offset - shimmerWidth) / bounds.width, ), ).createShader(bounds); }, child: child, ); }, ); } } class _SlidingGradientTransform extends GradientTransform { const _SlidingGradientTransform({required this.slidePercent}); final double slidePercent; @override Matrix4 transform(Rect bounds, {TextDirection? textDirection}) { return Matrix4.translationValues(bounds.width * slidePercent, 0, 0); } }