feat: add UTC parsing utilities and update date handling across entities
- Introduced `utc_parser.dart` with functions to convert UTC timestamps to local time. - Updated date parsing in various entities to use the new utility functions for consistency. - Refactored date handling in `BenefitHistory`, `Business`, `AttendanceStatus`, `AssignedWorker`, `TimeRange`, `Invoice`, `PaymentChartPoint`, `StaffPayment`, `TimeCardEntry`, `OrderItem`, `OrderPreview`, `RecentOrder`, `StaffRating`, `CoverageDayPoint`, `ForecastWeek`, `NoShowIncident`, `SpendDataPoint`, `AssignedShift`, `CancelledShift`, `CompletedShift`, `OpenShift`, `PendingAssignment`, `Shift`, `ShiftDetail`, `TodayShift`, `BusinessMembership`, and `Staff`. - Updated `ReorderWidget` and `OrderEditSheet` to handle date formatting correctly.
This commit is contained in:
@@ -4,4 +4,9 @@ class DateTimeUtils {
|
||||
static DateTime toDeviceTime(DateTime date) {
|
||||
return date.toLocal();
|
||||
}
|
||||
|
||||
/// Converts a local [DateTime] back to UTC for API payloads.
|
||||
static String toUtcIso(DateTime local) {
|
||||
return local.toUtc().toIso8601String();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,9 @@ export 'src/entities/enums/staff_skill.dart';
|
||||
export 'src/entities/enums/staff_status.dart';
|
||||
export 'src/entities/enums/user_role.dart';
|
||||
|
||||
// Utils
|
||||
export 'src/core/utils/utc_parser.dart';
|
||||
|
||||
// Core
|
||||
export 'src/core/services/api_services/api_endpoint.dart';
|
||||
export 'src/core/services/api_services/api_response.dart';
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
/// Parses a UTC ISO 8601 timestamp and converts to local device time.
|
||||
DateTime parseUtcToLocal(String value) => DateTime.parse(value).toLocal();
|
||||
|
||||
/// Parses a nullable UTC ISO 8601 timestamp. Returns null if input is null.
|
||||
DateTime? tryParseUtcToLocal(String? value) =>
|
||||
value != null ? DateTime.parse(value).toLocal() : null;
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/benefit_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A historical record of a staff benefit accrual period.
|
||||
///
|
||||
/// Returned by `GET /staff/profile/benefits/history`.
|
||||
@@ -28,10 +30,8 @@ class BenefitHistory extends Equatable {
|
||||
benefitType: json['benefitType'] as String,
|
||||
title: json['title'] as String,
|
||||
status: BenefitStatus.fromJson(json['status'] as String?),
|
||||
effectiveAt: DateTime.parse(json['effectiveAt'] as String),
|
||||
endedAt: json['endedAt'] != null
|
||||
? DateTime.parse(json['endedAt'] as String)
|
||||
: null,
|
||||
effectiveAt: parseUtcToLocal(json['effectiveAt'] as String),
|
||||
endedAt: tryParseUtcToLocal(json['endedAt'] as String?),
|
||||
trackedHours: (json['trackedHours'] as num).toInt(),
|
||||
targetHours: (json['targetHours'] as num).toInt(),
|
||||
notes: json['notes'] as String?,
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/business_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A client company registered on the platform.
|
||||
///
|
||||
/// Maps to the V2 `businesses` table.
|
||||
@@ -35,12 +37,8 @@ class Business extends Equatable {
|
||||
metadata: json['metadata'] is Map
|
||||
? Map<String, dynamic>.from(json['metadata'] as Map<dynamic, dynamic>)
|
||||
: const <String, dynamic>{},
|
||||
createdAt: json['createdAt'] != null
|
||||
? DateTime.parse(json['createdAt'] as String)
|
||||
: null,
|
||||
updatedAt: json['updatedAt'] != null
|
||||
? DateTime.parse(json['updatedAt'] as String)
|
||||
: null,
|
||||
createdAt: tryParseUtcToLocal(json['createdAt'] as String?),
|
||||
updatedAt: tryParseUtcToLocal(json['updatedAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/attendance_status_type.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Current clock-in / attendance status of the staff member.
|
||||
///
|
||||
/// Returned by `GET /staff/clock-in/status`. When no open session exists
|
||||
@@ -20,9 +22,7 @@ class AttendanceStatus extends Equatable {
|
||||
activeShiftId: json['activeShiftId'] as String?,
|
||||
attendanceStatus:
|
||||
AttendanceStatusType.fromJson(json['attendanceStatus'] as String?),
|
||||
clockInAt: json['clockInAt'] != null
|
||||
? DateTime.parse(json['clockInAt'] as String)
|
||||
: null,
|
||||
clockInAt: tryParseUtcToLocal(json['clockInAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/assignment_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A worker assigned to a coverage shift.
|
||||
///
|
||||
/// Nested within [ShiftWithWorkers].
|
||||
@@ -23,9 +25,7 @@ class AssignedWorker extends Equatable {
|
||||
staffId: json['staffId'] as String,
|
||||
fullName: json['fullName'] as String,
|
||||
status: AssignmentStatus.fromJson(json['status'] as String?),
|
||||
checkInAt: json['checkInAt'] != null
|
||||
? DateTime.parse(json['checkInAt'] as String)
|
||||
: null,
|
||||
checkInAt: tryParseUtcToLocal(json['checkInAt'] as String?),
|
||||
hasReview: json['hasReview'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A time range with start and end timestamps.
|
||||
///
|
||||
/// Used within [ShiftWithWorkers] for shift time windows.
|
||||
@@ -13,8 +15,8 @@ class TimeRange extends Equatable {
|
||||
/// Deserialises a [TimeRange] from a V2 API JSON map.
|
||||
factory TimeRange.fromJson(Map<String, dynamic> json) {
|
||||
return TimeRange(
|
||||
startsAt: DateTime.parse(json['startsAt'] as String),
|
||||
endsAt: DateTime.parse(json['endsAt'] as String),
|
||||
startsAt: parseUtcToLocal(json['startsAt'] as String),
|
||||
endsAt: parseUtcToLocal(json['endsAt'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/invoice_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// An invoice issued to a business for services rendered.
|
||||
///
|
||||
/// Returned by `GET /client/billing/invoices/*`.
|
||||
@@ -25,12 +27,8 @@ class Invoice extends Equatable {
|
||||
invoiceNumber: json['invoiceNumber'] as String,
|
||||
amountCents: (json['amountCents'] as num).toInt(),
|
||||
status: InvoiceStatus.fromJson(json['status'] as String?),
|
||||
dueDate: json['dueDate'] != null
|
||||
? DateTime.parse(json['dueDate'] as String)
|
||||
: null,
|
||||
paymentDate: json['paymentDate'] != null
|
||||
? DateTime.parse(json['paymentDate'] as String)
|
||||
: null,
|
||||
dueDate: tryParseUtcToLocal(json['dueDate'] as String?),
|
||||
paymentDate: tryParseUtcToLocal(json['paymentDate'] as String?),
|
||||
vendorId: json['vendorId'] as String?,
|
||||
vendorName: json['vendorName'] as String?,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A single data point in the staff payment chart.
|
||||
///
|
||||
/// Returned by `GET /staff/payments/chart`.
|
||||
@@ -13,7 +15,7 @@ class PaymentChartPoint extends Equatable {
|
||||
/// Deserialises a [PaymentChartPoint] from a V2 API JSON map.
|
||||
factory PaymentChartPoint.fromJson(Map<String, dynamic> json) {
|
||||
return PaymentChartPoint(
|
||||
bucket: DateTime.parse(json['bucket'] as String),
|
||||
bucket: parseUtcToLocal(json['bucket'] as String),
|
||||
amountCents: (json['amountCents'] as num).toInt(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/payment_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A single payment record for a staff member.
|
||||
///
|
||||
/// Returned by `GET /staff/payments/history`.
|
||||
@@ -23,7 +25,7 @@ class PaymentRecord extends Equatable {
|
||||
return PaymentRecord(
|
||||
paymentId: json['paymentId'] as String,
|
||||
amountCents: (json['amountCents'] as num).toInt(),
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
status: PaymentStatus.fromJson(json['status'] as String?),
|
||||
shiftName: json['shiftName'] as String?,
|
||||
location: json['location'] as String?,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A single time-card entry for a completed shift.
|
||||
///
|
||||
/// Returned by `GET /staff/profile/time-card`.
|
||||
@@ -19,15 +21,11 @@ class TimeCardEntry extends Equatable {
|
||||
/// Deserialises a [TimeCardEntry] from a V2 API JSON map.
|
||||
factory TimeCardEntry.fromJson(Map<String, dynamic> json) {
|
||||
return TimeCardEntry(
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
shiftName: json['shiftName'] as String,
|
||||
location: json['location'] as String?,
|
||||
clockInAt: json['clockInAt'] != null
|
||||
? DateTime.parse(json['clockInAt'] as String)
|
||||
: null,
|
||||
clockOutAt: json['clockOutAt'] != null
|
||||
? DateTime.parse(json['clockOutAt'] as String)
|
||||
: null,
|
||||
clockInAt: tryParseUtcToLocal(json['clockInAt'] as String?),
|
||||
clockOutAt: tryParseUtcToLocal(json['clockOutAt'] as String?),
|
||||
minutesWorked: (json['minutesWorked'] as num).toInt(),
|
||||
hourlyRateCents: json['hourlyRateCents'] != null
|
||||
? (json['hourlyRateCents'] as num).toInt()
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:equatable/equatable.dart';
|
||||
import 'package:krow_domain/src/entities/enums/order_type.dart';
|
||||
import 'package:krow_domain/src/entities/enums/shift_status.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
import 'assigned_worker_summary.dart';
|
||||
|
||||
/// A line item within an order, representing a role needed for a shift.
|
||||
@@ -42,9 +43,9 @@ class OrderItem extends Equatable {
|
||||
orderId: json['orderId'] as String,
|
||||
orderType: OrderType.fromJson(json['orderType'] as String?),
|
||||
roleName: json['roleName'] as String,
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
startsAt: DateTime.parse(json['startsAt'] as String),
|
||||
endsAt: DateTime.parse(json['endsAt'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
startsAt: parseUtcToLocal(json['startsAt'] as String),
|
||||
endsAt: parseUtcToLocal(json['endsAt'] as String),
|
||||
requiredWorkerCount: (json['requiredWorkerCount'] as num).toInt(),
|
||||
filledCount: (json['filledCount'] as num).toInt(),
|
||||
hourlyRateCents: (json['hourlyRateCents'] as num).toInt(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A preview of an order for reordering purposes.
|
||||
///
|
||||
/// Returned by `GET /client/orders/:id/reorder-preview`.
|
||||
@@ -31,12 +33,8 @@ class OrderPreview extends Equatable {
|
||||
orderId: json['orderId'] as String,
|
||||
title: json['title'] as String,
|
||||
description: json['description'] as String?,
|
||||
startsAt: json['startsAt'] != null
|
||||
? DateTime.parse(json['startsAt'] as String)
|
||||
: null,
|
||||
endsAt: json['endsAt'] != null
|
||||
? DateTime.parse(json['endsAt'] as String)
|
||||
: null,
|
||||
startsAt: tryParseUtcToLocal(json['startsAt'] as String?),
|
||||
endsAt: tryParseUtcToLocal(json['endsAt'] as String?),
|
||||
locationName: json['locationName'] as String?,
|
||||
locationAddress: json['locationAddress'] as String?,
|
||||
metadata: json['metadata'] is Map
|
||||
@@ -128,8 +126,8 @@ class OrderPreviewShift extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
shiftCode: json['shiftCode'] as String,
|
||||
title: json['title'] as String,
|
||||
startsAt: DateTime.parse(json['startsAt'] as String),
|
||||
endsAt: DateTime.parse(json['endsAt'] as String),
|
||||
startsAt: parseUtcToLocal(json['startsAt'] as String),
|
||||
endsAt: parseUtcToLocal(json['endsAt'] as String),
|
||||
roles: rolesList,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/entities/enums/order_type.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A recently completed order available for reordering.
|
||||
///
|
||||
/// Returned by `GET /client/reorders`.
|
||||
@@ -21,9 +23,7 @@ class RecentOrder extends Equatable {
|
||||
return RecentOrder(
|
||||
id: json['id'] as String,
|
||||
title: json['title'] as String,
|
||||
date: json['date'] != null
|
||||
? DateTime.parse(json['date'] as String)
|
||||
: null,
|
||||
date: tryParseUtcToLocal(json['date'] as String?),
|
||||
hubName: json['hubName'] as String?,
|
||||
positionCount: (json['positionCount'] as num).toInt(),
|
||||
orderType: OrderType.fromJson(json['orderType'] as String?),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Status of a staff certificate.
|
||||
enum CertificateStatus {
|
||||
/// Certificate uploaded, pending verification.
|
||||
@@ -45,8 +47,8 @@ class StaffCertificate extends Equatable {
|
||||
fileUri: json['fileUri'] as String?,
|
||||
issuer: json['issuer'] as String?,
|
||||
certificateNumber: json['certificateNumber'] as String?,
|
||||
issuedAt: json['issuedAt'] != null ? DateTime.parse(json['issuedAt'] as String) : null,
|
||||
expiresAt: json['expiresAt'] != null ? DateTime.parse(json['expiresAt'] as String) : null,
|
||||
issuedAt: tryParseUtcToLocal(json['issuedAt'] as String?),
|
||||
expiresAt: tryParseUtcToLocal(json['expiresAt'] as String?),
|
||||
status: _parseStatus(json['status'] as String?),
|
||||
verificationStatus: json['verificationStatus'] as String?,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Status of a profile document.
|
||||
enum ProfileDocumentStatus {
|
||||
/// Document has not been uploaded yet.
|
||||
@@ -59,7 +61,7 @@ class ProfileDocument extends Equatable {
|
||||
staffDocumentId: json['staffDocumentId'] as String?,
|
||||
fileUri: json['fileUri'] as String?,
|
||||
status: _parseStatus(json['status'] as String?),
|
||||
expiresAt: json['expiresAt'] != null ? DateTime.parse(json['expiresAt'] as String) : null,
|
||||
expiresAt: tryParseUtcToLocal(json['expiresAt'] as String?),
|
||||
metadata: (json['metadata'] as Map<String, dynamic>?) ?? const <String, dynamic>{},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// A review left for a staff member after an assignment.
|
||||
///
|
||||
/// Maps to the V2 `staff_reviews` table.
|
||||
@@ -35,9 +37,7 @@ class StaffRating extends Equatable {
|
||||
rating: (json['rating'] as num).toInt(),
|
||||
reviewText: json['reviewText'] as String?,
|
||||
tags: tagsList,
|
||||
createdAt: json['createdAt'] != null
|
||||
? DateTime.parse(json['createdAt'] as String)
|
||||
: null,
|
||||
createdAt: tryParseUtcToLocal(json['createdAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Coverage report with daily breakdown.
|
||||
///
|
||||
/// Returned by `GET /client/reports/coverage`.
|
||||
@@ -75,7 +77,7 @@ class CoverageDayPoint extends Equatable {
|
||||
/// Deserialises a [CoverageDayPoint] from a V2 API JSON map.
|
||||
factory CoverageDayPoint.fromJson(Map<String, dynamic> json) {
|
||||
return CoverageDayPoint(
|
||||
day: DateTime.parse(json['day'] as String),
|
||||
day: parseUtcToLocal(json['day'] as String),
|
||||
needed: (json['needed'] as num).toInt(),
|
||||
filled: (json['filled'] as num).toInt(),
|
||||
coveragePercentage: (json['coveragePercentage'] as num).toDouble(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Staffing and spend forecast report.
|
||||
///
|
||||
/// Returned by `GET /client/reports/forecast`.
|
||||
@@ -83,7 +85,7 @@ class ForecastWeek extends Equatable {
|
||||
/// Deserialises a [ForecastWeek] from a V2 API JSON map.
|
||||
factory ForecastWeek.fromJson(Map<String, dynamic> json) {
|
||||
return ForecastWeek(
|
||||
week: DateTime.parse(json['week'] as String),
|
||||
week: parseUtcToLocal(json['week'] as String),
|
||||
shiftCount: (json['shiftCount'] as num).toInt(),
|
||||
workerHours: (json['workerHours'] as num).toDouble(),
|
||||
forecastSpendCents: (json['forecastSpendCents'] as num).toInt(),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// No-show report with per-worker incident details.
|
||||
///
|
||||
/// Returned by `GET /client/reports/no-show`.
|
||||
@@ -143,7 +145,7 @@ class NoShowIncident extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
shiftTitle: json['shiftTitle'] as String,
|
||||
roleName: json['roleName'] as String,
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
import '../financial/spend_item.dart';
|
||||
|
||||
/// Spend report with total, chart data points, and category breakdown.
|
||||
@@ -71,7 +72,7 @@ class SpendDataPoint extends Equatable {
|
||||
/// Deserialises a [SpendDataPoint] from a V2 API JSON map.
|
||||
factory SpendDataPoint.fromJson(Map<String, dynamic> json) {
|
||||
return SpendDataPoint(
|
||||
bucket: DateTime.parse(json['bucket'] as String),
|
||||
bucket: parseUtcToLocal(json['bucket'] as String),
|
||||
amountCents: (json['amountCents'] as num).toInt(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/assignment_status.dart';
|
||||
import 'package:krow_domain/src/entities/enums/order_type.dart';
|
||||
|
||||
@@ -33,9 +34,9 @@ class AssignedShift extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
roleName: json['roleName'] as String,
|
||||
location: json['location'] as String? ?? '',
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
startTime: DateTime.parse(json['startTime'] as String),
|
||||
endTime: DateTime.parse(json['endTime'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
startTime: parseUtcToLocal(json['startTime'] as String),
|
||||
endTime: parseUtcToLocal(json['endTime'] as String),
|
||||
hourlyRateCents: json['hourlyRateCents'] as int? ?? 0,
|
||||
hourlyRate: (json['hourlyRate'] as num?)?.toDouble() ?? 0.0,
|
||||
totalRateCents: json['totalRateCents'] as int? ?? 0,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
|
||||
/// A shift whose assignment was cancelled.
|
||||
///
|
||||
/// Returned by `GET /staff/shifts/cancelled`. Shows past assignments
|
||||
@@ -22,7 +24,7 @@ class CancelledShift extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
title: json['title'] as String? ?? '',
|
||||
location: json['location'] as String? ?? '',
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
cancellationReason: json['cancellationReason'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/assignment_status.dart';
|
||||
import 'package:krow_domain/src/entities/enums/payment_status.dart';
|
||||
|
||||
/// A shift the staff member has completed.
|
||||
///
|
||||
@@ -34,12 +37,12 @@ class CompletedShift extends Equatable {
|
||||
title: json['title'] as String? ?? '',
|
||||
location: json['location'] as String? ?? '',
|
||||
clientName: json['clientName'] as String? ?? '',
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
startTime: json['startTime'] != null
|
||||
? DateTime.parse(json['startTime'] as String)
|
||||
? parseUtcToLocal(json['startTime'] as String)
|
||||
: DateTime.now(),
|
||||
endTime: json['endTime'] != null
|
||||
? DateTime.parse(json['endTime'] as String)
|
||||
? parseUtcToLocal(json['endTime'] as String)
|
||||
: DateTime.now(),
|
||||
minutesWorked: json['minutesWorked'] as int? ?? 0,
|
||||
hourlyRateCents: json['hourlyRateCents'] as int? ?? 0,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/order_type.dart';
|
||||
|
||||
/// An open shift available for the staff member to apply to.
|
||||
@@ -32,9 +33,9 @@ class OpenShift extends Equatable {
|
||||
roleName: json['roleName'] as String,
|
||||
clientName: json['clientName'] as String? ?? '',
|
||||
location: json['location'] as String? ?? '',
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
startTime: DateTime.parse(json['startTime'] as String),
|
||||
endTime: DateTime.parse(json['endTime'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
startTime: parseUtcToLocal(json['startTime'] as String),
|
||||
endTime: parseUtcToLocal(json['endTime'] as String),
|
||||
hourlyRateCents: json['hourlyRateCents'] as int? ?? 0,
|
||||
hourlyRate: (json['hourlyRate'] as num?)?.toDouble() ?? 0.0,
|
||||
orderType: OrderType.fromJson(json['orderType'] as String?),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
|
||||
/// An assignment awaiting the staff member's acceptance.
|
||||
///
|
||||
/// Returned by `GET /staff/shifts/pending`. These are assignments with
|
||||
@@ -24,10 +26,10 @@ class PendingAssignment extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
title: json['title'] as String? ?? '',
|
||||
roleName: json['roleName'] as String,
|
||||
startTime: DateTime.parse(json['startTime'] as String),
|
||||
endTime: DateTime.parse(json['endTime'] as String),
|
||||
startTime: parseUtcToLocal(json['startTime'] as String),
|
||||
endTime: parseUtcToLocal(json['endTime'] as String),
|
||||
location: json['location'] as String? ?? '',
|
||||
responseDeadline: DateTime.parse(json['responseDeadline'] as String),
|
||||
responseDeadline: parseUtcToLocal(json['responseDeadline'] as String),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/shift_status.dart';
|
||||
|
||||
/// Core shift entity aligned with the V2 `shifts` table.
|
||||
@@ -48,10 +49,10 @@ class Shift extends Equatable {
|
||||
clientName ??
|
||||
'',
|
||||
status: ShiftStatus.fromJson(json['status'] as String?),
|
||||
startsAt: DateTime.parse(
|
||||
startsAt: parseUtcToLocal(
|
||||
json['startsAt'] as String? ?? json['startTime'] as String,
|
||||
),
|
||||
endsAt: DateTime.parse(
|
||||
endsAt: parseUtcToLocal(
|
||||
json['endsAt'] as String? ?? json['endTime'] as String,
|
||||
),
|
||||
timezone: json['timezone'] as String? ?? 'UTC',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/application_status.dart';
|
||||
import 'package:krow_domain/src/entities/enums/assignment_status.dart';
|
||||
import 'package:krow_domain/src/entities/enums/order_type.dart';
|
||||
@@ -53,9 +54,9 @@ class ShiftDetail extends Equatable {
|
||||
clientName: json['clientName'] as String? ?? '',
|
||||
latitude: Shift.parseDouble(json['latitude']),
|
||||
longitude: Shift.parseDouble(json['longitude']),
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
startTime: DateTime.parse(json['startTime'] as String),
|
||||
endTime: DateTime.parse(json['endTime'] as String),
|
||||
date: parseUtcToLocal(json['date'] as String),
|
||||
startTime: parseUtcToLocal(json['startTime'] as String),
|
||||
endTime: parseUtcToLocal(json['endTime'] as String),
|
||||
roleId: json['roleId'] as String,
|
||||
roleName: json['roleName'] as String,
|
||||
hourlyRateCents: json['hourlyRateCents'] as int? ?? 0,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/src/core/utils/utc_parser.dart';
|
||||
import 'package:krow_domain/src/entities/enums/attendance_status_type.dart';
|
||||
|
||||
/// A shift assigned to the staff member for today.
|
||||
@@ -33,8 +34,8 @@ class TodayShift extends Equatable {
|
||||
shiftId: json['shiftId'] as String,
|
||||
roleName: json['roleName'] as String,
|
||||
location: json['location'] as String? ?? '',
|
||||
startTime: DateTime.parse(json['startTime'] as String),
|
||||
endTime: DateTime.parse(json['endTime'] as String),
|
||||
startTime: parseUtcToLocal(json['startTime'] as String),
|
||||
endTime: parseUtcToLocal(json['endTime'] as String),
|
||||
attendanceStatus: AttendanceStatusType.fromJson(json['attendanceStatus'] as String?),
|
||||
clientName: json['clientName'] as String? ?? '',
|
||||
hourlyRateCents: json['hourlyRateCents'] as int? ?? 0,
|
||||
@@ -42,9 +43,7 @@ class TodayShift extends Equatable {
|
||||
totalRateCents: json['totalRateCents'] as int? ?? 0,
|
||||
totalRate: (json['totalRate'] as num?)?.toDouble() ?? 0.0,
|
||||
locationAddress: json['locationAddress'] as String?,
|
||||
clockInAt: json['clockInAt'] != null
|
||||
? DateTime.parse(json['clockInAt'] as String)
|
||||
: null,
|
||||
clockInAt: tryParseUtcToLocal(json['clockInAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Membership status within a business.
|
||||
enum BusinessMembershipStatus {
|
||||
/// The user has been invited but has not accepted.
|
||||
@@ -63,8 +65,8 @@ class BusinessMembership extends Equatable {
|
||||
businessName: json['businessName'] as String?,
|
||||
businessSlug: json['businessSlug'] as String?,
|
||||
metadata: (json['metadata'] as Map<String, dynamic>?) ?? const <String, dynamic>{},
|
||||
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt'] as String) : null,
|
||||
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt'] as String) : null,
|
||||
createdAt: tryParseUtcToLocal(json['createdAt'] as String?),
|
||||
updatedAt: tryParseUtcToLocal(json['updatedAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import 'package:equatable/equatable.dart';
|
||||
|
||||
import 'package:krow_domain/krow_domain.dart' show OnboardingStatus, StaffStatus;
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Represents a worker profile in the KROW platform.
|
||||
///
|
||||
/// Maps to the V2 `staffs` table. Linked to a [User] via [userId].
|
||||
@@ -47,8 +49,8 @@ class Staff extends Equatable {
|
||||
workforceId: json['workforceId'] as String?,
|
||||
vendorId: json['vendorId'] as String?,
|
||||
workforceNumber: json['workforceNumber'] as String?,
|
||||
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt'] as String) : null,
|
||||
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt'] as String) : null,
|
||||
createdAt: tryParseUtcToLocal(json['createdAt'] as String?),
|
||||
updatedAt: tryParseUtcToLocal(json['updatedAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
import '../../core/utils/utc_parser.dart';
|
||||
|
||||
/// Account status for a platform user.
|
||||
enum UserStatus {
|
||||
/// User is active and can sign in.
|
||||
@@ -37,8 +39,8 @@ class User extends Equatable {
|
||||
phone: json['phone'] as String?,
|
||||
status: _parseUserStatus(json['status'] as String?),
|
||||
metadata: (json['metadata'] as Map<String, dynamic>?) ?? const <String, dynamic>{},
|
||||
createdAt: json['createdAt'] != null ? DateTime.parse(json['createdAt'] as String) : null,
|
||||
updatedAt: json['updatedAt'] != null ? DateTime.parse(json['updatedAt'] as String) : null,
|
||||
createdAt: tryParseUtcToLocal(json['createdAt'] as String?),
|
||||
updatedAt: tryParseUtcToLocal(json['updatedAt'] as String?),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class ReorderWidget extends StatelessWidget {
|
||||
borderRadius: UiConstants.radiusLg,
|
||||
),
|
||||
child: const Icon(
|
||||
UiIcons.building,
|
||||
UiIcons.briefcase,
|
||||
size: 16,
|
||||
color: UiColors.primary,
|
||||
),
|
||||
@@ -104,18 +104,6 @@ class ReorderWidget extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
// Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.end,
|
||||
// children: <Widget>[
|
||||
// // ASSUMPTION: No i18n key for 'positions' under
|
||||
// // reorder section — carrying forward existing
|
||||
// // hardcoded string pattern for this migration.
|
||||
// Text(
|
||||
// '${order.positionCount} positions',
|
||||
// style: UiTypography.footnote2r.textSecondary,
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: UiConstants.space3),
|
||||
@@ -130,7 +118,7 @@ class ReorderWidget extends StatelessWidget {
|
||||
),
|
||||
const SizedBox(width: UiConstants.space2),
|
||||
_Badge(
|
||||
icon: UiIcons.building,
|
||||
icon: UiIcons.users,
|
||||
text: '${order.positionCount}',
|
||||
color: UiColors.textSecondary,
|
||||
bg: UiColors.buttonSecondaryStill,
|
||||
|
||||
@@ -48,13 +48,13 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
||||
_orderNameController = TextEditingController(text: widget.order.roleName);
|
||||
|
||||
final String startHH =
|
||||
widget.order.startsAt.toLocal().hour.toString().padLeft(2, '0');
|
||||
widget.order.startsAt.hour.toString().padLeft(2, '0');
|
||||
final String startMM =
|
||||
widget.order.startsAt.toLocal().minute.toString().padLeft(2, '0');
|
||||
widget.order.startsAt.minute.toString().padLeft(2, '0');
|
||||
final String endHH =
|
||||
widget.order.endsAt.toLocal().hour.toString().padLeft(2, '0');
|
||||
widget.order.endsAt.hour.toString().padLeft(2, '0');
|
||||
final String endMM =
|
||||
widget.order.endsAt.toLocal().minute.toString().padLeft(2, '0');
|
||||
widget.order.endsAt.minute.toString().padLeft(2, '0');
|
||||
|
||||
_positions = <Map<String, dynamic>>[
|
||||
<String, dynamic>{
|
||||
|
||||
@@ -77,9 +77,8 @@ class _ViewOrderCardState extends State<ViewOrderCard> {
|
||||
|
||||
/// Formats a [DateTime] to a display time string (e.g. "9:00 AM").
|
||||
String _formatTime({required DateTime dateTime}) {
|
||||
final DateTime local = dateTime.toLocal();
|
||||
final int hour24 = local.hour;
|
||||
final int minute = local.minute;
|
||||
final int hour24 = dateTime.hour;
|
||||
final int minute = dateTime.minute;
|
||||
final String ampm = hour24 >= 12 ? 'PM' : 'AM';
|
||||
int hour = hour24 % 12;
|
||||
if (hour == 0) hour = 12;
|
||||
|
||||
Reference in New Issue
Block a user