import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:shimmer/shimmer.dart'; import '../../../../application/analytic/inventory_analytic_loader/inventory_analytic_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 InventoryHeader extends StatelessWidget { final InventoryAnalyticLoaderState state; final int selectedTabIndex; final ValueChanged onTabChanged; final void Function(DateTime startDate, DateTime endDate)? onDateRangeChanged; const InventoryHeader({ super.key, required this.state, required this.selectedTabIndex, required this.onTabChanged, this.onDateRangeChanged, }); @override Widget build(BuildContext context) { final outletLabel = state.inventoryAnalytic.summary.outletName.isNotEmpty ? state.inventoryAnalytic.summary.outletName : context.lang.all_outlets; final dateLabel = _formatDateRange(state.dateFrom, state.dateTo); 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: [ if (context.router.canPop()) ...[ 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.inventory, 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(20), // Tab selector (Product / Ingredient) _buildTabSelector(context), const SpaceHeight(24), // Total Value label Text( context.lang.total_inventory_value, style: AppStyle.sm.copyWith( color: AppColor.textWhite.withOpacity(0.75), fontWeight: FontWeight.w400, fontSize: 13, ), ), const SpaceHeight(4), // Big total value state.isFetching ? _buildHeaderValueShimmer() : Text( state .inventoryAnalytic .summary .totalValue .currencyFormatRp, style: AppStyle.h1.copyWith( color: AppColor.textWhite, fontWeight: FontWeight.w900, fontSize: 32, ), ), const SpaceHeight(16), // Chips row state.isFetching ? _buildHeaderChipsShimmer() : _buildHeaderChips(context), ], ), ), ), ], ), ); } Widget _buildTabSelector(BuildContext context) { return Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: AppColor.textWhite.withOpacity(0.15), borderRadius: BorderRadius.circular(30), border: Border.all(color: AppColor.textWhite.withOpacity(0.2)), ), child: Row( children: [ Expanded( child: _buildTab( icon: Icons.inventory_2_rounded, label: context.lang.product, isSelected: selectedTabIndex == 0, onTap: () => onTabChanged(0), ), ), Expanded( child: _buildTab( icon: Icons.restaurant_menu_rounded, label: context.lang.ingredients, isSelected: selectedTabIndex == 1, onTap: () => onTabChanged(1), ), ), ], ), ); } Widget _buildTab({ required IconData icon, required String label, required bool isSelected, required VoidCallback onTap, }) { return GestureDetector( onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( color: isSelected ? AppColor.white : Colors.transparent, borderRadius: BorderRadius.circular(26), ), child: Center( child: Row( mainAxisSize: MainAxisSize.min, children: [ Icon( icon, size: 16, color: isSelected ? AppColor.textPrimary : AppColor.textWhite, ), const SizedBox(width: 6), Text( label, style: AppStyle.md.copyWith( color: isSelected ? AppColor.textPrimary : AppColor.textWhite, fontWeight: FontWeight.w600, ), ), ], ), ), ), ); } 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.inventoryAnalytic.summary; if (selectedTabIndex == 0) { return Wrap( spacing: 8, runSpacing: 8, children: [ _buildChip('${summary.totalProducts} ${context.lang.product}'), _buildChip('${summary.lowStockProducts} ${context.lang.low_stock}'), _buildChip('${summary.zeroStockProducts} ${context.lang.zero_stock}'), ], ); } else { return Wrap( spacing: 8, runSpacing: 8, children: [ _buildChip('${summary.totalIngredients} ${context.lang.ingredients}'), _buildChip( '${summary.lowStockIngredients} ${context.lang.low_stock}', ), _buildChip( '${summary.zeroStockIngredients} ${context.lang.zero_stock}', ), ], ); } } 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) { 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 '${from.day} ${months[from.month - 1]} ${from.year}'; } return '${from.day} ${months[from.month - 1]} - ${to.day} ${months[to.month - 1]} ${to.year}'; } }