feat: Implement client hubs management feature, including CRUD operations and NFC tag assignment.

This commit is contained in:
Achintha Isuru
2026-01-21 19:50:16 -05:00
parent 78917a5f84
commit 12dfde0551
27 changed files with 1670 additions and 5 deletions

View File

@@ -196,6 +196,40 @@
"clock_in_hubs": "Clock-In Hubs",
"billing_payments": "Billing & Payments"
}
},
"client_hubs": {
"title": "Hubs",
"subtitle": "Manage clock-in locations",
"add_hub": "Add Hub",
"empty_state": {
"title": "No hubs yet",
"description": "Create clock-in stations for your locations",
"button": "Add Your First Hub"
},
"about_hubs": {
"title": "About Hubs",
"description": "Hubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones."
},
"hub_card": {
"tag_label": "Tag: $id"
},
"add_hub_dialog": {
"title": "Add New Hub",
"name_label": "Hub Name *",
"name_hint": "e.g., Main Kitchen, Front Desk",
"location_label": "Location Name",
"location_hint": "e.g., Downtown Restaurant",
"address_label": "Address",
"address_hint": "Full address",
"create_button": "Create Hub"
},
"nfc_dialog": {
"title": "Identify NFC Tag",
"instruction": "Tap your phone to the NFC tag to identify it",
"scan_button": "Scan NFC Tag",
"tag_identified": "Tag Identified",
"assign_button": "Assign Tag"
}
}
}

View File

@@ -196,5 +196,39 @@
"clock_in_hubs": "Hubs de Marcaje",
"billing_payments": "Facturación y Pagos"
}
},
"client_hubs": {
"title": "Hubs",
"subtitle": "Gestionar ubicaciones de marcaje",
"add_hub": "Añadir Hub",
"empty_state": {
"title": "No hay hubs aún",
"description": "Crea estaciones de marcaje para tus ubicaciones",
"button": "Añade tu primer Hub"
},
"about_hubs": {
"title": "Sobre los Hubs",
"description": "Los Hubs son estaciones de marcaje en tus ubicaciones. Asigna etiquetas NFC a cada hub para que los trabajadores puedan marcar entrada/salida rápidamente usando sus teléfonos."
},
"hub_card": {
"tag_label": "Etiqueta: $id"
},
"add_hub_dialog": {
"title": "Añadir Nuevo Hub",
"name_label": "Nombre del Hub *",
"name_hint": "ej., Cocina Principal, Recepción",
"location_label": "Nombre de la Ubicación",
"location_hint": "ej., Restaurante Centro",
"address_label": "Dirección",
"address_hint": "Dirección completa",
"create_button": "Crear Hub"
},
"nfc_dialog": {
"title": "Identificar Etiqueta NFC",
"instruction": "Acerque su teléfono a la etiqueta NFC para identificarla",
"scan_button": "Escanear Etiqueta NFC",
"tag_identified": "Etiqueta Identificada",
"assign_button": "Asignar Etiqueta"
}
}
}

View File

@@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 288 (144 per locale)
/// Strings: 332 (166 per locale)
///
/// Built on 2026-01-22 at 00:33 UTC
/// Built on 2026-01-22 at 00:48 UTC
// coverage:ignore-file
// ignore_for_file: type=lint, unused_import

View File

@@ -46,6 +46,7 @@ class Translations with BaseTranslations<AppLocale, Translations> {
late final TranslationsClientAuthenticationEn client_authentication = TranslationsClientAuthenticationEn._(_root);
late final TranslationsClientHomeEn client_home = TranslationsClientHomeEn._(_root);
late final TranslationsClientSettingsEn client_settings = TranslationsClientSettingsEn._(_root);
late final TranslationsClientHubsEn client_hubs = TranslationsClientHubsEn._(_root);
}
// Path: common
@@ -138,6 +139,30 @@ class TranslationsClientSettingsEn {
late final TranslationsClientSettingsProfileEn profile = TranslationsClientSettingsProfileEn._(_root);
}
// Path: client_hubs
class TranslationsClientHubsEn {
TranslationsClientHubsEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'Hubs'
String get title => 'Hubs';
/// en: 'Manage clock-in locations'
String get subtitle => 'Manage clock-in locations';
/// en: 'Add Hub'
String get add_hub => 'Add Hub';
late final TranslationsClientHubsEmptyStateEn empty_state = TranslationsClientHubsEmptyStateEn._(_root);
late final TranslationsClientHubsAboutHubsEn about_hubs = TranslationsClientHubsAboutHubsEn._(_root);
late final TranslationsClientHubsHubCardEn hub_card = TranslationsClientHubsHubCardEn._(_root);
late final TranslationsClientHubsAddHubDialogEn add_hub_dialog = TranslationsClientHubsAddHubDialogEn._(_root);
late final TranslationsClientHubsNfcDialogEn nfc_dialog = TranslationsClientHubsNfcDialogEn._(_root);
}
// Path: staff_authentication.get_started_page
class TranslationsStaffAuthenticationGetStartedPageEn {
TranslationsStaffAuthenticationGetStartedPageEn._(this._root);
@@ -578,6 +603,108 @@ class TranslationsClientSettingsProfileEn {
String get billing_payments => 'Billing & Payments';
}
// Path: client_hubs.empty_state
class TranslationsClientHubsEmptyStateEn {
TranslationsClientHubsEmptyStateEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'No hubs yet'
String get title => 'No hubs yet';
/// en: 'Create clock-in stations for your locations'
String get description => 'Create clock-in stations for your locations';
/// en: 'Add Your First Hub'
String get button => 'Add Your First Hub';
}
// Path: client_hubs.about_hubs
class TranslationsClientHubsAboutHubsEn {
TranslationsClientHubsAboutHubsEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'About Hubs'
String get title => 'About Hubs';
/// en: 'Hubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones.'
String get description => 'Hubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones.';
}
// Path: client_hubs.hub_card
class TranslationsClientHubsHubCardEn {
TranslationsClientHubsHubCardEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'Tag: $id'
String tag_label({required Object id}) => 'Tag: ${id}';
}
// Path: client_hubs.add_hub_dialog
class TranslationsClientHubsAddHubDialogEn {
TranslationsClientHubsAddHubDialogEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'Add New Hub'
String get title => 'Add New Hub';
/// en: 'Hub Name *'
String get name_label => 'Hub Name *';
/// en: 'e.g., Main Kitchen, Front Desk'
String get name_hint => 'e.g., Main Kitchen, Front Desk';
/// en: 'Location Name'
String get location_label => 'Location Name';
/// en: 'e.g., Downtown Restaurant'
String get location_hint => 'e.g., Downtown Restaurant';
/// en: 'Address'
String get address_label => 'Address';
/// en: 'Full address'
String get address_hint => 'Full address';
/// en: 'Create Hub'
String get create_button => 'Create Hub';
}
// Path: client_hubs.nfc_dialog
class TranslationsClientHubsNfcDialogEn {
TranslationsClientHubsNfcDialogEn._(this._root);
final Translations _root; // ignore: unused_field
// Translations
/// en: 'Identify NFC Tag'
String get title => 'Identify NFC Tag';
/// en: 'Tap your phone to the NFC tag to identify it'
String get instruction => 'Tap your phone to the NFC tag to identify it';
/// en: 'Scan NFC Tag'
String get scan_button => 'Scan NFC Tag';
/// en: 'Tag Identified'
String get tag_identified => 'Tag Identified';
/// en: 'Assign Tag'
String get assign_button => 'Assign Tag';
}
// Path: staff_authentication.profile_setup_page.steps
class TranslationsStaffAuthenticationProfileSetupPageStepsEn {
TranslationsStaffAuthenticationProfileSetupPageStepsEn._(this._root);
@@ -898,6 +1025,28 @@ extension on Translations {
'client_settings.profile.quick_links' => 'Quick Links',
'client_settings.profile.clock_in_hubs' => 'Clock-In Hubs',
'client_settings.profile.billing_payments' => 'Billing & Payments',
'client_hubs.title' => 'Hubs',
'client_hubs.subtitle' => 'Manage clock-in locations',
'client_hubs.add_hub' => 'Add Hub',
'client_hubs.empty_state.title' => 'No hubs yet',
'client_hubs.empty_state.description' => 'Create clock-in stations for your locations',
'client_hubs.empty_state.button' => 'Add Your First Hub',
'client_hubs.about_hubs.title' => 'About Hubs',
'client_hubs.about_hubs.description' => 'Hubs are clock-in stations at your locations. Assign NFC tags to each hub so workers can quickly clock in/out using their phones.',
'client_hubs.hub_card.tag_label' => ({required Object id}) => 'Tag: ${id}',
'client_hubs.add_hub_dialog.title' => 'Add New Hub',
'client_hubs.add_hub_dialog.name_label' => 'Hub Name *',
'client_hubs.add_hub_dialog.name_hint' => 'e.g., Main Kitchen, Front Desk',
'client_hubs.add_hub_dialog.location_label' => 'Location Name',
'client_hubs.add_hub_dialog.location_hint' => 'e.g., Downtown Restaurant',
'client_hubs.add_hub_dialog.address_label' => 'Address',
'client_hubs.add_hub_dialog.address_hint' => 'Full address',
'client_hubs.add_hub_dialog.create_button' => 'Create Hub',
'client_hubs.nfc_dialog.title' => 'Identify NFC Tag',
'client_hubs.nfc_dialog.instruction' => 'Tap your phone to the NFC tag to identify it',
'client_hubs.nfc_dialog.scan_button' => 'Scan NFC Tag',
'client_hubs.nfc_dialog.tag_identified' => 'Tag Identified',
'client_hubs.nfc_dialog.assign_button' => 'Assign Tag',
_ => null,
};
}

View File

@@ -43,6 +43,7 @@ class TranslationsEs with BaseTranslations<AppLocale, Translations> implements T
@override late final _TranslationsClientAuthenticationEs client_authentication = _TranslationsClientAuthenticationEs._(_root);
@override late final _TranslationsClientHomeEs client_home = _TranslationsClientHomeEs._(_root);
@override late final _TranslationsClientSettingsEs client_settings = _TranslationsClientSettingsEs._(_root);
@override late final _TranslationsClientHubsEs client_hubs = _TranslationsClientHubsEs._(_root);
}
// Path: common
@@ -121,6 +122,23 @@ class _TranslationsClientSettingsEs implements TranslationsClientSettingsEn {
@override late final _TranslationsClientSettingsProfileEs profile = _TranslationsClientSettingsProfileEs._(_root);
}
// Path: client_hubs
class _TranslationsClientHubsEs implements TranslationsClientHubsEn {
_TranslationsClientHubsEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Hubs';
@override String get subtitle => 'Gestionar ubicaciones de marcaje';
@override String get add_hub => 'Añadir Hub';
@override late final _TranslationsClientHubsEmptyStateEs empty_state = _TranslationsClientHubsEmptyStateEs._(_root);
@override late final _TranslationsClientHubsAboutHubsEs about_hubs = _TranslationsClientHubsAboutHubsEs._(_root);
@override late final _TranslationsClientHubsHubCardEs hub_card = _TranslationsClientHubsHubCardEs._(_root);
@override late final _TranslationsClientHubsAddHubDialogEs add_hub_dialog = _TranslationsClientHubsAddHubDialogEs._(_root);
@override late final _TranslationsClientHubsNfcDialogEs nfc_dialog = _TranslationsClientHubsNfcDialogEs._(_root);
}
// Path: staff_authentication.get_started_page
class _TranslationsStaffAuthenticationGetStartedPageEs implements TranslationsStaffAuthenticationGetStartedPageEn {
_TranslationsStaffAuthenticationGetStartedPageEs._(this._root);
@@ -360,6 +378,70 @@ class _TranslationsClientSettingsProfileEs implements TranslationsClientSettings
@override String get billing_payments => 'Facturación y Pagos';
}
// Path: client_hubs.empty_state
class _TranslationsClientHubsEmptyStateEs implements TranslationsClientHubsEmptyStateEn {
_TranslationsClientHubsEmptyStateEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'No hay hubs aún';
@override String get description => 'Crea estaciones de marcaje para tus ubicaciones';
@override String get button => 'Añade tu primer Hub';
}
// Path: client_hubs.about_hubs
class _TranslationsClientHubsAboutHubsEs implements TranslationsClientHubsAboutHubsEn {
_TranslationsClientHubsAboutHubsEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Sobre los Hubs';
@override String get description => 'Los Hubs son estaciones de marcaje en tus ubicaciones. Asigna etiquetas NFC a cada hub para que los trabajadores puedan marcar entrada/salida rápidamente usando sus teléfonos.';
}
// Path: client_hubs.hub_card
class _TranslationsClientHubsHubCardEs implements TranslationsClientHubsHubCardEn {
_TranslationsClientHubsHubCardEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String tag_label({required Object id}) => 'Etiqueta: ${id}';
}
// Path: client_hubs.add_hub_dialog
class _TranslationsClientHubsAddHubDialogEs implements TranslationsClientHubsAddHubDialogEn {
_TranslationsClientHubsAddHubDialogEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Añadir Nuevo Hub';
@override String get name_label => 'Nombre del Hub *';
@override String get name_hint => 'ej., Cocina Principal, Recepción';
@override String get location_label => 'Nombre de la Ubicación';
@override String get location_hint => 'ej., Restaurante Centro';
@override String get address_label => 'Dirección';
@override String get address_hint => 'Dirección completa';
@override String get create_button => 'Crear Hub';
}
// Path: client_hubs.nfc_dialog
class _TranslationsClientHubsNfcDialogEs implements TranslationsClientHubsNfcDialogEn {
_TranslationsClientHubsNfcDialogEs._(this._root);
final TranslationsEs _root; // ignore: unused_field
// Translations
@override String get title => 'Identificar Etiqueta NFC';
@override String get instruction => 'Acerque su teléfono a la etiqueta NFC para identificarla';
@override String get scan_button => 'Escanear Etiqueta NFC';
@override String get tag_identified => 'Etiqueta Identificada';
@override String get assign_button => 'Asignar Etiqueta';
}
// Path: staff_authentication.profile_setup_page.steps
class _TranslationsStaffAuthenticationProfileSetupPageStepsEs implements TranslationsStaffAuthenticationProfileSetupPageStepsEn {
_TranslationsStaffAuthenticationProfileSetupPageStepsEs._(this._root);
@@ -605,6 +687,28 @@ extension on TranslationsEs {
'client_settings.profile.quick_links' => 'Enlaces rápidos',
'client_settings.profile.clock_in_hubs' => 'Hubs de Marcaje',
'client_settings.profile.billing_payments' => 'Facturación y Pagos',
'client_hubs.title' => 'Hubs',
'client_hubs.subtitle' => 'Gestionar ubicaciones de marcaje',
'client_hubs.add_hub' => 'Añadir Hub',
'client_hubs.empty_state.title' => 'No hay hubs aún',
'client_hubs.empty_state.description' => 'Crea estaciones de marcaje para tus ubicaciones',
'client_hubs.empty_state.button' => 'Añade tu primer Hub',
'client_hubs.about_hubs.title' => 'Sobre los Hubs',
'client_hubs.about_hubs.description' => 'Los Hubs son estaciones de marcaje en tus ubicaciones. Asigna etiquetas NFC a cada hub para que los trabajadores puedan marcar entrada/salida rápidamente usando sus teléfonos.',
'client_hubs.hub_card.tag_label' => ({required Object id}) => 'Etiqueta: ${id}',
'client_hubs.add_hub_dialog.title' => 'Añadir Nuevo Hub',
'client_hubs.add_hub_dialog.name_label' => 'Nombre del Hub *',
'client_hubs.add_hub_dialog.name_hint' => 'ej., Cocina Principal, Recepción',
'client_hubs.add_hub_dialog.location_label' => 'Nombre de la Ubicación',
'client_hubs.add_hub_dialog.location_hint' => 'ej., Restaurante Centro',
'client_hubs.add_hub_dialog.address_label' => 'Dirección',
'client_hubs.add_hub_dialog.address_hint' => 'Dirección completa',
'client_hubs.add_hub_dialog.create_button' => 'Crear Hub',
'client_hubs.nfc_dialog.title' => 'Identificar Etiqueta NFC',
'client_hubs.nfc_dialog.instruction' => 'Acerque su teléfono a la etiqueta NFC para identificarla',
'client_hubs.nfc_dialog.scan_button' => 'Escanear Etiqueta NFC',
'client_hubs.nfc_dialog.tag_identified' => 'Etiqueta Identificada',
'client_hubs.nfc_dialog.assign_button' => 'Asignar Etiqueta',
_ => null,
};
}