diff --git a/modules/auth/lib/src/onboarding/domain/onboarding_page.dart b/modules/auth/lib/src/onboarding/domain/onboarding_page.dart new file mode 100644 index 00000000..6af9886d --- /dev/null +++ b/modules/auth/lib/src/onboarding/domain/onboarding_page.dart @@ -0,0 +1,31 @@ +import 'package:sf_localizations/sf_localizations.dart'; + +class OnboardingPage { + final String image; + final String title; + final String subtitle; + + const OnboardingPage({ + required this.image, + required this.title, + required this.subtitle, + }); +} + +const List onboardingPages = [ + OnboardingPage( + image: 'assets/images/ui/bienvenida_paso1.svg', + title: I18n.onboardingTitle1, + subtitle: I18n.onboardingSubtitle1, + ), + OnboardingPage( + image: 'assets/images/ui/bienvenida_paso2.svg', + title: I18n.onboardingTitle2, + subtitle: I18n.onboardingSubtitle2, + ), + OnboardingPage( + image: 'assets/images/ui/bienvenida_paso3.svg', + title: I18n.onboardingTitle3, + subtitle: I18n.onboardingSubtitle3, + ), +]; diff --git a/modules/auth/lib/src/onboarding/onboarding_builder.dart b/modules/auth/lib/src/onboarding/onboarding_builder.dart index a1299a53..45c469ec 100644 --- a/modules/auth/lib/src/onboarding/onboarding_builder.dart +++ b/modules/auth/lib/src/onboarding/onboarding_builder.dart @@ -1,4 +1,4 @@ -import 'package:auth/src/onboarding/presentation/welcome_screen.dart'; +import 'package:auth/src/onboarding/presentation/onboarding_screen.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:get_it/get_it.dart'; @@ -12,7 +12,7 @@ class OnboardingBuilder { return MaterialPage( key: state.pageKey, - child: WelcomeScreen(navigationContract: navigationContract), + child: OnboardingScreen(navigationContract: navigationContract), ); } } diff --git a/modules/auth/lib/src/onboarding/presentation/onboarding_screen.dart b/modules/auth/lib/src/onboarding/presentation/onboarding_screen.dart new file mode 100644 index 00000000..f647159e --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/onboarding_screen.dart @@ -0,0 +1,127 @@ +import 'package:auth/src/onboarding/domain/onboarding_page.dart'; +import 'package:auth/src/onboarding/presentation/onboarding_view_model.dart'; +import 'package:auth/src/onboarding/presentation/widgets/onboarding_content.dart'; +import 'package:auth/src/onboarding/presentation/widgets/onboarding_dots_indicator.dart'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:navigation/navigation.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +final onboardingPageControllerProvider = Provider.autoDispose(( + ref, +) { + final controller = PageController(); + ref.onDispose(controller.dispose); + return controller; +}); + +class OnboardingScreen extends ConsumerWidget { + final NavigationContract navigationContract; + + const OnboardingScreen({super.key, required this.navigationContract}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(onBoardingViewModelProvider); + final viewModel = ref.read(onBoardingViewModelProvider.notifier); + final pageController = ref.watch(onboardingPageControllerProvider); + + final isLast = state.cardIndex >= onboardingPages.length - 1; + + void goToNext() { + if (isLast) { + navigationContract.goTo(AppRoutes.linkPhone); + } else { + pageController.nextPage( + duration: const Duration(milliseconds: 400), + curve: Curves.easeOut, + ); + } + } + + return Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 24), + child: Column( + children: [ + Expanded( + child: PageView.builder( + controller: pageController, + itemCount: onboardingPages.length, + onPageChanged: viewModel.onPageChanged, + itemBuilder: (context, index) { + final page = onboardingPages[index]; + return OnboardingContent( + image: page.image, + title: page.title, + subtitle: page.subtitle, + ); + }, + ), + ), + OnboardingDotsIndicator( + currentIndex: state.cardIndex, + total: onboardingPages.length, + ), + const SizedBox(height: 38), + Container( + padding: const EdgeInsets.symmetric(horizontal: 24), + width: double.infinity, + child: TextButton( + onPressed: goToNext, + style: TextButton.styleFrom( + backgroundColor: isLast + ? const Color(0xFF329E95) + : const Color(0xFF333333), + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric( + vertical: 16, + horizontal: 24, + ), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(18), + ), + ), + child: Text( + isLast + ? context.translate(I18n.start) + : context.translate(I18n.next), + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + const SizedBox(height: 8), + SizedBox( + height: 48, + child: Center( + child: isLast + ? const SizedBox.shrink() + : TextButton( + onPressed: () => + navigationContract.goTo(AppRoutes.linkPhone), + child: Text( + context.translate(I18n.skip), + style: TextStyle( + color: Color(0xFF333333), + decoration: TextDecoration.underline, + fontWeight: FontWeight.w500, + fontSize: 18, + ), + ), + ), + ), + ), + const SizedBox(height: 36), + ], + ), + ), + ), + ); + } +} diff --git a/modules/auth/lib/src/onboarding/presentation/onboarding_view_model.dart b/modules/auth/lib/src/onboarding/presentation/onboarding_view_model.dart new file mode 100644 index 00000000..640e645d --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/onboarding_view_model.dart @@ -0,0 +1,19 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import 'package:auth/src/onboarding/presentation/onboarding_view_state.dart'; + +final onBoardingViewModelProvider = + NotifierProvider.autoDispose( + OnBoardingViewModel.new, + ); + +class OnBoardingViewModel extends Notifier { + @override + OnboardingViewState build() { + return const OnboardingViewState(); + } + + void onPageChanged(int index) { + state = state.copyWith(cardIndex: index); + } +} diff --git a/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.dart b/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.dart new file mode 100644 index 00000000..ada89447 --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.dart @@ -0,0 +1,11 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +part 'onboarding_view_state.freezed.dart'; + +@freezed +abstract class OnboardingViewState with _$OnboardingViewState { + const factory OnboardingViewState({ + @Default(0) int cardIndex, + String? error, + }) = _OnboardingViewState; +} diff --git a/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.freezed.dart b/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.freezed.dart new file mode 100644 index 00000000..846ae76d --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/onboarding_view_state.freezed.dart @@ -0,0 +1,274 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'onboarding_view_state.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$OnboardingViewState { + + int get cardIndex; String? get error; +/// Create a copy of OnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$OnboardingViewStateCopyWith get copyWith => _$OnboardingViewStateCopyWithImpl(this as OnboardingViewState, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is OnboardingViewState&&(identical(other.cardIndex, cardIndex) || other.cardIndex == cardIndex)&&(identical(other.error, error) || other.error == error)); +} + + +@override +int get hashCode => Object.hash(runtimeType,cardIndex,error); + +@override +String toString() { + return 'OnboardingViewState(cardIndex: $cardIndex, error: $error)'; +} + + +} + +/// @nodoc +abstract mixin class $OnboardingViewStateCopyWith<$Res> { + factory $OnboardingViewStateCopyWith(OnboardingViewState value, $Res Function(OnboardingViewState) _then) = _$OnboardingViewStateCopyWithImpl; +@useResult +$Res call({ + int cardIndex, String? error +}); + + + + +} +/// @nodoc +class _$OnboardingViewStateCopyWithImpl<$Res> + implements $OnboardingViewStateCopyWith<$Res> { + _$OnboardingViewStateCopyWithImpl(this._self, this._then); + + final OnboardingViewState _self; + final $Res Function(OnboardingViewState) _then; + +/// Create a copy of OnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? cardIndex = null,Object? error = freezed,}) { + return _then(_self.copyWith( +cardIndex: null == cardIndex ? _self.cardIndex : cardIndex // ignore: cast_nullable_to_non_nullable +as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [OnboardingViewState]. +extension OnboardingViewStatePatterns on OnboardingViewState { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _OnboardingViewState value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _OnboardingViewState() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _OnboardingViewState value) $default,){ +final _that = this; +switch (_that) { +case _OnboardingViewState(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _OnboardingViewState value)? $default,){ +final _that = this; +switch (_that) { +case _OnboardingViewState() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( int cardIndex, String? error)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _OnboardingViewState() when $default != null: +return $default(_that.cardIndex,_that.error);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( int cardIndex, String? error) $default,) {final _that = this; +switch (_that) { +case _OnboardingViewState(): +return $default(_that.cardIndex,_that.error);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( int cardIndex, String? error)? $default,) {final _that = this; +switch (_that) { +case _OnboardingViewState() when $default != null: +return $default(_that.cardIndex,_that.error);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _OnboardingViewState implements OnboardingViewState { + const _OnboardingViewState({this.cardIndex = 0, this.error}); + + +@override@JsonKey() final int cardIndex; +@override final String? error; + +/// Create a copy of OnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$OnboardingViewStateCopyWith<_OnboardingViewState> get copyWith => __$OnboardingViewStateCopyWithImpl<_OnboardingViewState>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _OnboardingViewState&&(identical(other.cardIndex, cardIndex) || other.cardIndex == cardIndex)&&(identical(other.error, error) || other.error == error)); +} + + +@override +int get hashCode => Object.hash(runtimeType,cardIndex,error); + +@override +String toString() { + return 'OnboardingViewState(cardIndex: $cardIndex, error: $error)'; +} + + +} + +/// @nodoc +abstract mixin class _$OnboardingViewStateCopyWith<$Res> implements $OnboardingViewStateCopyWith<$Res> { + factory _$OnboardingViewStateCopyWith(_OnboardingViewState value, $Res Function(_OnboardingViewState) _then) = __$OnboardingViewStateCopyWithImpl; +@override @useResult +$Res call({ + int cardIndex, String? error +}); + + + + +} +/// @nodoc +class __$OnboardingViewStateCopyWithImpl<$Res> + implements _$OnboardingViewStateCopyWith<$Res> { + __$OnboardingViewStateCopyWithImpl(this._self, this._then); + + final _OnboardingViewState _self; + final $Res Function(_OnboardingViewState) _then; + +/// Create a copy of OnboardingViewState +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? cardIndex = null,Object? error = freezed,}) { + return _then(_OnboardingViewState( +cardIndex: null == cardIndex ? _self.cardIndex : cardIndex // ignore: cast_nullable_to_non_nullable +as int,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable +as String?, + )); +} + + +} + +// dart format on diff --git a/modules/auth/lib/src/onboarding/presentation/welcome_screen.dart b/modules/auth/lib/src/onboarding/presentation/welcome_screen.dart index 41747d8b..e69de29b 100644 --- a/modules/auth/lib/src/onboarding/presentation/welcome_screen.dart +++ b/modules/auth/lib/src/onboarding/presentation/welcome_screen.dart @@ -1,160 +0,0 @@ -import 'package:design_system/design_system.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:navigation/navigation.dart'; - -class WelcomeScreen extends ConsumerStatefulWidget { - final NavigationContract navigationContract; - - const WelcomeScreen({super.key, required this.navigationContract}); - - @override - ConsumerState createState() => WelcomeScreenState(navigationContract: navigationContract); - -} - -class WelcomeScreenState extends ConsumerState{ - late int currentStep; - final NavigationContract navigationContract; - - WelcomeScreenState({required this.navigationContract}); - - @override - void initState() { - super.initState(); - currentStep = 0; - } - - @override - Widget build(BuildContext context) { - final theme = ref.watch(themePortProvider); - - return Scaffold( - backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), - body: Container( - padding: EdgeInsets.only(top: 24), - child: Center( - child: Column( - spacing: 48, - children: [ - Spacer(), - generateSteps()[currentStep], - Column( - spacing: 24, - children: [ - StepIndicator( - max: 3, - current: currentStep+1, - color: theme.getColorFor(ThemeCode.buttonSecondary) - ), - generateButtons(theme, 3, currentStep+1) - ] - ), - Spacer() - ] - ) - ) - ) - ); - } - - Widget generateButtons(ThemePort theme, int max, int step){ - if (step==max) { - return PrimaryButton( - onPressed: () => navigationContract.goTo(AppRoutes.linkPhone), - text: "Continuar", - color: theme.getColorFor(ThemeCode.buttonPrimary), - width: 324, - ); - } else { - return Column( - spacing: 16, - children: [ - PrimaryButton( - onPressed: ()=>setState(() { - currentStep++; - }), - text: "Siguiente", - color: theme.getColorFor(ThemeCode.buttonSecondary), - width: 324, - ), - CustomTextButton( - onPressed: ()=>navigationContract.goTo(AppRoutes.linkPhone), - text: "Omitir", - size: 18, - weight: FontWeight.w500, - ) - ], - ); - } - } - - List generateSteps() { - return [ - Column( - spacing: 48, - children: [ - SvgPicture.asset("assets/images/ui/bienvenida_paso1.svg"), - Column( - spacing: 16, - children: [ - Text( - "Aprende a gestionar su dinero", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0) - ), - Text( - "Tu peque crea hábitos y se divierte mientras lo hace", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18, letterSpacing: 0) - ) - ] - ) - ] - ), - Column( - spacing: 48, - children: [ - SvgPicture.asset("assets/images/ui/bienvenida_paso2.svg"), - Column( - spacing: 16, - children: [ - Text( - "Tranquilidad en cada pago que hace", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0) - ), - Text( - "Supervisa sus gastos, fija límites y acompáñale en cada paso", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18, letterSpacing: 0) - ), - ], - ) - ], - ), - Column( - spacing: 48, - children: [ - SvgPicture.asset("assets/images/ui/bienvenida_paso3.svg"), - Column( - spacing: 16, - children: [ - Text( - "Pagos fáciles y seguros, en sus manos", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 30, fontWeight: FontWeight.w500, letterSpacing: 0) - ), - Text( - "Podrá pagar desde su reloj.\n Sin móvil ni efectivo", - textAlign: TextAlign.center, - style: TextStyle(fontSize: 18, letterSpacing: 0) - ), - ], - ) - ], - ), - ]; - } -} \ No newline at end of file diff --git a/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_content.dart b/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_content.dart new file mode 100644 index 00000000..5e2c434a --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_content.dart @@ -0,0 +1,52 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:sf_localizations/sf_localizations.dart'; + +class OnboardingContent extends StatelessWidget { + final String image; + final String title; + final String subtitle; + + const OnboardingContent({ + super.key, + required this.image, + required this.title, + required this.subtitle, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Flexible(flex: 3, child: SvgPicture.asset(image)), + const SizedBox(height: 48), + Text( + context.translate(title), + textAlign: TextAlign.center, + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 28, + height: 1.4, + letterSpacing: 0.3, + color: Color(0xFF4A4A4A), + ), + ), + const SizedBox(height: 16), + Text( + context.translate(subtitle), + textAlign: TextAlign.center, + style: const TextStyle( + fontSize: 18, + height: 1.4, + letterSpacing: 0.3, + color: Color(0xFF9B9B9B), + ), + ), + ], + ), + ); + } +} diff --git a/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_dots_indicator.dart b/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_dots_indicator.dart new file mode 100644 index 00000000..2d6adbf9 --- /dev/null +++ b/modules/auth/lib/src/onboarding/presentation/widgets/onboarding_dots_indicator.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; + +class OnboardingDotsIndicator extends StatelessWidget { + final int currentIndex; + final int total; + + const OnboardingDotsIndicator({ + super.key, + required this.currentIndex, + required this.total, + }); + + @override + Widget build(BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate(total, (index) { + final bool isActive = index == currentIndex; + + return AnimatedContainer( + duration: const Duration(milliseconds: 200), + curve: Curves.easeOut, + margin: const EdgeInsets.symmetric(horizontal: 6), + width: 16.0, + height: 16.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: isActive ? const Color(0xFF4A4A4A) : Colors.white, + border: Border.all(color: const Color(0xFF4A4A4A), width: 2), + ), + ); + }), + ); + } +} diff --git a/modules/auth/pubspec.yaml b/modules/auth/pubspec.yaml index 53e47f0d..feffab44 100644 --- a/modules/auth/pubspec.yaml +++ b/modules/auth/pubspec.yaml @@ -27,12 +27,16 @@ dependencies: get_it: ^9.0.5 go_router: ^17.0.0 flutter_riverpod: ^3.0.3 - + freezed_annotation: ^3.1.0 + freezed: ^3.2.3 + dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^5.0.0 - + riverpod_generator: ^3.0.3 + build_runner: ^2.7.1 + riverpod_lint: ^3.0.3 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec diff --git a/packages/sf_localizations/assets/l10n/de.json b/packages/sf_localizations/assets/l10n/de.json index ffca1395..72c4b830 100644 --- a/packages/sf_localizations/assets/l10n/de.json +++ b/packages/sf_localizations/assets/l10n/de.json @@ -1,3 +1,12 @@ { - "example": "Beispiel" + "example": "Beispiel", + "start": "Starten", + "next": "Weiter", + "skip": "Überspringen", + "onboardingTitle1": "Lerne, ihr Geld zu verwalten", + "onboardingSubtitle1": "Dein Kind entwickelt Gewohnheiten und hat Spaß dabei", + "onboardingTitle2": "Gelassenheit bei jeder Zahlung", + "onboardingSubtitle2": "Überwache ihre Ausgaben, setze Limits und begleite sie bei jedem Schritt", + "onboardingTitle3": "Einfache und sichere Zahlungen in ihren Händen", + "onboardingSubtitle3": "Sie können mit ihrer Uhr bezahlen.\nGanz ohne Handy und Bargeld" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index 9003e9e5..bcbf501b 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -1,3 +1,12 @@ { - "example": "example" + "example": "example", + "onboardingTitle1": "Learn to manage their money", + "onboardingSubtitle1": "Your kid builds habits and has fun while doing it", + "onboardingTitle2": "Peace of mind in every payment", + "onboardingSubtitle2": "Monitor their spending, set limits and guide them step by step", + "onboardingTitle3": "Easy and secure payments in their hands", + "onboardingSubtitle3": "They can pay from their watch.\nNo phone or cash needed", + "start": "Start", + "next": "Next", + "skip": "Skip" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/es.json b/packages/sf_localizations/assets/l10n/es.json index 09c9ad94..01aa6084 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -1,3 +1,12 @@ { - "example": "ejemplo" + "example": "ejemplo", + "onboardingTitle1": "Aprende a gestionar su dinero", + "onboardingSubtitle1": "Tu peque crea hábitos y se divierte mientras lo hace", + "onboardingTitle2": "Tranquilidad en cada pago que hacen", + "onboardingSubtitle2": "Supervisa sus gastos, fija límites y acompáñalos en cada paso", + "onboardingTitle3": "Pagos fáciles y seguros en sus manos", + "onboardingSubtitle3": "Podrá pagar desde su reloj.\nSin móvil ni efectivo", + "start": "Comenzar", + "next": "Siguiente", + "skip": "Omitir" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/fr.json b/packages/sf_localizations/assets/l10n/fr.json index ddd38b2d..bf1c9a68 100644 --- a/packages/sf_localizations/assets/l10n/fr.json +++ b/packages/sf_localizations/assets/l10n/fr.json @@ -1,3 +1,12 @@ { - "example": "exemple" + "example": "exemple", + "start": "Commencer", + "next": "Suivant", + "skip": "Passer", + "onboardingTitle1": "Apprenez à gérer leur argent", + "onboardingSubtitle1": "Votre enfant développe de bonnes habitudes et s'amuse en le faisant", + "onboardingTitle2": "La tranquillité à chaque paiement", + "onboardingSubtitle2": "Surveillez leurs dépenses, fixez des limites et accompagnez-les à chaque étape", + "onboardingTitle3": "Des paiements faciles et sécurisés entre leurs mains", + "onboardingSubtitle3": "Ils peuvent payer avec leur montre.\nSans téléphone ni espèces" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/it.json b/packages/sf_localizations/assets/l10n/it.json index 1d4d871f..78ef0c94 100644 --- a/packages/sf_localizations/assets/l10n/it.json +++ b/packages/sf_localizations/assets/l10n/it.json @@ -1,3 +1,12 @@ { - "example": "esempio" + "example": "esempio", + "start": "Inizia", + "next": "Avanti", + "skip": "Salta", + "onboardingTitle1": "Impara a gestire il loro denaro", + "onboardingSubtitle1": "Tuo figlio crea abitudini e si diverte mentre lo fa", + "onboardingTitle2": "Tranquillità in ogni pagamento", + "onboardingSubtitle2": "Monitora le sue spese, imposta limiti e accompagnalo in ogni passo", + "onboardingTitle3": "Pagamenti facili e sicuri nelle sue mani", + "onboardingSubtitle3": "Potrà pagare dal suo orologio.\nSenza telefono né contanti" } \ No newline at end of file diff --git a/packages/sf_localizations/assets/l10n/pt.json b/packages/sf_localizations/assets/l10n/pt.json index 86dc85c3..8b8e7c94 100644 --- a/packages/sf_localizations/assets/l10n/pt.json +++ b/packages/sf_localizations/assets/l10n/pt.json @@ -1,3 +1,12 @@ { - "example": "exemplo" + "example": "exemplo", + "start": "Começar", + "next": "Próximo", + "skip": "Pular", + "onboardingTitle1": "Aprenda a gerenciar o dinheiro deles", + "onboardingSubtitle1": "Seu filho cria hábitos e se diverte enquanto faz isso", + "onboardingTitle2": "Tranquilidade em cada pagamento", + "onboardingSubtitle2": "Monitore os gastos deles, defina limites e acompanhe cada passo", + "onboardingTitle3": "Pagamentos fáceis e seguros nas mãos deles", + "onboardingSubtitle3": "Eles poderão pagar pelo relógio.\nSem celular nem dinheiro em espécie" } \ No newline at end of file diff --git a/packages/sf_localizations/lib/src/generated/i18n.dart b/packages/sf_localizations/lib/src/generated/i18n.dart index 5afd221a..a3cb657a 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -4,4 +4,13 @@ class I18n { const I18n._(); static const String example = 'example'; + static const String start = 'start'; + static const String next = 'next'; + static const String skip = 'skip'; + static const String onboardingTitle1 = 'onboardingTitle1'; + static const String onboardingSubtitle1 = 'onboardingSubtitle1'; + static const String onboardingTitle2 = 'onboardingTitle2'; + static const String onboardingSubtitle2 = 'onboardingSubtitle2'; + static const String onboardingTitle3 = 'onboardingTitle3'; + static const String onboardingSubtitle3 = 'onboardingSubtitle3'; }