feat: Implement order details retrieval for pre-filling new order forms for reordering.
This commit is contained in:
@@ -42,6 +42,7 @@ export 'src/entities/orders/permanent_order.dart';
|
||||
export 'src/entities/orders/permanent_order_position.dart';
|
||||
export 'src/entities/orders/order_type.dart';
|
||||
export 'src/entities/orders/order_item.dart';
|
||||
export 'src/entities/orders/reorder_data.dart';
|
||||
|
||||
// Skills & Certs
|
||||
export 'src/entities/skills/skill.dart';
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'one_time_order.dart';
|
||||
import 'order_type.dart';
|
||||
|
||||
/// Represents the full details of an order retrieved for reordering.
|
||||
class ReorderData extends Equatable {
|
||||
const ReorderData({
|
||||
required this.orderId,
|
||||
required this.orderType,
|
||||
required this.eventName,
|
||||
required this.vendorId,
|
||||
required this.hub,
|
||||
required this.positions,
|
||||
this.date,
|
||||
this.startDate,
|
||||
this.endDate,
|
||||
this.recurringDays = const <String>[],
|
||||
this.permanentDays = const <String>[],
|
||||
});
|
||||
|
||||
final String orderId;
|
||||
final OrderType orderType;
|
||||
final String eventName;
|
||||
final String? vendorId;
|
||||
final OneTimeOrderHubDetails hub;
|
||||
final List<ReorderPosition> positions;
|
||||
|
||||
// One-time specific
|
||||
final DateTime? date;
|
||||
|
||||
// Recurring/Permanent specific
|
||||
final DateTime? startDate;
|
||||
final DateTime? endDate;
|
||||
final List<String> recurringDays;
|
||||
final List<String> permanentDays;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
orderId,
|
||||
orderType,
|
||||
eventName,
|
||||
vendorId,
|
||||
hub,
|
||||
positions,
|
||||
date,
|
||||
startDate,
|
||||
endDate,
|
||||
recurringDays,
|
||||
permanentDays,
|
||||
];
|
||||
}
|
||||
|
||||
class ReorderPosition extends Equatable {
|
||||
const ReorderPosition({
|
||||
required this.roleId,
|
||||
required this.count,
|
||||
required this.startTime,
|
||||
required this.endTime,
|
||||
this.lunchBreak = 'NO_BREAK',
|
||||
});
|
||||
|
||||
final String roleId;
|
||||
final int count;
|
||||
final String startTime;
|
||||
final String endTime;
|
||||
final String lunchBreak;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
roleId,
|
||||
count,
|
||||
startTime,
|
||||
endTime,
|
||||
lunchBreak,
|
||||
];
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import 'domain/usecases/create_one_time_order_usecase.dart';
|
||||
import 'domain/usecases/create_permanent_order_usecase.dart';
|
||||
import 'domain/usecases/create_recurring_order_usecase.dart';
|
||||
import 'domain/usecases/create_rapid_order_usecase.dart';
|
||||
import 'domain/usecases/get_order_details_for_reorder_usecase.dart';
|
||||
import 'presentation/blocs/index.dart';
|
||||
import 'presentation/pages/create_order_page.dart';
|
||||
import 'presentation/pages/one_time_order_page.dart';
|
||||
@@ -27,13 +28,16 @@ class ClientCreateOrderModule extends Module {
|
||||
@override
|
||||
void binds(Injector i) {
|
||||
// Repositories
|
||||
i.addLazySingleton<ClientCreateOrderRepositoryInterface>(ClientCreateOrderRepositoryImpl.new);
|
||||
i.addLazySingleton<ClientCreateOrderRepositoryInterface>(
|
||||
ClientCreateOrderRepositoryImpl.new,
|
||||
);
|
||||
|
||||
// UseCases
|
||||
i.addLazySingleton(CreateOneTimeOrderUseCase.new);
|
||||
i.addLazySingleton(CreatePermanentOrderUseCase.new);
|
||||
i.addLazySingleton(CreateRecurringOrderUseCase.new);
|
||||
i.addLazySingleton(CreateRapidOrderUseCase.new);
|
||||
i.addLazySingleton(GetOrderDetailsForReorderUseCase.new);
|
||||
|
||||
// BLoCs
|
||||
i.add<RapidOrderBloc>(RapidOrderBloc.new);
|
||||
@@ -49,19 +53,31 @@ class ClientCreateOrderModule extends Module {
|
||||
child: (BuildContext context) => const ClientCreateOrderPage(),
|
||||
);
|
||||
r.child(
|
||||
ClientPaths.childRoute(ClientPaths.createOrder, ClientPaths.createOrderRapid),
|
||||
ClientPaths.childRoute(
|
||||
ClientPaths.createOrder,
|
||||
ClientPaths.createOrderRapid,
|
||||
),
|
||||
child: (BuildContext context) => const RapidOrderPage(),
|
||||
);
|
||||
r.child(
|
||||
ClientPaths.childRoute(ClientPaths.createOrder, ClientPaths.createOrderOneTime),
|
||||
ClientPaths.childRoute(
|
||||
ClientPaths.createOrder,
|
||||
ClientPaths.createOrderOneTime,
|
||||
),
|
||||
child: (BuildContext context) => const OneTimeOrderPage(),
|
||||
);
|
||||
r.child(
|
||||
ClientPaths.childRoute(ClientPaths.createOrder, ClientPaths.createOrderRecurring),
|
||||
ClientPaths.childRoute(
|
||||
ClientPaths.createOrder,
|
||||
ClientPaths.createOrderRecurring,
|
||||
),
|
||||
child: (BuildContext context) => const RecurringOrderPage(),
|
||||
);
|
||||
r.child(
|
||||
ClientPaths.childRoute(ClientPaths.createOrder, ClientPaths.createOrderPermanent),
|
||||
ClientPaths.childRoute(
|
||||
ClientPaths.createOrder,
|
||||
ClientPaths.createOrderPermanent,
|
||||
),
|
||||
child: (BuildContext context) => const PermanentOrderPage(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
import 'package:krow_domain/krow_domain.dart' as domain;
|
||||
@@ -11,10 +11,10 @@ import '../../domain/repositories/client_create_order_repository_interface.dart'
|
||||
///
|
||||
/// It follows the KROW Clean Architecture by keeping the data layer focused
|
||||
/// on delegation and data mapping, without business logic.
|
||||
class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInterface {
|
||||
ClientCreateOrderRepositoryImpl({
|
||||
required dc.DataConnectService service,
|
||||
}) : _service = service;
|
||||
class ClientCreateOrderRepositoryImpl
|
||||
implements ClientCreateOrderRepositoryInterface {
|
||||
ClientCreateOrderRepositoryImpl({required dc.DataConnectService service})
|
||||
: _service = service;
|
||||
|
||||
final dc.DataConnectService _service;
|
||||
|
||||
@@ -36,19 +36,19 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
order.date.month,
|
||||
order.date.day,
|
||||
);
|
||||
final fdc.Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final fdc.OperationResult<dc.CreateOrderData, dc.CreateOrderVariables> orderResult =
|
||||
await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.ONE_TIME,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.execute();
|
||||
final Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final OperationResult<dc.CreateOrderData, dc.CreateOrderVariables>
|
||||
orderResult = await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.ONE_TIME,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.execute();
|
||||
|
||||
final String orderId = orderResult.data.order_insert.id;
|
||||
|
||||
@@ -59,32 +59,34 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
final String shiftTitle = 'Shift 1 ${_formatDate(order.date)}';
|
||||
final double shiftCost = _calculateShiftCost(order);
|
||||
|
||||
final fdc.OperationResult<dc.CreateShiftData, dc.CreateShiftVariables> shiftResult =
|
||||
await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(orderTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
final OperationResult<dc.CreateShiftData, dc.CreateShiftVariables>
|
||||
shiftResult = await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(orderTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
|
||||
final String shiftId = shiftResult.data.shift_insert.id;
|
||||
|
||||
for (final domain.OneTimeOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(order.date, position.startTime);
|
||||
final DateTime end = _parseTime(order.date, position.endTime);
|
||||
final DateTime normalizedEnd = end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
final double totalValue = rate * hours * position.count;
|
||||
@@ -106,7 +108,7 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
|
||||
await _service.connector
|
||||
.updateOrder(id: orderId, teamHubId: hub.id)
|
||||
.shifts(fdc.AnyValue(<String>[shiftId]))
|
||||
.shifts(AnyValue(<String>[shiftId]))
|
||||
.execute();
|
||||
});
|
||||
}
|
||||
@@ -129,74 +131,78 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
order.startDate.month,
|
||||
order.startDate.day,
|
||||
);
|
||||
final fdc.Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final fdc.Timestamp startTimestamp = orderTimestamp;
|
||||
final fdc.Timestamp endTimestamp = _service.toTimestamp(order.endDate);
|
||||
final Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final Timestamp startTimestamp = orderTimestamp;
|
||||
final Timestamp endTimestamp = _service.toTimestamp(order.endDate);
|
||||
|
||||
final fdc.OperationResult<dc.CreateOrderData, dc.CreateOrderVariables> orderResult =
|
||||
await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.RECURRING,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.startDate(startTimestamp)
|
||||
.endDate(endTimestamp)
|
||||
.recurringDays(order.recurringDays)
|
||||
.execute();
|
||||
final OperationResult<dc.CreateOrderData, dc.CreateOrderVariables>
|
||||
orderResult = await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.RECURRING,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.startDate(startTimestamp)
|
||||
.endDate(endTimestamp)
|
||||
.recurringDays(order.recurringDays)
|
||||
.execute();
|
||||
|
||||
final String orderId = orderResult.data.order_insert.id;
|
||||
|
||||
// NOTE: Recurring orders are limited to 30 days of generated shifts.
|
||||
// Future shifts beyond 30 days should be created by a scheduled job.
|
||||
final DateTime maxEndDate = orderDateOnly.add(const Duration(days: 29));
|
||||
final DateTime effectiveEndDate =
|
||||
order.endDate.isAfter(maxEndDate) ? maxEndDate : order.endDate;
|
||||
final DateTime effectiveEndDate = order.endDate.isAfter(maxEndDate)
|
||||
? maxEndDate
|
||||
: order.endDate;
|
||||
|
||||
final Set<String> selectedDays = Set<String>.from(order.recurringDays);
|
||||
final int workersNeeded = order.positions.fold<int>(
|
||||
0,
|
||||
(int sum, domain.RecurringOrderPosition position) => sum + position.count,
|
||||
(int sum, domain.RecurringOrderPosition position) =>
|
||||
sum + position.count,
|
||||
);
|
||||
final double shiftCost = _calculateRecurringShiftCost(order);
|
||||
|
||||
final List<String> shiftIds = <String>[];
|
||||
for (DateTime day = orderDateOnly;
|
||||
!day.isAfter(effectiveEndDate);
|
||||
day = day.add(const Duration(days: 1))) {
|
||||
for (
|
||||
DateTime day = orderDateOnly;
|
||||
!day.isAfter(effectiveEndDate);
|
||||
day = day.add(const Duration(days: 1))
|
||||
) {
|
||||
final String dayLabel = _weekdayLabel(day);
|
||||
if (!selectedDays.contains(dayLabel)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String shiftTitle = 'Shift ${_formatDate(day)}';
|
||||
final fdc.Timestamp dayTimestamp = _service.toTimestamp(
|
||||
final Timestamp dayTimestamp = _service.toTimestamp(
|
||||
DateTime(day.year, day.month, day.day),
|
||||
);
|
||||
|
||||
final fdc.OperationResult<dc.CreateShiftData, dc.CreateShiftVariables> shiftResult =
|
||||
await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(dayTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
final OperationResult<dc.CreateShiftData, dc.CreateShiftVariables>
|
||||
shiftResult = await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(dayTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
|
||||
final String shiftId = shiftResult.data.shift_insert.id;
|
||||
shiftIds.add(shiftId);
|
||||
@@ -204,8 +210,9 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
for (final domain.RecurringOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(day, position.startTime);
|
||||
final DateTime end = _parseTime(day, position.endTime);
|
||||
final DateTime normalizedEnd =
|
||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
final double totalValue = rate * hours * position.count;
|
||||
@@ -228,7 +235,7 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
|
||||
await _service.connector
|
||||
.updateOrder(id: orderId, teamHubId: hub.id)
|
||||
.shifts(fdc.AnyValue(shiftIds))
|
||||
.shifts(AnyValue(shiftIds))
|
||||
.execute();
|
||||
});
|
||||
}
|
||||
@@ -251,23 +258,23 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
order.startDate.month,
|
||||
order.startDate.day,
|
||||
);
|
||||
final fdc.Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final fdc.Timestamp startTimestamp = orderTimestamp;
|
||||
final Timestamp orderTimestamp = _service.toTimestamp(orderDateOnly);
|
||||
final Timestamp startTimestamp = orderTimestamp;
|
||||
|
||||
final fdc.OperationResult<dc.CreateOrderData, dc.CreateOrderVariables> orderResult =
|
||||
await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.PERMANENT,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.startDate(startTimestamp)
|
||||
.permanentDays(order.permanentDays)
|
||||
.execute();
|
||||
final OperationResult<dc.CreateOrderData, dc.CreateOrderVariables>
|
||||
orderResult = await _service.connector
|
||||
.createOrder(
|
||||
businessId: businessId,
|
||||
orderType: dc.OrderType.PERMANENT,
|
||||
teamHubId: hub.id,
|
||||
)
|
||||
.vendorId(vendorId)
|
||||
.eventName(order.eventName)
|
||||
.status(dc.OrderStatus.POSTED)
|
||||
.date(orderTimestamp)
|
||||
.startDate(startTimestamp)
|
||||
.permanentDays(order.permanentDays)
|
||||
.execute();
|
||||
|
||||
final String orderId = orderResult.data.order_insert.id;
|
||||
|
||||
@@ -283,38 +290,40 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
final double shiftCost = _calculatePermanentShiftCost(order);
|
||||
|
||||
final List<String> shiftIds = <String>[];
|
||||
for (DateTime day = orderDateOnly;
|
||||
!day.isAfter(maxEndDate);
|
||||
day = day.add(const Duration(days: 1))) {
|
||||
for (
|
||||
DateTime day = orderDateOnly;
|
||||
!day.isAfter(maxEndDate);
|
||||
day = day.add(const Duration(days: 1))
|
||||
) {
|
||||
final String dayLabel = _weekdayLabel(day);
|
||||
if (!selectedDays.contains(dayLabel)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String shiftTitle = 'Shift ${_formatDate(day)}';
|
||||
final fdc.Timestamp dayTimestamp = _service.toTimestamp(
|
||||
final Timestamp dayTimestamp = _service.toTimestamp(
|
||||
DateTime(day.year, day.month, day.day),
|
||||
);
|
||||
|
||||
final fdc.OperationResult<dc.CreateShiftData, dc.CreateShiftVariables> shiftResult =
|
||||
await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(dayTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
final OperationResult<dc.CreateShiftData, dc.CreateShiftVariables>
|
||||
shiftResult = await _service.connector
|
||||
.createShift(title: shiftTitle, orderId: orderId)
|
||||
.date(dayTimestamp)
|
||||
.location(hub.name)
|
||||
.locationAddress(hub.address)
|
||||
.latitude(hub.latitude)
|
||||
.longitude(hub.longitude)
|
||||
.placeId(hub.placeId)
|
||||
.city(hub.city)
|
||||
.state(hub.state)
|
||||
.street(hub.street)
|
||||
.country(hub.country)
|
||||
.status(dc.ShiftStatus.OPEN)
|
||||
.workersNeeded(workersNeeded)
|
||||
.filled(0)
|
||||
.durationDays(1)
|
||||
.cost(shiftCost)
|
||||
.execute();
|
||||
|
||||
final String shiftId = shiftResult.data.shift_insert.id;
|
||||
shiftIds.add(shiftId);
|
||||
@@ -322,8 +331,9 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
for (final domain.OneTimeOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(day, position.startTime);
|
||||
final DateTime end = _parseTime(day, position.endTime);
|
||||
final DateTime normalizedEnd =
|
||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
final double totalValue = rate * hours * position.count;
|
||||
@@ -346,7 +356,7 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
|
||||
await _service.connector
|
||||
.updateOrder(id: orderId, teamHubId: hub.id)
|
||||
.shifts(fdc.AnyValue(shiftIds))
|
||||
.shifts(AnyValue(shiftIds))
|
||||
.execute();
|
||||
});
|
||||
}
|
||||
@@ -363,13 +373,76 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
throw UnimplementedError('Reorder functionality is not yet implemented.');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<domain.ReorderData> getOrderDetailsForReorder(String orderId) async {
|
||||
return _service.run(() async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
final QueryResult<
|
||||
dc.ListShiftRolesByBusinessAndOrderData,
|
||||
dc.ListShiftRolesByBusinessAndOrderVariables
|
||||
>
|
||||
result = await _service.connector
|
||||
.listShiftRolesByBusinessAndOrder(
|
||||
businessId: businessId,
|
||||
orderId: orderId,
|
||||
)
|
||||
.execute();
|
||||
|
||||
final List<dc.ListShiftRolesByBusinessAndOrderShiftRoles> shiftRoles =
|
||||
result.data.shiftRoles;
|
||||
|
||||
if (shiftRoles.isEmpty) {
|
||||
throw Exception('Order not found or has no roles.');
|
||||
}
|
||||
|
||||
final dc.ListShiftRolesByBusinessAndOrderShiftRolesShiftOrder order =
|
||||
shiftRoles.first.shift.order;
|
||||
|
||||
final domain.OrderType orderType = _mapOrderType(order.orderType);
|
||||
|
||||
final dc.ListShiftRolesByBusinessAndOrderShiftRolesShiftOrderTeamHub
|
||||
teamHub = order.teamHub;
|
||||
|
||||
return domain.ReorderData(
|
||||
orderId: orderId,
|
||||
eventName: order.eventName ?? '',
|
||||
vendorId: order.vendorId ?? '',
|
||||
orderType: orderType,
|
||||
hub: domain.OneTimeOrderHubDetails(
|
||||
id: teamHub.id,
|
||||
name: teamHub.hubName,
|
||||
address: teamHub.address,
|
||||
placeId: teamHub.placeId,
|
||||
latitude: 0, // Not available in this query
|
||||
longitude: 0,
|
||||
),
|
||||
positions: shiftRoles.map((
|
||||
dc.ListShiftRolesByBusinessAndOrderShiftRoles role,
|
||||
) {
|
||||
return domain.ReorderPosition(
|
||||
roleId: role.roleId,
|
||||
count: role.count,
|
||||
startTime: _formatTimestamp(role.startTime),
|
||||
endTime: _formatTimestamp(role.endTime),
|
||||
lunchBreak: _formatBreakDuration(role.breakType),
|
||||
);
|
||||
}).toList(),
|
||||
startDate: order.startDate?.toDateTime(),
|
||||
endDate: order.endDate?.toDateTime(),
|
||||
recurringDays: order.recurringDays ?? const <String>[],
|
||||
permanentDays: order.permanentDays ?? const <String>[],
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
double _calculateShiftCost(domain.OneTimeOrder order) {
|
||||
double total = 0;
|
||||
for (final domain.OneTimeOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(order.date, position.startTime);
|
||||
final DateTime end = _parseTime(order.date, position.endTime);
|
||||
final DateTime normalizedEnd =
|
||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
total += rate * hours * position.count;
|
||||
@@ -382,8 +455,9 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
for (final domain.RecurringOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(order.startDate, position.startTime);
|
||||
final DateTime end = _parseTime(order.startDate, position.endTime);
|
||||
final DateTime normalizedEnd =
|
||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
total += rate * hours * position.count;
|
||||
@@ -396,8 +470,9 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
for (final domain.OneTimeOrderPosition position in order.positions) {
|
||||
final DateTime start = _parseTime(order.startDate, position.startTime);
|
||||
final DateTime end = _parseTime(order.startDate, position.endTime);
|
||||
final DateTime normalizedEnd =
|
||||
end.isBefore(start) ? end.add(const Duration(days: 1)) : end;
|
||||
final DateTime normalizedEnd = end.isBefore(start)
|
||||
? end.add(const Duration(days: 1))
|
||||
: end;
|
||||
final double hours = normalizedEnd.difference(start).inMinutes / 60.0;
|
||||
final double rate = order.roleRates[position.role] ?? 0;
|
||||
total += rate * hours * position.count;
|
||||
@@ -473,4 +548,49 @@ class ClientCreateOrderRepositoryImpl implements ClientCreateOrderRepositoryInte
|
||||
final String day = dateTime.day.toString().padLeft(2, '0');
|
||||
return '$year-$month-$day';
|
||||
}
|
||||
|
||||
String _formatTimestamp(Timestamp? value) {
|
||||
if (value == null) return '';
|
||||
try {
|
||||
return DateFormat('HH:mm').format(value.toDateTime());
|
||||
} catch (_) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
String _formatBreakDuration(dc.EnumValue<dc.BreakDuration>? breakType) {
|
||||
if (breakType is dc.Known<dc.BreakDuration>) {
|
||||
switch (breakType.value) {
|
||||
case dc.BreakDuration.MIN_10:
|
||||
return 'MIN_10';
|
||||
case dc.BreakDuration.MIN_15:
|
||||
return 'MIN_15';
|
||||
case dc.BreakDuration.MIN_30:
|
||||
return 'MIN_30';
|
||||
case dc.BreakDuration.MIN_45:
|
||||
return 'MIN_45';
|
||||
case dc.BreakDuration.MIN_60:
|
||||
return 'MIN_60';
|
||||
case dc.BreakDuration.NO_BREAK:
|
||||
return 'NO_BREAK';
|
||||
}
|
||||
}
|
||||
return 'NO_BREAK';
|
||||
}
|
||||
|
||||
domain.OrderType _mapOrderType(dc.EnumValue<dc.OrderType>? orderType) {
|
||||
if (orderType is dc.Known<dc.OrderType>) {
|
||||
switch (orderType.value) {
|
||||
case dc.OrderType.ONE_TIME:
|
||||
return domain.OrderType.oneTime;
|
||||
case dc.OrderType.RECURRING:
|
||||
return domain.OrderType.recurring;
|
||||
case dc.OrderType.PERMANENT:
|
||||
return domain.OrderType.permanent;
|
||||
case dc.OrderType.RAPID:
|
||||
return domain.OrderType.oneTime;
|
||||
}
|
||||
}
|
||||
return domain.OrderType.oneTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,4 +29,9 @@ abstract interface class ClientCreateOrderRepositoryInterface {
|
||||
/// [previousOrderId] is the ID of the order to reorder.
|
||||
/// [newDate] is the new date for the order.
|
||||
Future<void> reorder(String previousOrderId, DateTime newDate);
|
||||
|
||||
/// Fetches the details of an existing order to be used as a template for a new order.
|
||||
///
|
||||
/// returns [ReorderData] containing the order details and positions.
|
||||
Future<ReorderData> getOrderDetailsForReorder(String orderId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_domain/krow_domain.dart';
|
||||
import '../repositories/client_create_order_repository_interface.dart';
|
||||
|
||||
/// Use case for fetching order details for reordering.
|
||||
class GetOrderDetailsForReorderUseCase implements UseCase<String, ReorderData> {
|
||||
const GetOrderDetailsForReorderUseCase(this._repository);
|
||||
final ClientCreateOrderRepositoryInterface _repository;
|
||||
|
||||
@override
|
||||
Future<ReorderData> call(String orderId) {
|
||||
return _repository.getOrderDetailsForReorder(orderId);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:client_create_order/src/domain/arguments/one_time_order_arguments.dart';
|
||||
import 'package:client_create_order/src/domain/usecases/create_one_time_order_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||
import 'package:client_create_order/src/domain/usecases/get_order_details_for_reorder_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
@@ -14,8 +15,11 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||
with
|
||||
BlocErrorHandler<OneTimeOrderState>,
|
||||
SafeBloc<OneTimeOrderEvent, OneTimeOrderState> {
|
||||
OneTimeOrderBloc(this._createOneTimeOrderUseCase, this._service)
|
||||
: super(OneTimeOrderState.initial()) {
|
||||
OneTimeOrderBloc(
|
||||
this._createOneTimeOrderUseCase,
|
||||
this._getOrderDetailsForReorderUseCase,
|
||||
this._service,
|
||||
) : super(OneTimeOrderState.initial()) {
|
||||
on<OneTimeOrderVendorsLoaded>(_onVendorsLoaded);
|
||||
on<OneTimeOrderVendorChanged>(_onVendorChanged);
|
||||
on<OneTimeOrderHubsLoaded>(_onHubsLoaded);
|
||||
@@ -32,12 +36,13 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||
_loadHubs();
|
||||
}
|
||||
final CreateOneTimeOrderUseCase _createOneTimeOrderUseCase;
|
||||
final GetOrderDetailsForReorderUseCase _getOrderDetailsForReorderUseCase;
|
||||
final dc.DataConnectService _service;
|
||||
|
||||
Future<void> _loadVendors() async {
|
||||
final List<Vendor>? vendors = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
final fdc.QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
.connector
|
||||
.listVendors()
|
||||
.execute();
|
||||
@@ -65,7 +70,7 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||
) async {
|
||||
final List<OneTimeOrderRoleOption>? roles = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListRolesByVendorIdData,
|
||||
dc.ListRolesByVendorIdVariables
|
||||
>
|
||||
@@ -95,7 +100,7 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||
final List<OneTimeOrderHubOption>? hubs = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListTeamHubsByOwnerIdData,
|
||||
dc.ListTeamHubsByOwnerIdVariables
|
||||
>
|
||||
@@ -274,27 +279,72 @@ class OneTimeOrderBloc extends Bloc<OneTimeOrderEvent, OneTimeOrderState>
|
||||
);
|
||||
}
|
||||
|
||||
void _onInitialized(
|
||||
Future<void> _onInitialized(
|
||||
OneTimeOrderInitialized event,
|
||||
Emitter<OneTimeOrderState> emit,
|
||||
) {
|
||||
) async {
|
||||
final Map<String, dynamic> data = event.data;
|
||||
final String title = data['title']?.toString() ?? '';
|
||||
final int workers = (data['workers'] as int?) ?? 1;
|
||||
final DateTime? startDate = data['startDate'] as DateTime?;
|
||||
final String? orderId = data['orderId']?.toString();
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: title,
|
||||
date: startDate ?? DateTime.now(),
|
||||
positions: <OneTimeOrderPosition>[
|
||||
OneTimeOrderPosition(
|
||||
role: data['roleName']?.toString() ?? '',
|
||||
count: workers,
|
||||
startTime: data['startTime']?.toString() ?? '09:00',
|
||||
endTime: data['endTime']?.toString() ?? '17:00',
|
||||
emit(state.copyWith(eventName: title, date: startDate ?? DateTime.now()));
|
||||
|
||||
if (orderId == null || orderId.isEmpty) return;
|
||||
|
||||
emit(state.copyWith(status: OneTimeOrderStatus.loading));
|
||||
|
||||
await handleError(
|
||||
emit: emit.call,
|
||||
action: () async {
|
||||
final ReorderData orderDetails =
|
||||
await _getOrderDetailsForReorderUseCase(orderId);
|
||||
|
||||
// Map positions
|
||||
final List<OneTimeOrderPosition> positions = orderDetails.positions.map(
|
||||
(ReorderPosition role) {
|
||||
return OneTimeOrderPosition(
|
||||
role: role.roleId,
|
||||
count: role.count,
|
||||
startTime: role.startTime,
|
||||
endTime: role.endTime,
|
||||
lunchBreak: role.lunchBreak,
|
||||
);
|
||||
},
|
||||
).toList();
|
||||
|
||||
// Update state with order details
|
||||
final Vendor? selectedVendor = state.vendors
|
||||
.where((Vendor v) => v.id == orderDetails.vendorId)
|
||||
.firstOrNull;
|
||||
|
||||
final OneTimeOrderHubOption? selectedHub = state.hubs
|
||||
.where(
|
||||
(OneTimeOrderHubOption h) =>
|
||||
h.placeId == orderDetails.hub.placeId,
|
||||
)
|
||||
.firstOrNull;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: orderDetails.eventName.isNotEmpty
|
||||
? orderDetails.eventName
|
||||
: title,
|
||||
positions: positions,
|
||||
selectedVendor: selectedVendor,
|
||||
selectedHub: selectedHub,
|
||||
location: selectedHub?.name ?? '',
|
||||
status: OneTimeOrderStatus.initial,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (selectedVendor != null) {
|
||||
await _loadRolesForVendor(selectedVendor.id, emit);
|
||||
}
|
||||
},
|
||||
onError: (String errorKey) => state.copyWith(
|
||||
status: OneTimeOrderStatus.failure,
|
||||
errorMessage: errorKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:client_create_order/src/domain/usecases/create_permanent_order_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||
import 'package:client_create_order/src/domain/usecases/get_order_details_for_reorder_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
@@ -13,8 +14,11 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
with
|
||||
BlocErrorHandler<PermanentOrderState>,
|
||||
SafeBloc<PermanentOrderEvent, PermanentOrderState> {
|
||||
PermanentOrderBloc(this._createPermanentOrderUseCase, this._service)
|
||||
: super(PermanentOrderState.initial()) {
|
||||
PermanentOrderBloc(
|
||||
this._createPermanentOrderUseCase,
|
||||
this._getOrderDetailsForReorderUseCase,
|
||||
this._service,
|
||||
) : super(PermanentOrderState.initial()) {
|
||||
on<PermanentOrderVendorsLoaded>(_onVendorsLoaded);
|
||||
on<PermanentOrderVendorChanged>(_onVendorChanged);
|
||||
on<PermanentOrderHubsLoaded>(_onHubsLoaded);
|
||||
@@ -33,6 +37,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
}
|
||||
|
||||
final CreatePermanentOrderUseCase _createPermanentOrderUseCase;
|
||||
final GetOrderDetailsForReorderUseCase _getOrderDetailsForReorderUseCase;
|
||||
final dc.DataConnectService _service;
|
||||
|
||||
static const List<String> _dayLabels = <String>[
|
||||
@@ -48,7 +53,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
Future<void> _loadVendors() async {
|
||||
final List<domain.Vendor>? vendors = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
final fdc.QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
.connector
|
||||
.listVendors()
|
||||
.execute();
|
||||
@@ -76,7 +81,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
) async {
|
||||
final List<PermanentOrderRoleOption>? roles = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListRolesByVendorIdData,
|
||||
dc.ListRolesByVendorIdVariables
|
||||
>
|
||||
@@ -106,7 +111,7 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
final List<PermanentOrderHubOption>? hubs = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListTeamHubsByOwnerIdData,
|
||||
dc.ListTeamHubsByOwnerIdVariables
|
||||
>
|
||||
@@ -337,27 +342,76 @@ class PermanentOrderBloc extends Bloc<PermanentOrderEvent, PermanentOrderState>
|
||||
);
|
||||
}
|
||||
|
||||
void _onInitialized(
|
||||
Future<void> _onInitialized(
|
||||
PermanentOrderInitialized event,
|
||||
Emitter<PermanentOrderState> emit,
|
||||
) {
|
||||
) async {
|
||||
final Map<String, dynamic> data = event.data;
|
||||
final String title = data['title']?.toString() ?? '';
|
||||
final int workers = (data['workers'] as int?) ?? 1;
|
||||
final DateTime? startDate = data['startDate'] as DateTime?;
|
||||
final String? orderId = data['orderId']?.toString();
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: title,
|
||||
startDate: startDate ?? DateTime.now(),
|
||||
positions: <PermanentOrderPosition>[
|
||||
PermanentOrderPosition(
|
||||
role: data['roleName']?.toString() ?? '',
|
||||
count: workers,
|
||||
startTime: data['startTime']?.toString() ?? '09:00',
|
||||
endTime: data['endTime']?.toString() ?? '17:00',
|
||||
state.copyWith(eventName: title, startDate: startDate ?? DateTime.now()),
|
||||
);
|
||||
|
||||
if (orderId == null || orderId.isEmpty) return;
|
||||
|
||||
emit(state.copyWith(status: PermanentOrderStatus.loading));
|
||||
|
||||
await handleError(
|
||||
emit: emit.call,
|
||||
action: () async {
|
||||
final domain.ReorderData orderDetails =
|
||||
await _getOrderDetailsForReorderUseCase(orderId);
|
||||
|
||||
// Map positions
|
||||
final List<PermanentOrderPosition> positions = orderDetails.positions
|
||||
.map((domain.ReorderPosition role) {
|
||||
return PermanentOrderPosition(
|
||||
role: role.roleId,
|
||||
count: role.count,
|
||||
startTime: role.startTime,
|
||||
endTime: role.endTime,
|
||||
lunchBreak: role.lunchBreak,
|
||||
);
|
||||
})
|
||||
.toList();
|
||||
|
||||
// Update state with order details
|
||||
final domain.Vendor? selectedVendor = state.vendors
|
||||
.where((domain.Vendor v) => v.id == orderDetails.vendorId)
|
||||
.firstOrNull;
|
||||
|
||||
final PermanentOrderHubOption? selectedHub = state.hubs
|
||||
.where(
|
||||
(PermanentOrderHubOption h) =>
|
||||
h.placeId == orderDetails.hub.placeId,
|
||||
)
|
||||
.firstOrNull;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: orderDetails.eventName.isNotEmpty
|
||||
? orderDetails.eventName
|
||||
: title,
|
||||
positions: positions,
|
||||
selectedVendor: selectedVendor,
|
||||
selectedHub: selectedHub,
|
||||
location: selectedHub?.name ?? '',
|
||||
status: PermanentOrderStatus.initial,
|
||||
startDate: startDate ?? orderDetails.startDate ?? DateTime.now(),
|
||||
permanentDays: orderDetails.permanentDays,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (selectedVendor != null) {
|
||||
await _loadRolesForVendor(selectedVendor.id, emit);
|
||||
}
|
||||
},
|
||||
onError: (String errorKey) => state.copyWith(
|
||||
status: PermanentOrderStatus.failure,
|
||||
errorMessage: errorKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:client_create_order/src/domain/usecases/create_recurring_order_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||
import 'package:client_create_order/src/domain/usecases/get_order_details_for_reorder_usecase.dart';
|
||||
import 'package:firebase_data_connect/firebase_data_connect.dart' as fdc;
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:krow_core/core.dart';
|
||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||
@@ -13,8 +14,11 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
with
|
||||
BlocErrorHandler<RecurringOrderState>,
|
||||
SafeBloc<RecurringOrderEvent, RecurringOrderState> {
|
||||
RecurringOrderBloc(this._createRecurringOrderUseCase, this._service)
|
||||
: super(RecurringOrderState.initial()) {
|
||||
RecurringOrderBloc(
|
||||
this._createRecurringOrderUseCase,
|
||||
this._getOrderDetailsForReorderUseCase,
|
||||
this._service,
|
||||
) : super(RecurringOrderState.initial()) {
|
||||
on<RecurringOrderVendorsLoaded>(_onVendorsLoaded);
|
||||
on<RecurringOrderVendorChanged>(_onVendorChanged);
|
||||
on<RecurringOrderHubsLoaded>(_onHubsLoaded);
|
||||
@@ -34,6 +38,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
}
|
||||
|
||||
final CreateRecurringOrderUseCase _createRecurringOrderUseCase;
|
||||
final GetOrderDetailsForReorderUseCase _getOrderDetailsForReorderUseCase;
|
||||
final dc.DataConnectService _service;
|
||||
|
||||
static const List<String> _dayLabels = <String>[
|
||||
@@ -49,7 +54,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
Future<void> _loadVendors() async {
|
||||
final List<domain.Vendor>? vendors = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
final fdc.QueryResult<dc.ListVendorsData, void> result = await _service
|
||||
.connector
|
||||
.listVendors()
|
||||
.execute();
|
||||
@@ -77,7 +82,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
) async {
|
||||
final List<RecurringOrderRoleOption>? roles = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListRolesByVendorIdData,
|
||||
dc.ListRolesByVendorIdVariables
|
||||
>
|
||||
@@ -107,7 +112,7 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
final List<RecurringOrderHubOption>? hubs = await handleErrorWithResult(
|
||||
action: () async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
final QueryResult<
|
||||
final fdc.QueryResult<
|
||||
dc.ListTeamHubsByOwnerIdData,
|
||||
dc.ListTeamHubsByOwnerIdVariables
|
||||
>
|
||||
@@ -356,27 +361,77 @@ class RecurringOrderBloc extends Bloc<RecurringOrderEvent, RecurringOrderState>
|
||||
);
|
||||
}
|
||||
|
||||
void _onInitialized(
|
||||
Future<void> _onInitialized(
|
||||
RecurringOrderInitialized event,
|
||||
Emitter<RecurringOrderState> emit,
|
||||
) {
|
||||
) async {
|
||||
final Map<String, dynamic> data = event.data;
|
||||
final String title = data['title']?.toString() ?? '';
|
||||
final int workers = (data['workers'] as int?) ?? 1;
|
||||
final DateTime? startDate = data['startDate'] as DateTime?;
|
||||
final String? orderId = data['orderId']?.toString();
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: title,
|
||||
startDate: startDate ?? DateTime.now(),
|
||||
positions: <RecurringOrderPosition>[
|
||||
RecurringOrderPosition(
|
||||
role: data['roleName']?.toString() ?? '',
|
||||
count: workers,
|
||||
startTime: data['startTime']?.toString() ?? '09:00',
|
||||
endTime: data['endTime']?.toString() ?? '17:00',
|
||||
state.copyWith(eventName: title, startDate: startDate ?? DateTime.now()),
|
||||
);
|
||||
|
||||
if (orderId == null || orderId.isEmpty) return;
|
||||
|
||||
emit(state.copyWith(status: RecurringOrderStatus.loading));
|
||||
|
||||
await handleError(
|
||||
emit: emit.call,
|
||||
action: () async {
|
||||
final domain.ReorderData orderDetails =
|
||||
await _getOrderDetailsForReorderUseCase(orderId);
|
||||
|
||||
// Map positions
|
||||
final List<RecurringOrderPosition> positions = orderDetails.positions
|
||||
.map((domain.ReorderPosition role) {
|
||||
return RecurringOrderPosition(
|
||||
role: role.roleId,
|
||||
count: role.count,
|
||||
startTime: role.startTime,
|
||||
endTime: role.endTime,
|
||||
lunchBreak: role.lunchBreak,
|
||||
);
|
||||
})
|
||||
.toList();
|
||||
|
||||
// Update state with order details
|
||||
final domain.Vendor? selectedVendor = state.vendors
|
||||
.where((domain.Vendor v) => v.id == orderDetails.vendorId)
|
||||
.firstOrNull;
|
||||
|
||||
final RecurringOrderHubOption? selectedHub = state.hubs
|
||||
.where(
|
||||
(RecurringOrderHubOption h) =>
|
||||
h.placeId == orderDetails.hub.placeId,
|
||||
)
|
||||
.firstOrNull;
|
||||
|
||||
emit(
|
||||
state.copyWith(
|
||||
eventName: orderDetails.eventName.isNotEmpty
|
||||
? orderDetails.eventName
|
||||
: title,
|
||||
positions: positions,
|
||||
selectedVendor: selectedVendor,
|
||||
selectedHub: selectedHub,
|
||||
location: selectedHub?.name ?? '',
|
||||
status: RecurringOrderStatus.initial,
|
||||
startDate: startDate ?? orderDetails.startDate ?? DateTime.now(),
|
||||
endDate: orderDetails.endDate ?? DateTime.now(),
|
||||
recurringDays: orderDetails.recurringDays,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
if (selectedVendor != null) {
|
||||
await _loadRolesForVendor(selectedVendor.id, emit);
|
||||
}
|
||||
},
|
||||
onError: (String errorKey) => state.copyWith(
|
||||
status: RecurringOrderStatus.failure,
|
||||
errorMessage: errorKey,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -404,9 +404,15 @@ query listShiftRolesByBusinessAndOrder(
|
||||
vendorId
|
||||
eventName
|
||||
date
|
||||
startDate
|
||||
endDate
|
||||
recurringDays
|
||||
permanentDays
|
||||
orderType
|
||||
#location
|
||||
|
||||
teamHub {
|
||||
id
|
||||
address
|
||||
placeId
|
||||
hubName
|
||||
|
||||
Reference in New Issue
Block a user