Move apps to mobile directory structure
Relocated all app directories (client, design_system_viewer, staff) and their contents under the new 'apps/mobile' path. This change improves project organization and prepares for future platform-specific structuring.
This commit is contained in:
31
apps/mobile/packages/core_localization/.gitignore
vendored
Normal file
31
apps/mobile/packages/core_localization/.gitignore
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
# Miscellaneous
|
||||
*.class
|
||||
*.log
|
||||
*.pyc
|
||||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
*.iws
|
||||
.idea/
|
||||
|
||||
# The .vscode folder contains launch configuration and tasks you configure in
|
||||
# VS Code which you may wish to be included in version control, so this line
|
||||
# is commented out by default.
|
||||
#.vscode/
|
||||
|
||||
# Flutter/Dart/Pub related
|
||||
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
/pubspec.lock
|
||||
**/doc/api/
|
||||
.dart_tool/
|
||||
.flutter-plugins-dependencies
|
||||
/build/
|
||||
/coverage/
|
||||
10
apps/mobile/packages/core_localization/.metadata
Normal file
10
apps/mobile/packages/core_localization/.metadata
Normal file
@@ -0,0 +1,10 @@
|
||||
# This file tracks properties of this Flutter project.
|
||||
# Used by Flutter tool to assess capabilities and perform upgrades etc.
|
||||
#
|
||||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "3b62efc2a3da49882f43c372e0bc53daef7295a6"
|
||||
channel: "stable"
|
||||
|
||||
project_type: package
|
||||
@@ -0,0 +1,4 @@
|
||||
include: package:flutter_lints/flutter.yaml
|
||||
|
||||
# Additional information about this file can be found at
|
||||
# https://dart.dev/guides/language/analysis-options
|
||||
@@ -0,0 +1,10 @@
|
||||
export 'src/bloc/locale_bloc.dart';
|
||||
export 'src/bloc/locale_event.dart';
|
||||
export 'src/bloc/locale_state.dart';
|
||||
export 'src/l10n/strings.g.dart';
|
||||
export 'src/domain/repositories/locale_repository_interface.dart';
|
||||
export 'src/domain/usecases/get_locale_use_case.dart';
|
||||
export 'src/domain/usecases/set_locale_use_case.dart';
|
||||
export 'src/data/repositories_impl/locale_repository_impl.dart';
|
||||
export 'src/data/datasources/locale_local_data_source.dart';
|
||||
export 'src/localization_module.dart';
|
||||
@@ -0,0 +1,56 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../domain/usecases/get_locale_use_case.dart';
|
||||
import '../domain/usecases/set_locale_use_case.dart';
|
||||
import '../l10n/strings.g.dart';
|
||||
import 'locale_event.dart';
|
||||
import 'locale_state.dart';
|
||||
|
||||
/// A [Bloc] that manages the application's locale state.
|
||||
///
|
||||
/// It coordinates the flow between user language requests and persistent storage
|
||||
/// using [SetLocaleUseCase] and [GetLocaleUseCase].
|
||||
class LocaleBloc extends Bloc<LocaleEvent, LocaleState> {
|
||||
final GetLocaleUseCase getLocaleUseCase;
|
||||
final SetLocaleUseCase setLocaleUseCase;
|
||||
|
||||
/// Creates a [LocaleBloc] with the required use cases.
|
||||
LocaleBloc({required this.getLocaleUseCase, required this.setLocaleUseCase})
|
||||
: super(LocaleState.initial()) {
|
||||
on<ChangeLocale>(_onChangeLocale);
|
||||
on<LoadLocale>(_onLoadLocale);
|
||||
}
|
||||
|
||||
/// Handles the [ChangeLocale] event by saving it via the use case and emitting new state.
|
||||
Future<void> _onChangeLocale(
|
||||
ChangeLocale event,
|
||||
Emitter<LocaleState> emit,
|
||||
) async {
|
||||
// 1. Update slang settings
|
||||
LocaleSettings.setLocaleRaw(event.locale.languageCode);
|
||||
|
||||
// 2. Persist using Use Case
|
||||
await setLocaleUseCase(event.locale);
|
||||
|
||||
// 3. Emit new state
|
||||
emit(
|
||||
LocaleState(
|
||||
locale: event.locale,
|
||||
supportedLocales: state.supportedLocales,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Handles the [LoadLocale] event by retrieving it via the use case and updating settings.
|
||||
Future<void> _onLoadLocale(
|
||||
LoadLocale event,
|
||||
Emitter<LocaleState> emit,
|
||||
) async {
|
||||
final savedLocale = await getLocaleUseCase();
|
||||
final locale = const Locale('es');
|
||||
|
||||
LocaleSettings.setLocaleRaw(locale.languageCode);
|
||||
|
||||
emit(LocaleState(locale: locale, supportedLocales: state.supportedLocales));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// Base class for all locale-related events.
|
||||
sealed class LocaleEvent {
|
||||
/// Creates a [LocaleEvent].
|
||||
const LocaleEvent();
|
||||
}
|
||||
|
||||
/// Event triggered when the user wants to change the application locale.
|
||||
class ChangeLocale extends LocaleEvent {
|
||||
/// The new locale to apply.
|
||||
final Locale locale;
|
||||
|
||||
/// Creates a [ChangeLocale] event.
|
||||
const ChangeLocale(this.locale);
|
||||
}
|
||||
|
||||
/// Event triggered to load the saved locale from persistent storage.
|
||||
class LoadLocale extends LocaleEvent {
|
||||
/// Creates a [LoadLocale] event.
|
||||
const LoadLocale();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../l10n/strings.g.dart';
|
||||
|
||||
/// Represents the current state of the application's localization.
|
||||
class LocaleState {
|
||||
/// The current active locale.
|
||||
final Locale locale;
|
||||
|
||||
/// The list of supported locales for the application.
|
||||
final List<Locale> supportedLocales;
|
||||
|
||||
/// Creates a [LocaleState] with the specified [locale].
|
||||
const LocaleState({required this.locale, required this.supportedLocales});
|
||||
|
||||
/// The initial state of the application, defaulting to English.
|
||||
factory LocaleState.initial() => LocaleState(
|
||||
locale: const Locale('es'),
|
||||
supportedLocales: AppLocaleUtils.supportedLocales,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
/// Interface for the local data source that manages locale persistence.
|
||||
abstract interface class LocaleLocalDataSource {
|
||||
/// Saves the language code to local storage.
|
||||
Future<void> saveLanguageCode(String languageCode);
|
||||
|
||||
/// Retrieves the saved language code from local storage.
|
||||
Future<String?> getLanguageCode();
|
||||
}
|
||||
|
||||
/// Implementation of [LocaleLocalDataSource] using [SharedPreferencesAsync].
|
||||
class LocaleLocalDataSourceImpl implements LocaleLocalDataSource {
|
||||
static const String _localeKey = 'app_locale';
|
||||
final SharedPreferencesAsync _sharedPreferences;
|
||||
|
||||
/// Creates a [LocaleLocalDataSourceImpl] with the required [SharedPreferencesAsync] instance.
|
||||
LocaleLocalDataSourceImpl(this._sharedPreferences);
|
||||
|
||||
@override
|
||||
Future<void> saveLanguageCode(String languageCode) async {
|
||||
await _sharedPreferences.setString(_localeKey, languageCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String?> getLanguageCode() async {
|
||||
return _sharedPreferences.getString(_localeKey);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'dart:ui';
|
||||
import '../../domain/repositories/locale_repository_interface.dart';
|
||||
import '../datasources/locale_local_data_source.dart';
|
||||
|
||||
/// Implementation of [LocaleRepositoryInterface] that coordinates with a local data source.
|
||||
///
|
||||
/// This class handles the mapping between domain [Locale] objects and the raw
|
||||
/// strings handled by the [LocaleLocalDataSource].
|
||||
class LocaleRepositoryImpl implements LocaleRepositoryInterface {
|
||||
final LocaleLocalDataSource _localDataSource;
|
||||
|
||||
/// Creates a [LocaleRepositoryImpl] with the provided [_localDataSource].
|
||||
LocaleRepositoryImpl(this._localDataSource);
|
||||
|
||||
@override
|
||||
Future<void> saveLocale(Locale locale) {
|
||||
return _localDataSource.saveLanguageCode(locale.languageCode);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Locale?> getSavedLocale() async {
|
||||
final languageCode = await _localDataSource.getLanguageCode();
|
||||
if (languageCode != null) {
|
||||
return Locale(languageCode);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'dart:ui';
|
||||
|
||||
/// Interface for the locale repository.
|
||||
///
|
||||
/// This defines the contracts for persisting and retrieving the application's locale.
|
||||
/// Implementations of this interface should handle the details of the storage mechanism.
|
||||
abstract interface class LocaleRepositoryInterface {
|
||||
/// Saves the specified [locale] to persistent storage.
|
||||
///
|
||||
/// Throws a [RepositoryException] if the operation fails.
|
||||
Future<void> saveLocale(Locale locale);
|
||||
|
||||
/// Retrieves the saved [locale] from persistent storage.
|
||||
///
|
||||
/// Returns `null` if no locale has been previously saved.
|
||||
Future<Locale?> getSavedLocale();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'dart:ui';
|
||||
import 'package:krow_core/core.dart';
|
||||
import '../repositories/locale_repository_interface.dart';
|
||||
|
||||
/// Use case to retrieve the persisted application locale.
|
||||
///
|
||||
/// This class extends [NoInputUseCase] and interacts with [LocaleRepositoryInterface]
|
||||
/// to fetch the saved locale.
|
||||
class GetLocaleUseCase extends NoInputUseCase<Locale?> {
|
||||
final LocaleRepositoryInterface _repository;
|
||||
|
||||
/// Creates a [GetLocaleUseCase] with the required [LocaleRepositoryInterface].
|
||||
GetLocaleUseCase(this._repository);
|
||||
|
||||
@override
|
||||
Future<Locale?> call() {
|
||||
return _repository.getSavedLocale();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'dart:ui';
|
||||
import 'package:krow_core/core.dart';
|
||||
import '../repositories/locale_repository_interface.dart';
|
||||
|
||||
/// Use case to save the application locale to persistent storage.
|
||||
///
|
||||
/// This class extends [UseCase] and interacts with [LocaleRepositoryInterface]
|
||||
/// to save a given locale.
|
||||
class SetLocaleUseCase extends UseCase<Locale, void> {
|
||||
final LocaleRepositoryInterface _repository;
|
||||
|
||||
/// Creates a [SetLocaleUseCase] with the required [LocaleRepositoryInterface].
|
||||
SetLocaleUseCase(this._repository);
|
||||
|
||||
@override
|
||||
Future<void> call(Locale input) {
|
||||
return _repository.saveLocale(input);
|
||||
}
|
||||
}
|
||||
237
apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json
Normal file
237
apps/mobile/packages/core_localization/lib/src/l10n/en.i18n.json
Normal file
@@ -0,0 +1,237 @@
|
||||
{
|
||||
"common": {
|
||||
"ok": "OK",
|
||||
"cancel": "Cancel",
|
||||
"save": "Save",
|
||||
"delete": "Delete",
|
||||
"continue_text": "Continue"
|
||||
},
|
||||
"settings": {
|
||||
"language": "Language",
|
||||
"change_language": "Change Language"
|
||||
},
|
||||
"staff_authentication": {
|
||||
"get_started_page": {
|
||||
"title_part1": "Work, Grow, ",
|
||||
"title_part2": "Elevate",
|
||||
"subtitle": "Build your career in hospitality with \nflexibility and freedom.",
|
||||
"sign_up_button": "Sign Up",
|
||||
"log_in_button": "Log In"
|
||||
},
|
||||
"phone_verification_page": {
|
||||
"validation_error": "Please enter a valid 10-digit phone number",
|
||||
"send_code_button": "Send Code",
|
||||
"enter_code_title": "Enter verification code",
|
||||
"code_sent_message": "We sent a 6-digit code to ",
|
||||
"code_sent_instruction": ". Enter it below to verify your account."
|
||||
},
|
||||
"phone_input": {
|
||||
"title": "Verify your phone number",
|
||||
"subtitle": "We'll send you a verification code to get started.",
|
||||
"label": "Phone Number",
|
||||
"hint": "Enter your number"
|
||||
},
|
||||
"otp_verification": {
|
||||
"did_not_get_code": "Didn't get the code ?",
|
||||
"resend_in": "Resend in $seconds s",
|
||||
"resend_code": "Resend code"
|
||||
},
|
||||
"profile_setup_page": {
|
||||
"step_indicator": "Step $current of $total",
|
||||
"error_occurred": "An error occurred",
|
||||
"complete_setup_button": "Complete Setup",
|
||||
"steps": {
|
||||
"basic": "Basic Info",
|
||||
"location": "Location",
|
||||
"experience": "Experience"
|
||||
},
|
||||
"basic_info": {
|
||||
"title": "Let's get to know you",
|
||||
"subtitle": "Tell us a bit about yourself",
|
||||
"full_name_label": "Full Name *",
|
||||
"full_name_hint": "John Smith",
|
||||
"bio_label": "Short Bio",
|
||||
"bio_hint": "Experienced hospitality professional..."
|
||||
},
|
||||
"location": {
|
||||
"title": "Where do you want to work?",
|
||||
"subtitle": "Add your preferred work locations",
|
||||
"add_location_label": "Add Location *",
|
||||
"add_location_hint": "City or ZIP code",
|
||||
"add_button": "Add",
|
||||
"max_distance": "Max Distance: $distance miles",
|
||||
"min_dist_label": "5 mi",
|
||||
"max_dist_label": "50 mi"
|
||||
},
|
||||
"experience": {
|
||||
"title": "What are your skills?",
|
||||
"subtitle": "Select all that apply",
|
||||
"skills_label": "Skills *",
|
||||
"industries_label": "Preferred Industries",
|
||||
"skills": {
|
||||
"food_service": "Food Service",
|
||||
"bartending": "Bartending",
|
||||
"warehouse": "Warehouse",
|
||||
"retail": "Retail",
|
||||
"events": "Events",
|
||||
"customer_service": "Customer Service",
|
||||
"cleaning": "Cleaning",
|
||||
"security": "Security",
|
||||
"driving": "Driving",
|
||||
"cooking": "Cooking"
|
||||
},
|
||||
"industries": {
|
||||
"hospitality": "Hospitality",
|
||||
"food_service": "Food Service",
|
||||
"warehouse": "Warehouse",
|
||||
"events": "Events",
|
||||
"retail": "Retail",
|
||||
"healthcare": "Healthcare"
|
||||
}
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"trouble_question": "Having trouble? ",
|
||||
"contact_support": "Contact Support"
|
||||
}
|
||||
},
|
||||
"client_authentication": {
|
||||
"get_started_page": {
|
||||
"title": "Take Control of Your\nShifts and Events",
|
||||
"subtitle": "Streamline your operations with powerful tools to manage schedules, track performance, and keep your team on the same page—all in one place",
|
||||
"sign_in_button": "Sign In",
|
||||
"create_account_button": "Create Account"
|
||||
},
|
||||
"sign_in_page": {
|
||||
"title": "Welcome Back",
|
||||
"subtitle": "Sign in to manage your shifts and workers",
|
||||
"email_label": "Email",
|
||||
"email_hint": "Enter your email",
|
||||
"password_label": "Password",
|
||||
"password_hint": "Enter your password",
|
||||
"forgot_password": "Forgot Password?",
|
||||
"sign_in_button": "Sign In",
|
||||
"or_divider": "or",
|
||||
"social_apple": "Sign In with Apple",
|
||||
"social_google": "Sign In with Google",
|
||||
"no_account": "Don't have an account? ",
|
||||
"sign_up_link": "Sign Up"
|
||||
},
|
||||
"sign_up_page": {
|
||||
"title": "Create Account",
|
||||
"subtitle": "Get started with Krow for your business",
|
||||
"company_label": "Company Name",
|
||||
"company_hint": "Enter company name",
|
||||
"email_label": "Email",
|
||||
"email_hint": "Enter your email",
|
||||
"password_label": "Password",
|
||||
"password_hint": "Create a password",
|
||||
"confirm_password_label": "Confirm Password",
|
||||
"confirm_password_hint": "Confirm your password",
|
||||
"create_account_button": "Create Account",
|
||||
"or_divider": "or",
|
||||
"social_apple": "Sign Up with Apple",
|
||||
"social_google": "Sign Up with Google",
|
||||
"has_account": "Already have an account? ",
|
||||
"sign_in_link": "Sign In"
|
||||
}
|
||||
},
|
||||
"client_home": {
|
||||
"dashboard": {
|
||||
"welcome_back": "Welcome back",
|
||||
"edit_mode_active": "Edit Mode Active",
|
||||
"drag_instruction": "Drag to reorder, toggle visibility",
|
||||
"reset": "Reset",
|
||||
"metric_needed": "Needed",
|
||||
"metric_filled": "Filled",
|
||||
"metric_open": "Open",
|
||||
"view_all": "View all",
|
||||
"insight_lightbulb": "Save $amount/month",
|
||||
"insight_tip": "Book 48hrs ahead for better rates"
|
||||
},
|
||||
"widgets": {
|
||||
"actions": "Quick Actions",
|
||||
"reorder": "Reorder",
|
||||
"coverage": "Today's Coverage",
|
||||
"spending": "Spending Insights",
|
||||
"live_activity": "Live Activity"
|
||||
},
|
||||
"actions": {
|
||||
"rapid": "RAPID",
|
||||
"rapid_subtitle": "Urgent same-day",
|
||||
"create_order": "Create Order",
|
||||
"create_order_subtitle": "Schedule shifts",
|
||||
"hubs": "Hubs",
|
||||
"hubs_subtitle": "Clock-in points"
|
||||
},
|
||||
"reorder": {
|
||||
"title": "REORDER",
|
||||
"reorder_button": "Reorder",
|
||||
"per_hr": "$amount/hr"
|
||||
},
|
||||
"form": {
|
||||
"edit_reorder": "Edit & Reorder",
|
||||
"post_new": "Post a New Shift",
|
||||
"review_subtitle": "Review and edit the details before posting",
|
||||
"date_label": "Date *",
|
||||
"date_hint": "mm/dd/yyyy",
|
||||
"location_label": "Location *",
|
||||
"location_hint": "Business address",
|
||||
"positions_title": "Positions",
|
||||
"add_position": "Add Position",
|
||||
"role_label": "Role *",
|
||||
"role_hint": "Select role",
|
||||
"start_time": "Start Time *",
|
||||
"end_time": "End Time *",
|
||||
"workers_needed": "Workers Needed *",
|
||||
"hourly_rate": "Hourly Rate (\\$) *",
|
||||
"post_shift": "Post Shift"
|
||||
}
|
||||
},
|
||||
"client_settings": {
|
||||
"profile": {
|
||||
"title": "Profile",
|
||||
"edit_profile": "Edit Profile",
|
||||
"hubs": "Hubs",
|
||||
"log_out": "Log Out",
|
||||
"quick_links": "Quick Links",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
236
apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json
Normal file
236
apps/mobile/packages/core_localization/lib/src/l10n/es.i18n.json
Normal file
@@ -0,0 +1,236 @@
|
||||
{
|
||||
"common": {
|
||||
"ok": "Aceptar",
|
||||
"cancel": "Cancelar",
|
||||
"save": "Guardar",
|
||||
"delete": "Eliminar",
|
||||
"continue_text": "Continuar"
|
||||
},
|
||||
"settings": {
|
||||
"language": "Idioma",
|
||||
"change_language": "Cambiar Idioma"
|
||||
},
|
||||
"staff_authentication": {
|
||||
"get_started_page": {
|
||||
"title_part1": "Trabaja, Crece, ",
|
||||
"title_part2": "Elévate",
|
||||
"subtitle": "Construye tu carrera en hostelería con \nflexibilidad y libertad.",
|
||||
"sign_up_button": "Registrarse",
|
||||
"log_in_button": "Iniciar sesión"
|
||||
},
|
||||
"phone_verification_page": {
|
||||
"validation_error": "Por favor, ingresa un número de teléfono válido de 10 dígitos",
|
||||
"send_code_button": "Enviar código",
|
||||
"enter_code_title": "Ingresa el código de verificación",
|
||||
"code_sent_message": "Enviamos un código de 6 dígitos a ",
|
||||
"code_sent_instruction": ". Ingrésalo a continuación para verificar tu cuenta."
|
||||
},
|
||||
"phone_input": {
|
||||
"title": "Verifica tu número de teléfono",
|
||||
"subtitle": "Te enviaremos un código de verificación para comenzar.",
|
||||
"label": "Número de teléfono",
|
||||
"hint": "Ingresa tu número"
|
||||
},
|
||||
"otp_verification": {
|
||||
"did_not_get_code": "¿No recibiste el código?",
|
||||
"resend_in": "Reenviar en $seconds s",
|
||||
"resend_code": "Reenviar código"
|
||||
},
|
||||
"profile_setup_page": {
|
||||
"step_indicator": "Paso $current de $total",
|
||||
"error_occurred": "Ocurrió un error",
|
||||
"complete_setup_button": "Completar configuración",
|
||||
"steps": {
|
||||
"basic": "Información básica",
|
||||
"location": "Ubicación",
|
||||
"experience": "Experiencia"
|
||||
},
|
||||
"basic_info": {
|
||||
"title": "Conozcámonos",
|
||||
"subtitle": "Cuéntanos un poco sobre ti",
|
||||
"full_name_label": "Nombre completo *",
|
||||
"full_name_hint": "Juan Pérez",
|
||||
"bio_label": "Biografía corta",
|
||||
"bio_hint": "Profesional experimentado en hostelería..."
|
||||
},
|
||||
"location": {
|
||||
"title": "¿Dónde quieres trabajar?",
|
||||
"subtitle": "Agrega tus ubicaciones de trabajo preferidas",
|
||||
"add_location_label": "Agregar ubicación *",
|
||||
"add_location_hint": "Ciudad o código postal",
|
||||
"add_button": "Agregar",
|
||||
"max_distance": "Distancia máxima: $distance millas",
|
||||
"min_dist_label": "5 mi",
|
||||
"max_dist_label": "50 mi"
|
||||
},
|
||||
"experience": {
|
||||
"title": "¿Cuáles son tus habilidades?",
|
||||
"subtitle": "Selecciona todas las que correspondan",
|
||||
"skills_label": "Habilidades *",
|
||||
"industries_label": "Industrias preferidas",
|
||||
"skills": {
|
||||
"food_service": "Servicio de comida",
|
||||
"bartending": "Preparación de bebidas",
|
||||
"warehouse": "Almacén",
|
||||
"retail": "Venta minorista",
|
||||
"events": "Eventos",
|
||||
"customer_service": "Servicio al cliente",
|
||||
"cleaning": "Limpieza",
|
||||
"security": "Seguridad",
|
||||
"driving": "Conducción",
|
||||
"cooking": "Cocina"
|
||||
},
|
||||
"industries": {
|
||||
"hospitality": "Hostelería",
|
||||
"food_service": "Servicio de comida",
|
||||
"warehouse": "Almacén",
|
||||
"events": "Eventos",
|
||||
"retail": "Venta minorista",
|
||||
"healthcare": "Atención médica"
|
||||
}
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"trouble_question": "¿Tienes problemas? ",
|
||||
"contact_support": "Contactar a soporte"
|
||||
}
|
||||
},
|
||||
"client_authentication": {
|
||||
"get_started_page": {
|
||||
"title": "Toma el control de tus\nturnos y eventos",
|
||||
"subtitle": "Optimiza tus operaciones con potentes herramientas para gestionar horarios, realizar un seguimiento del rendimiento y mantener a tu equipo en la misma página, todo en un solo lugar",
|
||||
"sign_in_button": "Iniciar sesión",
|
||||
"create_account_button": "Crear cuenta"
|
||||
},
|
||||
"sign_in_page": {
|
||||
"title": "Bienvenido de nuevo",
|
||||
"subtitle": "Inicia sesión para gestionar tus turnos y trabajadores",
|
||||
"email_label": "Correo electrónico",
|
||||
"email_hint": "Ingresa tu correo electrónico",
|
||||
"password_label": "Contraseña",
|
||||
"password_hint": "Ingresa tu contraseña",
|
||||
"forgot_password": "¿Olvidaste tu contraseña?",
|
||||
"sign_in_button": "Iniciar sesión",
|
||||
"or_divider": "o",
|
||||
"social_apple": "Iniciar sesión con Apple",
|
||||
"social_google": "Iniciar sesión con Google",
|
||||
"no_account": "¿No tienes una cuenta? ",
|
||||
"sign_up_link": "Regístrate"
|
||||
},
|
||||
"sign_up_page": {
|
||||
"title": "Crear cuenta",
|
||||
"subtitle": "Comienza con Krow para tu negocio",
|
||||
"company_label": "Nombre de la empresa",
|
||||
"company_hint": "Ingresa el nombre de la empresa",
|
||||
"email_label": "Correo electrónico",
|
||||
"email_hint": "Ingresa tu correo electrónico",
|
||||
"password_label": "Contraseña",
|
||||
"password_hint": "Crea una contraseña",
|
||||
"confirm_password_label": "Confirmar contraseña",
|
||||
"confirm_password_hint": "Confirma tu contraseña",
|
||||
"create_account_button": "Crear cuenta",
|
||||
"or_divider": "o",
|
||||
"social_apple": "Regístrate con Apple",
|
||||
"social_google": "Regístrate con Google",
|
||||
"has_account": "¿Ya tienes una cuenta? ",
|
||||
"sign_in_link": "Iniciar sesión"
|
||||
}
|
||||
},
|
||||
"client_home": {
|
||||
"dashboard": {
|
||||
"welcome_back": "Bienvenido de nuevo",
|
||||
"edit_mode_active": "Modo Edición Activo",
|
||||
"drag_instruction": "Arrastra para reordenar, cambia la visibilidad",
|
||||
"reset": "Restablecer",
|
||||
"metric_needed": "Necesario",
|
||||
"metric_filled": "Lleno",
|
||||
"metric_open": "Abierto",
|
||||
"view_all": "Ver todo",
|
||||
"insight_lightbulb": "Ahorra $amount/mes",
|
||||
"insight_tip": "Reserva con 48h de antelación para mejores tarifas"
|
||||
},
|
||||
"widgets": {
|
||||
"actions": "Acciones Rápidas",
|
||||
"reorder": "Reordenar",
|
||||
"coverage": "Cobertura de Hoy",
|
||||
"spending": "Información de Gastos",
|
||||
"live_activity": "Actividad en Vivo"
|
||||
},
|
||||
"actions": {
|
||||
"rapid": "RÁPIDO",
|
||||
"rapid_subtitle": "Urgente mismo día",
|
||||
"create_order": "Crear Orden",
|
||||
"create_order_subtitle": "Programar turnos",
|
||||
"hubs": "Hubs",
|
||||
"hubs_subtitle": "Puntos marcaje"
|
||||
},
|
||||
"reorder": {
|
||||
"title": "REORDENAR",
|
||||
"reorder_button": "Reordenar",
|
||||
"per_hr": "$amount/hr"
|
||||
},
|
||||
"form": {
|
||||
"edit_reorder": "Editar y Reordenar",
|
||||
"post_new": "Publicar un Nuevo Turno",
|
||||
"review_subtitle": "Revisa y edita los detalles antes de publicar",
|
||||
"date_label": "Fecha *",
|
||||
"date_hint": "mm/dd/aaaa",
|
||||
"location_label": "Ubicación *",
|
||||
"location_hint": "Dirección del negocio",
|
||||
"positions_title": "Posiciones",
|
||||
"add_position": "Añadir Posición",
|
||||
"role_label": "Rol *",
|
||||
"role_hint": "Seleccionar rol",
|
||||
"start_time": "Hora de Inicio *",
|
||||
"end_time": "Hora de Fin *",
|
||||
"workers_needed": "Trabajadores Necesarios *",
|
||||
"hourly_rate": "Tarifa por hora (\\$) *",
|
||||
"post_shift": "Publicar Turno"
|
||||
}
|
||||
},
|
||||
"client_settings": {
|
||||
"profile": {
|
||||
"title": "Perfil",
|
||||
"edit_profile": "Editar Perfil",
|
||||
"hubs": "Hubs",
|
||||
"log_out": "Cerrar sesión",
|
||||
"quick_links": "Enlaces rápidos",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import 'package:flutter_modular/flutter_modular.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'data/datasources/locale_local_data_source.dart';
|
||||
import 'data/repositories_impl/locale_repository_impl.dart';
|
||||
import 'domain/repositories/locale_repository_interface.dart';
|
||||
import 'domain/usecases/get_locale_use_case.dart';
|
||||
import 'domain/usecases/set_locale_use_case.dart';
|
||||
import 'bloc/locale_bloc.dart';
|
||||
|
||||
/// A [ModularModule] that manages localization dependencies.
|
||||
///
|
||||
/// This module registers all necessary data sources, repositories, use cases,
|
||||
/// and the BLoC required for application-wide localization management.
|
||||
class LocalizationModule extends Module {
|
||||
@override
|
||||
void binds(Injector i) {
|
||||
// External Dependencies
|
||||
i.addInstance<SharedPreferencesAsync>(SharedPreferencesAsync());
|
||||
|
||||
// Data Sources
|
||||
i.addSingleton<LocaleLocalDataSource>(
|
||||
() => LocaleLocalDataSourceImpl(i.get<SharedPreferencesAsync>()),
|
||||
);
|
||||
|
||||
// Repositories
|
||||
i.addSingleton<LocaleRepositoryInterface>(
|
||||
() => LocaleRepositoryImpl(i.get<LocaleLocalDataSource>()),
|
||||
);
|
||||
|
||||
// Use Cases
|
||||
i.addSingleton<GetLocaleUseCase>(
|
||||
() => GetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
|
||||
);
|
||||
i.addSingleton<SetLocaleUseCase>(
|
||||
() => SetLocaleUseCase(i.get<LocaleRepositoryInterface>()),
|
||||
);
|
||||
|
||||
// BLoCs
|
||||
i.addSingleton<LocaleBloc>(
|
||||
() => LocaleBloc(
|
||||
getLocaleUseCase: i.get<GetLocaleUseCase>(),
|
||||
setLocaleUseCase: i.get<SetLocaleUseCase>(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
38
apps/mobile/packages/core_localization/pubspec.yaml
Normal file
38
apps/mobile/packages/core_localization/pubspec.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
name: core_localization
|
||||
description: "Core localization package using Slang."
|
||||
version: 0.0.1
|
||||
publish_to: none
|
||||
resolution: workspace
|
||||
|
||||
environment:
|
||||
sdk: '>=3.10.0 <4.0.0'
|
||||
flutter: ">=3.0.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
krow_core:
|
||||
path: ../core
|
||||
flutter_bloc: ^8.1.0
|
||||
flutter_modular: ^6.3.2
|
||||
slang: ^4.12.0
|
||||
slang_flutter: ^4.12.0
|
||||
shared_preferences: ^2.5.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^6.0.0
|
||||
build_runner: ^2.4.15
|
||||
slang_build_runner: ^4.12.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
slang:
|
||||
base_locale: en
|
||||
fallback_strategy: base_locale
|
||||
input_directory: lib/src/l10n
|
||||
input_file_pattern: .i18n.json
|
||||
output_directory: lib/src/l10n
|
||||
output_file_name: strings.g.dart
|
||||
@@ -0,0 +1,12 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:localization/localization.dart';
|
||||
|
||||
void main() {
|
||||
test('adds one to input values', () {
|
||||
final calculator = Calculator();
|
||||
expect(calculator.addOne(2), 3);
|
||||
expect(calculator.addOne(-7), -6);
|
||||
expect(calculator.addOne(0), 1);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user