#537 (Cost Center)#539 (Hub Manager)
This commit is contained in:
@@ -255,6 +255,7 @@
|
|||||||
"address_hint": "Full address",
|
"address_hint": "Full address",
|
||||||
"cost_center_label": "Cost Center",
|
"cost_center_label": "Cost Center",
|
||||||
"cost_center_hint": "eg: 1001, 1002",
|
"cost_center_hint": "eg: 1001, 1002",
|
||||||
|
"cost_centers_empty": "No cost centers available",
|
||||||
"name_required": "Name is required",
|
"name_required": "Name is required",
|
||||||
"address_required": "Address is required",
|
"address_required": "Address is required",
|
||||||
"create_button": "Create Hub"
|
"create_button": "Create Hub"
|
||||||
@@ -268,8 +269,12 @@
|
|||||||
"address_hint": "Full address",
|
"address_hint": "Full address",
|
||||||
"cost_center_label": "Cost Center",
|
"cost_center_label": "Cost Center",
|
||||||
"cost_center_hint": "eg: 1001, 1002",
|
"cost_center_hint": "eg: 1001, 1002",
|
||||||
|
"cost_centers_empty": "No cost centers available",
|
||||||
|
"name_required": "Name is required",
|
||||||
"save_button": "Save Changes",
|
"save_button": "Save Changes",
|
||||||
"success": "Hub updated successfully!"
|
"success": "Hub updated successfully!",
|
||||||
|
"created_success": "Hub created successfully",
|
||||||
|
"updated_success": "Hub updated successfully"
|
||||||
},
|
},
|
||||||
"hub_details": {
|
"hub_details": {
|
||||||
"title": "Hub Details",
|
"title": "Hub Details",
|
||||||
@@ -279,7 +284,8 @@
|
|||||||
"nfc_not_assigned": "Not Assigned",
|
"nfc_not_assigned": "Not Assigned",
|
||||||
"cost_center_label": "Cost Center",
|
"cost_center_label": "Cost Center",
|
||||||
"cost_center_none": "Not Assigned",
|
"cost_center_none": "Not Assigned",
|
||||||
"edit_button": "Edit Hub"
|
"edit_button": "Edit Hub",
|
||||||
|
"deleted_success": "Hub deleted successfully"
|
||||||
},
|
},
|
||||||
"nfc_dialog": {
|
"nfc_dialog": {
|
||||||
"title": "Identify NFC Tag",
|
"title": "Identify NFC Tag",
|
||||||
@@ -338,6 +344,8 @@
|
|||||||
"hub_manager_label": "Shift Contact",
|
"hub_manager_label": "Shift Contact",
|
||||||
"hub_manager_desc": "On-site manager or supervisor for this shift",
|
"hub_manager_desc": "On-site manager or supervisor for this shift",
|
||||||
"hub_manager_hint": "Select Contact",
|
"hub_manager_hint": "Select Contact",
|
||||||
|
"hub_manager_empty": "No hub managers available",
|
||||||
|
"hub_manager_none": "None",
|
||||||
"positions_title": "Positions",
|
"positions_title": "Positions",
|
||||||
"add_position": "Add Position",
|
"add_position": "Add Position",
|
||||||
"position_number": "Position $number",
|
"position_number": "Position $number",
|
||||||
@@ -389,6 +397,41 @@
|
|||||||
"active": "Active",
|
"active": "Active",
|
||||||
"completed": "Completed"
|
"completed": "Completed"
|
||||||
},
|
},
|
||||||
|
"order_edit_sheet": {
|
||||||
|
"title": "Edit Your Order",
|
||||||
|
"vendor_section": "VENDOR",
|
||||||
|
"location_section": "LOCATION",
|
||||||
|
"shift_contact_section": "SHIFT CONTACT",
|
||||||
|
"shift_contact_desc": "On-site manager or supervisor for this shift",
|
||||||
|
"select_contact": "Select Contact",
|
||||||
|
"no_hub_managers": "No hub managers available",
|
||||||
|
"none": "None",
|
||||||
|
"positions_section": "POSITIONS",
|
||||||
|
"add_position": "Add Position",
|
||||||
|
"review_positions": "Review $count Positions",
|
||||||
|
"order_name_hint": "Order name",
|
||||||
|
"remove": "Remove",
|
||||||
|
"select_role_hint": "Select role",
|
||||||
|
"start_label": "Start",
|
||||||
|
"end_label": "End",
|
||||||
|
"workers_label": "Workers",
|
||||||
|
"different_location": "Use different location for this position",
|
||||||
|
"different_location_title": "Different Location",
|
||||||
|
"enter_address_hint": "Enter different address",
|
||||||
|
"no_break": "No Break",
|
||||||
|
"positions": "Positions",
|
||||||
|
"workers": "Workers",
|
||||||
|
"est_cost": "Est. Cost",
|
||||||
|
"positions_breakdown": "Positions Breakdown",
|
||||||
|
"edit_button": "Edit",
|
||||||
|
"confirm_save": "Confirm & Save",
|
||||||
|
"position_singular": "Position",
|
||||||
|
"order_updated_title": "Order Updated!",
|
||||||
|
"order_updated_message": "Your shift has been updated successfully.",
|
||||||
|
"back_to_orders": "Back to Orders",
|
||||||
|
"one_time_order_title": "One-Time Order",
|
||||||
|
"refine_subtitle": "Refine your staffing needs"
|
||||||
|
},
|
||||||
"card": {
|
"card": {
|
||||||
"open": "OPEN",
|
"open": "OPEN",
|
||||||
"filled": "FILLED",
|
"filled": "FILLED",
|
||||||
|
|||||||
@@ -255,6 +255,7 @@
|
|||||||
"address_hint": "Direcci\u00f3n completa",
|
"address_hint": "Direcci\u00f3n completa",
|
||||||
"cost_center_label": "Centro de Costos",
|
"cost_center_label": "Centro de Costos",
|
||||||
"cost_center_hint": "ej: 1001, 1002",
|
"cost_center_hint": "ej: 1001, 1002",
|
||||||
|
"cost_centers_empty": "No hay centros de costos disponibles",
|
||||||
"name_required": "Nombre es obligatorio",
|
"name_required": "Nombre es obligatorio",
|
||||||
"address_required": "La direcci\u00f3n es obligatoria",
|
"address_required": "La direcci\u00f3n es obligatoria",
|
||||||
"create_button": "Crear Hub"
|
"create_button": "Crear Hub"
|
||||||
@@ -283,8 +284,12 @@
|
|||||||
"address_hint": "Ingresar direcci\u00f3n",
|
"address_hint": "Ingresar direcci\u00f3n",
|
||||||
"cost_center_label": "Centro de Costos",
|
"cost_center_label": "Centro de Costos",
|
||||||
"cost_center_hint": "ej: 1001, 1002",
|
"cost_center_hint": "ej: 1001, 1002",
|
||||||
|
"cost_centers_empty": "No hay centros de costos disponibles",
|
||||||
|
"name_required": "El nombre es obligatorio",
|
||||||
"save_button": "Guardar Cambios",
|
"save_button": "Guardar Cambios",
|
||||||
"success": "\u00a1Hub actualizado exitosamente!"
|
"success": "\u00a1Hub actualizado exitosamente!",
|
||||||
|
"created_success": "Hub creado exitosamente",
|
||||||
|
"updated_success": "Hub actualizado exitosamente"
|
||||||
},
|
},
|
||||||
"hub_details": {
|
"hub_details": {
|
||||||
"title": "Detalles del Hub",
|
"title": "Detalles del Hub",
|
||||||
@@ -294,7 +299,8 @@
|
|||||||
"nfc_label": "Etiqueta NFC",
|
"nfc_label": "Etiqueta NFC",
|
||||||
"nfc_not_assigned": "No asignada",
|
"nfc_not_assigned": "No asignada",
|
||||||
"cost_center_label": "Centro de Costos",
|
"cost_center_label": "Centro de Costos",
|
||||||
"cost_center_none": "No asignado"
|
"cost_center_none": "No asignado",
|
||||||
|
"deleted_success": "Hub eliminado exitosamente"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"client_create_order": {
|
"client_create_order": {
|
||||||
@@ -338,6 +344,8 @@
|
|||||||
"hub_manager_label": "Contacto del Turno",
|
"hub_manager_label": "Contacto del Turno",
|
||||||
"hub_manager_desc": "Gerente o supervisor en el sitio para este turno",
|
"hub_manager_desc": "Gerente o supervisor en el sitio para este turno",
|
||||||
"hub_manager_hint": "Seleccionar Contacto",
|
"hub_manager_hint": "Seleccionar Contacto",
|
||||||
|
"hub_manager_empty": "No hay contactos de turno disponibles",
|
||||||
|
"hub_manager_none": "Ninguno",
|
||||||
"positions_title": "Posiciones",
|
"positions_title": "Posiciones",
|
||||||
"add_position": "A\u00f1adir Posici\u00f3n",
|
"add_position": "A\u00f1adir Posici\u00f3n",
|
||||||
"position_number": "Posici\u00f3n $number",
|
"position_number": "Posici\u00f3n $number",
|
||||||
@@ -389,6 +397,41 @@
|
|||||||
"active": "Activos",
|
"active": "Activos",
|
||||||
"completed": "Completados"
|
"completed": "Completados"
|
||||||
},
|
},
|
||||||
|
"order_edit_sheet": {
|
||||||
|
"title": "Editar Tu Orden",
|
||||||
|
"vendor_section": "PROVEEDOR",
|
||||||
|
"location_section": "UBICACI\u00d3N",
|
||||||
|
"shift_contact_section": "CONTACTO DEL TURNO",
|
||||||
|
"shift_contact_desc": "Gerente o supervisor en el sitio para este turno",
|
||||||
|
"select_contact": "Seleccionar Contacto",
|
||||||
|
"no_hub_managers": "No hay contactos de turno disponibles",
|
||||||
|
"none": "Ninguno",
|
||||||
|
"positions_section": "POSICIONES",
|
||||||
|
"add_position": "A\u00f1adir Posici\u00f3n",
|
||||||
|
"review_positions": "Revisar $count Posiciones",
|
||||||
|
"order_name_hint": "Nombre de la orden",
|
||||||
|
"remove": "Eliminar",
|
||||||
|
"select_role_hint": "Seleccionar rol",
|
||||||
|
"start_label": "Inicio",
|
||||||
|
"end_label": "Fin",
|
||||||
|
"workers_label": "Trabajadores",
|
||||||
|
"different_location": "Usar ubicaci\u00f3n diferente para esta posici\u00f3n",
|
||||||
|
"different_location_title": "Ubicaci\u00f3n Diferente",
|
||||||
|
"enter_address_hint": "Ingresar direcci\u00f3n diferente",
|
||||||
|
"no_break": "Sin Descanso",
|
||||||
|
"positions": "Posiciones",
|
||||||
|
"workers": "Trabajadores",
|
||||||
|
"est_cost": "Costo Est.",
|
||||||
|
"positions_breakdown": "Desglose de Posiciones",
|
||||||
|
"edit_button": "Editar",
|
||||||
|
"confirm_save": "Confirmar y Guardar",
|
||||||
|
"position_singular": "Posici\u00f3n",
|
||||||
|
"order_updated_title": "\u00a1Orden Actualizada!",
|
||||||
|
"order_updated_message": "Tu turno ha sido actualizado exitosamente.",
|
||||||
|
"back_to_orders": "Volver a \u00d3rdenes",
|
||||||
|
"one_time_order_title": "Orden \u00danica Vez",
|
||||||
|
"refine_subtitle": "Ajusta tus necesidades de personal"
|
||||||
|
},
|
||||||
"card": {
|
"card": {
|
||||||
"open": "ABIERTO",
|
"open": "ABIERTO",
|
||||||
"filled": "LLENO",
|
"filled": "LLENO",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
|
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'package:firebase_data_connect/src/core/ref.dart';
|
import 'package:firebase_data_connect/src/core/ref.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
@@ -23,7 +23,25 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
.getTeamHubsByTeamId(teamId: teamId)
|
.getTeamHubsByTeamId(teamId: teamId)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
final QueryResult<
|
||||||
|
dc.ListTeamHudDepartmentsData,
|
||||||
|
dc.ListTeamHudDepartmentsVariables
|
||||||
|
>
|
||||||
|
deptsResult = await _service.connector.listTeamHudDepartments().execute();
|
||||||
|
final Map<String, dc.ListTeamHudDepartmentsTeamHudDepartments> hubToDept =
|
||||||
|
<String, dc.ListTeamHudDepartmentsTeamHudDepartments>{};
|
||||||
|
for (final dc.ListTeamHudDepartmentsTeamHudDepartments dep
|
||||||
|
in deptsResult.data.teamHudDepartments) {
|
||||||
|
if (dep.costCenter != null &&
|
||||||
|
dep.costCenter!.isNotEmpty &&
|
||||||
|
!hubToDept.containsKey(dep.teamHubId)) {
|
||||||
|
hubToDept[dep.teamHubId] = dep;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return response.data.teamHubs.map((dc.GetTeamHubsByTeamIdTeamHubs h) {
|
return response.data.teamHubs.map((dc.GetTeamHubsByTeamIdTeamHubs h) {
|
||||||
|
final dc.ListTeamHudDepartmentsTeamHudDepartments? dept =
|
||||||
|
hubToDept[h.id];
|
||||||
return Hub(
|
return Hub(
|
||||||
id: h.id,
|
id: h.id,
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
@@ -31,7 +49,13 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
address: h.address,
|
address: h.address,
|
||||||
nfcTagId: null,
|
nfcTagId: null,
|
||||||
status: h.isActive ? HubStatus.active : HubStatus.inactive,
|
status: h.isActive ? HubStatus.active : HubStatus.inactive,
|
||||||
costCenter: null,
|
costCenter: dept != null
|
||||||
|
? CostCenter(
|
||||||
|
id: dept.id,
|
||||||
|
name: dept.name,
|
||||||
|
code: dept.costCenter ?? dept.name,
|
||||||
|
)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
});
|
});
|
||||||
@@ -50,6 +74,7 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
String? street,
|
String? street,
|
||||||
String? country,
|
String? country,
|
||||||
String? zipCode,
|
String? zipCode,
|
||||||
|
String? costCenterId,
|
||||||
}) async {
|
}) async {
|
||||||
return _service.run(() async {
|
return _service.run(() async {
|
||||||
final String teamId = await _getOrCreateTeamId(businessId);
|
final String teamId = await _getOrCreateTeamId(businessId);
|
||||||
@@ -73,14 +98,27 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
.zipCode(zipCode ?? placeAddress?.zipCode)
|
.zipCode(zipCode ?? placeAddress?.zipCode)
|
||||||
.execute();
|
.execute();
|
||||||
|
|
||||||
|
final String hubId = result.data.teamHub_insert.id;
|
||||||
|
CostCenter? costCenter;
|
||||||
|
if (costCenterId != null && costCenterId.isNotEmpty) {
|
||||||
|
await _service.connector
|
||||||
|
.createTeamHudDepartment(
|
||||||
|
name: costCenterId,
|
||||||
|
teamHubId: hubId,
|
||||||
|
)
|
||||||
|
.costCenter(costCenterId)
|
||||||
|
.execute();
|
||||||
|
costCenter = CostCenter(id: costCenterId, name: costCenterId, code: costCenterId);
|
||||||
|
}
|
||||||
|
|
||||||
return Hub(
|
return Hub(
|
||||||
id: result.data.teamHub_insert.id,
|
id: hubId,
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
name: name,
|
name: name,
|
||||||
address: address,
|
address: address,
|
||||||
nfcTagId: null,
|
nfcTagId: null,
|
||||||
status: HubStatus.active,
|
status: HubStatus.active,
|
||||||
costCenter: null,
|
costCenter: costCenter,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -99,6 +137,7 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
String? street,
|
String? street,
|
||||||
String? country,
|
String? country,
|
||||||
String? zipCode,
|
String? zipCode,
|
||||||
|
String? costCenterId,
|
||||||
}) async {
|
}) async {
|
||||||
return _service.run(() async {
|
return _service.run(() async {
|
||||||
final _PlaceAddress? placeAddress = (placeId != null && placeId.isNotEmpty)
|
final _PlaceAddress? placeAddress = (placeId != null && placeId.isNotEmpty)
|
||||||
@@ -130,7 +169,43 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
|
|
||||||
await builder.execute();
|
await builder.execute();
|
||||||
|
|
||||||
// Return a basic hub object reflecting changes (or we could re-fetch)
|
CostCenter? costCenter;
|
||||||
|
final QueryResult<
|
||||||
|
dc.ListTeamHudDepartmentsByTeamHubIdData,
|
||||||
|
dc.ListTeamHudDepartmentsByTeamHubIdVariables
|
||||||
|
>
|
||||||
|
deptsResult = await _service.connector
|
||||||
|
.listTeamHudDepartmentsByTeamHubId(teamHubId: id)
|
||||||
|
.execute();
|
||||||
|
final List<dc.ListTeamHudDepartmentsByTeamHubIdTeamHudDepartments> depts =
|
||||||
|
deptsResult.data.teamHudDepartments;
|
||||||
|
|
||||||
|
if (costCenterId == null || costCenterId.isEmpty) {
|
||||||
|
if (depts.isNotEmpty) {
|
||||||
|
await _service.connector
|
||||||
|
.updateTeamHudDepartment(id: depts.first.id)
|
||||||
|
.costCenter(null)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (depts.isNotEmpty) {
|
||||||
|
await _service.connector
|
||||||
|
.updateTeamHudDepartment(id: depts.first.id)
|
||||||
|
.costCenter(costCenterId)
|
||||||
|
.execute();
|
||||||
|
costCenter = CostCenter(id: costCenterId, name: costCenterId, code: costCenterId);
|
||||||
|
} else {
|
||||||
|
await _service.connector
|
||||||
|
.createTeamHudDepartment(
|
||||||
|
name: costCenterId,
|
||||||
|
teamHubId: id,
|
||||||
|
)
|
||||||
|
.costCenter(costCenterId)
|
||||||
|
.execute();
|
||||||
|
costCenter = CostCenter(id: costCenterId, name: costCenterId, code: costCenterId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Hub(
|
return Hub(
|
||||||
id: id,
|
id: id,
|
||||||
businessId: businessId,
|
businessId: businessId,
|
||||||
@@ -138,7 +213,7 @@ class HubsConnectorRepositoryImpl implements HubsConnectorRepository {
|
|||||||
address: address ?? '',
|
address: address ?? '',
|
||||||
nfcTagId: null,
|
nfcTagId: null,
|
||||||
status: HubStatus.active,
|
status: HubStatus.active,
|
||||||
costCenter: null,
|
costCenter: costCenter,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ abstract interface class HubsConnectorRepository {
|
|||||||
String? street,
|
String? street,
|
||||||
String? country,
|
String? country,
|
||||||
String? zipCode,
|
String? zipCode,
|
||||||
|
String? costCenterId,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Updates an existing hub.
|
/// Updates an existing hub.
|
||||||
@@ -36,6 +37,7 @@ abstract interface class HubsConnectorRepository {
|
|||||||
String? street,
|
String? street,
|
||||||
String? country,
|
String? country,
|
||||||
String? zipCode,
|
String? zipCode,
|
||||||
|
String? costCenterId,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// Deletes a hub.
|
/// Deletes a hub.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
|
// ignore_for_file: always_specify_types, depend_on_referenced_packages, dead_code, dead_null_aware_expression, unused_local_variable, unused_import, sort_constructors_first, prefer_final_fields, prefer_const_constructors, deprecated_member_use, implicit_call_tearoffs
|
||||||
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
import 'package:krow_data_connect/krow_data_connect.dart' as dc;
|
||||||
import 'package:krow_domain/krow_domain.dart';
|
import 'package:krow_domain/krow_domain.dart';
|
||||||
import '../../domain/repositories/hub_repository_interface.dart';
|
import '../../domain/repositories/hub_repository_interface.dart';
|
||||||
@@ -26,13 +26,20 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<CostCenter>> getCostCenters() async {
|
Future<List<CostCenter>> getCostCenters() async {
|
||||||
// Mocking cost centers for now since the backend is not yet ready.
|
return _service.run(() async {
|
||||||
return <CostCenter>[
|
final result = await _service.connector.listTeamHudDepartments().execute();
|
||||||
const CostCenter(id: 'cc-001', name: 'Kitchen', code: '1001'),
|
final Set<String> seen = <String>{};
|
||||||
const CostCenter(id: 'cc-002', name: 'Front Desk', code: '1002'),
|
final List<CostCenter> costCenters = <CostCenter>[];
|
||||||
const CostCenter(id: 'cc-003', name: 'Waitstaff', code: '1003'),
|
for (final dc.ListTeamHudDepartmentsTeamHudDepartments dep
|
||||||
const CostCenter(id: 'cc-004', name: 'Management', code: '1004'),
|
in result.data.teamHudDepartments) {
|
||||||
];
|
final String? cc = dep.costCenter;
|
||||||
|
if (cc != null && cc.isNotEmpty && !seen.contains(cc)) {
|
||||||
|
seen.add(cc);
|
||||||
|
costCenters.add(CostCenter(id: cc, name: dep.name, code: cc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return costCenters;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -62,6 +69,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
|||||||
street: street,
|
street: street,
|
||||||
country: country,
|
country: country,
|
||||||
zipCode: zipCode,
|
zipCode: zipCode,
|
||||||
|
costCenterId: costCenterId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,6 +115,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
|||||||
street: street,
|
street: street,
|
||||||
country: country,
|
country: country,
|
||||||
zipCode: zipCode,
|
zipCode: zipCode,
|
||||||
|
costCenterId: costCenterId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class EditHubBloc extends Bloc<EditHubEvent, EditHubState>
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
status: EditHubStatus.success,
|
status: EditHubStatus.success,
|
||||||
successMessage: 'Hub created successfully',
|
successKey: 'created',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -109,7 +109,7 @@ class EditHubBloc extends Bloc<EditHubEvent, EditHubState>
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
status: EditHubStatus.success,
|
status: EditHubStatus.success,
|
||||||
successMessage: 'Hub updated successfully',
|
successKey: 'updated',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class EditHubState extends Equatable {
|
|||||||
this.status = EditHubStatus.initial,
|
this.status = EditHubStatus.initial,
|
||||||
this.errorMessage,
|
this.errorMessage,
|
||||||
this.successMessage,
|
this.successMessage,
|
||||||
|
this.successKey,
|
||||||
this.costCenters = const <CostCenter>[],
|
this.costCenters = const <CostCenter>[],
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -34,6 +35,9 @@ class EditHubState extends Equatable {
|
|||||||
/// The success message if the operation succeeded.
|
/// The success message if the operation succeeded.
|
||||||
final String? successMessage;
|
final String? successMessage;
|
||||||
|
|
||||||
|
/// Localization key for success message: 'created' | 'updated'.
|
||||||
|
final String? successKey;
|
||||||
|
|
||||||
/// Available cost centers for selection.
|
/// Available cost centers for selection.
|
||||||
final List<CostCenter> costCenters;
|
final List<CostCenter> costCenters;
|
||||||
|
|
||||||
@@ -42,12 +46,14 @@ class EditHubState extends Equatable {
|
|||||||
EditHubStatus? status,
|
EditHubStatus? status,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
String? successMessage,
|
String? successMessage,
|
||||||
|
String? successKey,
|
||||||
List<CostCenter>? costCenters,
|
List<CostCenter>? costCenters,
|
||||||
}) {
|
}) {
|
||||||
return EditHubState(
|
return EditHubState(
|
||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
errorMessage: errorMessage ?? this.errorMessage,
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
successMessage: successMessage ?? this.successMessage,
|
successMessage: successMessage ?? this.successMessage,
|
||||||
|
successKey: successKey ?? this.successKey,
|
||||||
costCenters: costCenters ?? this.costCenters,
|
costCenters: costCenters ?? this.costCenters,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -57,6 +63,7 @@ class EditHubState extends Equatable {
|
|||||||
status,
|
status,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
successMessage,
|
successMessage,
|
||||||
|
successKey,
|
||||||
costCenters,
|
costCenters,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class HubDetailsBloc extends Bloc<HubDetailsEvent, HubDetailsState>
|
|||||||
emit(
|
emit(
|
||||||
state.copyWith(
|
state.copyWith(
|
||||||
status: HubDetailsStatus.deleted,
|
status: HubDetailsStatus.deleted,
|
||||||
successMessage: 'Hub deleted successfully',
|
successKey: 'deleted',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ class HubDetailsState extends Equatable {
|
|||||||
this.status = HubDetailsStatus.initial,
|
this.status = HubDetailsStatus.initial,
|
||||||
this.errorMessage,
|
this.errorMessage,
|
||||||
this.successMessage,
|
this.successMessage,
|
||||||
|
this.successKey,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The status of the operation.
|
/// The status of the operation.
|
||||||
@@ -35,19 +36,24 @@ class HubDetailsState extends Equatable {
|
|||||||
/// The success message if the operation succeeded.
|
/// The success message if the operation succeeded.
|
||||||
final String? successMessage;
|
final String? successMessage;
|
||||||
|
|
||||||
|
/// Localization key for success message: 'deleted'.
|
||||||
|
final String? successKey;
|
||||||
|
|
||||||
/// Create a copy of this state with the given fields replaced.
|
/// Create a copy of this state with the given fields replaced.
|
||||||
HubDetailsState copyWith({
|
HubDetailsState copyWith({
|
||||||
HubDetailsStatus? status,
|
HubDetailsStatus? status,
|
||||||
String? errorMessage,
|
String? errorMessage,
|
||||||
String? successMessage,
|
String? successMessage,
|
||||||
|
String? successKey,
|
||||||
}) {
|
}) {
|
||||||
return HubDetailsState(
|
return HubDetailsState(
|
||||||
status: status ?? this.status,
|
status: status ?? this.status,
|
||||||
errorMessage: errorMessage ?? this.errorMessage,
|
errorMessage: errorMessage ?? this.errorMessage,
|
||||||
successMessage: successMessage ?? this.successMessage,
|
successMessage: successMessage ?? this.successMessage,
|
||||||
|
successKey: successKey ?? this.successKey,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => <Object?>[status, errorMessage, successMessage];
|
List<Object?> get props => <Object?>[status, errorMessage, successMessage, successKey];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:core_localization/core_localization.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@@ -34,14 +35,16 @@ class _EditHubPageState extends State<EditHubPage> {
|
|||||||
value: widget.bloc,
|
value: widget.bloc,
|
||||||
child: BlocListener<EditHubBloc, EditHubState>(
|
child: BlocListener<EditHubBloc, EditHubState>(
|
||||||
listenWhen: (EditHubState prev, EditHubState curr) =>
|
listenWhen: (EditHubState prev, EditHubState curr) =>
|
||||||
prev.status != curr.status ||
|
prev.status != curr.status || prev.successKey != curr.successKey,
|
||||||
prev.successMessage != curr.successMessage,
|
|
||||||
listener: (BuildContext context, EditHubState state) {
|
listener: (BuildContext context, EditHubState state) {
|
||||||
if (state.status == EditHubStatus.success &&
|
if (state.status == EditHubStatus.success &&
|
||||||
state.successMessage != null) {
|
state.successKey != null) {
|
||||||
|
final String message = state.successKey == 'created'
|
||||||
|
? t.client_hubs.edit_hub.created_success
|
||||||
|
: t.client_hubs.edit_hub.updated_success;
|
||||||
UiSnackbar.show(
|
UiSnackbar.show(
|
||||||
context,
|
context,
|
||||||
message: state.successMessage!,
|
message: message,
|
||||||
type: UiSnackbarType.success,
|
type: UiSnackbarType.success,
|
||||||
);
|
);
|
||||||
Modular.to.pop(true);
|
Modular.to.pop(true);
|
||||||
|
|||||||
@@ -29,9 +29,12 @@ class HubDetailsPage extends StatelessWidget {
|
|||||||
child: BlocListener<HubDetailsBloc, HubDetailsState>(
|
child: BlocListener<HubDetailsBloc, HubDetailsState>(
|
||||||
listener: (BuildContext context, HubDetailsState state) {
|
listener: (BuildContext context, HubDetailsState state) {
|
||||||
if (state.status == HubDetailsStatus.deleted) {
|
if (state.status == HubDetailsStatus.deleted) {
|
||||||
|
final String message = state.successKey == 'deleted'
|
||||||
|
? t.client_hubs.hub_details.deleted_success
|
||||||
|
: (state.successMessage ?? t.client_hubs.hub_details.deleted_success);
|
||||||
UiSnackbar.show(
|
UiSnackbar.show(
|
||||||
context,
|
context,
|
||||||
message: state.successMessage ?? 'Hub deleted successfully',
|
message: message,
|
||||||
type: UiSnackbarType.success,
|
type: UiSnackbarType.success,
|
||||||
);
|
);
|
||||||
Modular.to.pop(true); // Return true to indicate change
|
Modular.to.pop(true); // Return true to indicate change
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class EditHubFormSection extends StatelessWidget {
|
|||||||
textInputAction: TextInputAction.next,
|
textInputAction: TextInputAction.next,
|
||||||
validator: (String? value) {
|
validator: (String? value) {
|
||||||
if (value == null || value.trim().isEmpty) {
|
if (value == null || value.trim().isEmpty) {
|
||||||
return 'Name is required';
|
return t.client_hubs.edit_hub.name_required;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@@ -181,11 +181,11 @@ class EditHubFormSection extends StatelessWidget {
|
|||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxHeight: 400),
|
constraints: const BoxConstraints(maxHeight: 400),
|
||||||
child: costCenters.isEmpty
|
child : costCenters.isEmpty
|
||||||
? const Padding(
|
? Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
child: Text('No cost centers available'),
|
child: Text(t.client_hubs.edit_hub.cost_centers_empty),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: costCenters.length,
|
itemCount: costCenters.length,
|
||||||
|
|||||||
@@ -318,9 +318,9 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
|||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxHeight: 400),
|
constraints: const BoxConstraints(maxHeight: 400),
|
||||||
child: widget.costCenters.isEmpty
|
child: widget.costCenters.isEmpty
|
||||||
? const Padding(
|
? Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24),
|
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
child: Text('No cost centers available'),
|
child: Text(t.client_hubs.add_hub_dialog.cost_centers_empty),
|
||||||
)
|
)
|
||||||
: ListView.builder(
|
: ListView.builder(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ class HubManagerSelector extends StatelessWidget {
|
|||||||
required this.hintText,
|
required this.hintText,
|
||||||
required this.label,
|
required this.label,
|
||||||
this.description,
|
this.description,
|
||||||
|
this.noManagersText,
|
||||||
|
this.noneText,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,6 +22,8 @@ class HubManagerSelector extends StatelessWidget {
|
|||||||
final String hintText;
|
final String hintText;
|
||||||
final String label;
|
final String label;
|
||||||
final String? description;
|
final String? description;
|
||||||
|
final String? noManagersText;
|
||||||
|
final String? noneText;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -107,18 +111,20 @@ class HubManagerSelector extends StatelessWidget {
|
|||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
itemCount: managers.isEmpty ? 2 : managers.length + 1,
|
itemCount: managers.isEmpty ? 2 : managers.length + 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final String emptyText = noManagersText ?? 'No hub managers available';
|
||||||
|
final String noneLabel = noneText ?? 'None';
|
||||||
if (managers.isEmpty) {
|
if (managers.isEmpty) {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return const Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||||
child: Text('No hub managers available'),
|
child: Text(emptyText),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
title: Text('None', style: UiTypography.body1m.textSecondary),
|
title: Text(noneLabel, style: UiTypography.body1m.textSecondary),
|
||||||
onTap: () => Navigator.of(context).pop(
|
onTap: () => Navigator.of(context).pop(
|
||||||
const OrderManagerUiModel(id: 'NONE', name: 'None'),
|
OrderManagerUiModel(id: 'NONE', name: noneLabel),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -126,9 +132,9 @@ class HubManagerSelector extends StatelessWidget {
|
|||||||
if (index == managers.length) {
|
if (index == managers.length) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
title: Text('None', style: UiTypography.body1m.textSecondary),
|
title: Text(noneLabel, style: UiTypography.body1m.textSecondary),
|
||||||
onTap: () => Navigator.of(context).pop(
|
onTap: () => Navigator.of(context).pop(
|
||||||
const OrderManagerUiModel(id: 'NONE', name: 'None'),
|
OrderManagerUiModel(id: 'NONE', name: noneLabel),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -332,6 +332,8 @@ class _OneTimeOrderForm extends StatelessWidget {
|
|||||||
label: labels.hub_manager_label,
|
label: labels.hub_manager_label,
|
||||||
description: labels.hub_manager_desc,
|
description: labels.hub_manager_desc,
|
||||||
hintText: labels.hub_manager_hint,
|
hintText: labels.hub_manager_hint,
|
||||||
|
noManagersText: labels.hub_manager_empty,
|
||||||
|
noneText: labels.hub_manager_none,
|
||||||
managers: hubManagers,
|
managers: hubManagers,
|
||||||
selectedManager: selectedHubManager,
|
selectedManager: selectedHubManager,
|
||||||
onChanged: onHubManagerChanged,
|
onChanged: onHubManagerChanged,
|
||||||
|
|||||||
@@ -354,6 +354,8 @@ class _PermanentOrderForm extends StatelessWidget {
|
|||||||
label: oneTimeLabels.hub_manager_label,
|
label: oneTimeLabels.hub_manager_label,
|
||||||
description: oneTimeLabels.hub_manager_desc,
|
description: oneTimeLabels.hub_manager_desc,
|
||||||
hintText: oneTimeLabels.hub_manager_hint,
|
hintText: oneTimeLabels.hub_manager_hint,
|
||||||
|
noManagersText: oneTimeLabels.hub_manager_empty,
|
||||||
|
noneText: oneTimeLabels.hub_manager_none,
|
||||||
managers: hubManagers,
|
managers: hubManagers,
|
||||||
selectedManager: selectedHubManager,
|
selectedManager: selectedHubManager,
|
||||||
onChanged: onHubManagerChanged,
|
onChanged: onHubManagerChanged,
|
||||||
|
|||||||
@@ -375,6 +375,8 @@ class _RecurringOrderForm extends StatelessWidget {
|
|||||||
label: oneTimeLabels.hub_manager_label,
|
label: oneTimeLabels.hub_manager_label,
|
||||||
description: oneTimeLabels.hub_manager_desc,
|
description: oneTimeLabels.hub_manager_desc,
|
||||||
hintText: oneTimeLabels.hub_manager_hint,
|
hintText: oneTimeLabels.hub_manager_hint,
|
||||||
|
noManagersText: oneTimeLabels.hub_manager_empty,
|
||||||
|
noneText: oneTimeLabels.hub_manager_none,
|
||||||
managers: hubManagers,
|
managers: hubManagers,
|
||||||
selectedManager: selectedHubManager,
|
selectedManager: selectedHubManager,
|
||||||
onChanged: onHubManagerChanged,
|
onChanged: onHubManagerChanged,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:core_localization/core_localization.dart';
|
||||||
import 'package:design_system/design_system.dart';
|
import 'package:design_system/design_system.dart';
|
||||||
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
import 'package:firebase_auth/firebase_auth.dart' as firebase;
|
||||||
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
import 'package:firebase_data_connect/firebase_data_connect.dart';
|
||||||
@@ -686,7 +687,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
padding: const EdgeInsets.all(UiConstants.space5),
|
padding: const EdgeInsets.all(UiConstants.space5),
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
'Edit Your Order',
|
t.client_view_orders.order_edit_sheet.title,
|
||||||
style: UiTypography.headline3m.textPrimary,
|
style: UiTypography.headline3m.textPrimary,
|
||||||
),
|
),
|
||||||
const SizedBox(height: UiConstants.space4),
|
const SizedBox(height: UiConstants.space4),
|
||||||
@@ -744,7 +745,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
_buildSectionHeader('ORDER NAME'),
|
_buildSectionHeader('ORDER NAME'),
|
||||||
UiTextField(
|
UiTextField(
|
||||||
controller: _orderNameController,
|
controller: _orderNameController,
|
||||||
hintText: 'Order name',
|
hintText: t.client_view_orders.order_edit_sheet.order_name_hint,
|
||||||
prefixIcon: UiIcons.briefcase,
|
prefixIcon: UiIcons.briefcase,
|
||||||
),
|
),
|
||||||
const SizedBox(height: UiConstants.space4),
|
const SizedBox(height: UiConstants.space4),
|
||||||
@@ -801,7 +802,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
'POSITIONS',
|
t.client_view_orders.order_edit_sheet.positions_section,
|
||||||
style: UiTypography.headline4m.textPrimary,
|
style: UiTypography.headline4m.textPrimary,
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -821,7 +822,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
color: UiColors.primary,
|
color: UiColors.primary,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Add Position',
|
t.client_view_orders.order_edit_sheet.add_position,
|
||||||
style: UiTypography.body2m.primary,
|
style: UiTypography.body2m.primary,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -842,7 +843,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
_buildBottomAction(
|
_buildBottomAction(
|
||||||
label: 'Review ${_positions.length} Positions',
|
label: t.client_view_orders.order_edit_sheet.review_positions(count: _positions.length.toString()),
|
||||||
onPressed: () => setState(() => _showReview = true),
|
onPressed: () => setState(() => _showReview = true),
|
||||||
),
|
),
|
||||||
const Padding(
|
const Padding(
|
||||||
@@ -859,11 +860,13 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildHubManagerSelector() {
|
Widget _buildHubManagerSelector() {
|
||||||
|
final TranslationsClientViewOrdersOrderEditSheetEn oes =
|
||||||
|
t.client_view_orders.order_edit_sheet;
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildSectionHeader('SHIFT CONTACT'),
|
_buildSectionHeader(oes.shift_contact_section),
|
||||||
Text('On-site manager or supervisor for this shift', style: UiTypography.body2r.textSecondary),
|
Text(oes.shift_contact_desc, style: UiTypography.body2r.textSecondary),
|
||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () => _showHubManagerSelector(),
|
onTap: () => _showHubManagerSelector(),
|
||||||
@@ -895,7 +898,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space3),
|
const SizedBox(width: UiConstants.space3),
|
||||||
Text(
|
Text(
|
||||||
_selectedManager?.user.fullName ?? 'Select Contact',
|
_selectedManager?.user.fullName ?? oes.select_contact,
|
||||||
style: _selectedManager != null
|
style: _selectedManager != null
|
||||||
? UiTypography.body1r.textPrimary
|
? UiTypography.body1r.textPrimary
|
||||||
: UiTypography.body2r.textPlaceholder,
|
: UiTypography.body2r.textPlaceholder,
|
||||||
@@ -925,7 +928,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
borderRadius: BorderRadius.circular(UiConstants.radiusBase),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
'Shift Contact',
|
t.client_view_orders.order_edit_sheet.shift_contact_section,
|
||||||
style: UiTypography.headline3m.textPrimary,
|
style: UiTypography.headline3m.textPrimary,
|
||||||
),
|
),
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
contentPadding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
@@ -939,14 +942,14 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
if (_managers.isEmpty) {
|
if (_managers.isEmpty) {
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
return const Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 8),
|
||||||
child: Text('No hub managers available'),
|
child: Text(t.client_view_orders.order_edit_sheet.no_hub_managers),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
title: Text('None', style: UiTypography.body1m.textSecondary),
|
title: Text(t.client_view_orders.order_edit_sheet.none, style: UiTypography.body1m.textSecondary),
|
||||||
onTap: () => Navigator.of(context).pop(null),
|
onTap: () => Navigator.of(context).pop(null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -954,7 +957,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
if (index == _managers.length) {
|
if (index == _managers.length) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
title: Text('None', style: UiTypography.body1m.textSecondary),
|
title: Text(t.client_view_orders.order_edit_sheet.none, style: UiTypography.body1m.textSecondary),
|
||||||
onTap: () => Navigator.of(context).pop(null),
|
onTap: () => Navigator.of(context).pop(null),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1014,11 +1017,11 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
'One-Time Order',
|
t.client_view_orders.order_edit_sheet.one_time_order_title,
|
||||||
style: UiTypography.headline3m.copyWith(color: UiColors.white),
|
style: UiTypography.headline3m.copyWith(color: UiColors.white),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'Refine your staffing needs',
|
t.client_view_orders.order_edit_sheet.refine_subtitle,
|
||||||
style: UiTypography.footnote2r.copyWith(
|
style: UiTypography.footnote2r.copyWith(
|
||||||
color: UiColors.white.withValues(alpha: 0.8),
|
color: UiColors.white.withValues(alpha: 0.8),
|
||||||
),
|
),
|
||||||
@@ -1060,7 +1063,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => _removePosition(index),
|
onTap: () => _removePosition(index),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Remove',
|
t.client_view_orders.order_edit_sheet.remove,
|
||||||
style: UiTypography.footnote1m.copyWith(
|
style: UiTypography.footnote1m.copyWith(
|
||||||
color: UiColors.destructive,
|
color: UiColors.destructive,
|
||||||
),
|
),
|
||||||
@@ -1071,7 +1074,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
const SizedBox(height: UiConstants.space3),
|
const SizedBox(height: UiConstants.space3),
|
||||||
|
|
||||||
_buildDropdownField(
|
_buildDropdownField(
|
||||||
hint: 'Select role',
|
hint: t.client_view_orders.order_edit_sheet.select_role_hint,
|
||||||
value: pos['roleId'],
|
value: pos['roleId'],
|
||||||
items: <String>[
|
items: <String>[
|
||||||
..._roles.map((_RoleOption role) => role.id),
|
..._roles.map((_RoleOption role) => role.id),
|
||||||
@@ -1106,7 +1109,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildInlineTimeInput(
|
child: _buildInlineTimeInput(
|
||||||
label: 'Start',
|
label: t.client_view_orders.order_edit_sheet.start_label,
|
||||||
value: pos['start_time'],
|
value: pos['start_time'],
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final TimeOfDay? picked = await showTimePicker(
|
final TimeOfDay? picked = await showTimePicker(
|
||||||
@@ -1126,7 +1129,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
const SizedBox(width: UiConstants.space2),
|
const SizedBox(width: UiConstants.space2),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _buildInlineTimeInput(
|
child: _buildInlineTimeInput(
|
||||||
label: 'End',
|
label: t.client_view_orders.order_edit_sheet.end_label,
|
||||||
value: pos['end_time'],
|
value: pos['end_time'],
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final TimeOfDay? picked = await showTimePicker(
|
final TimeOfDay? picked = await showTimePicker(
|
||||||
@@ -1149,7 +1152,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
'Workers',
|
t.client_view_orders.order_edit_sheet.workers_label,
|
||||||
style: UiTypography.footnote2r.textSecondary,
|
style: UiTypography.footnote2r.textSecondary,
|
||||||
),
|
),
|
||||||
const SizedBox(height: UiConstants.space1),
|
const SizedBox(height: UiConstants.space1),
|
||||||
@@ -1204,7 +1207,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
const Icon(UiIcons.mapPin, size: 14, color: UiColors.primary),
|
const Icon(UiIcons.mapPin, size: 14, color: UiColors.primary),
|
||||||
const SizedBox(width: UiConstants.space1),
|
const SizedBox(width: UiConstants.space1),
|
||||||
Text(
|
Text(
|
||||||
'Use different location for this position',
|
t.client_view_orders.order_edit_sheet.different_location,
|
||||||
style: UiTypography.footnote1m.copyWith(
|
style: UiTypography.footnote1m.copyWith(
|
||||||
color: UiColors.primary,
|
color: UiColors.primary,
|
||||||
),
|
),
|
||||||
@@ -1228,7 +1231,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: UiConstants.space1),
|
const SizedBox(width: UiConstants.space1),
|
||||||
Text(
|
Text(
|
||||||
'Different Location',
|
t.client_view_orders.order_edit_sheet.different_location_title,
|
||||||
style: UiTypography.footnote1m.textSecondary,
|
style: UiTypography.footnote1m.textSecondary,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -1246,7 +1249,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
const SizedBox(height: UiConstants.space2),
|
const SizedBox(height: UiConstants.space2),
|
||||||
UiTextField(
|
UiTextField(
|
||||||
controller: TextEditingController(text: pos['location']),
|
controller: TextEditingController(text: pos['location']),
|
||||||
hintText: 'Enter different address',
|
hintText: t.client_view_orders.order_edit_sheet.enter_address_hint,
|
||||||
onChanged: (String val) =>
|
onChanged: (String val) =>
|
||||||
_updatePosition(index, 'location', val),
|
_updatePosition(index, 'location', val),
|
||||||
),
|
),
|
||||||
@@ -1257,7 +1260,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
|
|
||||||
_buildSectionHeader('LUNCH BREAK'),
|
_buildSectionHeader('LUNCH BREAK'),
|
||||||
_buildDropdownField(
|
_buildDropdownField(
|
||||||
hint: 'No Break',
|
hint: t.client_view_orders.order_edit_sheet.no_break,
|
||||||
value: pos['lunch_break'],
|
value: pos['lunch_break'],
|
||||||
items: <String>[
|
items: <String>[
|
||||||
'NO_BREAK',
|
'NO_BREAK',
|
||||||
@@ -1280,7 +1283,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
case 'MIN_60':
|
case 'MIN_60':
|
||||||
return '60 min (Unpaid)';
|
return '60 min (Unpaid)';
|
||||||
default:
|
default:
|
||||||
return 'No Break';
|
return t.client_view_orders.order_edit_sheet.no_break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onChanged: (dynamic val) =>
|
onChanged: (dynamic val) =>
|
||||||
@@ -1438,11 +1441,11 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
_buildSummaryItem('${_positions.length}', 'Positions'),
|
_buildSummaryItem('${_positions.length}', t.client_view_orders.order_edit_sheet.positions),
|
||||||
_buildSummaryItem('$totalWorkers', 'Workers'),
|
_buildSummaryItem('$totalWorkers', t.client_view_orders.order_edit_sheet.workers),
|
||||||
_buildSummaryItem(
|
_buildSummaryItem(
|
||||||
'\$${totalCost.round()}',
|
'\$${totalCost.round()}',
|
||||||
'Est. Cost',
|
t.client_view_orders.order_edit_sheet.est_cost,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -1501,7 +1504,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
'Positions Breakdown',
|
t.client_view_orders.order_edit_sheet.positions_breakdown,
|
||||||
style: UiTypography.body2b.textPrimary,
|
style: UiTypography.body2b.textPrimary,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
@@ -1532,14 +1535,14 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Expanded(
|
Expanded(
|
||||||
child: UiButton.secondary(
|
child: UiButton.secondary(
|
||||||
text: 'Edit',
|
text: t.client_view_orders.order_edit_sheet.edit_button,
|
||||||
onPressed: () => setState(() => _showReview = false),
|
onPressed: () => setState(() => _showReview = false),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: UiButton.primary(
|
child: UiButton.primary(
|
||||||
text: 'Confirm & Save',
|
text: t.client_view_orders.order_edit_sheet.confirm_save,
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
setState(() => _isLoading = true);
|
setState(() => _isLoading = true);
|
||||||
await _saveOrderChanges();
|
await _saveOrderChanges();
|
||||||
@@ -1601,7 +1604,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Text(
|
Text(
|
||||||
(role?.name ?? pos['roleName']?.toString() ?? '').isEmpty
|
(role?.name ?? pos['roleName']?.toString() ?? '').isEmpty
|
||||||
? 'Position'
|
? t.client_view_orders.order_edit_sheet.position_singular
|
||||||
: (role?.name ?? pos['roleName']?.toString() ?? ''),
|
: (role?.name ?? pos['roleName']?.toString() ?? ''),
|
||||||
style: UiTypography.body2b.textPrimary,
|
style: UiTypography.body2b.textPrimary,
|
||||||
),
|
),
|
||||||
@@ -1667,14 +1670,14 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
Text(
|
Text(
|
||||||
'Order Updated!',
|
t.client_view_orders.order_edit_sheet.order_updated_title,
|
||||||
style: UiTypography.headline1m.copyWith(color: UiColors.white),
|
style: UiTypography.headline1m.copyWith(color: UiColors.white),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Your shift has been updated successfully.',
|
t.client_view_orders.order_edit_sheet.order_updated_message,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: UiTypography.body1r.copyWith(
|
style: UiTypography.body1r.copyWith(
|
||||||
color: UiColors.white.withValues(alpha: 0.7),
|
color: UiColors.white.withValues(alpha: 0.7),
|
||||||
@@ -1685,7 +1688,7 @@ class OrderEditSheetState extends State<OrderEditSheet> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 40),
|
padding: const EdgeInsets.symmetric(horizontal: 40),
|
||||||
child: UiButton.secondary(
|
child: UiButton.secondary(
|
||||||
text: 'Back to Orders',
|
text: t.client_view_orders.order_edit_sheet.back_to_orders,
|
||||||
fullWidth: true,
|
fullWidth: true,
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
backgroundColor: UiColors.white,
|
backgroundColor: UiColors.white,
|
||||||
|
|||||||
Reference in New Issue
Block a user