first commit

This commit is contained in:
2026-08-11 13:16:33 +05:30
parent 18531bf46b
commit c8350563d9
388 changed files with 69656 additions and 0 deletions

137
lib/Models/login/login.dart Normal file
View File

@@ -0,0 +1,137 @@
class Login {
int? code;
String? message;
bool? status;
int? userid;
String? contactno;
String? devicetype;
int? configid;
String? deviceid;
String? userfcmtoken;
String? authname;
int? authmode;
int? roleid;
String? firstname;
String? lastname;
String? fullname;
String? password;
String? email;
String? address;
String? suburb;
String? city;
String? state;
String? postcode;
int? pin;
int? shiftid;
int? logid;
int? partnerid;
int? tenantid;
int? riderid;
int? pickupRadius;
int? locationid;
int? applocationid;
Login({
this.code,
this.message,
this.status,
this.userid,
this.contactno,
this.devicetype,
this.configid,
this.deviceid,
this.userfcmtoken,
this.authname,
this.authmode,
this.roleid,
this.firstname,
this.lastname,
this.fullname,
this.password,
this.email,
this.address,
this.suburb,
this.city,
this.state,
this.postcode,
this.pin,
this.shiftid,
this.logid,
this.partnerid,
this.tenantid,
this.riderid,
this.pickupRadius,
this.locationid,
this.applocationid,
});
/// Factory: builds a Login model from JSON (supports both "data" and "details")
factory Login.fromJson(Map<String, dynamic> json) {
// Safely extract nested data from either "data" or "details"
final Map<String, dynamic> nested =
(json['details'] ?? json['data'] ?? <String, dynamic>{});
final dynamic topAuthMode = json['authmode'];
final dynamic nestedAuthMode = nested['authmode'];
return Login(
code: json['code'] is int
? json['code']
: int.tryParse('${json['code']}'),
message: json['message']?.toString(),
status: json['status'] is bool ? json['status'] : json['status'] == 1,
userid: json['userid'] ?? nested['userid'],
contactno:
json['contactno']?.toString() ?? nested['contactno']?.toString(),
devicetype: json['devicetype']?.toString(),
configid: json['configid'] ?? nested['configid'],
deviceid: json['deviceid']?.toString(),
userfcmtoken:
json['userfcmtoken']?.toString() ??
nested['userfcmtoken']?.toString(),
authname: (json['authname'] ?? nested['authname'])?.toString(),
authmode: topAuthMode is int
? topAuthMode
: (nestedAuthMode is int
? nestedAuthMode
: int.tryParse('$topAuthMode')),
roleid: nested['roleid'],
firstname: nested['firstname']?.toString(),
lastname: nested['lastname']?.toString(),
fullname: nested['fullname']?.toString(),
password: nested['password']?.toString(),
email: nested['email']?.toString(),
address: nested['address']?.toString(),
suburb: nested['suburb']?.toString(),
city: nested['city']?.toString(),
state: nested['state']?.toString(),
postcode: nested['postcode']?.toString(),
pin: nested['pin'],
shiftid: nested['shiftid'],
logid: nested['logid'],
partnerid: nested['partnerid'],
tenantid: nested['tenantid'],
riderid: nested['riderid'],
pickupRadius: nested['pickupRadius'],
locationid: nested['locationid'] is int
? nested['locationid']
: int.tryParse('${nested['locationid'] ?? 0}'),
applocationid: nested['applocationid'] is int
? nested['applocationid']
: int.tryParse('${nested['applocationid'] ?? 0}'),
);
}
/// Convert this model to JSON for sending to the backend
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
if (contactno != null) data['contactno'] = contactno;
if (devicetype != null) data['devicetype'] = devicetype;
if (configid != null) data['configid'] = configid;
if (deviceid != null) data['deviceid'] = deviceid;
if (userfcmtoken != null) data['userfcmtoken'] = userfcmtoken;
if (pin != null) data['pin'] = pin;
return data;
}
}

View File

@@ -0,0 +1,287 @@
// Consolidated riders models
class RiderLog {
int? logid;
String? logdate;
int? userid;
int? partnerid;
int? shiftid;
double? shifthours;
String? login;
String? latitude;
double? workhours;
double? shorthours;
int? logstatus;
String? longitude;
double? breakhours;
int? onduty;
int? tenantid;
int? locationid;
int? applocationid;
String? userfcmtoken;
RiderLog({
this.logid,
this.logdate,
this.userid,
this.partnerid,
this.shiftid,
this.shifthours,
this.login,
this.latitude,
this.workhours,
this.shorthours,
this.logstatus,
this.longitude,
this.breakhours,
this.onduty,
this.tenantid,
this.locationid,
this.applocationid,
this.userfcmtoken,
});
factory RiderLog.fromJson(Map<String, dynamic> json) {
return RiderLog(
logid: json['logid'],
logdate: json['logdate'],
userid: json['userid'],
partnerid: json['partnerid'],
shiftid: json['shiftid'],
shifthours: (json['shifthours'] as num?)?.toDouble(),
login: json['login'],
latitude: json['latitude'],
workhours: (json['workhours'] as num?)?.toDouble(),
shorthours: (json['shorthours'] as num?)?.toDouble(),
logstatus: json['logstatus'],
longitude: json['longitude'],
breakhours: (json['breakhours'] as num?)?.toDouble(),
onduty: json['onduty'],
tenantid: json['tenantid'],
locationid: json['locationid'],
applocationid: json['applocationid'],
userfcmtoken: json['userfcmtoken'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['logid'] = logid;
data['logdate'] = logdate;
data['userid'] = userid;
data['partnerid'] = partnerid;
data['shiftid'] = shiftid;
data['shifthours'] = shifthours;
data['login'] = login;
data['latitude'] = latitude;
data['workhours'] = workhours;
data['shorthours'] = shorthours;
data['logstatus'] = logstatus;
data['longitude'] = longitude;
data['breakhours'] = breakhours;
data['onduty'] = onduty;
data['tenantid'] = tenantid;
data['locationid'] = locationid;
data['applocationid'] = applocationid;
data['userfcmtoken'] = userfcmtoken;
return data;
}
}
class RiderBreak {
int? breakid;
int? logid;
String? breakdate;
int? userid;
int? partnerid;
int? shiftid;
String? breakstart;
String? breakend;
double? breakhours;
String? latitude;
String? longitude;
RiderBreak({
this.breakid,
this.logid,
this.breakdate,
this.userid,
this.partnerid,
this.shiftid,
this.breakstart,
this.breakend,
this.breakhours,
this.latitude,
this.longitude,
});
factory RiderBreak.fromJson(Map<String, dynamic> json) {
return RiderBreak(
breakid: json['breakid'],
logid: json['logid'],
breakdate: json['breakdate'],
userid: json['userid'],
partnerid: json['partnerid'],
shiftid: json['shiftid'],
breakstart: json['breakstart'],
breakend: json['breakend'],
breakhours: (json['breakhours'] as num?)?.toDouble(),
latitude: json['latitude'],
longitude: json['longitude'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['breakid'] = breakid;
data['logid'] = logid;
data['breakdate'] = breakdate;
data['userid'] = userid;
data['partnerid'] = partnerid;
data['shiftid'] = shiftid;
data['breakstart'] = breakstart;
data['breakend'] = breakend;
data['breakhours'] = breakhours;
data['latitude'] = latitude;
data['longitude'] = longitude;
return data;
}
}
class RiderLogin {
int? logid;
int? userid;
int? partnerid;
int? shiftid;
String? logdate;
String? login;
double? shifthours;
String? latitude;
String? longitude;
int? onduty;
String? status; // "active" when there are active pickup, "idle" otherwise
String? username; // Rider display name for rider logs
String? contactno;
int? tenantid;
int? locationid;
int? applocationid;
String? userfcmtoken;
RiderLogin({
this.logid,
this.userid,
this.partnerid,
this.shiftid,
this.logdate,
this.login,
this.shifthours,
this.latitude,
this.longitude,
this.onduty,
this.status,
this.username,
this.contactno,
this.tenantid,
this.locationid,
this.applocationid,
this.userfcmtoken,
});
factory RiderLogin.fromJson(Map<String, dynamic> json) {
return RiderLogin(
logid: json['logid'],
userid: json['userid'],
partnerid: json['partnerid'],
shiftid: json['shiftid'],
logdate: json['logdate'],
login: json['Login'] ?? json['login'],
shifthours: (json['shifthours'] as num?)?.toDouble(),
latitude: json['latitude'],
longitude: json['longitude'],
onduty: json['onduty'],
status: json['status'],
username: json['username'],
contactno: json['contactno'],
tenantid: json['tenantid'],
locationid: json['locationid'],
applocationid: json['applocationid'],
userfcmtoken: json['userfcmtoken'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['logid'] = logid;
data['userid'] = userid;
data['partnerid'] = partnerid;
data['shiftid'] = shiftid;
data['logdate'] = logdate;
data['Login'] = login;
data['shifthours'] = shifthours;
data['latitude'] = latitude;
data['longitude'] = longitude;
if (onduty != null) data['onduty'] = onduty;
if (status != null) data['status'] = status;
if (username != null && username!.trim().isNotEmpty) {
data['username'] = username;
}
if (contactno != null) {
data['contactno'] = contactno;
}
data['tenantid'] = tenantid;
data['locationid'] = locationid;
data['applocationid'] = applocationid;
data['userfcmtoken'] = userfcmtoken;
return data;
}
}
class RiderUpdate {
int? userid;
int? logstatus;
String? logout;
double? workhours;
double? shorthours;
String? latitude;
String? longitude;
int? onduty;
RiderUpdate({
this.userid,
this.logstatus,
this.logout,
this.workhours,
this.shorthours,
this.latitude,
this.longitude,
this.onduty,
});
factory RiderUpdate.fromJson(Map<String, dynamic> json) {
return RiderUpdate(
userid: json['userid'],
logstatus: json['logstatus'],
logout: json['Logout'] ?? json['logout'],
workhours: (json['workhours'] as num?)?.toDouble(),
shorthours: (json['shorthours'] as num?)?.toDouble(),
latitude: json['latitude'],
longitude: json['longitude'],
onduty: json['onduty'],
);
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['userid'] = userid;
data['logstatus'] = logstatus;
data['Logout'] = logout;
data['workhours'] = workhours;
data['shorthours'] = shorthours;
data['latitude'] = latitude;
data['longitude'] = longitude;
if (onduty != null) data['onduty'] = onduty;
return data;
}
}

113
lib/Models/stop_status.dart Normal file
View File

@@ -0,0 +1,113 @@
/// Canonical lifecycle status for a booking/stop, parsed from the backend's
/// free-form `orderstatus` string.
///
/// Status used to be compared as raw string literals in ~90 places, with
/// case-sensitivity landmines (`'active'` vs `'ACTIVE'`) and variant spellings
/// (`'picked'` / `'picked up'` / `'pickuped'`). This normalizes all of that in
/// one place so filters agree everywhere.
///
/// NOTE: this is the *read* side. The status-change API still sends its own
/// protocol verbs (`ACCEPTED`/`ARRIVED`/`PICKED`/`REJECTED`/`CANCELLED`) — see
/// [OrderAction] for those canonical write values.
enum StopStatus {
newStop,
assigned,
accepted,
active,
arrived,
picked,
skipped,
cancelled,
rejected,
unknown,
}
/// Normalizes any raw `orderstatus` value (case-insensitive, trimmed, variant
/// spellings folded) into a [StopStatus].
StopStatus stopStatusFromRaw(dynamic raw) {
final s = (raw?.toString() ?? '').trim().toLowerCase();
switch (s) {
case 'new':
return StopStatus.newStop;
case 'assigned':
case 'miler_assigned':
case 'pending':
return StopStatus.assigned;
case 'accepted':
return StopStatus.accepted;
case 'active':
return StopStatus.active;
case 'arrived':
return StopStatus.arrived;
case 'picked':
case 'picked up':
case 'pickuped':
case 'pickedup':
return StopStatus.picked;
case 'skipped':
return StopStatus.skipped;
case 'cancelled':
case 'canceled':
return StopStatus.cancelled;
case 'rejected':
return StopStatus.rejected;
default:
return StopStatus.unknown;
}
}
/// Parse straight from a booking map's `orderstatus`.
StopStatus stopStatusOf(Map<String, dynamic> booking) =>
stopStatusFromRaw(booking['orderstatus']);
extension StopStatusX on StopStatus {
bool get isPicked => this == StopStatus.picked;
bool get isCancelled => this == StopStatus.cancelled;
bool get isSkipped => this == StopStatus.skipped;
bool get isActive => this == StopStatus.active;
bool get isRejected => this == StopStatus.rejected;
/// A completed pickup — picked up or cancelled. (Matches the long-standing
/// `!= 'picked' && != 'picked up' && != 'cancelled'` filter used to build the
/// "next stops" and remaining-pickups lists.)
bool get isFinishedPickup =>
this == StopStatus.picked || this == StopStatus.cancelled;
/// Still awaiting the rider's acceptance — belongs on Home, not Bookings.
bool get isPending =>
this == StopStatus.newStop || this == StopStatus.assigned;
/// What this state is *called*, in the rider's words.
///
/// The status vocabulary had been re-invented per widget: the live banner had
/// its own switch over raw `orderstatus` strings returning "At pickup" and
/// "In progress", the trip card wrote 'Accepted' as a literal, and the two
/// disagreed about the same backend state. A rider moving between Home, the
/// banner and Bookings was reading three vocabularies for one lifecycle and
/// re-learning the app at each stop.
///
/// One list, here, next to the parser that produces the states — so a new
/// status cannot be added without someone deciding what to call it.
String get label => switch (this) {
StopStatus.newStop => 'New',
StopStatus.assigned => 'Assigned',
StopStatus.accepted => 'Accepted',
StopStatus.active => 'In progress',
StopStatus.arrived => 'At the stop',
StopStatus.picked => 'Completed',
StopStatus.skipped => 'Skipped',
StopStatus.cancelled => 'Cancelled',
StopStatus.rejected => 'Rejected',
StopStatus.unknown => 'Active',
};
}
/// Canonical protocol verbs sent to the status-change API (the *write* side).
class OrderAction {
static const String accept = 'ACCEPT';
static const String accepted = 'ACCEPTED';
static const String arrived = 'ARRIVED';
static const String picked = 'PICKED';
static const String rejected = 'REJECTED';
static const String cancelled = 'CANCELLED';
}

View File

@@ -0,0 +1,25 @@
class PickupStats {
final int today;
final int week;
final int month;
final int total;
final int cancelled;
PickupStats({
required this.today,
required this.week,
required this.month,
required this.total,
required this.cancelled,
});
factory PickupStats.fromJson(Map<String, dynamic> json) {
return PickupStats(
today: json['today'] ?? 0,
week: json['week'] ?? 0,
month: json['month'] ?? 0,
total: json['total'] ?? 0,
cancelled: json['cancelled'] ?? 0,
);
}
}

View File

@@ -0,0 +1,44 @@
class RiderWeeklyKms {
final String day;
final double kms;
RiderWeeklyKms({required this.day, required this.kms});
factory RiderWeeklyKms.fromJson(Map<String, dynamic> json) {
return RiderWeeklyKms(
day: json['day'] ?? '',
kms: (json['kms'] ?? 0).toDouble(),
);
}
}
class RiderWeeklyKmsResponse {
final bool status;
final int code;
final String message;
final double totalKms;
final double overallKms;
final List<RiderWeeklyKms> details;
RiderWeeklyKmsResponse({
required this.status,
required this.code,
required this.message,
required this.totalKms,
required this.overallKms,
required this.details,
});
factory RiderWeeklyKmsResponse.fromJson(Map<String, dynamic> json) {
return RiderWeeklyKmsResponse(
status: json['status'] ?? false,
code: json['code'] ?? 0,
message: json['message'] ?? '',
totalKms: (json['total_kms'] ?? 0).toDouble(),
overallKms: (json['overall_kms'] ?? 0).toDouble(),
details: (json['details'] as List<dynamic>? ?? [])
.map((e) => RiderWeeklyKms.fromJson(e))
.toList(),
);
}
}

View File

@@ -0,0 +1,37 @@
class SupportTicketModel {
final int ridersupportid;
final int userid;
final String category;
final String priority;
final String subject;
final String issue;
final String? image;
final DateTime created;
final DateTime updated;
SupportTicketModel({
required this.ridersupportid,
required this.userid,
required this.category,
required this.priority,
required this.subject,
required this.issue,
this.image,
required this.created,
required this.updated,
});
factory SupportTicketModel.fromJson(Map<String, dynamic> json) {
return SupportTicketModel(
ridersupportid: json['ridersupportid'] as int,
userid: json['userid'] as int,
category: json['category'] as String,
priority: json['priority'] as String,
subject: json['subject'] as String,
issue: json['issue'] as String,
image: json['image'] as String?,
created: DateTime.parse(json['created'] as String),
updated: DateTime.parse(json['updated'] as String),
);
}
}