Update codebase

This commit is contained in:
Hamza-Ayed
2026-08-05 14:12:41 +03:00
parent 58928cd258
commit 95e2e4f35d
51 changed files with 3141 additions and 390 deletions
@@ -10,11 +10,38 @@ import '../../../core/ui/app_drawer.dart';
import '../cubit/duty_cubit.dart';
import '../cubit/duty_state.dart';
import '../data/models/geo_point.dart';
import '../data/models/route_info.dart';
import 'widgets/active_duty_sheet.dart';
import 'widgets/duty_toggle.dart';
import 'widgets/offer_sheet.dart';
import 'widgets/ride_map.dart';
/// نصيب الورقة السفلية من ارتفاع الشاشة — مطابق لتطبيق الراكب.
const double _sheetFraction = 0.33;
/// ما تحتاجه الخريطة وحدها — تغيّرُ الرصيد أو الانشغال لا يعيد بناءها.
class _MapData {
const _MapData({this.me, this.pickup, this.dropoff, this.route, this.target});
final GeoPoint? me;
final GeoPoint? pickup;
final GeoPoint? dropoff;
final RouteInfo? route;
final GeoPoint? target;
@override
bool operator ==(Object other) =>
other is _MapData &&
other.me == me &&
other.pickup == pickup &&
other.dropoff == dropoff &&
other.route == route &&
other.target == target;
@override
int get hashCode => Object.hash(me, pickup, dropoff, route, target);
}
/// شاشة السائق: خريطة + مفتاح الاتصال أعلى + ورقة تتبدّل بالمرحلة.
class DutyPage extends StatefulWidget {
const DutyPage({super.key});
@@ -42,9 +69,34 @@ class _DutyPageState extends State<DutyPage> {
children: [
// الخريطة معزولة عن بقية الحالة: نبضة موقع كل 25 متراً يجب ألّا
// تعيد بناء الورقة والمفتاح معها.
BlocSelector<DutyCubit, DutyState, GeoPoint?>(
selector: (s) => s.myLocation,
builder: (context, me) => RideMap(origin: me, cameraTarget: me),
//
// **مرفوعة عن القاع بالثلث** كما في تطبيق الراكب — الورقة لها
// مساحتها ولا تغطّي الخريطة.
Positioned(
top: 0,
left: 0,
right: 0,
bottom: MediaQuery.sizeOf(context).height * _sheetFraction,
child: BlocSelector<DutyCubit, DutyState, _MapData>(
selector: (s) => _MapData(
me: s.myLocation,
pickup: s.trip?.origin,
dropoff: s.trip?.destination,
route: s.navRoute,
target: s.navTarget,
),
// السائق كان يرى **موقعه وحده**: بلا نقطة الراكب ولا الوجهة
// ولا خط يقوده. الخريطة الآن تعرض ما تعرضه خريطة الراكب:
// نقطتَي الرحلة والمسار الحيّ إلى الهدف الحالي.
builder: (context, d) => RideMap(
origin: d.pickup ?? d.me,
destination: d.dropoff,
driver: d.pickup == null ? null : d.me,
route: d.route,
// الكاميرا تتبع الهدف حين يوجد، وإلا فموقع السائق.
cameraTarget: d.target ?? d.me,
),
),
),
SafeArea(
@@ -83,7 +135,7 @@ class _DutyPageState extends State<DutyPage> {
selector: (s) => s.creditBlocked,
builder: (context, blocked) => blocked
? StatusBanner(
message: context.l10n.errorGeneric,
message: context.l10n.creditBlocked,
tone: BannerTone.danger,
icon: Icons.account_balance_wallet_outlined,
)
@@ -132,13 +184,21 @@ class _Sheet extends StatelessWidget {
),
DutyPhase.offered => OfferSheet(offer: state.offer!),
DutyPhase.active =>
ActiveDutySheet(trip: state.trip!, busy: state.busy),
ActiveDutySheet(
trip: state.trip!,
busy: state.busy,
navRoute: state.navRoute,
),
};
if (state.phase == DutyPhase.offline) return const SizedBox.shrink();
return Container(
width: double.infinity,
// الحدّ الأدنى = المساحة المحجوزة تحت الخريطة، وإلا ظهر فراغ بينهما.
constraints: BoxConstraints(
minHeight: MediaQuery.sizeOf(context).height * _sheetFraction,
),
decoration: BoxDecoration(
color: context.colors.surface,
borderRadius: Radii.sheetTop,