import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../core/api/api_client.dart'; import '../../../core/chat/chat_opening_bloc.dart'; import '../../../core/chat/session_closure_bloc.dart'; import '../../../core/pairing/pairing_bloc.dart'; class PricingBottomSheet extends StatelessWidget { /// If set, the bottom sheet is in "extension" mode — selecting a tier extends the session. final String? extensionSessionId; const PricingBottomSheet({super.key, this.extensionSessionId}); /// Show for new pairing (from home screen) static Future show(BuildContext context) { return showModalBottomSheet( context: context, isScrollControlled: true, builder: (_) => BlocProvider( create: (ctx) => ChatOpeningBloc(apiClient: ctx.read())..add(LoadPricing()), child: MultiBlocProvider( providers: [ BlocProvider.value(value: context.read()), ], child: const PricingBottomSheet(), ), ), ); } /// Show for session extension (from chat screen) static Future showForExtension(BuildContext context, {required String sessionId}) { return showModalBottomSheet( context: context, isScrollControlled: true, builder: (_) => BlocProvider( create: (ctx) => ChatOpeningBloc(apiClient: ctx.read())..add(LoadPricing()), child: MultiBlocProvider( providers: [ BlocProvider.value(value: context.read()), ], child: PricingBottomSheet(extensionSessionId: sessionId), ), ), ); } String _formatPrice(int price) { final str = price.toString(); final buffer = StringBuffer(); for (var i = 0; i < str.length; i++) { if (i > 0 && (str.length - i) % 3 == 0) buffer.write('.'); buffer.write(str[i]); } return 'Rp $buffer'; } @override Widget build(BuildContext context) { final isExtension = extensionSessionId != null; return BlocBuilder( builder: (context, state) { if (state is PricingLoading || state is PricingInitial) { return const SizedBox( height: 200, child: Center(child: CircularProgressIndicator()), ); } if (state is PricingError) { return SizedBox( height: 200, child: Center(child: Text(state.message)), ); } if (state is PricingLoaded) { return DraggableScrollableSheet( initialChildSize: 0.6, minChildSize: 0.4, maxChildSize: 0.8, expand: false, builder: (_, scrollController) { return Padding( padding: const EdgeInsets.all(24), child: ListView( controller: scrollController, children: [ Text( isExtension ? 'Perpanjang Durasi' : 'Pilih Durasi Curhat', style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), textAlign: TextAlign.center, ), const SizedBox(height: 16), if (!isExtension && state.freeTrialEligible) ...[ Card( color: Colors.green.shade50, child: ListTile( leading: const Icon(Icons.card_giftcard, color: Colors.green), title: Text('Free Trial (${state.freeTrialDurationMinutes} Menit)'), subtitle: const Text('Gratis untuk pertama kali!'), trailing: const Icon(Icons.arrow_forward_ios, size: 16), onTap: () { Navigator.of(context).pop(); _startPairing(context, isFreeTrial: true); }, ), ), const Divider(height: 24), ], ...state.tiers.map((tier) => Card( child: ListTile( title: Text(tier.label), trailing: Text( _formatPrice(tier.price), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), onTap: () { Navigator.of(context).pop(); if (isExtension) { _requestExtension( context, sessionId: extensionSessionId!, durationMinutes: tier.durationMinutes, price: tier.price, ); } else { _startPairing( context, durationMinutes: tier.durationMinutes, price: tier.price, ); } }, ), )), ], ), ); }, ); } return const SizedBox.shrink(); }, ); } void _startPairing(BuildContext context, {bool isFreeTrial = false, int? durationMinutes, int? price}) { context.read().add(RequestPairingWithTier( durationMinutes: durationMinutes, price: price, isFreeTrial: isFreeTrial, )); } void _requestExtension(BuildContext context, {required String sessionId, required int durationMinutes, required int price}) { context.read().add(RequestExtension( sessionId: sessionId, durationMinutes: durationMinutes, price: price, )); } }