diff --git a/apps/mobile/packages/domain/lib/src/entities/home/reorder_item.dart b/apps/mobile/packages/domain/lib/src/entities/home/reorder_item.dart index 7d9e22a3..d13a80bd 100644 --- a/apps/mobile/packages/domain/lib/src/entities/home/reorder_item.dart +++ b/apps/mobile/packages/domain/lib/src/entities/home/reorder_item.dart @@ -1,46 +1,51 @@ import 'package:equatable/equatable.dart'; -/// Summary of a completed shift role used for reorder suggestions. +/// Summary of a completed order used for reorder suggestions. class ReorderItem extends Equatable { const ReorderItem({ required this.orderId, required this.title, required this.location, - required this.hourlyRate, - required this.hours, + required this.totalCost, required this.workers, required this.type, + this.hourlyRate = 0, + this.hours = 0, }); - /// Parent order id for the completed shift. + /// Unique identifier of the order. final String orderId; - /// Display title (role + shift title). + /// Display title of the order (e.g., event name or first shift title). final String title; - /// Location from the shift. + /// Location of the order (e.g., first shift location). final String location; - /// Hourly rate from the role. - final double hourlyRate; + /// Total calculated cost for the order. + final double totalCost; - /// Total hours for the shift role. - final double hours; - - /// Worker count for the shift role. + /// Total number of workers required for the order. final int workers; - /// Order type (e.g., ONE_TIME). + /// The type of order (e.g., ONE_TIME, RECURRING). final String type; + /// Average or primary hourly rate (optional, for display). + final double hourlyRate; + + /// Total hours for the order (optional, for display). + final double hours; + @override List get props => [ orderId, title, location, - hourlyRate, - hours, + totalCost, workers, type, + hourlyRate, + hours, ]; } diff --git a/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart b/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart index 2b335d19..9d594a93 100644 --- a/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart +++ b/apps/mobile/packages/features/client/home/lib/src/data/repositories_impl/home_repository_impl.dart @@ -148,31 +148,59 @@ class HomeRepositoryImpl implements HomeRepositoryInterface { final DateTime start = now.subtract(const Duration(days: 30)); final QueryResult< - dc.ListShiftRolesByBusinessDateRangeCompletedOrdersData, - dc.ListShiftRolesByBusinessDateRangeCompletedOrdersVariables + dc.ListCompletedOrdersByBusinessAndDateRangeData, + dc.ListCompletedOrdersByBusinessAndDateRangeVariables > result = await _service.connector - .listShiftRolesByBusinessDateRangeCompletedOrders( + .listCompletedOrdersByBusinessAndDateRange( businessId: businessId, start: _service.toTimestamp(start), end: _service.toTimestamp(now), ) .execute(); - return result.data.shiftRoles.map(( - dc.ListShiftRolesByBusinessDateRangeCompletedOrdersShiftRoles shiftRole, + return result.data.orders.map(( + dc.ListCompletedOrdersByBusinessAndDateRangeOrders order, ) { - final String location = - shiftRole.shift.location ?? shiftRole.shift.locationAddress ?? ''; - final String type = shiftRole.shift.order.orderType.stringValue; + final String title = + order.eventName ?? + (order.shifts_on_order.isNotEmpty + ? order.shifts_on_order[0].title + : 'Order'); + + final String location = order.shifts_on_order.isNotEmpty + ? (order.shifts_on_order[0].location ?? + order.shifts_on_order[0].locationAddress ?? + '') + : ''; + + int totalWorkers = 0; + double totalHours = 0; + double totalRate = 0; + int roleCount = 0; + + for (final dc.ListCompletedOrdersByBusinessAndDateRangeOrdersShiftsOnOrder + shift + in order.shifts_on_order) { + for (final dc.ListCompletedOrdersByBusinessAndDateRangeOrdersShiftsOnOrderShiftRolesOnShift + role + in shift.shiftRoles_on_shift) { + totalWorkers += role.count; + totalHours += role.hours ?? 0; + totalRate += role.role.costPerHour; + roleCount++; + } + } + return ReorderItem( - orderId: shiftRole.shift.order.id, - title: '${shiftRole.role.name} - ${shiftRole.shift.title}', + orderId: order.id, + title: title, location: location, - hourlyRate: shiftRole.role.costPerHour, - hours: shiftRole.hours ?? 0, - workers: shiftRole.count, - type: type, + totalCost: order.total ?? 0.0, + workers: totalWorkers, + type: order.orderType.stringValue, + hourlyRate: roleCount > 0 ? totalRate / roleCount : 0.0, + hours: totalHours, ); }).toList(); }); diff --git a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/reorder_widget.dart b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/reorder_widget.dart index b3544e48..9f67d4f1 100644 --- a/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/reorder_widget.dart +++ b/apps/mobile/packages/features/client/home/lib/src/presentation/widgets/reorder_widget.dart @@ -5,7 +5,6 @@ import 'package:krow_domain/krow_domain.dart'; /// A widget that allows clients to reorder recent shifts. class ReorderWidget extends StatelessWidget { - /// Creates a [ReorderWidget]. const ReorderWidget({ super.key, @@ -13,6 +12,7 @@ class ReorderWidget extends StatelessWidget { required this.onReorderPressed, this.subtitle, }); + /// Recent completed orders for reorder. final List orders; @@ -55,8 +55,7 @@ class ReorderWidget extends StatelessWidget { const SizedBox(width: UiConstants.space3), itemBuilder: (BuildContext context, int index) { final ReorderItem order = recentOrders[index]; - final double totalCost = - order.hourlyRate * order.hours * order.workers; + final double totalCost = order.totalCost; return Container( width: 260, @@ -163,6 +162,7 @@ class ReorderWidget extends StatelessWidget { 'hours': order.hours, 'workers': order.workers, 'type': order.type, + 'totalCost': order.totalCost, }), ), ], @@ -177,7 +177,6 @@ class ReorderWidget extends StatelessWidget { } class _Badge extends StatelessWidget { - const _Badge({ required this.icon, required this.text, diff --git a/backend/dataconnect/connector/order/queries.gql b/backend/dataconnect/connector/order/queries.gql index c500c595..f3aad90b 100644 --- a/backend/dataconnect/connector/order/queries.gql +++ b/backend/dataconnect/connector/order/queries.gql @@ -433,3 +433,98 @@ query listOrdersByBusinessAndTeamHub( createdBy } } + +# ------------------------------------------------------------ +# GET COMPLETED ORDERS BY BUSINESS AND DATE RANGE +# ------------------------------------------------------------ +query listCompletedOrdersByBusinessAndDateRange( + $businessId: UUID! + $start: Timestamp! + $end: Timestamp! + $offset: Int + $limit: Int +) @auth(level: USER) { + orders( + where: { + businessId: { eq: $businessId } + status: { eq: COMPLETED } + date: { ge: $start, le: $end } + } + offset: $offset + limit: $limit + orderBy: { createdAt: DESC } + ) { + id + eventName + + vendorId + businessId + orderType + status + date + startDate + endDate + duration + lunchBreak + total + assignedStaff + requested + recurringDays + permanentDays + poReference + notes + createdAt + + business { + id + businessName + email + contactName + } + + vendor { + id + companyName + } + + teamHub { + address + placeId + hubName + } + + # Assigned shifts and their roles + shifts_on_order { + id + title + date + startTime + endTime + hours + cost + location + locationAddress + status + workersNeeded + filled + + shiftRoles_on_shift { + id + roleId + count + assigned + startTime + endTime + hours + totalValue + + role { + id + name + costPerHour + } + } + } + } +} +