refactor(legacy-auth): simplify device setup to single carrier name field

This commit is contained in:
2026-04-26 05:12:05 +02:00
parent e9cceae485
commit cf2dbbeb63
13 changed files with 114 additions and 117 deletions

View File

@@ -5,7 +5,7 @@ abstract class LegacyDeviceSetupRemoteDatasource {
Future<LegacyDeviceResponseModel> createDevice({ Future<LegacyDeviceResponseModel> createDevice({
required String name, required String name,
required String genrer, required String genre,
required int weight, required int weight,
required int stepLength, required int stepLength,
required int bornAt, required int bornAt,

View File

@@ -12,7 +12,8 @@ class LegacyDeviceSetupRemoteDatasourceImpl
Future<void> generateActivationKey({required String identificator}) async { Future<void> generateActivationKey({required String identificator}) async {
await safeCall( await safeCall(
() => _repository.post<dynamic>( () => _repository.post<dynamic>(
'/recorded-devices/$identificator/activation-key', '/recorded-devices/activation-key',
body: <String, dynamic>{'regCode': identificator},
), ),
'Error generating activation key', 'Error generating activation key',
); );
@@ -21,7 +22,7 @@ class LegacyDeviceSetupRemoteDatasourceImpl
@override @override
Future<LegacyDeviceResponseModel> createDevice({ Future<LegacyDeviceResponseModel> createDevice({
required String name, required String name,
required String genrer, required String genre,
required int weight, required int weight,
required int stepLength, required int stepLength,
required int bornAt, required int bornAt,
@@ -33,7 +34,7 @@ class LegacyDeviceSetupRemoteDatasourceImpl
'/devices', '/devices',
body: <String, dynamic>{ body: <String, dynamic>{
'name': name, 'name': name,
'genre': genrer, 'genre': genre,
'weight': weight, 'weight': weight,
'stepLength': stepLength, 'stepLength': stepLength,
'bornAt': bornAt, 'bornAt': bornAt,

View File

@@ -14,7 +14,7 @@ class LegacyDeviceSetupRepositoryImpl implements LegacyDeviceSetupRepository {
@override @override
Future<void> createDevice({ Future<void> createDevice({
required String name, required String name,
required String genrer, required String genre,
required int weight, required int weight,
required int stepLength, required int stepLength,
required int bornAt, required int bornAt,
@@ -23,7 +23,7 @@ class LegacyDeviceSetupRepositoryImpl implements LegacyDeviceSetupRepository {
}) async { }) async {
final model = await _remote.createDevice( final model = await _remote.createDevice(
name: name, name: name,
genrer: genrer, genre: genre,
weight: weight, weight: weight,
stepLength: stepLength, stepLength: stepLength,
bornAt: bornAt, bornAt: bornAt,

View File

@@ -3,7 +3,7 @@ abstract class LegacyDeviceSetupRepository {
Future<void> createDevice({ Future<void> createDevice({
required String name, required String name,
required String genrer, required String genre,
required int weight, required int weight,
required int stepLength, required int stepLength,
required int bornAt, required int bornAt,

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.dart';
import 'dart:async'; import 'dart:async';
import 'package:design_system/design_system.dart'; import 'package:design_system/design_system.dart';
@@ -46,8 +47,7 @@ class _LegacyDeviceSetupScreenState
super.initState(); super.initState();
final initial = ref.read(deviceSetupControllerProvider); final initial = ref.read(deviceSetupControllerProvider);
_controllers = DeviceSetupFormControllers( _controllers = DeviceSetupFormControllers(
firstName: TextEditingController(text: initial.firstName), carrierName: TextEditingController(text: initial.carrierName),
lastName: TextEditingController(text: initial.lastName),
bornAt: TextEditingController( bornAt: TextEditingController(
text: initial.bornAt == null ? '' : formatDateDMY(initial.bornAt!), text: initial.bornAt == null ? '' : formatDateDMY(initial.bornAt!),
), ),
@@ -56,8 +56,7 @@ class _LegacyDeviceSetupScreenState
watchCode: TextEditingController(text: initial.watchCode), watchCode: TextEditingController(text: initial.watchCode),
activationKey: TextEditingController(text: initial.activationKey), activationKey: TextEditingController(text: initial.activationKey),
); );
_controllers.firstName.addListener(_onFirstNameChanged); _controllers.carrierName.addListener(_onCarrierNameChanged);
_controllers.lastName.addListener(_onLastNameChanged);
_controllers.bornAt.addListener(_onBornAtTextChanged); _controllers.bornAt.addListener(_onBornAtTextChanged);
_controllers.weight.addListener(_onWeightChanged); _controllers.weight.addListener(_onWeightChanged);
_controllers.height.addListener(_onHeightChanged); _controllers.height.addListener(_onHeightChanged);
@@ -78,16 +77,14 @@ class _LegacyDeviceSetupScreenState
@override @override
void dispose() { void dispose() {
_controllers.firstName.removeListener(_onFirstNameChanged); _controllers.carrierName.removeListener(_onCarrierNameChanged);
_controllers.lastName.removeListener(_onLastNameChanged);
_controllers.bornAt.removeListener(_onBornAtTextChanged); _controllers.bornAt.removeListener(_onBornAtTextChanged);
_controllers.weight.removeListener(_onWeightChanged); _controllers.weight.removeListener(_onWeightChanged);
_controllers.height.removeListener(_onHeightChanged); _controllers.height.removeListener(_onHeightChanged);
_controllers.watchCode.removeListener(_onWatchCodeChanged); _controllers.watchCode.removeListener(_onWatchCodeChanged);
_controllers.activationKey.removeListener(_onActivationKeyChanged); _controllers.activationKey.removeListener(_onActivationKeyChanged);
_controllers.firstName.dispose(); _controllers.carrierName.dispose();
_controllers.lastName.dispose();
_controllers.bornAt.dispose(); _controllers.bornAt.dispose();
_controllers.weight.dispose(); _controllers.weight.dispose();
_controllers.height.dispose(); _controllers.height.dispose();
@@ -96,18 +93,11 @@ class _LegacyDeviceSetupScreenState
super.dispose(); super.dispose();
} }
void _onFirstNameChanged() { void _onCarrierNameChanged() {
toCapitalizedController(_controllers.firstName); toCapitalizedController(_controllers.carrierName);
ref ref
.read(deviceSetupControllerProvider.notifier) .read(deviceSetupControllerProvider.notifier)
.setFirstName(_controllers.firstName.text); .setCarrierName(_controllers.carrierName.text);
}
void _onLastNameChanged() {
toCapitalizedController(_controllers.lastName);
ref
.read(deviceSetupControllerProvider.notifier)
.setLastName(_controllers.lastName.text);
} }
void _onBornAtTextChanged() { void _onBornAtTextChanged() {
@@ -170,7 +160,10 @@ class _LegacyDeviceSetupScreenState
if (didPop) return; if (didPop) return;
notifier.back(); notifier.back();
}, },
child: Scaffold( child: Stack(
children: [
Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Theme.of(context).colorScheme.surface, backgroundColor: Theme.of(context).colorScheme.surface,
body: SafeArea( body: SafeArea(
child: Column( child: Column(
@@ -235,18 +228,15 @@ class _LegacyDeviceSetupScreenState
final ok = await notifier.createDevice(); final ok = await notifier.createDevice();
if (!context.mounted) return; if (!context.mounted) return;
if (ok) { if (ok) {
if (widget.isFirstDevice) { Navigator.of(context).push(
Navigator.of(context).push( LegacyPageRoute(
MaterialPageRoute( builder: (_) => LegacySuccessScreen(
builder: (_) => LegacySuccessScreen( navigationContract: widget.navigationContract,
navigationContract: widget.navigationContract, formControllers: _controllers,
formControllers: _controllers, isFirstDevice: widget.isFirstDevice,
),
), ),
); ),
} else { );
Navigator.pop(context);
}
} }
return; return;
} }
@@ -264,6 +254,13 @@ class _LegacyDeviceSetupScreenState
], ],
), ),
), ),
),
if (state.isLoading)
ColoredBox(
color: Colors.black26,
child: Center(child: LegacyLoadingIndicator()),
),
],
), ),
); );
} }
@@ -271,7 +268,7 @@ class _LegacyDeviceSetupScreenState
void _confirmLogout(BuildContext context, WidgetRef ref) { void _confirmLogout(BuildContext context, WidgetRef ref) {
final primaryColor = context.sfColors.legacyPrimary; final primaryColor = context.sfColors.legacyPrimary;
showDialog<void>( showLegacyDialog<void>(
context: context, context: context,
builder: (dialogContext) => AlertDialog( builder: (dialogContext) => AlertDialog(
title: Text(context.translate(I18n.logOut)), title: Text(context.translate(I18n.logOut)),

View File

@@ -12,7 +12,7 @@ import 'package:utils/utils.dart';
part 'device_setup_controller.g.dart'; part 'device_setup_controller.g.dart';
@Riverpod(keepAlive: true) @riverpod
class DeviceSetupController extends _$DeviceSetupController { class DeviceSetupController extends _$DeviceSetupController {
DateTime? _currentStepEnteredAt; DateTime? _currentStepEnteredAt;
@@ -36,14 +36,9 @@ class DeviceSetupController extends _$DeviceSetupController {
_currentStepEnteredAt = DateTime.now(); _currentStepEnteredAt = DateTime.now();
} }
void setFirstName(String value) { void setCarrierName(String value) {
if (value == state.firstName) return; if (value == state.carrierName) return;
state = state.copyWith(firstName: value, validationErrorKey: ''); state = state.copyWith(carrierName: value, validationErrorKey: '');
}
void setLastName(String value) {
if (value == state.lastName) return;
state = state.copyWith(lastName: value, validationErrorKey: '');
} }
void setBornAt(DateTime? date) { void setBornAt(DateTime? date) {
@@ -71,10 +66,10 @@ class DeviceSetupController extends _$DeviceSetupController {
state = state.copyWith(activationKey: value, validationErrorKey: ''); state = state.copyWith(activationKey: value, validationErrorKey: '');
} }
void onGenrerChanged(String? value) { void onGenreChanged(String? value) {
final v = value ?? ''; final v = value ?? '';
if (v == state.genrer) return; if (v == state.genre) return;
state = state.copyWith(genrer: v, validationErrorKey: ''); state = state.copyWith(genre: v, validationErrorKey: '');
} }
void onRelationTypeChanged(String? value) { void onRelationTypeChanged(String? value) {
@@ -188,16 +183,14 @@ class DeviceSetupController extends _$DeviceSetupController {
} }
Future<bool> createDevice() async { Future<bool> createDevice() async {
final name = '${state.firstName.trim()} ${state.lastName.trim()}' final name = state.carrierName.trim().toUpperCase();
.trim()
.toUpperCase();
final birth = state.bornAt!; final birth = state.bornAt!;
final bornAt = DateTime.utc(birth.year, birth.month, birth.day) final bornAt = DateTime.utc(birth.year, birth.month, birth.day)
.millisecondsSinceEpoch; .millisecondsSinceEpoch;
final weight = int.parse(state.weight.trim()); final weight = int.parse(state.weight.trim());
final heightCm = double.parse(state.height.trim()); final heightCm = double.parse(state.height.trim());
final stepLength = (heightCm * 0.40).round(); final stepLength = (heightCm * 0.40).round();
final genrer = state.genrer.trim(); final genre = state.genre.trim();
final relationType = state.relationType.trim(); final relationType = state.relationType.trim();
final activationKey = state.activationKey.trim(); final activationKey = state.activationKey.trim();
@@ -211,7 +204,7 @@ class DeviceSetupController extends _$DeviceSetupController {
try { try {
await ref.read(legacyDeviceSetupRepositoryProvider).createDevice( await ref.read(legacyDeviceSetupRepositoryProvider).createDevice(
name: name, name: name,
genrer: genrer, genre: genre,
weight: weight, weight: weight,
stepLength: stepLength, stepLength: stepLength,
bornAt: bornAt, bornAt: bornAt,
@@ -223,7 +216,7 @@ class DeviceSetupController extends _$DeviceSetupController {
unawaited( unawaited(
tracking.legacyDeviceSetupCompleted( tracking.legacyDeviceSetupCompleted(
childGender: genrer, childGender: genre,
relationType: relationType, relationType: relationType,
childAgeYears: yearsBetween(birth, DateTime.now()), childAgeYears: yearsBetween(birth, DateTime.now()),
), ),
@@ -248,10 +241,9 @@ class DeviceSetupController extends _$DeviceSetupController {
} }
bool validateProfile() { bool validateProfile() {
final isInvalid = state.firstName.trim().isEmpty || final isInvalid = state.carrierName.trim().isEmpty ||
state.lastName.trim().isEmpty ||
state.bornAt == null || state.bornAt == null ||
state.genrer.trim().isEmpty || state.genre.trim().isEmpty ||
state.relationType.trim().isEmpty || state.relationType.trim().isEmpty ||
state.weight.trim().isEmpty || state.weight.trim().isEmpty ||
int.tryParse(state.weight.trim()) == null || int.tryParse(state.weight.trim()) == null ||

View File

@@ -20,7 +20,7 @@ final class DeviceSetupControllerProvider
argument: null, argument: null,
retry: null, retry: null,
name: r'deviceSetupControllerProvider', name: r'deviceSetupControllerProvider',
isAutoDispose: false, isAutoDispose: true,
dependencies: null, dependencies: null,
$allTransitiveDependencies: null, $allTransitiveDependencies: null,
); );
@@ -42,7 +42,7 @@ final class DeviceSetupControllerProvider
} }
String _$deviceSetupControllerHash() => String _$deviceSetupControllerHash() =>
r'2f2e75fd3e4790e8e49658098c2cfd8dc06084f7'; r'898dfa52fa97703331e9e5c25688426d1418731f';
abstract class _$DeviceSetupController extends $Notifier<DeviceSetupState> { abstract class _$DeviceSetupController extends $Notifier<DeviceSetupState> {
DeviceSetupState build(); DeviceSetupState build();

View File

@@ -2,8 +2,7 @@ import 'package:flutter/material.dart';
class DeviceSetupFormControllers { class DeviceSetupFormControllers {
DeviceSetupFormControllers({ DeviceSetupFormControllers({
required this.firstName, required this.carrierName,
required this.lastName,
required this.bornAt, required this.bornAt,
required this.weight, required this.weight,
required this.height, required this.height,
@@ -11,8 +10,7 @@ class DeviceSetupFormControllers {
required this.activationKey, required this.activationKey,
}); });
final TextEditingController firstName; final TextEditingController carrierName;
final TextEditingController lastName;
final TextEditingController bornAt; final TextEditingController bornAt;
final TextEditingController weight; final TextEditingController weight;
final TextEditingController height; final TextEditingController height;

View File

@@ -9,10 +9,9 @@ part 'device_setup_state.freezed.dart';
abstract class DeviceSetupState with _$DeviceSetupState { abstract class DeviceSetupState with _$DeviceSetupState {
const factory DeviceSetupState({ const factory DeviceSetupState({
@Default(LegacyAddKidStep.intro) LegacyAddKidStep step, @Default(LegacyAddKidStep.intro) LegacyAddKidStep step,
@Default('') String firstName, @Default('') String carrierName,
@Default('') String lastName,
DateTime? bornAt, DateTime? bornAt,
@Default('') String genrer, @Default('') String genre,
@Default('') String relationType, @Default('') String relationType,
@Default('') String weight, @Default('') String weight,
@Default('') String height, @Default('') String height,

View File

@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
/// @nodoc /// @nodoc
mixin _$DeviceSetupState { mixin _$DeviceSetupState {
LegacyAddKidStep get step; String get firstName; String get lastName; DateTime? get bornAt; String get genrer; String get relationType; String get weight; String get height; String get watchQr; String get watchCode; String get activationKey; bool get isLoading; String get validationErrorKey; LegacyDeviceSetupErrorEvent? get apiErrorEvent; bool get isSuccess; LegacyAddKidStep get step; String get carrierName; DateTime? get bornAt; String get genre; String get relationType; String get weight; String get height; String get watchQr; String get watchCode; String get activationKey; bool get isLoading; String get validationErrorKey; LegacyDeviceSetupErrorEvent? get apiErrorEvent; bool get isSuccess;
/// Create a copy of DeviceSetupState /// Create a copy of DeviceSetupState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false) @JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $DeviceSetupStateCopyWith<DeviceSetupState> get copyWith => _$DeviceSetupStateCo
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is DeviceSetupState&&(identical(other.step, step) || other.step == step)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.genrer, genrer) || other.genrer == genrer)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.height, height) || other.height == height)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.activationKey, activationKey) || other.activationKey == activationKey)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.validationErrorKey, validationErrorKey) || other.validationErrorKey == validationErrorKey)&&(identical(other.apiErrorEvent, apiErrorEvent) || other.apiErrorEvent == apiErrorEvent)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess)); return identical(this, other) || (other.runtimeType == runtimeType&&other is DeviceSetupState&&(identical(other.step, step) || other.step == step)&&(identical(other.carrierName, carrierName) || other.carrierName == carrierName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.genre, genre) || other.genre == genre)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.height, height) || other.height == height)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.activationKey, activationKey) || other.activationKey == activationKey)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.validationErrorKey, validationErrorKey) || other.validationErrorKey == validationErrorKey)&&(identical(other.apiErrorEvent, apiErrorEvent) || other.apiErrorEvent == apiErrorEvent)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess));
} }
@override @override
int get hashCode => Object.hash(runtimeType,step,firstName,lastName,bornAt,genrer,relationType,weight,height,watchQr,watchCode,activationKey,isLoading,validationErrorKey,apiErrorEvent,isSuccess); int get hashCode => Object.hash(runtimeType,step,carrierName,bornAt,genre,relationType,weight,height,watchQr,watchCode,activationKey,isLoading,validationErrorKey,apiErrorEvent,isSuccess);
@override @override
String toString() { String toString() {
return 'DeviceSetupState(step: $step, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, genrer: $genrer, relationType: $relationType, weight: $weight, height: $height, watchQr: $watchQr, watchCode: $watchCode, activationKey: $activationKey, isLoading: $isLoading, validationErrorKey: $validationErrorKey, apiErrorEvent: $apiErrorEvent, isSuccess: $isSuccess)'; return 'DeviceSetupState(step: $step, carrierName: $carrierName, bornAt: $bornAt, genre: $genre, relationType: $relationType, weight: $weight, height: $height, watchQr: $watchQr, watchCode: $watchCode, activationKey: $activationKey, isLoading: $isLoading, validationErrorKey: $validationErrorKey, apiErrorEvent: $apiErrorEvent, isSuccess: $isSuccess)';
} }
@@ -45,7 +45,7 @@ abstract mixin class $DeviceSetupStateCopyWith<$Res> {
factory $DeviceSetupStateCopyWith(DeviceSetupState value, $Res Function(DeviceSetupState) _then) = _$DeviceSetupStateCopyWithImpl; factory $DeviceSetupStateCopyWith(DeviceSetupState value, $Res Function(DeviceSetupState) _then) = _$DeviceSetupStateCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
LegacyAddKidStep step, String firstName, String lastName, DateTime? bornAt, String genrer, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess LegacyAddKidStep step, String carrierName, DateTime? bornAt, String genre, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess
}); });
@@ -62,13 +62,12 @@ class _$DeviceSetupStateCopyWithImpl<$Res>
/// Create a copy of DeviceSetupState /// Create a copy of DeviceSetupState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline') @override $Res call({Object? step = null,Object? firstName = null,Object? lastName = null,Object? bornAt = freezed,Object? genrer = null,Object? relationType = null,Object? weight = null,Object? height = null,Object? watchQr = null,Object? watchCode = null,Object? activationKey = null,Object? isLoading = null,Object? validationErrorKey = null,Object? apiErrorEvent = freezed,Object? isSuccess = null,}) { @pragma('vm:prefer-inline') @override $Res call({Object? step = null,Object? carrierName = null,Object? bornAt = freezed,Object? genre = null,Object? relationType = null,Object? weight = null,Object? height = null,Object? watchQr = null,Object? watchCode = null,Object? activationKey = null,Object? isLoading = null,Object? validationErrorKey = null,Object? apiErrorEvent = freezed,Object? isSuccess = null,}) {
return _then(_self.copyWith( return _then(_self.copyWith(
step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
as LegacyAddKidStep,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as LegacyAddKidStep,carrierName: null == carrierName ? _self.carrierName : carrierName // ignore: cast_nullable_to_non_nullable
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
as DateTime?,genrer: null == genrer ? _self.genrer : genrer // ignore: cast_nullable_to_non_nullable as DateTime?,genre: null == genre ? _self.genre : genre // ignore: cast_nullable_to_non_nullable
as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable
as String,weight: null == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable as String,weight: null == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable
as String,height: null == height ? _self.height : height // ignore: cast_nullable_to_non_nullable as String,height: null == height ? _self.height : height // ignore: cast_nullable_to_non_nullable
@@ -164,10 +163,10 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( LegacyAddKidStep step, String firstName, String lastName, DateTime? bornAt, String genrer, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess)? $default,{required TResult orElse(),}) {final _that = this; @optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( LegacyAddKidStep step, String carrierName, DateTime? bornAt, String genre, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _DeviceSetupState() when $default != null: case _DeviceSetupState() when $default != null:
return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.genrer,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _: return $default(_that.step,_that.carrierName,_that.bornAt,_that.genre,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _:
return orElse(); return orElse();
} }
@@ -185,10 +184,10 @@ return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.gen
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( LegacyAddKidStep step, String firstName, String lastName, DateTime? bornAt, String genrer, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess) $default,) {final _that = this; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( LegacyAddKidStep step, String carrierName, DateTime? bornAt, String genre, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _DeviceSetupState(): case _DeviceSetupState():
return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.genrer,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _: return $default(_that.step,_that.carrierName,_that.bornAt,_that.genre,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _:
throw StateError('Unexpected subclass'); throw StateError('Unexpected subclass');
} }
@@ -205,10 +204,10 @@ return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.gen
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( LegacyAddKidStep step, String firstName, String lastName, DateTime? bornAt, String genrer, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess)? $default,) {final _that = this; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( LegacyAddKidStep step, String carrierName, DateTime? bornAt, String genre, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _DeviceSetupState() when $default != null: case _DeviceSetupState() when $default != null:
return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.genrer,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _: return $default(_that.step,_that.carrierName,_that.bornAt,_that.genre,_that.relationType,_that.weight,_that.height,_that.watchQr,_that.watchCode,_that.activationKey,_that.isLoading,_that.validationErrorKey,_that.apiErrorEvent,_that.isSuccess);case _:
return null; return null;
} }
@@ -220,14 +219,13 @@ return $default(_that.step,_that.firstName,_that.lastName,_that.bornAt,_that.gen
class _DeviceSetupState implements DeviceSetupState { class _DeviceSetupState implements DeviceSetupState {
const _DeviceSetupState({this.step = LegacyAddKidStep.intro, this.firstName = '', this.lastName = '', this.bornAt, this.genrer = '', this.relationType = '', this.weight = '', this.height = '', this.watchQr = '', this.watchCode = '', this.activationKey = '', this.isLoading = false, this.validationErrorKey = '', this.apiErrorEvent, this.isSuccess = false}); const _DeviceSetupState({this.step = LegacyAddKidStep.intro, this.carrierName = '', this.bornAt, this.genre = '', this.relationType = '', this.weight = '', this.height = '', this.watchQr = '', this.watchCode = '', this.activationKey = '', this.isLoading = false, this.validationErrorKey = '', this.apiErrorEvent, this.isSuccess = false});
@override@JsonKey() final LegacyAddKidStep step; @override@JsonKey() final LegacyAddKidStep step;
@override@JsonKey() final String firstName; @override@JsonKey() final String carrierName;
@override@JsonKey() final String lastName;
@override final DateTime? bornAt; @override final DateTime? bornAt;
@override@JsonKey() final String genrer; @override@JsonKey() final String genre;
@override@JsonKey() final String relationType; @override@JsonKey() final String relationType;
@override@JsonKey() final String weight; @override@JsonKey() final String weight;
@override@JsonKey() final String height; @override@JsonKey() final String height;
@@ -249,16 +247,16 @@ _$DeviceSetupStateCopyWith<_DeviceSetupState> get copyWith => __$DeviceSetupStat
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _DeviceSetupState&&(identical(other.step, step) || other.step == step)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.genrer, genrer) || other.genrer == genrer)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.height, height) || other.height == height)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.activationKey, activationKey) || other.activationKey == activationKey)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.validationErrorKey, validationErrorKey) || other.validationErrorKey == validationErrorKey)&&(identical(other.apiErrorEvent, apiErrorEvent) || other.apiErrorEvent == apiErrorEvent)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess)); return identical(this, other) || (other.runtimeType == runtimeType&&other is _DeviceSetupState&&(identical(other.step, step) || other.step == step)&&(identical(other.carrierName, carrierName) || other.carrierName == carrierName)&&(identical(other.bornAt, bornAt) || other.bornAt == bornAt)&&(identical(other.genre, genre) || other.genre == genre)&&(identical(other.relationType, relationType) || other.relationType == relationType)&&(identical(other.weight, weight) || other.weight == weight)&&(identical(other.height, height) || other.height == height)&&(identical(other.watchQr, watchQr) || other.watchQr == watchQr)&&(identical(other.watchCode, watchCode) || other.watchCode == watchCode)&&(identical(other.activationKey, activationKey) || other.activationKey == activationKey)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.validationErrorKey, validationErrorKey) || other.validationErrorKey == validationErrorKey)&&(identical(other.apiErrorEvent, apiErrorEvent) || other.apiErrorEvent == apiErrorEvent)&&(identical(other.isSuccess, isSuccess) || other.isSuccess == isSuccess));
} }
@override @override
int get hashCode => Object.hash(runtimeType,step,firstName,lastName,bornAt,genrer,relationType,weight,height,watchQr,watchCode,activationKey,isLoading,validationErrorKey,apiErrorEvent,isSuccess); int get hashCode => Object.hash(runtimeType,step,carrierName,bornAt,genre,relationType,weight,height,watchQr,watchCode,activationKey,isLoading,validationErrorKey,apiErrorEvent,isSuccess);
@override @override
String toString() { String toString() {
return 'DeviceSetupState(step: $step, firstName: $firstName, lastName: $lastName, bornAt: $bornAt, genrer: $genrer, relationType: $relationType, weight: $weight, height: $height, watchQr: $watchQr, watchCode: $watchCode, activationKey: $activationKey, isLoading: $isLoading, validationErrorKey: $validationErrorKey, apiErrorEvent: $apiErrorEvent, isSuccess: $isSuccess)'; return 'DeviceSetupState(step: $step, carrierName: $carrierName, bornAt: $bornAt, genre: $genre, relationType: $relationType, weight: $weight, height: $height, watchQr: $watchQr, watchCode: $watchCode, activationKey: $activationKey, isLoading: $isLoading, validationErrorKey: $validationErrorKey, apiErrorEvent: $apiErrorEvent, isSuccess: $isSuccess)';
} }
@@ -269,7 +267,7 @@ abstract mixin class _$DeviceSetupStateCopyWith<$Res> implements $DeviceSetupSta
factory _$DeviceSetupStateCopyWith(_DeviceSetupState value, $Res Function(_DeviceSetupState) _then) = __$DeviceSetupStateCopyWithImpl; factory _$DeviceSetupStateCopyWith(_DeviceSetupState value, $Res Function(_DeviceSetupState) _then) = __$DeviceSetupStateCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
LegacyAddKidStep step, String firstName, String lastName, DateTime? bornAt, String genrer, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess LegacyAddKidStep step, String carrierName, DateTime? bornAt, String genre, String relationType, String weight, String height, String watchQr, String watchCode, String activationKey, bool isLoading, String validationErrorKey, LegacyDeviceSetupErrorEvent? apiErrorEvent, bool isSuccess
}); });
@@ -286,13 +284,12 @@ class __$DeviceSetupStateCopyWithImpl<$Res>
/// Create a copy of DeviceSetupState /// Create a copy of DeviceSetupState
/// with the given fields replaced by the non-null parameter values. /// with the given fields replaced by the non-null parameter values.
@override @pragma('vm:prefer-inline') $Res call({Object? step = null,Object? firstName = null,Object? lastName = null,Object? bornAt = freezed,Object? genrer = null,Object? relationType = null,Object? weight = null,Object? height = null,Object? watchQr = null,Object? watchCode = null,Object? activationKey = null,Object? isLoading = null,Object? validationErrorKey = null,Object? apiErrorEvent = freezed,Object? isSuccess = null,}) { @override @pragma('vm:prefer-inline') $Res call({Object? step = null,Object? carrierName = null,Object? bornAt = freezed,Object? genre = null,Object? relationType = null,Object? weight = null,Object? height = null,Object? watchQr = null,Object? watchCode = null,Object? activationKey = null,Object? isLoading = null,Object? validationErrorKey = null,Object? apiErrorEvent = freezed,Object? isSuccess = null,}) {
return _then(_DeviceSetupState( return _then(_DeviceSetupState(
step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
as LegacyAddKidStep,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable as LegacyAddKidStep,carrierName: null == carrierName ? _self.carrierName : carrierName // ignore: cast_nullable_to_non_nullable
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable as String,bornAt: freezed == bornAt ? _self.bornAt : bornAt // ignore: cast_nullable_to_non_nullable
as DateTime?,genrer: null == genrer ? _self.genrer : genrer // ignore: cast_nullable_to_non_nullable as DateTime?,genre: null == genre ? _self.genre : genre // ignore: cast_nullable_to_non_nullable
as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable as String,relationType: null == relationType ? _self.relationType : relationType // ignore: cast_nullable_to_non_nullable
as String,weight: null == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable as String,weight: null == weight ? _self.weight : weight // ignore: cast_nullable_to_non_nullable
as String,height: null == height ? _self.height : height // ignore: cast_nullable_to_non_nullable as String,height: null == height ? _self.height : height // ignore: cast_nullable_to_non_nullable

View File

@@ -33,7 +33,7 @@ class LegacyProfileStepScreen extends ConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final genrerItems = <String, String>{ final genreItems = <String, String>{
'F': context.translate(I18n.genderFemale), 'F': context.translate(I18n.genderFemale),
'M': context.translate(I18n.genderMale), 'M': context.translate(I18n.genderMale),
'O': context.translate(I18n.genderOther), 'O': context.translate(I18n.genderOther),
@@ -49,6 +49,9 @@ class LegacyProfileStepScreen extends ConsumerWidget {
final notifier = ref.read(deviceSetupControllerProvider.notifier); final notifier = ref.read(deviceSetupControllerProvider.notifier);
return SingleChildScrollView( return SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom + 16,
),
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@@ -79,15 +82,9 @@ class LegacyProfileStepScreen extends ConsumerWidget {
child: Column( child: Column(
children: [ children: [
CustomTextField( CustomTextField(
label: context.translate(I18n.firstNameLabel), label: context.translate(I18n.carrierNameLabel),
hint: context.translate(I18n.firstNameHint), hint: context.translate(I18n.carrierNameHint),
controller: controllers.firstName, controller: controllers.carrierName,
),
const SizedBox(height: 8),
CustomTextField(
label: context.translate(I18n.lastNameLabel),
hint: context.translate(I18n.lastNameHint),
controller: controllers.lastName,
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
GestureDetector( GestureDetector(
@@ -105,14 +102,14 @@ class LegacyProfileStepScreen extends ConsumerWidget {
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
CustomDropdown( CustomDropdown(
items: genrerItems.values items: genreItems.values
.map(Text.new) .map(Text.new)
.toList(growable: false), .toList(growable: false),
values: genrerItems.keys.toList(growable: false), values: genreItems.keys.toList(growable: false),
value: state.genrer.isEmpty ? null : state.genrer, value: state.genre.isEmpty ? null : state.genre,
label: context.translate(I18n.genderLabel), label: context.translate(I18n.genderLabel),
hint: context.translate(I18n.genderHint), hint: context.translate(I18n.genderHint),
onChanged: (v) => notifier.onGenrerChanged(v as String?), onChanged: (v) => notifier.onGenreChanged(v as String?),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
CustomDropdown( CustomDropdown(

View File

@@ -1,3 +1,4 @@
import 'package:legacy_ui/legacy_ui.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_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -6,6 +7,8 @@ import 'package:legacy_auth/src/features/device_setup/presentation/providers/dev
import 'package:legacy_auth/src/features/device_setup/presentation/providers/device_setup_form_controllers.dart'; import 'package:legacy_auth/src/features/device_setup/presentation/providers/device_setup_form_controllers.dart';
import 'package:legacy_auth/src/features/device_setup/presentation/qr_scanner_screen.dart'; import 'package:legacy_auth/src/features/device_setup/presentation/qr_scanner_screen.dart';
import 'package:sf_localizations/sf_localizations.dart'; import 'package:sf_localizations/sf_localizations.dart';
import 'package:sf_shared/sf_shared.dart';
import 'package:url_launcher/url_launcher.dart';
class LegacyScanWatchStepScreen extends ConsumerWidget { class LegacyScanWatchStepScreen extends ConsumerWidget {
final DeviceSetupFormControllers controllers; final DeviceSetupFormControllers controllers;
@@ -17,6 +20,9 @@ class LegacyScanWatchStepScreen extends ConsumerWidget {
final notifier = ref.read(deviceSetupControllerProvider.notifier); final notifier = ref.read(deviceSetupControllerProvider.notifier);
return SingleChildScrollView( return SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom + 16,
),
child: Column( child: Column(
mainAxisSize: MainAxisSize.max, mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
@@ -39,7 +45,7 @@ class LegacyScanWatchStepScreen extends ConsumerWidget {
borderRadius: BorderRadius.circular(16), borderRadius: BorderRadius.circular(16),
onTap: () async { onTap: () async {
final result = await Navigator.of(context).push<String>( final result = await Navigator.of(context).push<String>(
MaterialPageRoute( LegacyPageRoute(
builder: (_) => const LegacyQrScannerScreen(), builder: (_) => const LegacyQrScannerScreen(),
), ),
); );
@@ -102,7 +108,10 @@ class LegacyScanWatchStepScreen extends ConsumerWidget {
style: const TextStyle(fontSize: 18), style: const TextStyle(fontSize: 18),
), ),
CustomTextButton( CustomTextButton(
onPressed: () {}, onPressed: () {
final url = BrandLinks.helpCenter;
if (url.isNotEmpty) launchUrl(Uri.parse(url));
},
text: context.translate(I18n.deviceSetupContactUs), text: context.translate(I18n.deviceSetupContactUs),
weight: FontWeight.w800, weight: FontWeight.w800,
size: 18, size: 18,

View File

@@ -10,11 +10,13 @@ import 'package:sf_localizations/sf_localizations.dart';
class LegacySuccessScreen extends ConsumerWidget { class LegacySuccessScreen extends ConsumerWidget {
final NavigationContract navigationContract; final NavigationContract navigationContract;
final DeviceSetupFormControllers formControllers; final DeviceSetupFormControllers formControllers;
final bool isFirstDevice;
const LegacySuccessScreen({ const LegacySuccessScreen({
super.key, super.key,
required this.navigationContract, required this.navigationContract,
required this.formControllers, required this.formControllers,
this.isFirstDevice = true,
}); });
@override @override
@@ -40,7 +42,7 @@ class LegacySuccessScreen extends ConsumerWidget {
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Text( Text(
context.translate(I18n.accountCreatedTitle), context.translate(I18n.deviceSetupSuccessTitle),
style: const TextStyle( style: const TextStyle(
fontSize: 30, fontSize: 30,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@@ -48,12 +50,12 @@ class LegacySuccessScreen extends ConsumerWidget {
), ),
const SizedBox(height: 30), const SizedBox(height: 30),
Text( Text(
context.translate(I18n.accountCreatedForLabel), context.translate(I18n.deviceSetupSuccessForLabel),
style: const TextStyle(fontSize: 18), style: const TextStyle(fontSize: 18),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
Text( Text(
'${state.firstName} ${state.lastName}', state.carrierName,
style: const TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@@ -66,13 +68,18 @@ class LegacySuccessScreen extends ConsumerWidget {
LegacyFlowFooter( LegacyFlowFooter(
primaryText: context.translate(I18n.continueKey), primaryText: context.translate(I18n.continueKey),
onPrimary: () { onPrimary: () {
navigationContract.goTo(AppRoutes.controlPanel); if (isFirstDevice) {
navigationContract.goTo(AppRoutes.controlPanel);
} else {
Navigator.of(context)
..pop()
..pop();
}
}, },
secondaryText: context.translate(I18n.deviceSetupAddAnotherKid), secondaryText: context.translate(I18n.deviceSetupAddAnotherKid),
onSecondary: () { onSecondary: () {
notifier.resetForNewKid(); notifier.resetForNewKid();
formControllers.firstName.clear(); formControllers.carrierName.clear();
formControllers.lastName.clear();
formControllers.bornAt.clear(); formControllers.bornAt.clear();
formControllers.weight.clear(); formControllers.weight.clear();
formControllers.height.clear(); formControllers.height.clear();