import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../../core/chat/chat_opening_provider.dart'; import '../../../core/constants.dart'; import '../../../core/theme/halo_tokens.dart'; import '../../../core/theme/widgets/halo_button.dart'; import '../state/payment_draft_provider.dart'; /// "Pemilihan harga" — tier list scoped to the currently-selected mode. /// A chat|call mode toggle at the top rebuilds the list and resets the /// selection. Bottom CTA carries the picked tier into `/payment/method`. class DurationPickScreen extends ConsumerWidget { const DurationPickScreen({super.key}); List _tiersForMode(PricingData pricing, PaymentMode mode) { return mode == PaymentMode.call ? pricing.callTiers : pricing.chatTiers; } @override Widget build(BuildContext context, WidgetRef ref) { final pricingAsync = ref.watch(chatPricingProvider); final draft = ref.watch(paymentDraftNotifierProvider); return Scaffold( backgroundColor: HaloTokens.bg, appBar: AppBar( backgroundColor: HaloTokens.bg, elevation: 0, leading: IconButton( icon: const Icon(Icons.chevron_left, color: HaloTokens.brandDark), onPressed: () { if (context.canPop()) { context.pop(); } else { context.go('/payment/method-pick'); } }, ), title: const Text( 'pilih durasi', style: TextStyle( fontFamily: HaloTokens.fontDisplay, fontSize: 18, fontWeight: FontWeight.w700, color: HaloTokens.brandDark, ), ), centerTitle: false, ), body: pricingAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (_, __) => const Center( child: Padding( padding: EdgeInsets.all(HaloSpacing.s24), child: Text( 'Gagal memuat harga. Coba lagi.', textAlign: TextAlign.center, ), ), ), data: (pricing) => _Body( pricing: pricing, mode: draft.mode, selectedDurationId: draft.durationId, tiers: _tiersForMode(pricing, draft.mode), ), ), ); } } class _Body extends ConsumerWidget { final PricingData pricing; final PaymentMode mode; final String? selectedDurationId; final List tiers; const _Body({ required this.pricing, required this.mode, required this.selectedDurationId, required this.tiers, }); void _onModeToggle(WidgetRef ref, PaymentMode next) { if (next == mode) return; ref.read(paymentDraftNotifierProvider.notifier).setMode(next); } void _onTierTap(WidgetRef ref, PriceTier tier) { ref.read(paymentDraftNotifierProvider.notifier).setTier( durationId: tier.id ?? tier.durationMinutes.toString(), durationMinutes: tier.durationMinutes, priceIDR: tier.price, ); } void _onPay(BuildContext context) { context.push('/payment/method'); } @override Widget build(BuildContext context, WidgetRef ref) { final selectedTier = tiers.firstWhere( (t) => (t.id ?? t.durationMinutes.toString()) == selectedDurationId, orElse: () => const PriceTier(durationMinutes: 0, price: 0, label: ''), ); final hasSelection = selectedTier.durationMinutes > 0; final ctaLabel = hasSelection ? '${mode == PaymentMode.call ? '📞' : '💬'} bayar ${formatRupiah(selectedTier.price)}' : 'pilih durasi dulu'; return Column( children: [ Padding( padding: const EdgeInsets.fromLTRB( HaloSpacing.s24, HaloSpacing.s8, HaloSpacing.s24, HaloSpacing.s8, ), child: _ModeToggle(mode: mode, onChanged: (m) => _onModeToggle(ref, m)), ), Expanded( child: tiers.isEmpty ? const _EmptyState() : ListView.separated( padding: const EdgeInsets.fromLTRB( HaloSpacing.s24, HaloSpacing.s12, HaloSpacing.s24, HaloSpacing.s24, ), itemCount: tiers.length, separatorBuilder: (_, __) => const SizedBox(height: HaloSpacing.s8), itemBuilder: (context, i) { final tier = tiers[i]; final id = tier.id ?? tier.durationMinutes.toString(); final selected = id == selectedDurationId; return _TierCard( tier: tier, selected: selected, onTap: () => _onTierTap(ref, tier), ); }, ), ), Container( padding: const EdgeInsets.fromLTRB( HaloSpacing.s24, HaloSpacing.s12, HaloSpacing.s24, HaloSpacing.s32, ), decoration: const BoxDecoration( color: HaloTokens.bg, border: Border(top: BorderSide(color: HaloTokens.border)), ), child: HaloButton( label: ctaLabel, size: HaloButtonSize.lg, fullWidth: true, onPressed: hasSelection ? () => _onPay(context) : null, ), ), ], ); } } class _ModeToggle extends StatelessWidget { final PaymentMode mode; final ValueChanged onChanged; const _ModeToggle({required this.mode, required this.onChanged}); @override Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(4), decoration: const BoxDecoration( color: HaloTokens.brandSofter, borderRadius: HaloRadius.pill, ), child: Row( children: [ Expanded(child: _Pill(label: 'chat', selected: mode == PaymentMode.chat, onTap: () => onChanged(PaymentMode.chat))), Expanded(child: _Pill(label: 'call', selected: mode == PaymentMode.call, onTap: () => onChanged(PaymentMode.call))), ], ), ); } } class _Pill extends StatelessWidget { final String label; final bool selected; final VoidCallback onTap; const _Pill({required this.label, required this.selected, required this.onTap}); @override Widget build(BuildContext context) { return Material( color: selected ? HaloTokens.surface : Colors.transparent, borderRadius: HaloRadius.pill, child: InkWell( borderRadius: HaloRadius.pill, onTap: onTap, child: Container( padding: const EdgeInsets.symmetric(vertical: HaloSpacing.s8), alignment: Alignment.center, child: Text( label, style: TextStyle( fontFamily: HaloTokens.fontBody, fontSize: 13.5, fontWeight: FontWeight.w600, color: selected ? HaloTokens.brandDark : HaloTokens.inkSoft, ), ), ), ), ); } } class _TierCard extends StatelessWidget { final PriceTier tier; final bool selected; final VoidCallback onTap; const _TierCard({required this.tier, required this.selected, required this.onTap}); @override Widget build(BuildContext context) { return Material( color: selected ? HaloTokens.brandSofter : HaloTokens.surface, borderRadius: HaloRadius.lg, child: InkWell( borderRadius: HaloRadius.lg, onTap: onTap, child: AnimatedContainer( duration: HaloMotion.fast, padding: const EdgeInsets.all(HaloSpacing.s16), decoration: BoxDecoration( border: Border.all( color: selected ? HaloTokens.brand : HaloTokens.border, width: selected ? 2 : 1, ), borderRadius: HaloRadius.lg, ), child: Row( children: [ Container( width: 44, height: 44, decoration: const BoxDecoration( color: HaloTokens.surface, borderRadius: HaloRadius.md, ), alignment: Alignment.center, child: Text( '${tier.durationMinutes}', style: const TextStyle( fontFamily: HaloTokens.fontDisplay, fontSize: 16, fontWeight: FontWeight.w700, color: HaloTokens.brandDark, ), ), ), const SizedBox(width: HaloSpacing.s12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ Text( '${tier.durationMinutes} menit', style: const TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: HaloTokens.ink, ), ), if (tier.tag != null) ...[ const SizedBox(width: HaloSpacing.s8), Container( padding: const EdgeInsets.symmetric( horizontal: HaloSpacing.s8, vertical: 2, ), decoration: const BoxDecoration( color: HaloTokens.mint, borderRadius: HaloRadius.pill, ), child: Text( tier.tag!, style: const TextStyle( fontSize: 9, fontWeight: FontWeight.w700, color: Color(0xFF1F4D34), letterSpacing: 0.4, ), ), ), ], ], ), ], ), ), Text( formatRupiah(tier.price), style: const TextStyle( fontFamily: HaloTokens.fontDisplay, fontSize: 16, fontWeight: FontWeight.w700, color: HaloTokens.brandDark, ), ), ], ), ), ), ); } } class _EmptyState extends StatelessWidget { const _EmptyState(); @override Widget build(BuildContext context) { return const Center( child: Padding( padding: EdgeInsets.all(HaloSpacing.s24), child: Text( 'Belum ada paket untuk mode ini.', style: TextStyle(color: HaloTokens.inkSoft), ), ), ); } }