import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../core/design/tokens.dart'; import '../../../core/design/tripz_colors.dart'; import '../../../core/di.dart'; import '../../../core/l10n/l10n.dart'; import '../../../core/ui/status_banner.dart'; import '../../../core/ui/app_drawer.dart'; import '../cubit/duty_cubit.dart'; import '../cubit/duty_state.dart'; import '../data/models/geo_point.dart'; import 'widgets/active_duty_sheet.dart'; import 'widgets/duty_toggle.dart'; import 'widgets/offer_sheet.dart'; import 'widgets/ride_map.dart'; /// شاشة السائق: خريطة + مفتاح الاتصال أعلى + ورقة تتبدّل بالمرحلة. class DutyPage extends StatefulWidget { const DutyPage({super.key}); @override State createState() => _DutyPageState(); } class _DutyPageState extends State { late final DutyCubit _cubit = sl()..init(); @override void dispose() { _cubit.close(); super.dispose(); } @override Widget build(BuildContext context) { return BlocProvider.value( value: _cubit, child: Scaffold( drawer: const AppDrawer(), body: Stack( children: [ // الخريطة معزولة عن بقية الحالة: نبضة موقع كل 25 متراً يجب ألّا // تعيد بناء الورقة والمفتاح معها. BlocSelector( selector: (s) => s.myLocation, builder: (context, me) => RideMap(origin: me, cameraTarget: me), ), SafeArea( child: Padding( padding: Space.page, child: Column( children: [ Builder( builder: (context) => Align( alignment: AlignmentDirectional.topStart, child: Material( color: context.tripzColors.surfaceRaised, shape: const CircleBorder(), clipBehavior: Clip.antiAlias, child: InkWell( onTap: Scaffold.of(context).openDrawer, child: const Padding( padding: EdgeInsets.all(Space.sm), child: Icon(Icons.menu_rounded, size: Sizes.icon), ), ), ), ), ), const SizedBox(height: Space.xs), BlocSelector( selector: (s) => (online: s.isOnline, busy: s.busy), builder: (context, d) => DutyToggle( isOnline: d.online, busy: d.busy, onToggle: _cubit.toggleOnline, ), ), const SizedBox(height: Space.xs), BlocSelector( selector: (s) => s.creditBlocked, builder: (context, blocked) => blocked ? StatusBanner( message: context.l10n.errorGeneric, tone: BannerTone.danger, icon: Icons.account_balance_wallet_outlined, ) : const SizedBox.shrink(), ), ], ), ), ), Align( alignment: Alignment.bottomCenter, child: BlocBuilder( builder: (context, state) => _Sheet(state: state), ), ), ], ), ), ); } } class _Sheet extends StatelessWidget { const _Sheet({required this.state}); final DutyState state; @override Widget build(BuildContext context) { final l10n = context.l10n; final child = switch (state.phase) { DutyPhase.offline => const SizedBox.shrink(), DutyPhase.waiting => Padding( padding: const EdgeInsets.symmetric(vertical: Space.md), child: Text( state.error == DutyError.offerTaken ? l10n.driverOfferTaken : l10n.driverNoOffers, textAlign: TextAlign.center, style: context.texts.bodyMedium?.copyWith( color: context.colors.onSurfaceVariant, ), ), ), DutyPhase.offered => OfferSheet(offer: state.offer!), DutyPhase.active => ActiveDutySheet(trip: state.trip!, busy: state.busy), }; if (state.phase == DutyPhase.offline) return const SizedBox.shrink(); return Container( width: double.infinity, decoration: BoxDecoration( color: context.colors.surface, borderRadius: Radii.sheetTop, ), child: SafeArea( top: false, child: Padding( padding: Space.page, child: AnimatedSize( duration: Motion.inScreen, curve: Motion.curve, alignment: Alignment.bottomCenter, child: child, ), ), ), ); } }