UI fields for cost center
This commit is contained in:
@@ -252,6 +252,8 @@
|
||||
"location_hint": "e.g., Downtown Restaurant",
|
||||
"address_label": "Address",
|
||||
"address_hint": "Full address",
|
||||
"cost_center_label": "Cost Center",
|
||||
"cost_center_hint": "eg: 1001, 1002",
|
||||
"create_button": "Create Hub"
|
||||
},
|
||||
"edit_hub": {
|
||||
@@ -261,6 +263,8 @@
|
||||
"name_hint": "e.g., Main Kitchen, Front Desk",
|
||||
"address_label": "Address",
|
||||
"address_hint": "Full address",
|
||||
"cost_center_label": "Cost Center",
|
||||
"cost_center_hint": "eg: 1001, 1002",
|
||||
"save_button": "Save Changes",
|
||||
"success": "Hub updated successfully!"
|
||||
},
|
||||
@@ -270,6 +274,8 @@
|
||||
"address_label": "Address",
|
||||
"nfc_label": "NFC Tag",
|
||||
"nfc_not_assigned": "Not Assigned",
|
||||
"cost_center_label": "Cost Center",
|
||||
"cost_center_none": "Not Assigned",
|
||||
"edit_button": "Edit Hub"
|
||||
},
|
||||
"nfc_dialog": {
|
||||
|
||||
@@ -252,6 +252,8 @@
|
||||
"location_hint": "ej., Restaurante Centro",
|
||||
"address_label": "Direcci\u00f3n",
|
||||
"address_hint": "Direcci\u00f3n completa",
|
||||
"cost_center_label": "Centro de Costos",
|
||||
"cost_center_hint": "ej: 1001, 1002",
|
||||
"create_button": "Crear Hub"
|
||||
},
|
||||
"nfc_dialog": {
|
||||
@@ -276,6 +278,8 @@
|
||||
"name_hint": "Ingresar nombre del hub",
|
||||
"address_label": "Direcci\u00f3n",
|
||||
"address_hint": "Ingresar direcci\u00f3n",
|
||||
"cost_center_label": "Centro de Costos",
|
||||
"cost_center_hint": "ej: 1001, 1002",
|
||||
"save_button": "Guardar Cambios",
|
||||
"success": "\u00a1Hub actualizado exitosamente!"
|
||||
},
|
||||
@@ -285,7 +289,9 @@
|
||||
"name_label": "Nombre del Hub",
|
||||
"address_label": "Direcci\u00f3n",
|
||||
"nfc_label": "Etiqueta NFC",
|
||||
"nfc_not_assigned": "No asignada"
|
||||
"nfc_not_assigned": "No asignada",
|
||||
"cost_center_label": "Centro de Costos",
|
||||
"cost_center_none": "No asignado"
|
||||
}
|
||||
},
|
||||
"client_create_order": {
|
||||
|
||||
@@ -14,7 +14,6 @@ enum HubStatus {
|
||||
|
||||
/// Represents a branch location or operational unit within a [Business].
|
||||
class Hub extends Equatable {
|
||||
|
||||
const Hub({
|
||||
required this.id,
|
||||
required this.businessId,
|
||||
@@ -22,6 +21,7 @@ class Hub extends Equatable {
|
||||
required this.address,
|
||||
this.nfcTagId,
|
||||
required this.status,
|
||||
this.costCenter,
|
||||
});
|
||||
/// Unique identifier.
|
||||
final String id;
|
||||
@@ -41,6 +41,9 @@ class Hub extends Equatable {
|
||||
/// Operational status.
|
||||
final HubStatus status;
|
||||
|
||||
/// Assigned cost center for this hub.
|
||||
final String? costCenter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[id, businessId, name, address, nfcTagId, status];
|
||||
List<Object?> get props => <Object?>[id, businessId, name, address, nfcTagId, status, costCenter];
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
String? street,
|
||||
String? country,
|
||||
String? zipCode,
|
||||
String? costCenter,
|
||||
}) async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
return _connectorRepository.createHub(
|
||||
@@ -79,6 +80,7 @@ class HubRepositoryImpl implements HubRepositoryInterface {
|
||||
String? street,
|
||||
String? country,
|
||||
String? zipCode,
|
||||
String? costCenter,
|
||||
}) async {
|
||||
final String businessId = await _service.getBusinessId();
|
||||
return _connectorRepository.updateHub(
|
||||
|
||||
@@ -19,6 +19,7 @@ class CreateHubArguments extends UseCaseArgument {
|
||||
this.street,
|
||||
this.country,
|
||||
this.zipCode,
|
||||
this.costCenter,
|
||||
});
|
||||
/// The name of the hub.
|
||||
final String name;
|
||||
@@ -34,6 +35,9 @@ class CreateHubArguments extends UseCaseArgument {
|
||||
final String? street;
|
||||
final String? country;
|
||||
final String? zipCode;
|
||||
|
||||
/// The cost center of the hub.
|
||||
final String? costCenter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
@@ -47,5 +51,6 @@ class CreateHubArguments extends UseCaseArgument {
|
||||
street,
|
||||
country,
|
||||
zipCode,
|
||||
costCenter,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ abstract interface class HubRepositoryInterface {
|
||||
String? street,
|
||||
String? country,
|
||||
String? zipCode,
|
||||
String? costCenter,
|
||||
});
|
||||
|
||||
/// Deletes a hub by its [id].
|
||||
@@ -51,5 +52,6 @@ abstract interface class HubRepositoryInterface {
|
||||
String? street,
|
||||
String? country,
|
||||
String? zipCode,
|
||||
String? costCenter,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,7 +16,9 @@ class UpdateHubArguments extends UseCaseArgument {
|
||||
this.state,
|
||||
this.street,
|
||||
this.country,
|
||||
this.country,
|
||||
this.zipCode,
|
||||
this.costCenter,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@@ -30,6 +32,7 @@ class UpdateHubArguments extends UseCaseArgument {
|
||||
final String? street;
|
||||
final String? country;
|
||||
final String? zipCode;
|
||||
final String? costCenter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
@@ -44,6 +47,7 @@ class UpdateHubArguments extends UseCaseArgument {
|
||||
street,
|
||||
country,
|
||||
zipCode,
|
||||
costCenter,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -67,6 +71,7 @@ class UpdateHubUseCase implements UseCase<UpdateHubArguments, Hub> {
|
||||
street: params.street,
|
||||
country: params.country,
|
||||
zipCode: params.zipCode,
|
||||
costCenter: params.costCenter,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
street: event.street,
|
||||
country: event.country,
|
||||
zipCode: event.zipCode,
|
||||
costCenter: event.costCenter,
|
||||
),
|
||||
);
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
@@ -147,6 +148,7 @@ class ClientHubsBloc extends Bloc<ClientHubsEvent, ClientHubsState>
|
||||
street: event.street,
|
||||
country: event.country,
|
||||
zipCode: event.zipCode,
|
||||
costCenter: event.costCenter,
|
||||
),
|
||||
);
|
||||
final List<Hub> hubs = await _getHubsUseCase();
|
||||
|
||||
@@ -28,6 +28,7 @@ class ClientHubsAddRequested extends ClientHubsEvent {
|
||||
this.street,
|
||||
this.country,
|
||||
this.zipCode,
|
||||
this.costCenter,
|
||||
});
|
||||
final String name;
|
||||
final String address;
|
||||
@@ -39,6 +40,7 @@ class ClientHubsAddRequested extends ClientHubsEvent {
|
||||
final String? street;
|
||||
final String? country;
|
||||
final String? zipCode;
|
||||
final String? costCenter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
@@ -52,6 +54,7 @@ class ClientHubsAddRequested extends ClientHubsEvent {
|
||||
street,
|
||||
country,
|
||||
zipCode,
|
||||
costCenter,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -69,6 +72,7 @@ class ClientHubsUpdateRequested extends ClientHubsEvent {
|
||||
this.street,
|
||||
this.country,
|
||||
this.zipCode,
|
||||
this.costCenter,
|
||||
});
|
||||
|
||||
final String id;
|
||||
@@ -82,6 +86,7 @@ class ClientHubsUpdateRequested extends ClientHubsEvent {
|
||||
final String? street;
|
||||
final String? country;
|
||||
final String? zipCode;
|
||||
final String? costCenter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => <Object?>[
|
||||
@@ -96,6 +101,7 @@ class ClientHubsUpdateRequested extends ClientHubsEvent {
|
||||
street,
|
||||
country,
|
||||
zipCode,
|
||||
costCenter,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ class EditHubPage extends StatefulWidget {
|
||||
class _EditHubPageState extends State<EditHubPage> {
|
||||
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
|
||||
late final TextEditingController _nameController;
|
||||
late final TextEditingController _costCenterController;
|
||||
late final TextEditingController _addressController;
|
||||
late final FocusNode _addressFocusNode;
|
||||
Prediction? _selectedPrediction;
|
||||
@@ -40,6 +41,7 @@ class _EditHubPageState extends State<EditHubPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_nameController = TextEditingController(text: widget.hub.name);
|
||||
_costCenterController = TextEditingController(text: widget.hub.costCenter);
|
||||
_addressController = TextEditingController(text: widget.hub.address);
|
||||
_addressFocusNode = FocusNode();
|
||||
}
|
||||
@@ -47,6 +49,7 @@ class _EditHubPageState extends State<EditHubPage> {
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_costCenterController.dispose();
|
||||
_addressController.dispose();
|
||||
_addressFocusNode.dispose();
|
||||
super.dispose();
|
||||
@@ -72,6 +75,7 @@ class _EditHubPageState extends State<EditHubPage> {
|
||||
placeId: _selectedPrediction?.placeId,
|
||||
latitude: double.tryParse(_selectedPrediction?.lat ?? ''),
|
||||
longitude: double.tryParse(_selectedPrediction?.lng ?? ''),
|
||||
costCenter: _costCenterController.text.trim().isEmpty ? null : _costCenterController.text.trim(),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -160,6 +164,19 @@ class _EditHubPageState extends State<EditHubPage> {
|
||||
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
|
||||
// ── Cost Center field ────────────────────────────
|
||||
_FieldLabel(t.client_hubs.edit_hub.cost_center_label),
|
||||
TextFormField(
|
||||
controller: _costCenterController,
|
||||
style: UiTypography.body1r.textPrimary,
|
||||
textInputAction: TextInputAction.next,
|
||||
decoration: _inputDecoration(
|
||||
t.client_hubs.edit_hub.cost_center_hint,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
|
||||
// ── Address field ────────────────────────────────
|
||||
_FieldLabel(t.client_hubs.edit_hub.address_label),
|
||||
HubAddressAutocomplete(
|
||||
|
||||
@@ -54,6 +54,14 @@ class HubDetailsPage extends StatelessWidget {
|
||||
icon: UiIcons.home,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildDetailItem(
|
||||
label: t.client_hubs.hub_details.cost_center_label,
|
||||
value: hub.costCenter?.isNotEmpty == true
|
||||
? hub.costCenter!
|
||||
: t.client_hubs.hub_details.cost_center_none,
|
||||
icon: UiIcons.dollarSign, // or UiIcons.building, hash, etc.
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildDetailItem(
|
||||
label: t.client_hubs.hub_details.address_label,
|
||||
value: hub.address,
|
||||
|
||||
@@ -21,6 +21,7 @@ class AddHubDialog extends StatefulWidget {
|
||||
String? placeId,
|
||||
double? latitude,
|
||||
double? longitude,
|
||||
String? costCenter,
|
||||
}) onCreate;
|
||||
|
||||
/// Callback when the dialog is cancelled.
|
||||
@@ -32,6 +33,7 @@ class AddHubDialog extends StatefulWidget {
|
||||
|
||||
class _AddHubDialogState extends State<AddHubDialog> {
|
||||
late final TextEditingController _nameController;
|
||||
late final TextEditingController _costCenterController;
|
||||
late final TextEditingController _addressController;
|
||||
late final FocusNode _addressFocusNode;
|
||||
Prediction? _selectedPrediction;
|
||||
@@ -40,6 +42,7 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_nameController = TextEditingController();
|
||||
_costCenterController = TextEditingController();
|
||||
_addressController = TextEditingController();
|
||||
_addressFocusNode = FocusNode();
|
||||
}
|
||||
@@ -47,6 +50,7 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_costCenterController.dispose();
|
||||
_addressController.dispose();
|
||||
_addressFocusNode.dispose();
|
||||
super.dispose();
|
||||
@@ -96,6 +100,16 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildFieldLabel(t.client_hubs.add_hub_dialog.cost_center_label),
|
||||
TextFormField(
|
||||
controller: _costCenterController,
|
||||
style: UiTypography.body1r.textPrimary,
|
||||
decoration: _buildInputDecoration(
|
||||
t.client_hubs.add_hub_dialog.cost_center_hint,
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildFieldLabel(t.client_hubs.add_hub_dialog.address_label),
|
||||
// Assuming HubAddressAutocomplete is a custom widget wrapper.
|
||||
// If it doesn't expose a validator, we might need to modify it or manually check _addressController.
|
||||
@@ -139,6 +153,7 @@ class _AddHubDialogState extends State<AddHubDialog> {
|
||||
longitude: double.tryParse(
|
||||
_selectedPrediction?.lng ?? '',
|
||||
),
|
||||
costCenter: _costCenterController.text.trim().isEmpty ? null : _costCenterController.text.trim(),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -27,6 +27,7 @@ class HubFormDialog extends StatefulWidget {
|
||||
String? placeId,
|
||||
double? latitude,
|
||||
double? longitude,
|
||||
String? costCenter,
|
||||
}) onSave;
|
||||
|
||||
/// Callback when the dialog is cancelled.
|
||||
@@ -38,6 +39,7 @@ class HubFormDialog extends StatefulWidget {
|
||||
|
||||
class _HubFormDialogState extends State<HubFormDialog> {
|
||||
late final TextEditingController _nameController;
|
||||
late final TextEditingController _costCenterController;
|
||||
late final TextEditingController _addressController;
|
||||
late final FocusNode _addressFocusNode;
|
||||
Prediction? _selectedPrediction;
|
||||
@@ -46,6 +48,7 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_nameController = TextEditingController(text: widget.hub?.name);
|
||||
_costCenterController = TextEditingController(text: widget.hub?.costCenter);
|
||||
_addressController = TextEditingController(text: widget.hub?.address);
|
||||
_addressFocusNode = FocusNode();
|
||||
}
|
||||
@@ -53,6 +56,7 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
||||
@override
|
||||
void dispose() {
|
||||
_nameController.dispose();
|
||||
_costCenterController.dispose();
|
||||
_addressController.dispose();
|
||||
_addressFocusNode.dispose();
|
||||
super.dispose();
|
||||
@@ -68,7 +72,7 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
||||
: t.client_hubs.add_hub_dialog.title;
|
||||
|
||||
final String buttonText = isEditing
|
||||
? 'Save Changes' // TODO: localize
|
||||
? t.client_hubs.edit_hub.save_button
|
||||
: t.client_hubs.add_hub_dialog.create_button;
|
||||
|
||||
return Container(
|
||||
@@ -111,6 +115,16 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildFieldLabel(t.client_hubs.add_hub_dialog.cost_center_label),
|
||||
TextFormField(
|
||||
controller: _costCenterController,
|
||||
style: UiTypography.body1r.textPrimary,
|
||||
decoration: _buildInputDecoration(
|
||||
t.client_hubs.add_hub_dialog.cost_center_hint,
|
||||
),
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
const SizedBox(height: UiConstants.space4),
|
||||
_buildFieldLabel(t.client_hubs.add_hub_dialog.address_label),
|
||||
HubAddressAutocomplete(
|
||||
controller: _addressController,
|
||||
@@ -146,10 +160,11 @@ class _HubFormDialogState extends State<HubFormDialog> {
|
||||
latitude: double.tryParse(
|
||||
_selectedPrediction?.lat ?? '',
|
||||
),
|
||||
longitude: double.tryParse(
|
||||
_selectedPrediction?.lng ?? '',
|
||||
),
|
||||
);
|
||||
longitude: double.tryParse(
|
||||
_selectedPrediction?.lng ?? '',
|
||||
),
|
||||
costCenter: _costCenterController.text.trim().isEmpty ? null : _costCenterController.text.trim(),
|
||||
);
|
||||
}
|
||||
},
|
||||
text: buttonText,
|
||||
|
||||
Reference in New Issue
Block a user