feat: implement core architecture, design system, localization, and trip features for both driver and rider apps.

This commit is contained in:
Hamza-Ayed
2026-07-19 16:21:58 +03:00
parent 959e2fa758
commit c4dfeb4c6f
207 changed files with 14017 additions and 5567 deletions
@@ -0,0 +1,33 @@
import 'package:equatable/equatable.dart';
/// نقطة توقف أثناء الرحلة.
class StopModel extends Equatable {
final double lat;
final double lng;
final String? label;
final String? address;
const StopModel({
required this.lat,
required this.lng,
this.label,
this.address,
});
factory StopModel.fromJson(Map<String, dynamic> j) => StopModel(
lat: (j['lat'] as num).toDouble(),
lng: (j['lng'] as num).toDouble(),
label: j['label'] as String?,
address: j['address'] as String?,
);
Map<String, dynamic> toJson() => {
'lat': lat,
'lng': lng,
if (label != null) 'label': label,
if (address != null) 'address': address,
};
@override
List<Object?> get props => [lat, lng, label, address];
}
@@ -0,0 +1,121 @@
import 'package:equatable/equatable.dart';
/// حالة الرحلة — تُرتيب حسب docs/03 §7.
enum TripStatus {
requested,
accepted,
arriving,
arrived,
inProgress,
completed,
cancelled,
}
/// نموذج الرحلة المُنشأة من trips endpoint.
class TripModel extends Equatable {
final String id;
final String status;
final String clientId;
final double pickupLat;
final double pickupLng;
final String? pickupAddress;
final double dropoffLat;
final double dropoffLng;
final String? dropoffAddress;
final String vehicleClass;
final num? fare;
final String? currency;
final String? paymentMethod;
final String? couponCode;
final String? driverId;
final String? driverName;
final String? driverPhone;
final double? driverLat;
final double? driverLng;
final String? vehicleMake;
final String? vehicleModel;
final String? vehicleColor;
final String? plateNumber;
final DateTime? createdAt;
final DateTime? updatedAt;
const TripModel({
required this.id,
required this.status,
required this.clientId,
required this.pickupLat,
required this.pickupLng,
this.pickupAddress,
required this.dropoffLat,
required this.dropoffLng,
this.dropoffAddress,
required this.vehicleClass,
this.fare,
this.currency,
this.paymentMethod,
this.couponCode,
this.driverId,
this.driverName,
this.driverPhone,
this.driverLat,
this.driverLng,
this.vehicleMake,
this.vehicleModel,
this.vehicleColor,
this.plateNumber,
this.createdAt,
this.updatedAt,
});
factory TripModel.fromJson(Map<String, dynamic> j) => TripModel(
id: j['id'] as String,
status: j['status'] as String,
clientId: (j['clientId'] ?? '') as String,
pickupLat: (j['pickup']?['lat'] ?? j['pickupLat'] ?? 0).toDouble(),
pickupLng: (j['pickup']?['lng'] ?? j['pickupLng'] ?? 0).toDouble(),
pickupAddress: (j['pickup']?['address'] ?? j['pickupAddress']) as String?,
dropoffLat: (j['dropoff']?['lat'] ?? j['dropoffLat'] ?? 0).toDouble(),
dropoffLng: (j['dropoff']?['lng'] ?? j['dropoffLng'] ?? 0).toDouble(),
dropoffAddress: (j['dropoff']?['address'] ?? j['dropoffAddress']) as String?,
vehicleClass: (j['vehicleClass'] ?? '') as String,
fare: (j['fare'] as num?),
currency: j['currency'] as String?,
paymentMethod: j['paymentMethod'] as String?,
couponCode: j['couponCode'] as String?,
driverId: j['driverId'] as String?,
driverName: j['driverName'] as String?,
driverPhone: j['driverPhone'] as String?,
driverLat: (j['driverLat'] as num?)?.toDouble(),
driverLng: (j['driverLng'] as num?)?.toDouble(),
vehicleMake: j['vehicleMake'] as String?,
vehicleModel: j['vehicleModel'] as String?,
vehicleColor: j['vehicleColor'] as String?,
plateNumber: j['plateNumber'] as String?,
createdAt: j['createdAt'] != null ? DateTime.tryParse(j['createdAt'] as String) : null,
updatedAt: j['updatedAt'] != null ? DateTime.tryParse(j['updatedAt'] as String) : null,
);
TripStatus get parsedStatus {
switch (status) {
case 'requested':
return TripStatus.requested;
case 'accepted':
return TripStatus.accepted;
case 'arriving':
return TripStatus.arriving;
case 'arrived':
return TripStatus.arrived;
case 'in_progress':
return TripStatus.inProgress;
case 'completed':
return TripStatus.completed;
case 'cancelled':
return TripStatus.cancelled;
default:
return TripStatus.requested;
}
}
@override
List<Object?> get props => [id, status, clientId, vehicleClass];
}