import 'package:flutter/material.dart'; import '../../../../common/theme/theme.dart'; import '../../../../domain/outlet/outlet.dart'; /// Outlet selector field — styled like DateRangePickerField. /// Opens a bottom sheet to pick an outlet or "Semua Outlet". class PurchaseOutletSelectorField extends StatefulWidget { final String? selectedOutletId; final List outlets; final bool isLoading; final ValueChanged onOutletChanged; const PurchaseOutletSelectorField({ super.key, required this.selectedOutletId, required this.outlets, required this.isLoading, required this.onOutletChanged, }); @override State createState() => _PurchaseOutletSelectorFieldState(); } class _PurchaseOutletSelectorFieldState extends State { bool _isPressed = false; Outlet? get _selectedOutlet => widget.outlets .where((o) => o.id == widget.selectedOutletId) .firstOrNull; String get _label => _selectedOutlet?.name ?? 'Semua Outlet'; bool get _hasValue => widget.selectedOutletId != null; void _showSheet() { if (widget.isLoading) return; showModalBottomSheet( context: context, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), builder: (_) => _OutletBottomSheet( outlets: widget.outlets, selectedOutletId: widget.selectedOutletId, onSelected: (outletId) { Navigator.pop(context); widget.onOutletChanged(outletId); }, ), ); } @override Widget build(BuildContext context) { return GestureDetector( onTap: _showSheet, onTapDown: (_) => setState(() => _isPressed = true), onTapUp: (_) => setState(() => _isPressed = false), onTapCancel: () => setState(() => _isPressed = false), child: AnimatedContainer( duration: const Duration(milliseconds: 150), height: 52, padding: const EdgeInsets.symmetric(horizontal: 16), decoration: BoxDecoration( color: _isPressed ? AppColor.backgroundLight : AppColor.white, borderRadius: BorderRadius.circular(12), border: Border.all( color: _isPressed ? AppColor.primary : AppColor.border, width: _isPressed ? 2 : 1, ), boxShadow: _isPressed ? [ BoxShadow( color: AppColor.primary.withOpacity(0.1), blurRadius: 8, offset: const Offset(0, 2), ), ] : null, ), child: Row( children: [ Expanded( child: Text( _label, style: TextStyle( fontSize: 15, fontWeight: _hasValue ? FontWeight.w500 : FontWeight.w400, color: _hasValue ? AppColor.textPrimary : AppColor.textSecondary, ), overflow: TextOverflow.ellipsis, ), ), Container( padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: AppColor.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(8), ), child: widget.isLoading ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator( strokeWidth: 2, color: AppColor.primary, ), ) : const Icon( Icons.store_rounded, size: 20, color: AppColor.primary, ), ), ], ), ), ); } } // ─── Bottom Sheet ───────────────────────────────────────────────────────────── class _OutletBottomSheet extends StatelessWidget { final List outlets; final String? selectedOutletId; final ValueChanged onSelected; const _OutletBottomSheet({ required this.outlets, required this.selectedOutletId, required this.onSelected, }); @override Widget build(BuildContext context) { return SafeArea( child: Padding( padding: const EdgeInsets.fromLTRB(20, 16, 20, 20), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ // Handle bar Center( child: Container( width: 40, height: 4, decoration: BoxDecoration( color: Colors.grey.shade300, borderRadius: BorderRadius.circular(2), ), ), ), const SizedBox(height: 16), Text( 'Pilih Outlet', style: AppStyle.lg.copyWith(fontWeight: FontWeight.w700), ), const SizedBox(height: 12), // "Semua Outlet" option _OutletItem( label: 'Semua Outlet', icon: Icons.store_rounded, isSelected: selectedOutletId == null, onTap: () => onSelected(null), ), const Divider(height: 1), // Individual outlets ...outlets.map( (outlet) => Column( children: [ _OutletItem( label: outlet.name, icon: Icons.storefront_rounded, isSelected: selectedOutletId == outlet.id, isActive: outlet.isActive, onTap: () => onSelected(outlet.id), ), if (outlet != outlets.last) const Divider(height: 1), ], ), ), ], ), ), ); } } // ─── List Item ──────────────────────────────────────────────────────────────── class _OutletItem extends StatelessWidget { final String label; final IconData icon; final bool isSelected; final bool? isActive; final VoidCallback onTap; const _OutletItem({ required this.label, required this.icon, required this.isSelected, required this.onTap, this.isActive, }); @override Widget build(BuildContext context) { return ListTile( onTap: onTap, contentPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 2), leading: Container( width: 36, height: 36, decoration: BoxDecoration( color: isSelected ? AppColor.primary.withOpacity(0.1) : AppColor.background, borderRadius: BorderRadius.circular(10), ), child: Icon( icon, size: 18, color: isSelected ? AppColor.primary : AppColor.textSecondary, ), ), title: Text( label, style: AppStyle.md.copyWith( fontWeight: isSelected ? FontWeight.w700 : FontWeight.w500, color: isSelected ? AppColor.primary : AppColor.textPrimary, ), ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ if (isActive != null) ...[ Container( width: 8, height: 8, decoration: BoxDecoration( shape: BoxShape.circle, color: isActive! ? AppColor.success : AppColor.error, ), ), const SizedBox(width: 8), ], if (isSelected) const Icon(Icons.check_rounded, color: AppColor.primary, size: 20), ], ), ); } }