import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:shimmer/shimmer.dart'; import '../../../../application/analytic/sales_loader/sales_loader_bloc.dart'; import '../../../../common/extension/extension.dart'; import '../../../../common/painter/wave_painter.dart'; import '../../../../common/theme/theme.dart'; import '../../../components/bottom_sheet/date_range_bottom_sheet.dart'; import '../../../components/spacer/spacer.dart'; class SalesHeader extends StatelessWidget { final SalesLoaderState state; final void Function(DateTime startDate, DateTime endDate)? onDateRangeChanged; const SalesHeader({super.key, required this.state, this.onDateRangeChanged}); @override Widget build(BuildContext context) { final dateLabel = _formatDateRange(state.dateFrom, state.dateTo, context); final outletLabel = state.sales.outletName.isNotEmpty ? state.sales.outletName : 'Semua Outlet'; return Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: AppColor.primaryGradient, begin: Alignment.topCenter, end: Alignment.bottomCenter, ), borderRadius: BorderRadius.only( bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24), ), ), child: Stack( children: [ // Decorative circles Positioned( top: -20, right: -30, child: Container( width: 120, height: 120, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.textWhite.withOpacity(0.08), ), ), ), Positioned( top: 30, right: 20, child: Container( width: 60, height: 60, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.textWhite.withOpacity(0.05), ), ), ), Positioned( top: 10, left: -20, child: Container( width: 80, height: 80, decoration: BoxDecoration( shape: BoxShape.circle, color: AppColor.textWhite.withOpacity(0.04), ), ), ), // Wave pattern Positioned.fill( child: CustomPaint( painter: WavePainter( animation: 0.0, color: AppColor.textWhite.withOpacity(0.1), ), ), ), // Content SafeArea( bottom: false, child: Padding( padding: const EdgeInsets.fromLTRB(16, 12, 16, 24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Back button + Title row + Calendar button Row( children: [ GestureDetector( onTap: () => context.router.maybePop(), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.chevron_left_rounded, color: AppColor.textWhite, size: 24, ), ), ), const SpaceWidth(12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( context.lang.sales, style: AppStyle.xl.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w700, fontSize: 20, ), ), const SizedBox(height: 2), Text( '$dateLabel · $outletLabel', style: AppStyle.sm.copyWith( color: AppColor.textWhite.withOpacity(0.75), fontWeight: FontWeight.w400, fontSize: 12, ), maxLines: 1, overflow: TextOverflow.ellipsis, ), ], ), ), const SpaceWidth(8), // Date filter button GestureDetector( onTap: () => _showDatePicker(context), child: Container( width: 40, height: 40, decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.15), borderRadius: BorderRadius.circular(12), ), child: const Icon( Icons.calendar_month_rounded, color: AppColor.textWhite, size: 20, ), ), ), ], ), const SpaceHeight(24), // Total Penjualan label Text( context.lang.total_sales_label, style: AppStyle.sm.copyWith( color: AppColor.textWhite.withOpacity(0.75), fontWeight: FontWeight.w400, fontSize: 13, ), ), const SpaceHeight(4), // Big value state.isFetching ? _buildHeaderValueShimmer() : Text( state.sales.summary.totalSales.currencyFormatRp, style: AppStyle.h1.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w900, fontSize: 32, ), ), const SpaceHeight(16), // Chips row state.isFetching ? _buildHeaderChipsShimmer() : _buildHeaderChips(context), ], ), ), ), ], ), ); } void _showDatePicker(BuildContext context) { DateRangePickerBottomSheet.show( context: context, primaryColor: AppColor.primary, initialStartDate: state.dateFrom, initialEndDate: state.dateTo, maxDate: DateTime.now(), onChanged: (startDate, endDate) { if (startDate != null && endDate != null) { onDateRangeChanged?.call(startDate, endDate); } }, ); } Widget _buildHeaderValueShimmer() { return Shimmer.fromColors( baseColor: AppColor.textWhite.withOpacity(0.3), highlightColor: AppColor.textWhite.withOpacity(0.6), child: Container( width: 200, height: 36, decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.3), borderRadius: BorderRadius.circular(8), ), ), ); } Widget _buildHeaderChipsShimmer() { return Row( children: List.generate( 3, (index) => Padding( padding: const EdgeInsets.only(right: 8), child: Shimmer.fromColors( baseColor: AppColor.textWhite.withOpacity(0.15), highlightColor: AppColor.textWhite.withOpacity(0.3), child: Container( width: 90, height: 32, decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.15), borderRadius: BorderRadius.circular(20), ), ), ), ), ), ); } Widget _buildHeaderChips(BuildContext context) { final summary = state.sales.summary; final avgPerInvoice = summary.totalOrders > 0 ? (summary.totalSales / summary.totalOrders).round() : 0; return Wrap( spacing: 8, runSpacing: 8, children: [ _buildChip('${summary.totalOrders} invoice'), _buildChip( '${summary.totalItems} ${context.lang.items_sold.toLowerCase()}', ), _buildChip('≈ ${avgPerInvoice.currencyFormatRp}/invoice'), ], ); } Widget _buildChip(String label) { return Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.15), borderRadius: BorderRadius.circular(20), border: Border.all(color: AppColor.textWhite.withOpacity(0.25)), ), child: Text( label, style: AppStyle.sm.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w600, fontSize: 12, ), ), ); } String _formatDateRange(DateTime from, DateTime to, BuildContext context) { const months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des', ]; if (from.year == to.year && from.month == to.month && from.day == to.day) { return '${context.lang.report} ${from.day} ${months[from.month - 1]} ${from.year}'; } return '${context.lang.report} ${from.day} ${months[from.month - 1]} - ${to.day} ${months[to.month - 1]} ${to.year}'; } }