diff --git a/.idea/modules.xml b/.idea/modules.xml index 54a5b847..09ca2fec 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -17,6 +17,7 @@ + diff --git a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart index 56f074d8..7f83e2c8 100644 --- a/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/account_settings/presentation/account_settings_screen.dart @@ -20,7 +20,8 @@ class AccountSettingsScreen extends ConsumerWidget { final selectedDevice = ref.watch(selectedDeviceProvider); - return PageLayout( + return LegacyPageLayout( +theme: theme, title: context.translate(I18n.accountSettings), body: SingleChildScrollView(child: Container( padding: SizeUtils.getByScreen( @@ -32,31 +33,31 @@ class AccountSettingsScreen extends ConsumerWidget { AppSectionButton( onPressed: (){navigationContract.pushTo(AppRoutes.personalData);}, icon: SFIcons.account, - text: I18n.legacyPersonalData + text: I18n.personalData ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( onPressed: (){navigationContract.pushTo(AppRoutes.changePassword);}, icon: Icons.lock, - text: I18n.legacyChangePassword + text: I18n.changePassword ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( onPressed: (){}, icon: Icons.add_circle_outline, - text: I18n.legacyAddNewSF + text: I18n.addNewSF ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( onPressed: (){navigationContract.pushTo(AppRoutes.linkedDevices);}, icon: Icons.account_circle_outlined, - text: I18n.legacyLinkedDevices + text: I18n.linkedDevices ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( onPressed: (){navigationContract.pushTo(AppRoutes.appUsers);}, icon: Icons.groups_outlined, - text: I18n.legacyAppUsers + text: I18n.appUsers ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( @@ -67,7 +68,7 @@ class AccountSettingsScreen extends ConsumerWidget { } }, icon: SFIcons.privacy, - text: I18n.legacyPrivacyPolicy + text: I18n.privacyPolicy ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( @@ -82,13 +83,13 @@ class AccountSettingsScreen extends ConsumerWidget { )); }, icon: Icons.qr_code, - text: I18n.legacyRegCode + text: I18n.regCode ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), AppSectionButton( onPressed: (){navigationContract.pushTo(AppRoutes.deleteAccount);}, icon: Icons.no_accounts, - text: I18n.legacyDeleteAccount + text: I18n.deleteAccount ), ], ), @@ -98,7 +99,7 @@ class AccountSettingsScreen extends ConsumerWidget { small: EdgeInsets.symmetric(vertical: 12, horizontal: 30), big: EdgeInsets.symmetric(vertical: 10, horizontal: 28) ), - child: PrimaryButton(text: context.translate(I18n.legacyLogOut), color: Color(0xFF588EA5)), + child: PrimaryButton(text: context.translate(I18n.logOut), color: theme.getColorFor(ThemeCode.legacyPrimary)), ) ); } @@ -118,7 +119,7 @@ class AppSectionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); return GestureDetector( onTap: onPressed, @@ -141,7 +142,7 @@ class AppSectionButton extends ConsumerWidget { padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), child: Icon(icon, size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), weight: 30, ), ), @@ -206,11 +207,11 @@ class RegCodeDialog extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(context.translate(I18n.legacyDeviceIdLabel, + Text(context.translate(I18n.deviceIdLabel, args: {'deviceId': deviceId})), TextButton( onPressed: (){Clipboard.setData(ClipboardData(text: deviceId));}, - child: Text(context.translate(I18n.legacyCopy)), + child: Text(context.translate(I18n.copy)), ) ], ), @@ -223,11 +224,11 @@ class RegCodeDialog extends StatelessWidget { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text(context.translate(I18n.legacyRegCodeLabel, + Text(context.translate(I18n.regCodeLabel, args: {'regCode': regCode})), TextButton( onPressed: (){Clipboard.setData(ClipboardData(text: regCode));}, - child: Text(context.translate(I18n.legacyCopy)) + child: Text(context.translate(I18n.copy)) ) ], ) diff --git a/modules/legacy/modules/account/lib/src/features/app_users/presentation/app_users_screen.dart b/modules/legacy/modules/account/lib/src/features/app_users/presentation/app_users_screen.dart index ccdd457c..256a96ca 100644 --- a/modules/legacy/modules/account/lib/src/features/app_users/presentation/app_users_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/app_users/presentation/app_users_screen.dart @@ -19,10 +19,11 @@ class AppUsersScreen extends ConsumerWidget { final theme = ref.watch(themePortProvider); - return PageLayout( + return LegacyPageLayout( +theme: theme, showEdit: true, onEditChange: vm.toggleIsEditing, - title: context.translate(I18n.legacyAppUsers), + title: context.translate(I18n.appUsers), body: Container( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), @@ -42,8 +43,8 @@ class AppUsersScreen extends ConsumerWidget { footer: state.isEditing ? PrimaryButton( onPressed: vm.toggleIsEditing, - text: context.translate(I18n.legacySave), - color: Color(0xFF588EA5), + text: context.translate(I18n.save), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 44, big: 42), ) : null ); @@ -62,7 +63,7 @@ class AppUserCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); return Container( padding: SizeUtils.getByScreen( @@ -83,7 +84,7 @@ class AppUserCard extends ConsumerWidget { padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), child: Icon(SFIcons.account, size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), weight: 30, ), ), @@ -98,12 +99,12 @@ class AppUserCard extends ConsumerWidget { fontWeight: FontWeight.w500 ) ), - Text(context.translate(I18n.legacyUserAccount, args: {'email': user.email}), + Text(context.translate(I18n.userAccount, args: {'email': user.email}), style: TextStyle( fontSize: SizeUtils.getByScreen(small: 14, big: 13), ) ), - Text(context.translate(I18n.legacyUserRole, args: {'role': user.role}), + Text(context.translate(I18n.userRole, args: {'role': user.role}), style: TextStyle( fontSize: SizeUtils.getByScreen(small: 14, big: 13), ) @@ -128,7 +129,7 @@ class AppUserCard extends ConsumerWidget { height: SizeUtils.getByScreen(small: 195, big: 185), child: Column( children: [ - Text(context.translate(I18n.legacyDeleteUserDialog), + Text(context.translate(I18n.deleteUserDialog), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), ), @@ -138,8 +139,8 @@ class AppUserCard extends ConsumerWidget { children: [ Expanded(child: PrimaryButton( onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )), @@ -148,8 +149,8 @@ class AppUserCard extends ConsumerWidget { onPressed: (){ Navigator.pop(context); }, - text: context.translate(I18n.legacyDelete), - color: Color(0xFF588EA5), + text: context.translate(I18n.delete), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )) diff --git a/modules/legacy/modules/account/lib/src/features/change_password/presentation/change_password_screen.dart b/modules/legacy/modules/account/lib/src/features/change_password/presentation/change_password_screen.dart index c0f8f2a6..56b6c93a 100644 --- a/modules/legacy/modules/account/lib/src/features/change_password/presentation/change_password_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/change_password/presentation/change_password_screen.dart @@ -19,8 +19,9 @@ class ChangePasswordScreen extends ConsumerWidget { final theme = ref.watch(themePortProvider); - return PageLayout( - title: context.translate(I18n.legacyChangePassword), + return LegacyPageLayout( +theme: theme, + title: context.translate(I18n.changePassword), body: Container( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 28, vertical: 10), @@ -68,7 +69,7 @@ class ChangePasswordScreen extends ConsumerWidget { } }, text: context.translate('OK'), - color: Color(0xFF588EA5) + color: theme.getColorFor(ThemeCode.legacyPrimary) ), ); } diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/delete_account_screen.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/delete_account_screen.dart index 48ea4a75..6fbb0bdd 100644 --- a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/delete_account_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/delete_account_screen.dart @@ -1,4 +1,5 @@ import 'package:account/src/features/delete_account/presentation/state/delete_account_view_model.dart'; +import 'package:account/src/features/delete_account/presentation/widgets/confirm_dialog.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -19,8 +20,9 @@ class DeleteAccountScreen extends ConsumerWidget { final state = ref.watch(deleteAccountViewModelProvider); final viewModel = ref.read(deleteAccountViewModelProvider.notifier); - return PageLayout( - title: context.translate(I18n.legacyDeleteAccount), + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.deleteAccount), body: SingleChildScrollView(child: Container( margin: EdgeInsets.symmetric(horizontal: 10), child: Column( @@ -49,18 +51,18 @@ class DeleteAccountScreen extends ConsumerWidget { color: Colors.white, ), ), - Text(context.translate(I18n.legacyDeleteAccount), + Text(context.translate(I18n.deleteAccount), style: TextStyle(fontSize: SizeUtils.getByScreen(small: 20, big: 19)), ) ], ), ), SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), - Text(context.translate(I18n.legacyDeleteAccountBody1), + Text(context.translate(I18n.deleteAccountBody1), textAlign: TextAlign.start, ), SizedBox(height: SizeUtils.getByScreen(small: 38, big: 36)), - Text(context.translate(I18n.legacyDeleteAccountBody2), + Text(context.translate(I18n.deleteAccountBody2), textAlign: TextAlign.start, style: TextStyle( fontSize: 12, @@ -86,171 +88,11 @@ class DeleteAccountScreen extends ConsumerWidget { ); } }, - text: context.translate(I18n.legacyRequestCancelButton), - color: Color(0xFF588EA5) + text: context.translate(I18n.requestCancelButton), + color: theme.getColorFor(ThemeCode.legacyPrimary) ), ), ); } } -class ConfirmDialog extends ConsumerWidget{ - - final NavigationContract navigationContract; - - const ConfirmDialog({ - super.key, - required this.navigationContract, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final state = ref.watch(deleteAccountViewModelProvider); - final viewModel = ref.read(deleteAccountViewModelProvider.notifier); - - final steps = [ - Container( - height: 210, - width: 500, - color: Colors.white, - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 11), - big: EdgeInsets.symmetric(horizontal: 20, vertical: 10), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text(context.translate(I18n.legacyVerifyAccount), - style: TextStyle( - fontWeight: FontWeight.w500 - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)), - Text('${context.translate(I18n.email)}: ${state.loggedUser!.email}'), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), - Row( - children: [ - Text('${context.translate(I18n.password)}: '), - SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), - Expanded(child: TextField( - controller: viewModel.passwordController, - style: TextStyle(fontSize: 12), - decoration: InputDecoration(hintText: context.translate(I18n.password)), - obscureText: true, - enableSuggestions: false, - autocorrect: true, - )) - ], - ), - if (state.errorMessage.isNotEmpty) - Text( - state.errorMessage, - textAlign: TextAlign.center, - style: TextStyle( - color: Theme.of(context).colorScheme.error, - fontSize: 13, - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), - Row( - children: [ - Expanded(child: SecondaryButton( - onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), - height: 40, - radius: 20, - )), - SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), - Expanded(child: PrimaryButton( - onPressed: viewModel.nextStep, - text: context.translate(I18n.accept), - color: Color(0xFF588EA5), - height: 40, - radius: 20, - )), - ], - ) - ], - ), - ), - Container( - height: 400, - width: 500, - color: Colors.white, - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 11), - big: EdgeInsets.symmetric(horizontal: 20, vertical: 10), - ), - child: Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), - Text(context.translate(I18n.legacyRequestCancelTitle), - style: TextStyle( - fontWeight: FontWeight.w500 - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), - Expanded(child: SingleChildScrollView(child: Column( - children: [ - Text(context.translate(I18n.legacyRequestCancelBody), - style: TextStyle(height: 1.5), - ), - SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), - ...List.generate(state.devices.length, (int index) => - CheckboxListTile( - contentPadding: EdgeInsets.zero, - title: Text(context.translate(I18n.legacyDeleteDeviceData, - args: {'name': state.devices[index].carrierName} - ), - style: TextStyle(height: 0), - ), - controlAffinity: ListTileControlAffinity.leading, - value: false, - onChanged: (_){ - viewModel.updateDeleteDevice(index); - } - ) - ), - ] - ))), - SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), - Row( - children: [ - Expanded(child: SecondaryButton( - onPressed: (){ - viewModel.resetConfirmStep(); - Navigator.pop(context); - }, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), - height: 50, - radius: 25, - )), - SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), - Expanded(child: PrimaryButton( - onPressed: () async { - viewModel.deleteAccount(); - if (!context.mounted) return; - - navigationContract.goTo(AppRoutes.login); - }, - text: context.translate(I18n.legacyConfirm), - color: Color(0xFF588EA5), - height: 50, - radius: 25, - )), - ], - ) - ], - ), - ) - ]; - - return steps[state.confirmStep]; - } - -} diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart index ab0700f9..d3e22667 100644 --- a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_model.dart @@ -27,29 +27,33 @@ class DeleteAccountViewModel extends Notifier { passwordController = TextEditingController(); passwordController.addListener(_onPasswordChanged); - ref.read(loggedUserProvider.future) - .then((user){ - setUser(user); - return _getLinkedDevicesUseCase.getLinkedDevices(userId: user.id); - }).then(setDevices); - ref.onDispose(disposeListeners); + Future.microtask(() => load()); + return const DeleteAccountViewState(); } + Future load() async { + final user = await ref.read(loggedUserProvider.future); + setUser(user); + + final devices = await _getLinkedDevicesUseCase.getLinkedDevices(userId: user.id); + setDevices(devices); + } + void setUser(UserEntity user) { state = state.copyWith(loggedUser: user); } void setDevices(List devices) { state = state.copyWith( - devices: devices, + deviceNames: devices.map((device) => device.carrierName).toList(), deleteDevices: List.generate(devices.length, (_)=>false), ); } - void updateDeleteDevice(int index) { + void toggleDeleteDevice(int index) { List deleteDevices = state.deleteDevices; deleteDevices[index] = !deleteDevices[index]; diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.dart index 1b7e9ecb..abb076d3 100644 --- a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.dart +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.dart @@ -11,7 +11,7 @@ abstract class DeleteAccountViewState with _$DeleteAccountViewState { @Default(false) bool isLoading, @Default(false) bool isDeleted, @Default(0) int confirmStep, - @Default([]) List devices, + @Default([]) List deviceNames, @Default([]) List deleteDevices, @Default('') String errorMessage, }) = _DeleteAccountViewState; diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.freezed.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.freezed.dart index c0c64d1b..47f79f30 100644 --- a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.freezed.dart +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/state/delete_account_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$DeleteAccountViewState { - UserEntity? get loggedUser; String get password; bool get isLoading; bool get isDeleted; int get confirmStep; List get devices; List get deleteDevices; String get errorMessage; + UserEntity? get loggedUser; String get password; bool get isLoading; bool get isDeleted; int get confirmStep; List get deviceNames; List get deleteDevices; String get errorMessage; /// Create a copy of DeleteAccountViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $DeleteAccountViewStateCopyWith get copyWith => _$Delete @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is DeleteAccountViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.password, password) || other.password == password)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isDeleted, isDeleted) || other.isDeleted == isDeleted)&&(identical(other.confirmStep, confirmStep) || other.confirmStep == confirmStep)&&const DeepCollectionEquality().equals(other.devices, devices)&&const DeepCollectionEquality().equals(other.deleteDevices, deleteDevices)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is DeleteAccountViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.password, password) || other.password == password)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isDeleted, isDeleted) || other.isDeleted == isDeleted)&&(identical(other.confirmStep, confirmStep) || other.confirmStep == confirmStep)&&const DeepCollectionEquality().equals(other.deviceNames, deviceNames)&&const DeepCollectionEquality().equals(other.deleteDevices, deleteDevices)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,loggedUser,password,isLoading,isDeleted,confirmStep,const DeepCollectionEquality().hash(devices),const DeepCollectionEquality().hash(deleteDevices),errorMessage); +int get hashCode => Object.hash(runtimeType,loggedUser,password,isLoading,isDeleted,confirmStep,const DeepCollectionEquality().hash(deviceNames),const DeepCollectionEquality().hash(deleteDevices),errorMessage); @override String toString() { - return 'DeleteAccountViewState(loggedUser: $loggedUser, password: $password, isLoading: $isLoading, isDeleted: $isDeleted, confirmStep: $confirmStep, devices: $devices, deleteDevices: $deleteDevices, errorMessage: $errorMessage)'; + return 'DeleteAccountViewState(loggedUser: $loggedUser, password: $password, isLoading: $isLoading, isDeleted: $isDeleted, confirmStep: $confirmStep, deviceNames: $deviceNames, deleteDevices: $deleteDevices, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $DeleteAccountViewStateCopyWith<$Res> { factory $DeleteAccountViewStateCopyWith(DeleteAccountViewState value, $Res Function(DeleteAccountViewState) _then) = _$DeleteAccountViewStateCopyWithImpl; @useResult $Res call({ - UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List devices, List deleteDevices, String errorMessage + UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List deviceNames, List deleteDevices, String errorMessage }); @@ -62,15 +62,15 @@ class _$DeleteAccountViewStateCopyWithImpl<$Res> /// Create a copy of DeleteAccountViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? loggedUser = freezed,Object? password = null,Object? isLoading = null,Object? isDeleted = null,Object? confirmStep = null,Object? devices = null,Object? deleteDevices = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? loggedUser = freezed,Object? password = null,Object? isLoading = null,Object? isDeleted = null,Object? confirmStep = null,Object? deviceNames = null,Object? deleteDevices = null,Object? errorMessage = null,}) { return _then(_self.copyWith( loggedUser: freezed == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable as UserEntity?,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isDeleted: null == isDeleted ? _self.isDeleted : isDeleted // ignore: cast_nullable_to_non_nullable as bool,confirmStep: null == confirmStep ? _self.confirmStep : confirmStep // ignore: cast_nullable_to_non_nullable -as int,devices: null == devices ? _self.devices : devices // ignore: cast_nullable_to_non_nullable -as List,deleteDevices: null == deleteDevices ? _self.deleteDevices : deleteDevices // ignore: cast_nullable_to_non_nullable +as int,deviceNames: null == deviceNames ? _self.deviceNames : deviceNames // ignore: cast_nullable_to_non_nullable +as List,deleteDevices: null == deleteDevices ? _self.deleteDevices : deleteDevices // ignore: cast_nullable_to_non_nullable as List,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); @@ -169,10 +169,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List devices, List deleteDevices, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List deviceNames, List deleteDevices, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _DeleteAccountViewState() when $default != null: -return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.devices,_that.deleteDevices,_that.errorMessage);case _: +return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.deviceNames,_that.deleteDevices,_that.errorMessage);case _: return orElse(); } @@ -190,10 +190,10 @@ return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted, /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List devices, List deleteDevices, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List deviceNames, List deleteDevices, String errorMessage) $default,) {final _that = this; switch (_that) { case _DeleteAccountViewState(): -return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.devices,_that.deleteDevices,_that.errorMessage);case _: +return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.deviceNames,_that.deleteDevices,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -210,10 +210,10 @@ return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted, /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List devices, List deleteDevices, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List deviceNames, List deleteDevices, String errorMessage)? $default,) {final _that = this; switch (_that) { case _DeleteAccountViewState() when $default != null: -return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.devices,_that.deleteDevices,_that.errorMessage);case _: +return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted,_that.confirmStep,_that.deviceNames,_that.deleteDevices,_that.errorMessage);case _: return null; } @@ -225,7 +225,7 @@ return $default(_that.loggedUser,_that.password,_that.isLoading,_that.isDeleted, class _DeleteAccountViewState implements DeleteAccountViewState { - const _DeleteAccountViewState({this.loggedUser, this.password = '', this.isLoading = false, this.isDeleted = false, this.confirmStep = 0, final List devices = const [], final List deleteDevices = const [], this.errorMessage = ''}): _devices = devices,_deleteDevices = deleteDevices; + const _DeleteAccountViewState({this.loggedUser, this.password = '', this.isLoading = false, this.isDeleted = false, this.confirmStep = 0, final List deviceNames = const [], final List deleteDevices = const [], this.errorMessage = ''}): _deviceNames = deviceNames,_deleteDevices = deleteDevices; @override final UserEntity? loggedUser; @@ -233,11 +233,11 @@ class _DeleteAccountViewState implements DeleteAccountViewState { @override@JsonKey() final bool isLoading; @override@JsonKey() final bool isDeleted; @override@JsonKey() final int confirmStep; - final List _devices; -@override@JsonKey() List get devices { - if (_devices is EqualUnmodifiableListView) return _devices; + final List _deviceNames; +@override@JsonKey() List get deviceNames { + if (_deviceNames is EqualUnmodifiableListView) return _deviceNames; // ignore: implicit_dynamic_type - return EqualUnmodifiableListView(_devices); + return EqualUnmodifiableListView(_deviceNames); } final List _deleteDevices; @@ -259,16 +259,16 @@ _$DeleteAccountViewStateCopyWith<_DeleteAccountViewState> get copyWith => __$Del @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _DeleteAccountViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.password, password) || other.password == password)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isDeleted, isDeleted) || other.isDeleted == isDeleted)&&(identical(other.confirmStep, confirmStep) || other.confirmStep == confirmStep)&&const DeepCollectionEquality().equals(other._devices, _devices)&&const DeepCollectionEquality().equals(other._deleteDevices, _deleteDevices)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _DeleteAccountViewState&&(identical(other.loggedUser, loggedUser) || other.loggedUser == loggedUser)&&(identical(other.password, password) || other.password == password)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isDeleted, isDeleted) || other.isDeleted == isDeleted)&&(identical(other.confirmStep, confirmStep) || other.confirmStep == confirmStep)&&const DeepCollectionEquality().equals(other._deviceNames, _deviceNames)&&const DeepCollectionEquality().equals(other._deleteDevices, _deleteDevices)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,loggedUser,password,isLoading,isDeleted,confirmStep,const DeepCollectionEquality().hash(_devices),const DeepCollectionEquality().hash(_deleteDevices),errorMessage); +int get hashCode => Object.hash(runtimeType,loggedUser,password,isLoading,isDeleted,confirmStep,const DeepCollectionEquality().hash(_deviceNames),const DeepCollectionEquality().hash(_deleteDevices),errorMessage); @override String toString() { - return 'DeleteAccountViewState(loggedUser: $loggedUser, password: $password, isLoading: $isLoading, isDeleted: $isDeleted, confirmStep: $confirmStep, devices: $devices, deleteDevices: $deleteDevices, errorMessage: $errorMessage)'; + return 'DeleteAccountViewState(loggedUser: $loggedUser, password: $password, isLoading: $isLoading, isDeleted: $isDeleted, confirmStep: $confirmStep, deviceNames: $deviceNames, deleteDevices: $deleteDevices, errorMessage: $errorMessage)'; } @@ -279,7 +279,7 @@ abstract mixin class _$DeleteAccountViewStateCopyWith<$Res> implements $DeleteAc factory _$DeleteAccountViewStateCopyWith(_DeleteAccountViewState value, $Res Function(_DeleteAccountViewState) _then) = __$DeleteAccountViewStateCopyWithImpl; @override @useResult $Res call({ - UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List devices, List deleteDevices, String errorMessage + UserEntity? loggedUser, String password, bool isLoading, bool isDeleted, int confirmStep, List deviceNames, List deleteDevices, String errorMessage }); @@ -296,15 +296,15 @@ class __$DeleteAccountViewStateCopyWithImpl<$Res> /// Create a copy of DeleteAccountViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? loggedUser = freezed,Object? password = null,Object? isLoading = null,Object? isDeleted = null,Object? confirmStep = null,Object? devices = null,Object? deleteDevices = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? loggedUser = freezed,Object? password = null,Object? isLoading = null,Object? isDeleted = null,Object? confirmStep = null,Object? deviceNames = null,Object? deleteDevices = null,Object? errorMessage = null,}) { return _then(_DeleteAccountViewState( loggedUser: freezed == loggedUser ? _self.loggedUser : loggedUser // ignore: cast_nullable_to_non_nullable as UserEntity?,password: null == password ? _self.password : password // ignore: cast_nullable_to_non_nullable as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable as bool,isDeleted: null == isDeleted ? _self.isDeleted : isDeleted // ignore: cast_nullable_to_non_nullable as bool,confirmStep: null == confirmStep ? _self.confirmStep : confirmStep // ignore: cast_nullable_to_non_nullable -as int,devices: null == devices ? _self._devices : devices // ignore: cast_nullable_to_non_nullable -as List,deleteDevices: null == deleteDevices ? _self._deleteDevices : deleteDevices // ignore: cast_nullable_to_non_nullable +as int,deviceNames: null == deviceNames ? _self._deviceNames : deviceNames // ignore: cast_nullable_to_non_nullable +as List,deleteDevices: null == deleteDevices ? _self._deleteDevices : deleteDevices // ignore: cast_nullable_to_non_nullable as List,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable as String, )); diff --git a/modules/legacy/modules/account/lib/src/features/delete_account/presentation/widgets/confirm_dialog.dart b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/widgets/confirm_dialog.dart new file mode 100644 index 00000000..4e6956c4 --- /dev/null +++ b/modules/legacy/modules/account/lib/src/features/delete_account/presentation/widgets/confirm_dialog.dart @@ -0,0 +1,229 @@ +import 'package:account/src/features/delete_account/presentation/state/delete_account_view_model.dart'; +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:navigation/app_routes.dart'; +import 'package:navigation/navigation_contract.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +class ConfirmDialog extends ConsumerWidget{ + + final NavigationContract navigationContract; + + const ConfirmDialog({ + super.key, + required this.navigationContract, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.watch(themePortProvider); + + final state = ref.watch(deleteAccountViewModelProvider); + final viewModel = ref.read(deleteAccountViewModelProvider.notifier); + + final steps = [ + VerifyAccountStep( + theme: theme, + email: state.loggedUser!.email, + passwordController: viewModel.passwordController, + errorMessage: state.errorMessage, + nextStep: viewModel.nextStep, + ), + ConfirmRequestStep( + theme: theme, + toggleDeleteDevice: viewModel.toggleDeleteDevice, + deviceNames: state.deviceNames, + onCancel: (){ + viewModel.resetConfirmStep(); + Navigator.pop(context); + }, + onSubmit: () async { + viewModel.deleteAccount(); + if (!context.mounted) return; + + navigationContract.goTo(AppRoutes.login); + }, + ), + ]; + + return steps[state.confirmStep]; + } +} + +class VerifyAccountStep extends StatelessWidget { + + final String email; + final TextEditingController passwordController; + final String errorMessage; + final VoidCallback nextStep; + final ThemePort theme; + + const VerifyAccountStep({ + required this.email, + required this.passwordController, + required this.errorMessage, + required this.nextStep, + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: 210, + width: 500, + color: Colors.white, + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 11), + big: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(context.translate(I18n.verifyAccount), + style: TextStyle( + fontWeight: FontWeight.w500 + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)), + Text('${context.translate(I18n.email)}: ${email}'), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 6)), + Row( + children: [ + Text('${context.translate(I18n.password)}: '), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), + Expanded(child: TextField( + controller: passwordController, + style: TextStyle(fontSize: 12), + decoration: InputDecoration(hintText: context.translate(I18n.password)), + obscureText: true, + enableSuggestions: false, + autocorrect: true, + )) + ], + ), + if (errorMessage.isNotEmpty) + Text( + errorMessage, + textAlign: TextAlign.center, + style: TextStyle( + color: Theme.of(context).colorScheme.error, + fontSize: 13, + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Row( + children: [ + Expanded(child: SecondaryButton( + onPressed: (){Navigator.pop(context);}, + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: 40, + radius: 20, + )), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), + Expanded(child: PrimaryButton( + onPressed: nextStep, + text: context.translate(I18n.accept), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: 40, + radius: 20, + )), + ], + ) + ], + ), + ); + } + +} + +class ConfirmRequestStep extends StatelessWidget { + + final ThemePort theme; + final Function toggleDeleteDevice; + final List deviceNames; + final VoidCallback onCancel; + final VoidCallback onSubmit; + + const ConfirmRequestStep({ + required this.theme, + required this.toggleDeleteDevice, + required this.deviceNames, + required this.onCancel, + required this.onSubmit, + }); + + @override + Widget build(BuildContext context) { + return Container( + height: 400, + width: 500, + color: Colors.white, + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 11), + big: EdgeInsets.symmetric(horizontal: 20, vertical: 10), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), + Text(context.translate(I18n.requestCancelTitle), + style: TextStyle( + fontWeight: FontWeight.w500 + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)), + Expanded(child: SingleChildScrollView(child: Column( + children: [ + Text(context.translate(I18n.requestCancelBody), + style: TextStyle(height: 1.5), + ), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + ...List.generate(deviceNames.length, (int index) => + CheckboxListTile( + contentPadding: EdgeInsets.zero, + title: Text(context.translate(I18n.deleteDeviceData, + args: {'name': deviceNames[index]} + ), + style: TextStyle(height: 0), + ), + controlAffinity: ListTileControlAffinity.leading, + value: false, + onChanged: (_){ + toggleDeleteDevice(index); + } + ) + ), + ] + ))), + SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)), + Row( + children: [ + Expanded(child: SecondaryButton( + onPressed: onCancel, + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: 50, + radius: 25, + )), + SizedBox(width: SizeUtils.getByScreen(small: 12, big: 10)), + Expanded(child: PrimaryButton( + onPressed: onSubmit, + text: context.translate(I18n.confirm), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: 50, + radius: 25, + )), + ], + ) + ], + ), + ); + } + +} \ No newline at end of file diff --git a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart index 3a29e975..bfd77859 100644 --- a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/edit_linked_device_screen.dart @@ -22,8 +22,9 @@ class EditLinkedDeviceScreen extends ConsumerWidget { final theme = ref.watch(themePortProvider); - return /*PageLayout( - title: context.translate(I18n.legacyEditDeviceTitle), + return /*LegacyPageLayout( +theme: theme, + title: context.translate(I18n.editDeviceTitle), showEdit: true, onEditChange: vm.toggleIsEditing, body: body @@ -43,7 +44,7 @@ class EditLinkedDeviceScreen extends ConsumerWidget { IconButton(onPressed: () {Navigator.pop(context);}, icon: Icon(Icons.arrow_back)), Center( - child: Text(context.translate(I18n.legacyEditDeviceTitle), + child: Text(context.translate(I18n.editDeviceTitle), style: TextStyle( fontSize: SizeUtils.getByScreen(small: 28, big: 27) ), @@ -94,14 +95,14 @@ class EditLinkedDeviceScreen extends ConsumerWidget { CustomTextField( controller: vm.deviceNameController, hint: device.carrierName, - label: context.translate(I18n.legacyName), + label: context.translate(I18n.name), ) ], ), PrimaryButton( onPressed: (){vm.updateDevice(device);}, - text: context.translate(I18n.legacySave), - color: Color(0xFF588EA5) + text: context.translate(I18n.save), + color: theme.getColorFor(ThemeCode.legacyPrimary) ) ], )) diff --git a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/linked_devices_screen.dart b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/linked_devices_screen.dart index c5eac3f4..7fc6c5b1 100644 --- a/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/linked_devices_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/linked_devices/presentation/linked_devices_screen.dart @@ -21,8 +21,9 @@ class LinkedDevicesScreen extends ConsumerWidget { final theme = ref.watch(themePortProvider); - return PageLayout( - title: context.translate(I18n.legacyLinkedDevices), + return LegacyPageLayout( +theme: theme, + title: context.translate(I18n.linkedDevices), showEdit: true, onEditChange: vm.toggleIsEditing, body: Container( @@ -60,7 +61,7 @@ class LinkedDeviceCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); return Container( padding: SizeUtils.getByScreen( @@ -81,7 +82,7 @@ class LinkedDeviceCard extends ConsumerWidget { padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), child: Icon(SFIcons.watch, size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), weight: 30, ), ), @@ -121,7 +122,7 @@ class LinkedDeviceCard extends ConsumerWidget { height: SizeUtils.getByScreen(small: 195, big: 185), child: Column( children: [ - Text(context.translate(I18n.legacyDeleteDeviceDialog), + Text(context.translate(I18n.deleteDeviceDialog), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), ), @@ -131,8 +132,8 @@ class LinkedDeviceCard extends ConsumerWidget { children: [ Expanded(child: PrimaryButton( onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )), @@ -142,8 +143,8 @@ class LinkedDeviceCard extends ConsumerWidget { await onDelete(); Navigator.pop(context); }, - text: context.translate(I18n.legacyDelete), - color: Color(0xFF588EA5), + text: context.translate(I18n.delete), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )) @@ -162,7 +163,7 @@ class LinkedDeviceCard extends ConsumerWidget { SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14)), DecoratedBox( decoration: BoxDecoration( - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), borderRadius: BorderRadius.all(Radius.circular(12)), ), child: diff --git a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart index 92ac5845..e3a29e85 100644 --- a/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart +++ b/modules/legacy/modules/account/lib/src/features/personal_data/presentation/personal_data_screen.dart @@ -20,8 +20,9 @@ class PersonalDataScreen extends ConsumerWidget { final theme = ref.watch(themePortProvider); - return PageLayout( - title: context.translate(I18n.legacyPersonalData), + return LegacyPageLayout( +theme: theme, + title: context.translate(I18n.personalData), body: Container( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 48, vertical: 10), @@ -86,8 +87,8 @@ class PersonalDataScreen extends ConsumerWidget { ), footer: PrimaryButton( onPressed: vm.updateUser, - text: context.translate(I18n.legacySubmit), - color: Color(0xFF588EA5) + text: context.translate(I18n.submit), + color: theme.getColorFor(ThemeCode.legacyPrimary) ), ); } diff --git a/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.dart b/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.dart deleted file mode 100644 index 55204429..00000000 --- a/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:freezed_annotation/freezed_annotation.dart'; - -part 'send_email_request_entity.freezed.dart'; - -@freezed -abstract class SendEmailRequestEntity with _$SendEmailRequestEntity{ - const factory SendEmailRequestEntity({ - required String country, - required String channel, - required String name, - required String email, - required String subject, - required String body, - }) = _SendEmailRequestEntity; -} \ No newline at end of file diff --git a/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.freezed.dart b/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.freezed.dart deleted file mode 100644 index a92da8c7..00000000 --- a/modules/legacy/modules/customer_service/lib/src/domain/entities/send_email_request_entity.freezed.dart +++ /dev/null @@ -1,286 +0,0 @@ -// 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 'send_email_request_entity.dart'; - -// ************************************************************************** -// FreezedGenerator -// ************************************************************************** - -// dart format off -T _$identity(T value) => value; -/// @nodoc -mixin _$SendEmailRequestEntity { - - String get country; String get channel; String get name; String get email; String get subject; String get body; -/// Create a copy of SendEmailRequestEntity -/// with the given fields replaced by the non-null parameter values. -@JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -$SendEmailRequestEntityCopyWith get copyWith => _$SendEmailRequestEntityCopyWithImpl(this as SendEmailRequestEntity, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is SendEmailRequestEntity&&(identical(other.country, country) || other.country == country)&&(identical(other.channel, channel) || other.channel == channel)&&(identical(other.name, name) || other.name == name)&&(identical(other.email, email) || other.email == email)&&(identical(other.subject, subject) || other.subject == subject)&&(identical(other.body, body) || other.body == body)); -} - - -@override -int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,body); - -@override -String toString() { - return 'SendEmailRequestEntity(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, body: $body)'; -} - - -} - -/// @nodoc -abstract mixin class $SendEmailRequestEntityCopyWith<$Res> { - factory $SendEmailRequestEntityCopyWith(SendEmailRequestEntity value, $Res Function(SendEmailRequestEntity) _then) = _$SendEmailRequestEntityCopyWithImpl; -@useResult -$Res call({ - String country, String channel, String name, String email, String subject, String body -}); - - - - -} -/// @nodoc -class _$SendEmailRequestEntityCopyWithImpl<$Res> - implements $SendEmailRequestEntityCopyWith<$Res> { - _$SendEmailRequestEntityCopyWithImpl(this._self, this._then); - - final SendEmailRequestEntity _self; - final $Res Function(SendEmailRequestEntity) _then; - -/// Create a copy of SendEmailRequestEntity -/// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? country = null,Object? channel = null,Object? name = null,Object? email = null,Object? subject = null,Object? body = null,}) { - return _then(_self.copyWith( -country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable -as String,channel: null == channel ? _self.channel : channel // ignore: cast_nullable_to_non_nullable -as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,subject: null == subject ? _self.subject : subject // ignore: cast_nullable_to_non_nullable -as String,body: null == body ? _self.body : body // ignore: cast_nullable_to_non_nullable -as String, - )); -} - -} - - -/// Adds pattern-matching-related methods to [SendEmailRequestEntity]. -extension SendEmailRequestEntityPatterns on SendEmailRequestEntity { -/// 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( _SendEmailRequestEntity value)? $default,{required TResult orElse(),}){ -final _that = this; -switch (_that) { -case _SendEmailRequestEntity() 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( _SendEmailRequestEntity value) $default,){ -final _that = this; -switch (_that) { -case _SendEmailRequestEntity(): -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( _SendEmailRequestEntity value)? $default,){ -final _that = this; -switch (_that) { -case _SendEmailRequestEntity() 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( String country, String channel, String name, String email, String subject, String body)? $default,{required TResult orElse(),}) {final _that = this; -switch (_that) { -case _SendEmailRequestEntity() when $default != null: -return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body);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( String country, String channel, String name, String email, String subject, String body) $default,) {final _that = this; -switch (_that) { -case _SendEmailRequestEntity(): -return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body);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( String country, String channel, String name, String email, String subject, String body)? $default,) {final _that = this; -switch (_that) { -case _SendEmailRequestEntity() when $default != null: -return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body);case _: - return null; - -} -} - -} - -/// @nodoc - - -class _SendEmailRequestEntity implements SendEmailRequestEntity { - const _SendEmailRequestEntity({required this.country, required this.channel, required this.name, required this.email, required this.subject, required this.body}); - - -@override final String country; -@override final String channel; -@override final String name; -@override final String email; -@override final String subject; -@override final String body; - -/// Create a copy of SendEmailRequestEntity -/// with the given fields replaced by the non-null parameter values. -@override @JsonKey(includeFromJson: false, includeToJson: false) -@pragma('vm:prefer-inline') -_$SendEmailRequestEntityCopyWith<_SendEmailRequestEntity> get copyWith => __$SendEmailRequestEntityCopyWithImpl<_SendEmailRequestEntity>(this, _$identity); - - - -@override -bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _SendEmailRequestEntity&&(identical(other.country, country) || other.country == country)&&(identical(other.channel, channel) || other.channel == channel)&&(identical(other.name, name) || other.name == name)&&(identical(other.email, email) || other.email == email)&&(identical(other.subject, subject) || other.subject == subject)&&(identical(other.body, body) || other.body == body)); -} - - -@override -int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,body); - -@override -String toString() { - return 'SendEmailRequestEntity(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, body: $body)'; -} - - -} - -/// @nodoc -abstract mixin class _$SendEmailRequestEntityCopyWith<$Res> implements $SendEmailRequestEntityCopyWith<$Res> { - factory _$SendEmailRequestEntityCopyWith(_SendEmailRequestEntity value, $Res Function(_SendEmailRequestEntity) _then) = __$SendEmailRequestEntityCopyWithImpl; -@override @useResult -$Res call({ - String country, String channel, String name, String email, String subject, String body -}); - - - - -} -/// @nodoc -class __$SendEmailRequestEntityCopyWithImpl<$Res> - implements _$SendEmailRequestEntityCopyWith<$Res> { - __$SendEmailRequestEntityCopyWithImpl(this._self, this._then); - - final _SendEmailRequestEntity _self; - final $Res Function(_SendEmailRequestEntity) _then; - -/// Create a copy of SendEmailRequestEntity -/// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? country = null,Object? channel = null,Object? name = null,Object? email = null,Object? subject = null,Object? body = null,}) { - return _then(_SendEmailRequestEntity( -country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable -as String,channel: null == channel ? _self.channel : channel // ignore: cast_nullable_to_non_nullable -as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable -as String,email: null == email ? _self.email : email // ignore: cast_nullable_to_non_nullable -as String,subject: null == subject ? _self.subject : subject // ignore: cast_nullable_to_non_nullable -as String,body: null == body ? _self.body : body // ignore: cast_nullable_to_non_nullable -as String, - )); -} - - -} - -// dart format on diff --git a/modules/legacy/modules/customer_service/lib/src/domain/repositories/customer_service_repository.dart b/modules/legacy/modules/customer_service/lib/src/domain/repositories/customer_service_repository.dart deleted file mode 100644 index e69de29b..00000000 diff --git a/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case.dart b/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case.dart deleted file mode 100644 index e07870df..00000000 --- a/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:customer_service/src/domain/entities/send_email_request_entity.dart'; - -abstract class SendEmailUseCase { - Future sendEmail({required SendEmailRequestEntity request}); -} diff --git a/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case_impl.dart b/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case_impl.dart deleted file mode 100644 index 86002122..00000000 --- a/modules/legacy/modules/customer_service/lib/src/domain/send_email_use_case_impl.dart +++ /dev/null @@ -1,13 +0,0 @@ -import 'package:customer_service/src/domain/entities/send_email_request_entity.dart'; -import 'package:customer_service/src/domain/send_email_use_case.dart'; - -class SendEmailUseCaseImpl implements SendEmailUseCase { - //SignUpUseCaseImpl(this._repository); - - //final AuthRepository _repository; - - @override - Future sendEmail({required SendEmailRequestEntity request}) async { - //return _repository.signUp(request: request); - } -} diff --git a/modules/legacy/modules/customer_service/lib/src/presentation/contact_screen.dart b/modules/legacy/modules/customer_service/lib/src/presentation/contact_screen.dart index ce9f2eac..9ece614c 100644 --- a/modules/legacy/modules/customer_service/lib/src/presentation/contact_screen.dart +++ b/modules/legacy/modules/customer_service/lib/src/presentation/contact_screen.dart @@ -16,10 +16,45 @@ class ContactScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - final vm = ref.read(contactViewModelProvider.notifier); - final viewState = ref.watch(contactViewModelProvider); + final viewModel = ref.read(contactViewModelProvider.notifier); - final List country = [ + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.contactTitle), + body: Padding( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(small: 38, big: 36) + ), + child: SingleChildScrollView(child: Column( + children: [ + const _CountrySection(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), + const _ChannelSection(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), + const _NameSection(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), + const _EmailSection(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), + const _SubjectSection(), + SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), + _MessageSection(onSubmit: viewModel.sendEmail), + const _ErrorMessageSection(), + ], + )), + ), + footer: _SendSection(onSend: viewModel.sendEmail), + ); + } +} + +class _CountrySection extends ConsumerWidget { + + const _CountrySection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final List countries = [ 'España', 'Portugal', 'France', @@ -28,81 +63,163 @@ class ContactScreen extends ConsumerWidget { context.translate(I18n.other), ]; - final List channel = [ + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomDropdown( + items: countries.map(Text.new).toList(growable: false), + onChanged: (x){vm.setCountry(x);}, + hint: context.translate(I18n.selectCountry) + ); + } +} + +class _ChannelSection extends ConsumerWidget { + + const _ChannelSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final List channels = [ context.translate(I18n.channelOnline), context.translate(I18n.channelAmazon), context.translate(I18n.channelStore), context.translate(I18n.other), ]; - return PageLayout( - title: context.translate(I18n.contactTitle), - body: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 38), - big: EdgeInsets.symmetric(horizontal: 36) - ), - child: SingleChildScrollView(child: Column( - children: [ - CustomDropdown( - items: country.map(Text.new).toList(growable: false), - onChanged: (x){vm.setCountry(x);}, - hint: context.translate(I18n.selectCountry) - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), - CustomDropdown( - items: channel.map(Text.new).toList(growable: false), - onChanged: (x){vm.setChannel(x);}, - hint: context.translate(I18n.selectChannel) - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), - CustomTextField( - controller: vm.nameController, - hint: context.translate(I18n.enterName), - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), - CustomTextField( - controller: vm.emailController, - keyboardType: TextInputType.emailAddress, - hint: context.translate(I18n.enterEmail), - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), - CustomTextField( - controller: vm.subjectController, - hint: context.translate(I18n.enterSubject), - ), - SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)), - CustomTextField( - controller: vm.bodyController, - keyboardType: TextInputType.multiline, - hint: context.translate(I18n.enterMessage), - lines: 8, - ), - if (viewState.errorMessage.isNotEmpty) ...[ - const SizedBox(height: 4), - Text( - viewState.errorMessage, - textAlign: TextAlign.center, - style: const TextStyle( - color: Color.fromRGBO(239, 17, 17, 1), - fontSize: 12, - ), - ), - ], - ], - )), - ), - footer: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 38, vertical: 14), - big: EdgeInsets.symmetric(horizontal: 36, vertical: 12) - ), - child: PrimaryButton( - onPressed: vm.sendEmail, - text: context.translate(I18n.sendEmail), - color: theme.getColorFor(ThemeCode.buttonPrimary) - ) - ), + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomDropdown( + items: channels.map(Text.new).toList(growable: false), + onChanged: (x){vm.setChannel(x);}, + hint: context.translate(I18n.selectChannel) ); } +} + +class _NameSection extends ConsumerWidget { + + const _NameSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomTextField( + controller: vm.nameController, + hint: context.translate(I18n.enterName), + ); + } +} + +class _EmailSection extends ConsumerWidget { + + const _EmailSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomTextField( + controller: vm.emailController, + keyboardType: TextInputType.emailAddress, + hint: context.translate(I18n.enterEmail), + ); + } +} + +class _SubjectSection extends ConsumerWidget { + + const _SubjectSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomTextField( + controller: vm.subjectController, + hint: context.translate(I18n.enterSubject), + ); + } +} + +class _MessageSection extends ConsumerWidget { + + final VoidCallback onSubmit; + + const _MessageSection({ + required this.onSubmit, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final vm = ref.read(contactViewModelProvider.notifier); + + return CustomTextField( + controller: vm.bodyController, + keyboardType: TextInputType.multiline, + hint: context.translate(I18n.enterMessage), + lines: 8, + onSubmitted: (_) => onSubmit(), + ); + } +} + +class _ErrorMessageSection extends ConsumerWidget { + + const _ErrorMessageSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final viewState = ref.watch(contactViewModelProvider); + + if (viewState.errorMessage.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 4), + Text( + viewState.errorMessage, + textAlign: TextAlign.center, + style: const TextStyle( + color: Color.fromRGBO(239, 17, 17, 1), + fontSize: 12, + ), + ), + ], + ); + } else return SizedBox.shrink(); + } +} + +class _SendSection extends ConsumerWidget { + + final VoidCallback onSend; + + const _SendSection({ + required this.onSend, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.read(themePortProvider); + + return Container( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 38, vertical: 14), + big: EdgeInsets.symmetric(horizontal: 36, vertical: 12) + ), + child: PrimaryButton( + onPressed: onSend, + text: context.translate(I18n.sendEmail), + color: theme.getColorFor(ThemeCode.buttonPrimary) + ) + ); + } + } \ No newline at end of file diff --git a/modules/legacy/modules/customer_service/lib/src/presentation/customer_service_screen.dart b/modules/legacy/modules/customer_service/lib/src/presentation/customer_service_screen.dart index b984c077..53b0e3b0 100644 --- a/modules/legacy/modules/customer_service/lib/src/presentation/customer_service_screen.dart +++ b/modules/legacy/modules/customer_service/lib/src/presentation/customer_service_screen.dart @@ -15,14 +15,15 @@ class CustomerServiceScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - // final theme = ref.watch(themePortProvider); + final theme = ref.watch(themePortProvider); - return PageLayout( + return LegacyPageLayout( + theme: theme, title: context.translate(I18n.customerService), body: Container( padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 18), - big: EdgeInsets.symmetric(horizontal: 16) + small: EdgeInsets.symmetric(horizontal: 18), + big: EdgeInsets.symmetric(horizontal: 16) ), child: Column( children: [ @@ -33,8 +34,17 @@ class CustomerServiceScreen extends ConsumerWidget { throw Exception('Could not launch $url'); } }, - image: 'assets/images/ui/iso_sf.png', - text: context.translate(I18n.supportWebsite) + icon: Image.asset('assets/images/ui/iso_sf.png', + width: SizeUtils.getByScreen(small: 44, big: 48), + height: SizeUtils.getByScreen(small: 44, big: 48), + ), + body: Text(context.translate(I18n.supportWebsite), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + decoration: TextDecoration.underline + ) + ) ), SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)), SectionButton( @@ -44,88 +54,43 @@ class CustomerServiceScreen extends ConsumerWidget { throw Exception('Could not launch $url'); } }, - icon: SFIcons.handshake, - text: context.translate(I18n.supportHelp) + icon: Icon(SFIcons.handshake, + size: SizeUtils.getByScreen(small: 44, big: 48), + color: theme.getColorFor(ThemeCode.legacyPrimary), + weight: 30, + ), + body: Text(context.translate(I18n.supportHelp), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + decoration:TextDecoration.underline + ) + ) ), SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)), SectionButton( - onPressed: (){Navigator.push(context, - MaterialPageRoute( - builder: (_) => ContactScreen(navigationContract: navigationContract), - ));}, - icon: Icons.email_outlined, - text: context.translate(I18n.contactTitle) + onPressed: (){ + Navigator.push(context, + MaterialPageRoute( + builder: (_) => ContactScreen(navigationContract: navigationContract), + ) + ); + }, + icon: Icon(Icons.email_outlined, + size: SizeUtils.getByScreen(small: 44, big: 48), + color: theme.getColorFor(ThemeCode.legacyPrimary), + weight: 30, + ), + body: Text(context.translate(I18n.contactTitle), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + ) + ) ), ], ) ) ); } -} - - -class SectionButton extends ConsumerWidget { - - final GestureTapCallback onPressed; - final IconData? icon; - final String? image; - final String text; - - const SectionButton({ - required this.onPressed, - this.icon, - this.image, - required this.text, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 16), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 12) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all( - Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( - children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all( - SizeUtils.getByScreen(small: 12, big: 16)), - child: icon != null - ?Icon(icon, - size: SizeUtils.getByScreen(small: 44, big: 48), - color: Color(0xFF588EA5), - weight: 30, - ) - : Image.asset(image!, - width: SizeUtils.getByScreen(small: 44, big: 48), - height: SizeUtils.getByScreen(small: 44, big: 48), - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ), - ], - ), - ) - ); - } } \ No newline at end of file diff --git a/modules/legacy/modules/customer_service/lib/src/presentation/providers/send_email_use_case_provider.dart b/modules/legacy/modules/customer_service/lib/src/presentation/providers/send_email_use_case_provider.dart deleted file mode 100644 index b4fe853a..00000000 --- a/modules/legacy/modules/customer_service/lib/src/presentation/providers/send_email_use_case_provider.dart +++ /dev/null @@ -1,9 +0,0 @@ -import 'package:customer_service/src/domain/send_email_use_case.dart'; -import 'package:customer_service/src/domain/send_email_use_case_impl.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -final sendEmailUseCaseProvider = -Provider.autoDispose((ref) { - //final authRepository = ref.read(customerServiceRepositoryProvider); - return SendEmailUseCaseImpl(); -}); diff --git a/modules/legacy/modules/customer_service/lib/src/presentation/state/contact_view_model.dart b/modules/legacy/modules/customer_service/lib/src/presentation/state/contact_view_model.dart index 199b06a0..3a66b0eb 100644 --- a/modules/legacy/modules/customer_service/lib/src/presentation/state/contact_view_model.dart +++ b/modules/legacy/modules/customer_service/lib/src/presentation/state/contact_view_model.dart @@ -1,5 +1,3 @@ -// import 'package:customer_service/src/domain/send_email_use_case.dart'; -// import 'package:customer_service/src/presentation/providers/send_email_use_case_provider.dart'; import 'package:customer_service/src/presentation/state/contact_view_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -12,7 +10,6 @@ NotifierProvider.autoDispose( ); class ContactViewModel extends Notifier { - //late final SendEmailUseCase _sendEmailUseCase; late final TextEditingController nameController; late final TextEditingController emailController; @@ -26,7 +23,6 @@ class ContactViewModel extends Notifier { @override ContactViewState build() { - //_sendEmailUseCase = ref.read(sendEmailUseCaseProvider); nameController = TextEditingController(); emailController = TextEditingController(); diff --git a/modules/legacy/modules/customer_service/lib/src/providers/customer_service_repository_provider.dart b/modules/legacy/modules/customer_service/lib/src/providers/customer_service_repository_provider.dart deleted file mode 100644 index a8d0bd56..00000000 --- a/modules/legacy/modules/customer_service/lib/src/providers/customer_service_repository_provider.dart +++ /dev/null @@ -1,8 +0,0 @@ -/* -import 'package:flutter_riverpod/flutter_riverpod.dart'; - -final customerServiceRepositoryProvider = Provider((ref) { - final remote = ref.read(customerServiceRemoteDatasourceProvider); - return CustomerServiceRepositoryImpl(remote); -}); -*/ diff --git a/modules/legacy/modules/functions/lib/src/core/data/datasources/functions_remote_datasource_impl.dart b/modules/legacy/modules/functions/lib/src/core/data/datasources/functions_remote_datasource_impl.dart index ee555d94..b779a188 100644 --- a/modules/legacy/modules/functions/lib/src/core/data/datasources/functions_remote_datasource_impl.dart +++ b/modules/legacy/modules/functions/lib/src/core/data/datasources/functions_remote_datasource_impl.dart @@ -67,10 +67,10 @@ class FunctionsRemoteDatasourceImpl implements FunctionsRemoteDatasource { throw Exception('Empty response from /users/:userId/contacts'); } - final model = GetContactsResponseModel.fromJson(data); + final model = GetPicturesResponseModel.fromJson(data); return model.toEntity(); } on DioException catch (error) { - throw _mapDioError(error, defaultMessage: 'Error to get contacts'); + throw _mapDioError(error, defaultMessage: 'Error to get pictures'); }*/ return []; } @@ -92,7 +92,13 @@ class FunctionsRemoteDatasourceImpl implements FunctionsRemoteDatasource { } on DioException catch (error) { throw _mapDioError(error, defaultMessage: 'Error to get contacts'); }*/ - return PictureEntity(id: '1', userId: '1111', createdAt: 1111); + return PictureEntity( + id: '1', + deviceId: '1111', + createdAt: DateTime.now(), + takenAt: DateTime.now(), + asset: 'assets/images/ui/iso_sf.png' + ); } @override diff --git a/modules/legacy/modules/functions/lib/src/features/contacts/presentation/contacts_screen.dart b/modules/legacy/modules/functions/lib/src/features/contacts/presentation/contacts_screen.dart index 4b5f2f24..319c5f97 100644 --- a/modules/legacy/modules/functions/lib/src/features/contacts/presentation/contacts_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/contacts/presentation/contacts_screen.dart @@ -40,7 +40,7 @@ class ContactsScreen extends ConsumerWidget { if (!state.isEditing) ...[ DecoratedBox( decoration: BoxDecoration( - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), shape: BoxShape.circle ), child: IconButton(onPressed: vm.toggleIsEditing, @@ -91,7 +91,7 @@ class ContactsScreen extends ConsumerWidget { Container( decoration: BoxDecoration( shape: BoxShape.circle, - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), ), width: SizeUtils.getByScreen(small: 48, big: 46), child: CustomTextButton( @@ -120,7 +120,7 @@ class ContactCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); + final theme = ref.watch(themePortProvider); return Container( padding: SizeUtils.getByScreen( @@ -141,7 +141,7 @@ class ContactCard extends ConsumerWidget { padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), child: Icon(SFIcons.account, size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), weight: 30, ), ), @@ -181,7 +181,7 @@ class ContactCard extends ConsumerWidget { height: SizeUtils.getByScreen(small: 195, big: 185), child: Column( children: [ - Text(context.translate(I18n.legacyDeleteUserDialog), + Text(context.translate(I18n.deleteUserDialog), textAlign: TextAlign.center, style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), ), @@ -191,8 +191,8 @@ class ContactCard extends ConsumerWidget { children: [ Expanded(child: PrimaryButton( onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )), @@ -201,8 +201,8 @@ class ContactCard extends ConsumerWidget { onPressed: (){ Navigator.pop(context); }, - text: context.translate(I18n.legacyDelete), - color: Color(0xFF588EA5), + text: context.translate(I18n.delete), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), )) @@ -221,7 +221,7 @@ class ContactCard extends ConsumerWidget { SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14)), DecoratedBox( decoration: BoxDecoration( - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), borderRadius: BorderRadius.all(Radius.circular(12)), ), child: diff --git a/modules/legacy/modules/functions/lib/src/features/contacts/presentation/edit_contact_screen.dart b/modules/legacy/modules/functions/lib/src/features/contacts/presentation/edit_contact_screen.dart index eba3b459..ab4eab27 100644 --- a/modules/legacy/modules/functions/lib/src/features/contacts/presentation/edit_contact_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/contacts/presentation/edit_contact_screen.dart @@ -89,7 +89,7 @@ class EditContactScreen extends ConsumerWidget { CustomTextField( controller: vm.nameController, hint: contact.name, - label: context.translate(I18n.legacyName), + label: context.translate(I18n.name), ), SizedBox(height: SizeUtils.getByScreen(small: 28, big: 26)), Stack( @@ -109,7 +109,7 @@ class EditContactScreen extends ConsumerWidget { icon: DecoratedBox( decoration: BoxDecoration( shape: BoxShape.circle, - color: Color(0xFF588EA5) + color: theme.getColorFor(ThemeCode.legacyPrimary) ), child: Icon( SFIcons.contactsCircle, @@ -126,8 +126,8 @@ class EditContactScreen extends ConsumerWidget { ), PrimaryButton( onPressed: (){vm.updateContact(contact);}, - text: context.translate(I18n.legacySave), - color: Color(0xFF588EA5) + text: context.translate(I18n.save), + color: theme.getColorFor(ThemeCode.legacyPrimary) ) ], )) diff --git a/modules/legacy/modules/functions/lib/src/features/functions/functions_screen.dart b/modules/legacy/modules/functions/lib/src/features/functions/functions_screen.dart index 6a58eece..700865de 100644 --- a/modules/legacy/modules/functions/lib/src/features/functions/functions_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/functions/functions_screen.dart @@ -2,6 +2,7 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:functions/src/features/functions/widgets/call_watch_dialog.dart'; +import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; @@ -15,180 +16,120 @@ class FunctionsScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - return Scaffold( - backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), - body: SafeArea( - child: Column( - children: [ - Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - child: Stack( - children: [ - IconButton(onPressed: () {Navigator.pop(context);}, - icon: Icon(Icons.arrow_back)), - Center( - child: Text(context.translate('Device Features'), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 28, big: 27) - ), - ) - ) - ], - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 30, big: 28)), - Expanded(child: SingleChildScrollView(child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - child: Column( - children: [ - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.remoteConnection);}, - icon: SFIcons.connection, - text: 'Remote connection' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.calendarCircle, - text: 'Calendar' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.contacts);}, - icon: SFIcons.contactsCircle, - text: 'Contacts' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.doNotDisturbCircle, - text: 'Do not disturb' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.videoCallCircle, - text: 'Video call' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.healthCircle, - text: 'Health' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.healthCircle, - text: 'Activity meter' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.rewardsCircle, - text: 'Rewards' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: CallWatchDialog() - ));}, - icon: Icons.call_outlined, - text: 'Call watch' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.screenTime, - text: 'Apps use' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: Icons.app_registration_sharp, - text: 'Apps surveillance' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){}, - icon: SFIcons.friendsCircle, - text: 'Make friends' - ), - SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.locateDevice);}, - icon: SFIcons.locateSfCircle, - text: 'Locate your SaveFamily' - ), - ], - ), - ))), - ], - ) - ), - ); - } -} - -class AppSectionButton extends ConsumerWidget { - - final GestureTapCallback onPressed; - final IconData icon; - final String text; - - const AppSectionButton({ - required this.onPressed, - required this.icon, - required this.text, - }); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final theme = ref.read(themePortProvider); - - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 14), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 12) + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.functions), + body: SingleChildScrollView(child: Container( + padding: EdgeInsets.symmetric( + horizontal: SizeUtils.getByScreen(big: 22, small: 21), ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( + child: Column( children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 0, big: 0)), - child: Icon(icon, - size: SizeUtils.getByScreen(small: 52, big: 48), - color: Color(0xFF588EA5), - weight: 30, - ), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){navigationContract.pushTo(AppRoutes.remoteConnection);}, + icon: SFIcons.connection, + text: context.translate(I18n.remoteConnection) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.calendarCircle, + negativeIcon: true, + text: context.translate(I18n.calendar) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){navigationContract.pushTo(AppRoutes.contacts);}, + icon: SFIcons.contactsCircle, + negativeIcon: true, + text: context.translate(I18n.contacts) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.doNotDisturbCircle, + negativeIcon: true, + text: context.translate(I18n.doNotDisturb) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.videoCallCircle, + negativeIcon: true, + text: context.translate(I18n.videoCall) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.healthCircle, + negativeIcon: true, + text: context.translate(I18n.health) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.healthCircle, + negativeIcon: true, + text: context.translate(I18n.activityMeter) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.rewardsCircle, + negativeIcon: true, + text: context.translate(I18n.rewards) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){showDialog(context: context, builder: (context)=>Dialog( + child: CallWatchDialog() + ));}, + icon: Icons.call_outlined, + iconSize: SizeUtils.getByScreen(small: 42, big: 40), + text: context.translate(I18n.callWatch) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.screenTime, + text: context.translate(I18n.appsUse) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: Icons.app_registration_sharp, + text: context.translate(I18n.appsSurveillance) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){}, + icon: SFIcons.friendsCircle, + negativeIcon: true, + text: context.translate(I18n.makeFriends) + ), + SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), + AppMenuButton( + color: theme.getColorFor(ThemeCode.legacyPrimary), + onPressed: (){navigationContract.pushTo(AppRoutes.locateDevice);}, + icon: SFIcons.locateSfCircle, + negativeIcon: true, + text: context.translate(I18n.locateSF) ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ) ], ), - ) + )) ); } } \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/functions/widgets/call_watch_dialog.dart b/modules/legacy/modules/functions/lib/src/features/functions/widgets/call_watch_dialog.dart index 5276a08d..2770ad94 100644 --- a/modules/legacy/modules/functions/lib/src/features/functions/widgets/call_watch_dialog.dart +++ b/modules/legacy/modules/functions/lib/src/features/functions/widgets/call_watch_dialog.dart @@ -9,6 +9,7 @@ class CallWatchDialog extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.watch(themePortProvider); final viewModel = ref.read(callWatchViewModelProvider.notifier); final viewState = ref.watch(callWatchViewModelProvider); @@ -32,7 +33,7 @@ class CallWatchDialog extends ConsumerWidget { alignment: Alignment.centerRight, child: IconButton( onPressed: (){Navigator.pop(context);}, - icon: Icon(Icons.close, color: Color(0xFF588EA5)), + icon: Icon(Icons.close, color: theme.getColorFor(ThemeCode.legacyPrimary)), ) ) ], @@ -59,7 +60,7 @@ class CallWatchDialog extends ConsumerWidget { PrimaryButton( onPressed: viewModel.call, text: context.translate('Call me'), - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 38, big: 36), radius: SizeUtils.getByScreen(small: 32, big: 34), ), diff --git a/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/locate_device_screen.dart b/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/locate_device_screen.dart index 7d367592..4d044b23 100644 --- a/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/locate_device_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/locate_device_screen.dart @@ -1,7 +1,7 @@ import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:functions/src/features/locate_device/presentation/state/locate_device_view_model.dart'; +import 'package:functions/src/features/locate_device/presentation/widgets/locate_device_dialog.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; @@ -15,8 +15,11 @@ class LocateDeviceScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - return PageLayout( - title: context.translate('Find your device'), + final theme = ref.watch(themePortProvider); + + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.locateSF), body: Container( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 16), @@ -25,14 +28,14 @@ class LocateDeviceScreen extends ConsumerWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text(context.translate('Locate your SaveFamily in nearby locations'), + Text(context.translate(I18n.locateSFBody1), style: TextStyle( fontSize: SizeUtils.getByScreen(small: 18, big: 17), fontWeight: FontWeight.w500, ) ), SizedBox(height: SizeUtils.getByScreen(small: 10, big: 8)), - Text('This function allows you to find the device indoors or in places close to you. When you press the button, the smartwatch will start beeping and you will be able to hear it.', + Text(context.translate(I18n.locateSFBody2), style: TextStyle( fontSize: 16 )) @@ -50,99 +53,11 @@ class LocateDeviceScreen extends ConsumerWidget { child: LocateDialog(), )); }, - text: context.translate('Locate my SaveFamily'), - color: Color(0xFF588EA5), + text: context.translate(I18n.locateSFAction), + color: theme.getColorFor(ThemeCode.legacyPrimary), height: SizeUtils.getByScreen(small: 36, big: 35), ), ) ); } -} - -class LocateDialog extends ConsumerWidget { - - @override - Widget build(BuildContext context, WidgetRef ref) { - - final viewModel = ref.read(locateDeviceViewModelProvider.notifier); - final viewState = ref.watch(locateDeviceViewModelProvider); - - return Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), - big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) - ), - width: SizeUtils.getByScreen(small: 360, big: 350), - height: SizeUtils.getByScreen(small: 210, big: 205), - child: Column( - children: [ - if (viewState.isLoading) - Expanded(child: Center(child: Text(context.translate('Sending...'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 25, big: 24), - ), - ))), - if (viewState.isComplete) - Expanded(child: Center(child: Text(context.translate('Sent successfully'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 25, big: 24), - ), - ))), - if (viewState.errorMessage.isNotEmpty) ...[ - Expanded(child: Center(child: Text(context.translate('The device is not connected to the Internet'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - ), - ))), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), - Expanded(child: PrimaryButton( - onPressed: (){ - Navigator.pop(context); - viewModel.endLocation(); - }, - text: context.translate('OK'), - color: Color(0xFF588EA5), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )), - ], - if (!viewState.isComplete && !viewState.isLoading && viewState.errorMessage.isEmpty) ...[ - Text(context.translate('You are going to activate the remote location of your device. It will start ringing.'), - textAlign: TextAlign.center, - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 19, big: 18), - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded(child: PrimaryButton( - onPressed: (){Navigator.pop(context);}, - text: context.translate(I18n.legacyCancel), - color: Color(0xFF588EA5), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )), - SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)), - Expanded(child: PrimaryButton( - onPressed: () { - viewModel.locateDevice(); - }, - text: context.translate(I18n.accept), - color: Color(0xFF588EA5), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - )) - ], - ) - ] - ], - ), - ); - } - } \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart b/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart new file mode 100644 index 00000000..eefa1d35 --- /dev/null +++ b/modules/legacy/modules/functions/lib/src/features/locate_device/presentation/widgets/locate_device_dialog.dart @@ -0,0 +1,95 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:functions/src/features/locate_device/presentation/state/locate_device_view_model.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +class LocateDialog extends ConsumerWidget { + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.watch(themePortProvider); + + final viewModel = ref.read(locateDeviceViewModelProvider.notifier); + final viewState = ref.watch(locateDeviceViewModelProvider); + + return Container( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), + big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) + ), + width: SizeUtils.getByScreen(small: 360, big: 350), + height: SizeUtils.getByScreen(small: 210, big: 205), + child: Column( + children: [ + if (viewState.isLoading) + Expanded(child: Center(child: Text(context.translate('Sending...'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 25, big: 24), + ), + ))), + if (viewState.isComplete) + Expanded(child: Center(child: Text(context.translate('Sent successfully'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 25, big: 24), + ), + ))), + if (viewState.errorMessage.isNotEmpty) ...[ + Expanded(child: Center(child: Text(context.translate('The device is not connected to the Internet'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + ), + ))), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), + Expanded(child: PrimaryButton( + onPressed: (){ + Navigator.pop(context); + viewModel.endLocation(); + }, + text: context.translate('OK'), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + )), + ], + if (!viewState.isComplete && !viewState.isLoading && viewState.errorMessage.isEmpty) ...[ + Text(context.translate('You are going to activate the remote location of your device. It will start ringing.'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 19, big: 18), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 24, big: 23)), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: PrimaryButton( + onPressed: (){Navigator.pop(context);}, + text: context.translate(I18n.cancel), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + )), + SizedBox(width: SizeUtils.getByScreen(small: 4, big: 16)), + Expanded(child: PrimaryButton( + onPressed: () { + viewModel.locateDevice(); + }, + text: context.translate(I18n.accept), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + )) + ], + ) + ] + ], + ), + ); + } +} \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.dart index 22df5bc6..5d23a5f8 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.dart @@ -6,7 +6,9 @@ part 'picture_entity.freezed.dart'; abstract class PictureEntity with _$PictureEntity { const factory PictureEntity({ required String id, - required String? userId, - required int createdAt, + required String? deviceId, + required DateTime createdAt, + required DateTime takenAt, + required String asset, }) = _PictureEntity; } diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart index f08a6dcc..fcf3e652 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/entities/picture_entity.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$PictureEntity { - String get id; String? get userId; int get createdAt; + String get id; String? get deviceId; DateTime get createdAt; DateTime get takenAt; String get asset; /// Create a copy of PictureEntity /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $PictureEntityCopyWith get copyWith => _$PictureEntityCopyWithImp @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is PictureEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is PictureEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.takenAt, takenAt) || other.takenAt == takenAt)&&(identical(other.asset, asset) || other.asset == asset)); } @override -int get hashCode => Object.hash(runtimeType,id,userId,createdAt); +int get hashCode => Object.hash(runtimeType,id,deviceId,createdAt,takenAt,asset); @override String toString() { - return 'PictureEntity(id: $id, userId: $userId, createdAt: $createdAt)'; + return 'PictureEntity(id: $id, deviceId: $deviceId, createdAt: $createdAt, takenAt: $takenAt, asset: $asset)'; } @@ -45,7 +45,7 @@ abstract mixin class $PictureEntityCopyWith<$Res> { factory $PictureEntityCopyWith(PictureEntity value, $Res Function(PictureEntity) _then) = _$PictureEntityCopyWithImpl; @useResult $Res call({ - String id, String? userId, int createdAt + String id, String? deviceId, DateTime createdAt, DateTime takenAt, String asset }); @@ -62,12 +62,14 @@ class _$PictureEntityCopyWithImpl<$Res> /// Create a copy of PictureEntity /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? userId = freezed,Object? createdAt = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceId = freezed,Object? createdAt = null,Object? takenAt = null,Object? asset = null,}) { return _then(_self.copyWith( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,userId: freezed == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: freezed == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable -as int, +as DateTime,takenAt: null == takenAt ? _self.takenAt : takenAt // ignore: cast_nullable_to_non_nullable +as DateTime,asset: null == asset ? _self.asset : asset // ignore: cast_nullable_to_non_nullable +as String, )); } @@ -152,10 +154,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? userId, int createdAt)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String id, String? deviceId, DateTime createdAt, DateTime takenAt, String asset)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _PictureEntity() when $default != null: -return $default(_that.id,_that.userId,_that.createdAt);case _: +return $default(_that.id,_that.deviceId,_that.createdAt,_that.takenAt,_that.asset);case _: return orElse(); } @@ -173,10 +175,10 @@ return $default(_that.id,_that.userId,_that.createdAt);case _: /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String id, String? userId, int createdAt) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String id, String? deviceId, DateTime createdAt, DateTime takenAt, String asset) $default,) {final _that = this; switch (_that) { case _PictureEntity(): -return $default(_that.id,_that.userId,_that.createdAt);case _: +return $default(_that.id,_that.deviceId,_that.createdAt,_that.takenAt,_that.asset);case _: throw StateError('Unexpected subclass'); } @@ -193,10 +195,10 @@ return $default(_that.id,_that.userId,_that.createdAt);case _: /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? userId, int createdAt)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String id, String? deviceId, DateTime createdAt, DateTime takenAt, String asset)? $default,) {final _that = this; switch (_that) { case _PictureEntity() when $default != null: -return $default(_that.id,_that.userId,_that.createdAt);case _: +return $default(_that.id,_that.deviceId,_that.createdAt,_that.takenAt,_that.asset);case _: return null; } @@ -208,12 +210,14 @@ return $default(_that.id,_that.userId,_that.createdAt);case _: class _PictureEntity implements PictureEntity { - const _PictureEntity({required this.id, required this.userId, required this.createdAt}); + const _PictureEntity({required this.id, required this.deviceId, required this.createdAt, required this.takenAt, required this.asset}); @override final String id; -@override final String? userId; -@override final int createdAt; +@override final String? deviceId; +@override final DateTime createdAt; +@override final DateTime takenAt; +@override final String asset; /// Create a copy of PictureEntity /// with the given fields replaced by the non-null parameter values. @@ -225,16 +229,16 @@ _$PictureEntityCopyWith<_PictureEntity> get copyWith => __$PictureEntityCopyWith @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _PictureEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.userId, userId) || other.userId == userId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _PictureEntity&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.takenAt, takenAt) || other.takenAt == takenAt)&&(identical(other.asset, asset) || other.asset == asset)); } @override -int get hashCode => Object.hash(runtimeType,id,userId,createdAt); +int get hashCode => Object.hash(runtimeType,id,deviceId,createdAt,takenAt,asset); @override String toString() { - return 'PictureEntity(id: $id, userId: $userId, createdAt: $createdAt)'; + return 'PictureEntity(id: $id, deviceId: $deviceId, createdAt: $createdAt, takenAt: $takenAt, asset: $asset)'; } @@ -245,7 +249,7 @@ abstract mixin class _$PictureEntityCopyWith<$Res> implements $PictureEntityCopy factory _$PictureEntityCopyWith(_PictureEntity value, $Res Function(_PictureEntity) _then) = __$PictureEntityCopyWithImpl; @override @useResult $Res call({ - String id, String? userId, int createdAt + String id, String? deviceId, DateTime createdAt, DateTime takenAt, String asset }); @@ -262,12 +266,14 @@ class __$PictureEntityCopyWithImpl<$Res> /// Create a copy of PictureEntity /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? userId = freezed,Object? createdAt = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceId = freezed,Object? createdAt = null,Object? takenAt = null,Object? asset = null,}) { return _then(_PictureEntity( id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable -as String,userId: freezed == userId ? _self.userId : userId // ignore: cast_nullable_to_non_nullable +as String,deviceId: freezed == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable -as int, +as DateTime,takenAt: null == takenAt ? _self.takenAt : takenAt // ignore: cast_nullable_to_non_nullable +as DateTime,asset: null == asset ? _self.asset : asset // ignore: cast_nullable_to_non_nullable +as String, )); } diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/get_pictures_use_case_impl.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/get_pictures_use_case_impl.dart index b38a448a..91a21c1b 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/get_pictures_use_case_impl.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/domain/get_pictures_use_case_impl.dart @@ -8,7 +8,13 @@ class GetPicturesUseCaseImpl implements GetPicturesUseCase { final FunctionsRepository _repository; @override - Future> getPictures({required String userId}) { - return _repository.getPictures(userId: userId); + Future> getPictures({required String userId}) async { + // return _repository.getPictures(userId: userId); + return [ + PictureEntity(id: '1', deviceId: '1111', createdAt: DateTime.now(), asset: 'assets/images/ui/iso_sf.png', takenAt: DateTime.now()), + PictureEntity(id: '2', deviceId: '1111', createdAt: DateTime.now(), asset: 'assets/images/ui/iso_sf.png', takenAt: DateTime.now()), + PictureEntity(id: '3', deviceId: '1111', createdAt: DateTime.now(), asset: 'assets/images/ui/iso_sf.png', takenAt: DateTime.now()), + PictureEntity(id: '4', deviceId: '1111', createdAt: DateTime.now(), asset: 'assets/images/ui/iso_sf.png', takenAt: DateTime.now()), + ]; } } \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_camera_screen.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_camera_screen.dart index 12afa923..8f4c77b8 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_camera_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_camera_screen.dart @@ -1,9 +1,8 @@ -// import 'package:account/src/features/linked_devices/presentation/app_users_screen.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_svg/flutter_svg.dart'; import 'package:functions/src/features/remote_connection/presentation/state/remote_connection_view_model.dart'; +import 'package:functions/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; import 'package:utils/utils.dart'; @@ -18,59 +17,115 @@ class RemoteCameraScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - final viewModel = ref.read(remoteConnectionViewModelProvider.notifier); - final viewState = ref.watch(remoteConnectionViewModelProvider); + final isLoadingPictures = ref.watch( + remoteConnectionViewModelProvider.select((s)=>s.isLoadingPictures) + ); - return PageLayout( - title: context.translate('Remote camera'), - body: Expanded(child: GridView.count( - primary: false, - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 24, vertical: 12), - big: EdgeInsets.symmetric(horizontal: 23, vertical: 11) - ), - crossAxisSpacing: 11, - mainAxisSpacing: 11, - crossAxisCount: 3, - childAspectRatio: 0.8, - children: List.generate(12, (int index)=> - Container( - height: SizeUtils.getByScreen(small: 110, big: 105), - width: SizeUtils.getByScreen(small: 60, big: 58), - color: Colors.grey[200], - child: SvgPicture.asset('assets/images/ui/face.svg'), - ) - ), - )), - footer: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(vertical: 12, horizontal: 26), - big: EdgeInsets.symmetric(vertical: 10, horizontal: 25) - ), - child: PrimaryButton( - onPressed: () async { - showDialog(context: context, builder: (context)=>Dialog( - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), - big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) - ), - width: SizeUtils.getByScreen(small: 360, big: 350), - height: SizeUtils.getByScreen(small: 195, big: 185), - child: Center(child: Text(context.translate('Loading photo...'), - textAlign: TextAlign.center, - style: TextStyle(fontSize: SizeUtils.getByScreen(small: 26, big: 25)), - )), - ), - )); - await viewModel.takePicture(); - Navigator.pop(context); - }, - text: context.translate('Take a picture'), - color: Color(0xFF588EA5), - height: SizeUtils.getByScreen(small: 36, big: 35), - ), - ) + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.remoteCamera), + body: Expanded(child: isLoadingPictures + ? const Center(child: CircularProgressIndicator()) + : const _GallerySection() + ), + footer: _TakePictureSection(), ); } +} + +class _GallerySection extends ConsumerWidget { + + const _GallerySection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.read(themePortProvider); + + final vm = ref.read(remoteConnectionViewModelProvider.notifier); + + final pictures = ref.watch( + remoteConnectionViewModelProvider.select((s)=>s.pictures) + ); + + return GridView.count( + primary: false, + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 24, vertical: 12), + big: EdgeInsets.symmetric(horizontal: 23, vertical: 11) + ), + crossAxisSpacing: 11, + mainAxisSpacing: 11, + crossAxisCount: 3, + childAspectRatio: 0.8, + children: List.generate(pictures.length, (int index)=> + TextButton( + onPressed: (){ + vm.setPictureIndex(index); + showDialog(context: context, builder: (context)=>Dialog( + child: ShowPictureDialog(), + )); + }, + child: Container( + height: SizeUtils.getByScreen(small: 110, big: 105), + width: SizeUtils.getByScreen(small: 60, big: 58), + decoration: BoxDecoration( + border: Border.fromBorderSide(BorderSide( + color: theme.getColorFor(ThemeCode.textTertiary) + )) + ), + child: Column( + children: [ + Image.asset(pictures[index].asset), + ], + ) + ) + ) + ), + ); + } + +} + +class _TakePictureSection extends ConsumerWidget { + + const _TakePictureSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); + + final vm = ref.read(remoteConnectionViewModelProvider.notifier); + + return Padding( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(vertical: 12, horizontal: 26), + big: EdgeInsets.symmetric(vertical: 10, horizontal: 25) + ), + child: PrimaryButton( + onPressed: () async { + showDialog(context: context, builder: (context)=>Dialog( + child: Container( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 32, vertical: 30), + big: EdgeInsets.symmetric(horizontal: 30, vertical: 28) + ), + width: SizeUtils.getByScreen(small: 360, big: 350), + height: SizeUtils.getByScreen(small: 195, big: 185), + child: Center(child: Text(context.translate('Loading photo...'), + textAlign: TextAlign.center, + style: TextStyle(fontSize: SizeUtils.getByScreen(small: 26, big: 25)), + )), + ), + )); + await vm.takePicture(); + Navigator.pop(context); + }, + text: context.translate(I18n.takePicture), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 36, big: 35), + ), + ); + } + } \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_connection_screen.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_connection_screen.dart index 06c92051..a5d19125 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_connection_screen.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/remote_connection_screen.dart @@ -1,9 +1,8 @@ -// import 'package:account/src/features/linked_devices/presentation/app_users_screen.dart'; import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:functions/src/features/remote_connection/presentation/remote_camera_screen.dart'; -import 'package:functions/src/features/remote_connection/presentation/state/remote_connection_view_model.dart'; +import 'package:functions/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart'; import 'package:legacy_shared/legacy_shared.dart'; import 'package:navigation/navigation.dart'; import 'package:sf_localizations/sf_localizations.dart'; @@ -16,35 +15,32 @@ class RemoteConnectionScreen extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { - // final theme = ref.watch(themePortProvider); + final theme = ref.watch(themePortProvider); - final viewModel = ref.read(remoteConnectionViewModelProvider.notifier); - final viewState = ref.watch(remoteConnectionViewModelProvider); - - return PageLayout( - title: 'Remote Connection', - body: SingleChildScrollView(child: Container( + return LegacyPageLayout( + theme: theme, + title: context.translate(I18n.remoteConnection), + body: SingleChildScrollView(child: Padding( padding: SizeUtils.getByScreen( small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) ), child: Column( children: [ - AppSectionButton( + _SectionButton( onPressed: (){Navigator.push(context, MaterialPageRoute( builder: (_)=>RemoteCameraScreen(navigationContract: navigationContract) ));}, icon: Icons.photo_camera_outlined, - text: 'Remote camera' + text: I18n.remoteCamera ), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 15)), - AppSectionButton( + _SectionButton( onPressed: (){showDialog(context: context, builder: (context)=>Dialog( - child: CallDialog( - ) + child: SpyCallDialog() ));}, icon: SFIcons.listen, - text: 'Remote listening' + text: I18n.remoteListening ), ], ), @@ -53,82 +49,13 @@ class RemoteConnectionScreen extends ConsumerWidget { } } -class CallDialog extends ConsumerWidget { +class _SectionButton extends ConsumerWidget { - @override - Widget build(BuildContext context, WidgetRef ref) { - - final viewModel = ref.read(remoteConnectionViewModelProvider.notifier); - final viewState = ref.watch(remoteConnectionViewModelProvider); - - return Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 26, vertical: 20), - big: EdgeInsets.symmetric(horizontal: 24, vertical: 18) - ), - width: SizeUtils.getByScreen(small: 390, big: 380), - height: SizeUtils.getByScreen(small: 250, big: 243), - child: Column( - children: [ - Stack( - children: [ - Center(child: Text(context.translate('Remote listening'), - textAlign: TextAlign.center, - style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), - )), - Align( - alignment: Alignment.centerRight, - child: IconButton( - onPressed: (){Navigator.pop(context);}, - icon: Icon(Icons.close, color: Color(0xFF588EA5)), - ) - ) - ], - ), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), - CustomTextField( - controller: viewModel.phoneController, - hint: context.translate('Insert your phone number'), - keyboardType: TextInputType.number, - ), - if (viewState.errorMessage.isNotEmpty) ...[ - const SizedBox(height: 4), - Text( - viewState.errorMessage, - textAlign: TextAlign.center, - style: const TextStyle( - color: Color.fromRGBO(239, 17, 17, 1), - fontSize: 12, - ), - ), - ], - SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)), - PrimaryButton( - onPressed: () async { - await viewModel.call(); - if (viewState.errorMessage.isEmpty){ - Navigator.pop(context); - } - }, - text: context.translate('Call me'), - color: Color(0xFF588EA5), - height: SizeUtils.getByScreen(small: 38, big: 36), - radius: SizeUtils.getByScreen(small: 32, big: 34), - ), - ], - ), - ); - } - -} - -class AppSectionButton extends ConsumerWidget { - - final GestureTapCallback onPressed; + final VoidCallback onPressed; final IconData icon; final String text; - const AppSectionButton({ + const _SectionButton({ required this.onPressed, required this.icon, required this.text, @@ -136,45 +63,23 @@ class AppSectionButton extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 20), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 18) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( - children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), - child: Icon(icon, - size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), - weight: 30, - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ) - ], - ), + return SectionButton( + onPressed: onPressed, + icon: Icon(icon, + size: SizeUtils.getByScreen(small: 40, big: 44), + color: theme.getColorFor(ThemeCode.legacyPrimary), + weight: 30, + ), + body: Text(context.translate(text), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500 ) + ) ); } + } \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart index 5f56e935..96ab5dfa 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_model.dart @@ -6,9 +6,7 @@ import 'package:functions/src/features/remote_connection/domain/take_picture_use import 'package:functions/src/features/remote_connection/presentation/providers/get_pictures_use_case_provider.dart'; import 'package:functions/src/features/remote_connection/presentation/providers/take_picture_use_case_provider.dart'; import 'package:functions/src/features/remote_connection/presentation/state/remote_connection_view_state.dart'; -// import 'package:legacy_shared/src/providers/logged_user_provider.dart'; -// import 'package:legacy_shared/src/data/models/entities/user_entity.dart'; -// import 'package:sf_localizations/sf_localizations.dart'; +import 'package:legacy_shared/legacy_shared.dart'; final remoteConnectionViewModelProvider = NotifierProvider.autoDispose( @@ -21,8 +19,6 @@ class RemoteConnectionViewModel extends Notifier { late final TextEditingController phoneController; - // late final UserEntity loggedUser; - static final RegExp _phoneRegex = RegExp(r'^\+?\d{6,15}$'); @override @@ -30,22 +26,27 @@ class RemoteConnectionViewModel extends Notifier { _getPicturesUseCase = ref.read(getPicturesUseCaseProvider); _takePictureUseCase = ref.read(takePictureUseCaseProvider); - // loggedUser = ref.read(loggedUserProvider); - phoneController = TextEditingController(); - phoneController.addListener(_onPhoneChanged); - _getPicturesUseCase.getPictures(userId: '').then(setImages); - ref.onDispose(disposeControllers); + Future.microtask(load); + return const RemoteConnectionViewState(); } + Future load() async { + final loggedUser = await ref.read(loggedUserProvider.future); + + final pictures = await _getPicturesUseCase.getPictures(userId: loggedUser.id); + setImages(pictures); + } + void setImages(List pictures) { state = state.copyWith( - pictures: pictures + pictures: pictures, + isLoadingPictures: false, ); } @@ -56,6 +57,32 @@ class RemoteConnectionViewModel extends Notifier { state = state.copyWith(phone: text, errorMessage: ''); } + void prevPicture() { + int pictureIndex = state.pictureIndex - 1; + + if (pictureIndex < 0) { + pictureIndex = state.pictures.length - 1; + } + + state = state.copyWith( + pictureIndex: pictureIndex + ); + } + + void nextPicture() { + int pictureIndex = (state.pictureIndex + 1) % state.pictures.length; + + state = state.copyWith( + pictureIndex: pictureIndex + ); + } + + void setPictureIndex(int value) { + state = state.copyWith( + pictureIndex: value, + ); + } + Future takePicture() async { try { state = state.copyWith(isTakingPicture: true); @@ -63,7 +90,7 @@ class RemoteConnectionViewModel extends Notifier { await _takePictureUseCase.takePicture(userId: '') .then((picture) { List pictures = state.pictures; - //pictures.add(picture); + pictures.add(picture); state = state.copyWith( isTakingPicture: true, ); @@ -86,7 +113,6 @@ class RemoteConnectionViewModel extends Notifier { state = state.copyWith(errorMessage: 'errorMessagePhoneIsInvalid'); return; } - } void disposeControllers() { diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart index f0475062..4ea3be87 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.dart @@ -8,7 +8,8 @@ abstract class RemoteConnectionViewState with _$RemoteConnectionViewState { const factory RemoteConnectionViewState({ @Default('') String phone, @Default([]) List pictures, - @Default(true) bool isLoadingImages, + @Default(0) int pictureIndex, + @Default(true) bool isLoadingPictures, @Default(false) bool isTakingPicture, @Default(false) bool isCalling, @Default('') String errorMessage diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart index a7111a7f..b578eb3a 100644 --- a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/state/remote_connection_view_state.freezed.dart @@ -14,7 +14,7 @@ T _$identity(T value) => value; /// @nodoc mixin _$RemoteConnectionViewState { - String get phone; List get pictures; bool get isLoadingImages; bool get isTakingPicture; bool get isCalling; String get errorMessage; + String get phone; List get pictures; int get pictureIndex; bool get isLoadingPictures; bool get isTakingPicture; bool get isCalling; String get errorMessage; /// Create a copy of RemoteConnectionViewState /// with the given fields replaced by the non-null parameter values. @JsonKey(includeFromJson: false, includeToJson: false) @@ -25,16 +25,16 @@ $RemoteConnectionViewStateCopyWith get copyWith => _$ @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is RemoteConnectionViewState&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other.pictures, pictures)&&(identical(other.isLoadingImages, isLoadingImages) || other.isLoadingImages == isLoadingImages)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is RemoteConnectionViewState&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other.pictures, pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,phone,const DeepCollectionEquality().hash(pictures),isLoadingImages,isTakingPicture,isCalling,errorMessage); +int get hashCode => Object.hash(runtimeType,phone,const DeepCollectionEquality().hash(pictures),pictureIndex,isLoadingPictures,isTakingPicture,isCalling,errorMessage); @override String toString() { - return 'RemoteConnectionViewState(phone: $phone, pictures: $pictures, isLoadingImages: $isLoadingImages, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage)'; + return 'RemoteConnectionViewState(phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage)'; } @@ -45,7 +45,7 @@ abstract mixin class $RemoteConnectionViewStateCopyWith<$Res> { factory $RemoteConnectionViewStateCopyWith(RemoteConnectionViewState value, $Res Function(RemoteConnectionViewState) _then) = _$RemoteConnectionViewStateCopyWithImpl; @useResult $Res call({ - String phone, List pictures, bool isLoadingImages, bool isTakingPicture, bool isCalling, String errorMessage + String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage }); @@ -62,11 +62,12 @@ class _$RemoteConnectionViewStateCopyWithImpl<$Res> /// Create a copy of RemoteConnectionViewState /// with the given fields replaced by the non-null parameter values. -@pragma('vm:prefer-inline') @override $Res call({Object? phone = null,Object? pictures = null,Object? isLoadingImages = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,}) { +@pragma('vm:prefer-inline') @override $Res call({Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,}) { return _then(_self.copyWith( phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String,pictures: null == pictures ? _self.pictures : pictures // ignore: cast_nullable_to_non_nullable -as List,isLoadingImages: null == isLoadingImages ? _self.isLoadingImages : isLoadingImages // ignore: cast_nullable_to_non_nullable +as List,pictureIndex: null == pictureIndex ? _self.pictureIndex : pictureIndex // ignore: cast_nullable_to_non_nullable +as int,isLoadingPictures: null == isLoadingPictures ? _self.isLoadingPictures : isLoadingPictures // ignore: cast_nullable_to_non_nullable as bool,isTakingPicture: null == isTakingPicture ? _self.isTakingPicture : isTakingPicture // ignore: cast_nullable_to_non_nullable as bool,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable @@ -155,10 +156,10 @@ return $default(_that);case _: /// } /// ``` -@optionalTypeArgs TResult maybeWhen(TResult Function( String phone, List pictures, bool isLoadingImages, bool isTakingPicture, bool isCalling, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; +@optionalTypeArgs TResult maybeWhen(TResult Function( String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this; switch (_that) { case _RemoteConnectionViewState() when $default != null: -return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: +return $default(_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: return orElse(); } @@ -176,10 +177,10 @@ return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingP /// } /// ``` -@optionalTypeArgs TResult when(TResult Function( String phone, List pictures, bool isLoadingImages, bool isTakingPicture, bool isCalling, String errorMessage) $default,) {final _that = this; +@optionalTypeArgs TResult when(TResult Function( String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage) $default,) {final _that = this; switch (_that) { case _RemoteConnectionViewState(): -return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: +return $default(_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: throw StateError('Unexpected subclass'); } @@ -196,10 +197,10 @@ return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingP /// } /// ``` -@optionalTypeArgs TResult? whenOrNull(TResult? Function( String phone, List pictures, bool isLoadingImages, bool isTakingPicture, bool isCalling, String errorMessage)? $default,) {final _that = this; +@optionalTypeArgs TResult? whenOrNull(TResult? Function( String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage)? $default,) {final _that = this; switch (_that) { case _RemoteConnectionViewState() when $default != null: -return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: +return $default(_that.phone,_that.pictures,_that.pictureIndex,_that.isLoadingPictures,_that.isTakingPicture,_that.isCalling,_that.errorMessage);case _: return null; } @@ -211,7 +212,7 @@ return $default(_that.phone,_that.pictures,_that.isLoadingImages,_that.isTakingP class _RemoteConnectionViewState implements RemoteConnectionViewState { - const _RemoteConnectionViewState({this.phone = '', final List pictures = const [], this.isLoadingImages = true, this.isTakingPicture = false, this.isCalling = false, this.errorMessage = ''}): _pictures = pictures; + const _RemoteConnectionViewState({this.phone = '', final List pictures = const [], this.pictureIndex = 0, this.isLoadingPictures = true, this.isTakingPicture = false, this.isCalling = false, this.errorMessage = ''}): _pictures = pictures; @override@JsonKey() final String phone; @@ -222,7 +223,8 @@ class _RemoteConnectionViewState implements RemoteConnectionViewState { return EqualUnmodifiableListView(_pictures); } -@override@JsonKey() final bool isLoadingImages; +@override@JsonKey() final int pictureIndex; +@override@JsonKey() final bool isLoadingPictures; @override@JsonKey() final bool isTakingPicture; @override@JsonKey() final bool isCalling; @override@JsonKey() final String errorMessage; @@ -237,16 +239,16 @@ _$RemoteConnectionViewStateCopyWith<_RemoteConnectionViewState> get copyWith => @override bool operator ==(Object other) { - return identical(this, other) || (other.runtimeType == runtimeType&&other is _RemoteConnectionViewState&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other._pictures, _pictures)&&(identical(other.isLoadingImages, isLoadingImages) || other.isLoadingImages == isLoadingImages)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); + return identical(this, other) || (other.runtimeType == runtimeType&&other is _RemoteConnectionViewState&&(identical(other.phone, phone) || other.phone == phone)&&const DeepCollectionEquality().equals(other._pictures, _pictures)&&(identical(other.pictureIndex, pictureIndex) || other.pictureIndex == pictureIndex)&&(identical(other.isLoadingPictures, isLoadingPictures) || other.isLoadingPictures == isLoadingPictures)&&(identical(other.isTakingPicture, isTakingPicture) || other.isTakingPicture == isTakingPicture)&&(identical(other.isCalling, isCalling) || other.isCalling == isCalling)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)); } @override -int get hashCode => Object.hash(runtimeType,phone,const DeepCollectionEquality().hash(_pictures),isLoadingImages,isTakingPicture,isCalling,errorMessage); +int get hashCode => Object.hash(runtimeType,phone,const DeepCollectionEquality().hash(_pictures),pictureIndex,isLoadingPictures,isTakingPicture,isCalling,errorMessage); @override String toString() { - return 'RemoteConnectionViewState(phone: $phone, pictures: $pictures, isLoadingImages: $isLoadingImages, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage)'; + return 'RemoteConnectionViewState(phone: $phone, pictures: $pictures, pictureIndex: $pictureIndex, isLoadingPictures: $isLoadingPictures, isTakingPicture: $isTakingPicture, isCalling: $isCalling, errorMessage: $errorMessage)'; } @@ -257,7 +259,7 @@ abstract mixin class _$RemoteConnectionViewStateCopyWith<$Res> implements $Remot factory _$RemoteConnectionViewStateCopyWith(_RemoteConnectionViewState value, $Res Function(_RemoteConnectionViewState) _then) = __$RemoteConnectionViewStateCopyWithImpl; @override @useResult $Res call({ - String phone, List pictures, bool isLoadingImages, bool isTakingPicture, bool isCalling, String errorMessage + String phone, List pictures, int pictureIndex, bool isLoadingPictures, bool isTakingPicture, bool isCalling, String errorMessage }); @@ -274,11 +276,12 @@ class __$RemoteConnectionViewStateCopyWithImpl<$Res> /// Create a copy of RemoteConnectionViewState /// with the given fields replaced by the non-null parameter values. -@override @pragma('vm:prefer-inline') $Res call({Object? phone = null,Object? pictures = null,Object? isLoadingImages = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,}) { +@override @pragma('vm:prefer-inline') $Res call({Object? phone = null,Object? pictures = null,Object? pictureIndex = null,Object? isLoadingPictures = null,Object? isTakingPicture = null,Object? isCalling = null,Object? errorMessage = null,}) { return _then(_RemoteConnectionViewState( phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable as String,pictures: null == pictures ? _self._pictures : pictures // ignore: cast_nullable_to_non_nullable -as List,isLoadingImages: null == isLoadingImages ? _self.isLoadingImages : isLoadingImages // ignore: cast_nullable_to_non_nullable +as List,pictureIndex: null == pictureIndex ? _self.pictureIndex : pictureIndex // ignore: cast_nullable_to_non_nullable +as int,isLoadingPictures: null == isLoadingPictures ? _self.isLoadingPictures : isLoadingPictures // ignore: cast_nullable_to_non_nullable as bool,isTakingPicture: null == isTakingPicture ? _self.isTakingPicture : isTakingPicture // ignore: cast_nullable_to_non_nullable as bool,isCalling: null == isCalling ? _self.isCalling : isCalling // ignore: cast_nullable_to_non_nullable as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart new file mode 100644 index 00000000..b5eac26f --- /dev/null +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/show_picture_dialog.dart @@ -0,0 +1,105 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:functions/src/features/remote_connection/domain/entities/picture_entity.dart'; +import 'package:functions/src/features/remote_connection/presentation/state/remote_connection_view_model.dart'; +import 'package:utils/utils.dart'; + +class ShowPictureDialog extends ConsumerWidget { + + const ShowPictureDialog(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.read(themePortProvider); + + final viewModel = ref.read(remoteConnectionViewModelProvider.notifier); + final pictures = ref.watch( + remoteConnectionViewModelProvider.select((s)=>s.pictures) + ); + final pictureIndex = ref.watch( + remoteConnectionViewModelProvider.select((s)=>s.pictureIndex) + ); + + return Container( + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + borderRadius: BorderRadius.all(Radius.circular(8)) + ), + height: SizeUtils.getByScreen(small: 350, big: 340), + child: Column( + children: [ + _PictureSection(asset: pictures[pictureIndex].asset), + _MetadataSection(picture: pictures[pictureIndex]), + _ControlsSection( + prev: viewModel.prevPicture, + next: viewModel.nextPicture, + ), + ], + ), + ); + } +} + +class _PictureSection extends ConsumerWidget { + + final String asset; + + const _PictureSection({ + required this.asset, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + return Expanded( + child: Center( + child: Image.asset(asset), + ) + ); + } +} + +class _MetadataSection extends ConsumerWidget { + + final PictureEntity picture; + + const _MetadataSection({ + required this.picture, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + return Column( + children: [ + Text(picture.createdAt.toString()) + ], + ); + } +} + +class _ControlsSection extends ConsumerWidget { + + final VoidCallback prev; + final VoidCallback next; + + const _ControlsSection({ + required this.prev, + required this.next + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + IconButton(onPressed: prev, icon: Icon(Icons.arrow_back_ios_new_rounded)), + IconButton(onPressed: next, icon: Icon(Icons.arrow_forward_ios_rounded)), + ], + ); + } + +} \ No newline at end of file diff --git a/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart new file mode 100644 index 00000000..1e1da73a --- /dev/null +++ b/modules/legacy/modules/functions/lib/src/features/remote_connection/presentation/widgets/spy_call_dialog.dart @@ -0,0 +1,156 @@ +import 'package:design_system/design_system.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:functions/src/features/remote_connection/presentation/state/remote_connection_view_model.dart'; +import 'package:sf_localizations/sf_localizations.dart'; +import 'package:utils/utils.dart'; + +class SpyCallDialog extends ConsumerWidget { + + Future _onCall(BuildContext context, WidgetRef ref) async { + + final vm = ref.read(remoteConnectionViewModelProvider.notifier); + + await vm.call(); + if (!context.mounted) return; + + final errorMessage = ref.read( + remoteConnectionViewModelProvider.select((s)=>s.errorMessage) + ); + + if (errorMessage.isNotEmpty) return; + Navigator.pop(context); + + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.watch(themePortProvider); + + return Container( + padding: SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 26, vertical: 20), + big: EdgeInsets.symmetric(horizontal: 24, vertical: 18) + ), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + color: theme.getColorFor(ThemeCode.backgroundSecondary) + ), + width: SizeUtils.getByScreen(small: 390, big: 380), + height: SizeUtils.getByScreen(small: 250, big: 243), + child: Column( + children: [ + _Header(theme: theme), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), + _PhoneSection(onSubmit: () {_onCall(context, ref);}), + const _ErrorMessageSection(), + SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)), + _CallSection(onPressed: () {_onCall(context, ref);}), + ], + ), + ); + } +} + +class _Header extends StatelessWidget { + + final ThemePort theme; + + const _Header({ + required this.theme, + }); + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + Center(child: Text(context.translate('Remote listening'), + textAlign: TextAlign.center, + style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)), + )), + Align( + alignment: Alignment.centerRight, + child: IconButton( + onPressed: (){Navigator.pop(context);}, + icon: Icon(Icons.close, color: theme.getColorFor(ThemeCode.legacyPrimary)), + ) + ) + ], + ); + } + +} + +class _PhoneSection extends ConsumerWidget { + + final VoidCallback onSubmit; + + const _PhoneSection({ + required this.onSubmit, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final vm = ref.read(remoteConnectionViewModelProvider.notifier); + + return CustomTextField( + controller: vm.phoneController, + hint: context.translate(I18n.insertPhone), + keyboardType: TextInputType.number, + onSubmitted: (_) => onSubmit(), + ); + } + +} + +class _ErrorMessageSection extends ConsumerWidget { + + const _ErrorMessageSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final viewState = ref.watch(remoteConnectionViewModelProvider); + + if (viewState.errorMessage.isNotEmpty) { + return Column( + children: [ + const SizedBox(height: 4), + Text( + viewState.errorMessage, + textAlign: TextAlign.center, + style: const TextStyle( + color: Color.fromRGBO(239, 17, 17, 1), + fontSize: 12, + ), + ), + ], + ); + } else return SizedBox.shrink(); + } +} + +class _CallSection extends ConsumerWidget { + + final VoidCallback onPressed; + + const _CallSection({ + required this.onPressed, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); + + return PrimaryButton( + onPressed: onPressed, + text: context.translate(I18n.call), + color: theme.getColorFor(ThemeCode.legacyPrimary), + height: SizeUtils.getByScreen(small: 38, big: 36), + radius: SizeUtils.getByScreen(small: 32, big: 34), + ); + } + +} \ No newline at end of file diff --git a/modules/legacy/modules/hub/lib/src/core/data/datasource/hub_remote_datasource_impl.dart b/modules/legacy/modules/hub/lib/src/core/data/datasource/hub_remote_datasource_impl.dart index ac9c073a..dc68dc2d 100644 --- a/modules/legacy/modules/hub/lib/src/core/data/datasource/hub_remote_datasource_impl.dart +++ b/modules/legacy/modules/hub/lib/src/core/data/datasource/hub_remote_datasource_impl.dart @@ -16,7 +16,7 @@ class HomeRemoteDatasourceImpl implements HomeRemoteDatasource { @override Future> getDevices({required String userId}) async { try { - final response = await _repository.get>( + /*final response = await _repository.get>( '/$userId/devices', ); final data = response.data!['items']; @@ -24,17 +24,57 @@ class HomeRemoteDatasourceImpl implements HomeRemoteDatasource { throw Exception('Empty response from /:userId/devices'); } - final model = GetDevicesResponseModel.fromJson(data); - /*final model = GetDevicesResponseModel(items: [ + final model = GetDevicesResponseModel.fromJson(data);*/ + final model = GetDevicesResponseModel(items: [ GetDevicesItemResponseModel( id: '1', identificator: '1111', - carrierName: 'Carlos'), + carrierName: 'Carlos', + phone: '111111111', + settings: GetDevicesSettingsResponseModel( + frequency: 0, + frequencyHeartRate: 0, + timezone: 0, + pedometer: true, + language: 'es', + alerts: [] + ), + protocol: '', + type: '', + connectionServer: '', + createdAt: 0, + flags: GetDevicesFlagsResponseModel( + isInOrOut: 'out', + geofenceId: '1', + isBatteryLow: false, + isDisconnect: false + ) + ), GetDevicesItemResponseModel( - id: '2', - identificator: '1112', - carrierName: 'Ana'), - ]);*/ + id: '2', + identificator: '1112', + carrierName: 'Ana', + phone: '222222222', + settings: GetDevicesSettingsResponseModel( + frequency: 0, + frequencyHeartRate: 0, + timezone: 0, + pedometer: true, + language: 'es', + alerts: [] + ), + protocol: '', + type: '', + connectionServer: '', + createdAt: 0, + flags: GetDevicesFlagsResponseModel( + isInOrOut: 'out', + geofenceId: '2', + isBatteryLow: false, + isDisconnect: false + ) + ), + ]); return model.toEntity(); } on DioException catch (error) { throw _mapDioError( diff --git a/modules/legacy/modules/hub/lib/src/features/hub/presentation/hub_screen.dart b/modules/legacy/modules/hub/lib/src/features/hub/presentation/hub_screen.dart index 238b13e4..9225ab80 100644 --- a/modules/legacy/modules/hub/lib/src/features/hub/presentation/hub_screen.dart +++ b/modules/legacy/modules/hub/lib/src/features/hub/presentation/hub_screen.dart @@ -25,9 +25,6 @@ class HubScreen extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); - final viewState = ref.watch(hubViewModelProvider); - final viewModel = ref.read(hubViewModelProvider.notifier); - return Scaffold( backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary), body: SafeArea( @@ -36,83 +33,15 @@ class HubScreen extends ConsumerWidget { child: Column( children: [ SizedBox(height: SizeUtils.getByScreen(small: 8, big: 4)), - Stack( - children: [ - SizedBox( - height: SizeUtils.getByScreen(small: 36, big: 36), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Image.asset('assets/images/ui/iso_sf.png', - height: SizeUtils.getByScreen(small: 18, big: 18)), - SizedBox(width: SizeUtils.getByScreen(small: 8, big: 4)), - SizedBox( - width: SizeUtils.getByScreen(small: 104, big: 100), - height: 32, - child: CustomDropdown( - items: viewState.devices.map((DeviceEntity device)=> - Text(device.carrierName) - ).toList(), - values: viewState.devices, - value: viewState.selectedDevice, - onChanged: (device){viewModel.setSelectedDevice(device);}, - height: 32, - color: Colors.transparent, - padding: EdgeInsets.zero, - ), - ), - ] - ) - ), - Center( - child: SvgPicture.asset('assets/images/ui/logo_sf.svg', - height: SizeUtils.getByScreen(small: 36, big: 36)) - ), - ], - ), + _Header(), SizedBox(height: SizeUtils.getByScreen(small: 12, big: 14)), Expanded(child: SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.customerService);}, - icon: SFIcons.customerService, - text: I18n.customerService), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.dashboardHome);}, - icon: SFIcons.payments, - text: I18n.sfPay), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.dashboardFunctions);}, - icon: SFIcons.functions, - text: I18n.functions), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), - AppSectionButton( - onPressed: (){navigationContract.pushTo(AppRoutes.accountSettings);}, - icon: Icons.manage_accounts_outlined, - text: I18n.accountSettings), - SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), - AppSectionButton( - onPressed: (){}, - icon: Icons.settings_outlined, - text: I18n.deviceSettings), - + _MenuSection(navigationContract: navigationContract), SizedBox(height: SizeUtils.getByScreen(small: 16, big: 22)), - Text(context.translate(I18n.watchesOnMap), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 20, big: 19), - fontWeight: FontWeight.bold, - color: Color(0xFF588EA5), - ), - ), - SizedBox(height: SizeUtils.getByScreen(small: 4, big: 8)), - SizedBox( - height: SizeUtils.getByScreen(small: 200, big: 300), - child: Minimap(), - ), + _MapSection(), SizedBox(height: SizeUtils.getByScreen(small: 14, big: 13)), ], ), @@ -125,76 +54,165 @@ class HubScreen extends ConsumerWidget { } } -class AppSectionButton extends ConsumerWidget { +class _Header extends ConsumerWidget { - final GestureTapCallback onPressed; - final IconData icon; - final String text; + const _Header(); - const AppSectionButton({ - required this.onPressed, - required this.icon, - required this.text, + @override + Widget build(BuildContext context, WidgetRef ref) { + + final state = ref.watch(hubViewModelProvider); + final vm = ref.read(hubViewModelProvider.notifier); + + return Stack( + children: [ + SizedBox( + height: SizeUtils.getByScreen(small: 36, big: 36), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Image.asset('assets/images/ui/iso_sf.png', + height: SizeUtils.getByScreen(small: 18, big: 18)), + SizedBox(width: SizeUtils.getByScreen(small: 8, big: 4)), + SizedBox( + width: SizeUtils.getByScreen(small: 104, big: 100), + height: 32, + child: CustomDropdown( + items: state.devices.map((DeviceEntity device)=> + Text( + device.carrierName, + overflow: TextOverflow.ellipsis) + ).toList(), + values: state.devices, + value: state.selectedDevice, + onChanged: (device){vm.setSelectedDevice(device);}, + height: 32, + color: Colors.transparent, + padding: EdgeInsets.zero, + ), + ), + ] + ) + ), + Center( + child: SvgPicture.asset('assets/images/ui/logo_sf.svg', + height: SizeUtils.getByScreen(small: 36, big: 36)) + ), + ], + ); + } + +} + +class _MenuSection extends ConsumerWidget { + + final NavigationContract navigationContract; + + const _MenuSection({ + required this.navigationContract, }); @override Widget build(BuildContext context, WidgetRef ref) { + return Column( + children: [ + _SectionButton( + onPressed: (){navigationContract.pushTo(AppRoutes.customerService);}, + icon: SFIcons.customerService, + text: I18n.customerService), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), + _SectionButton( + onPressed: (){navigationContract.pushTo(AppRoutes.dashboardHome);}, + icon: SFIcons.payments, + text: I18n.sfPay), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), + _SectionButton( + onPressed: (){navigationContract.pushTo(AppRoutes.dashboardFunctions);}, + icon: SFIcons.functions, + text: I18n.functions), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), + _SectionButton( + onPressed: (){navigationContract.pushTo(AppRoutes.accountSettings);}, + icon: Icons.manage_accounts_outlined, + text: I18n.accountSettings), + SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)), + _SectionButton( + onPressed: (){}, + icon: Icons.settings_outlined, + text: I18n.deviceSettings), + ], + ); + } + +} + +class _SectionButton extends ConsumerWidget { + + final VoidCallback onPressed; + final IconData icon; + final String text; + + const _SectionButton({ + required this.onPressed, + required this.icon, + required this.text + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); - return GestureDetector( - onTap: onPressed, - child: Container( - padding: SizeUtils.getByScreen( - small: EdgeInsets.symmetric(horizontal: 22, vertical: 10), - big: EdgeInsets.symmetric(horizontal: 21, vertical: 8) - ), - decoration: BoxDecoration( - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), - color: theme.getColorFor(ThemeCode.backgroundSecondary), - ), - child: Row( - children: [ - Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.getColorFor(ThemeCode.backgroundPrimary), - ), - padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)), - child: Icon(icon, - size: SizeUtils.getByScreen(small: 40, big: 44), - color: Color(0xFF588EA5), - weight: 30, - ), - ), - SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), - Expanded( - child: Text(context.translate(text), - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 18, big: 19), - fontWeight: FontWeight.w500 - ) - ) - ) - ], - ), + return SectionButton( + onPressed: onPressed, + icon: Icon(icon, + size: SizeUtils.getByScreen(small: 40, big: 44), + color: theme.getColorFor(ThemeCode.legacyPrimary), + weight: 30, + ), + iconPadding: SizeUtils.getByScreen(small: 14, big: 12), + body: Text(context.translate(text), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500 + ) ) ); } } -class Minimap extends ConsumerWidget { +class _MapSection extends ConsumerWidget { - IconData batteryToIcon(int battery) { - if (battery < 15) return Icons.battery_0_bar; - if (battery < 30) return Icons.battery_1_bar; - if (battery < 45) return Icons.battery_2_bar; - if (battery < 60) return Icons.battery_3_bar; - if (battery < 75) return Icons.battery_4_bar; - if (battery < 90) return Icons.battery_5_bar; - return Icons.battery_6_bar; + const _MapSection(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final theme = ref.read(themePortProvider); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(context.translate(I18n.watchesOnMap), + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 20, big: 19), + fontWeight: FontWeight.bold, + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + ), + SizedBox(height: SizeUtils.getByScreen(small: 4, big: 8)), + SizedBox( + height: SizeUtils.getByScreen(small: 200, big: 300), + child: _Minimap(), + ) + ], + ); } +} + +class _Minimap extends ConsumerWidget { + @override Widget build(BuildContext context, WidgetRef ref) { final theme = ref.watch(themePortProvider); @@ -202,11 +220,6 @@ class Minimap extends ConsumerWidget { final viewState = ref.watch(hubViewModelProvider); final viewModel = ref.read(hubViewModelProvider.notifier); - final battery = viewState.selectedPosition?.ncell ?? 0; - final IconData batteryIcon = batteryToIcon(battery); - - final positionDate = DateTime.fromMillisecondsSinceEpoch(viewState.selectedPosition?.positionDate ?? 0); - return FlutterMap( mapController: viewModel.mapController, options: MapOptions( @@ -235,64 +248,96 @@ class Minimap extends ConsumerWidget { if (viewState.selectedPosition != null) Align( alignment: Alignment.bottomCenter, - child: Container( - height: SizeUtils.getByScreen(small: 60, big: 58), - width: SizeUtils.getByScreen(small: 300, big: 298), - margin: EdgeInsets.only(bottom: SizeUtils.getByScreen(small: 20, big: 16)), - decoration: BoxDecoration( - color: theme.getColorFor(ThemeCode.backgroundPrimary), - borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 9, big: 8))) - ), - child: Row( - children: [ - Icon(SFIcons.location, - size: SizeUtils.getByScreen(small: 40, big: 38), - color: Color(0xFF588EA5), - ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SizedBox( - width: SizeUtils.getByScreen(small: 250, big: 248), - child: Text('${viewState.selectedPosition!.address?.street}, ' - '${viewState.selectedPosition!.address?.province}, ' - '${viewState.selectedPosition!.address?.country}', - overflow: TextOverflow.ellipsis, - ) - ), - Row( - children: [ - Text('${positionDate.month.toString().padLeft(2, '0')}-' - '${positionDate.day.toString().padLeft(2, '0')} ' - '${positionDate.hour.toString().padLeft(2, '0')}:' - '${positionDate.minute.toString().padLeft(2, '0')}:' - '${positionDate.second.toString().padLeft(2, '0')}', - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11) - ), - ), - if (viewState.selectedPosition!.networks.isNotEmpty) - Text(' | ${viewState.selectedPosition!.networks.first.signal}', - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11) - ), - ), - Icon(batteryIcon), - Text('${viewState.selectedPosition!.ncell ?? 0}%', - style: TextStyle( - fontSize: SizeUtils.getByScreen(small: 12, big: 11) - ), - ) - ], - ) - ], - ) - ], - ), - ), + child: _LocationBanner(), ) ], ); } +} + +class _LocationBanner extends ConsumerWidget { + + IconData toBatteryIcon(int battery) { + if (battery < 15) return Icons.battery_0_bar; + if (battery < 30) return Icons.battery_1_bar; + if (battery < 45) return Icons.battery_2_bar; + if (battery < 60) return Icons.battery_3_bar; + if (battery < 75) return Icons.battery_4_bar; + if (battery < 90) return Icons.battery_5_bar; + return Icons.battery_6_bar; + } + + const _LocationBanner(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + + final theme = ref.read(themePortProvider); + + final viewState = ref.watch(hubViewModelProvider); + + final battery = viewState.selectedPosition?.ncell ?? 0; + final IconData batteryIcon = toBatteryIcon(battery); + + final positionDate = DateTime.fromMillisecondsSinceEpoch(viewState.selectedPosition?.positionDate ?? 0); + + + return Container( + height: SizeUtils.getByScreen(small: 60, big: 58), + width: SizeUtils.getByScreen(small: 300, big: 298), + margin: EdgeInsets.only(bottom: SizeUtils.getByScreen(small: 20, big: 16)), + decoration: BoxDecoration( + color: theme.getColorFor(ThemeCode.backgroundPrimary), + borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 9, big: 8))) + ), + child: Row( + children: [ + Icon(SFIcons.location, + size: SizeUtils.getByScreen(small: 40, big: 38), + color: theme.getColorFor(ThemeCode.legacyPrimary), + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: SizeUtils.getByScreen(small: 250, big: 248), + child: Text('${viewState.selectedPosition!.address?.street}, ' + '${viewState.selectedPosition!.address?.province}, ' + '${viewState.selectedPosition!.address?.country}', + overflow: TextOverflow.ellipsis, + ) + ), + Row( + children: [ + Text('${positionDate.month.toString().padLeft(2, '0')}-' + '${positionDate.day.toString().padLeft(2, '0')} ' + '${positionDate.hour.toString().padLeft(2, '0')}:' + '${positionDate.minute.toString().padLeft(2, '0')}:' + '${positionDate.second.toString().padLeft(2, '0')}', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11) + ), + ), + if (viewState.selectedPosition!.networks.isNotEmpty) + Text(' | ${viewState.selectedPosition!.networks.first.signal}', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11) + ), + ), + Icon(batteryIcon), + Text('${viewState.selectedPosition!.ncell ?? 0}%', + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 12, big: 11) + ), + ) + ], + ) + ], + ) + ], + ), + ); + } + } \ No newline at end of file diff --git a/modules/legacy/modules/hub/pubspec.lock b/modules/legacy/modules/hub/pubspec.lock index 16307937..e96db751 100644 --- a/modules/legacy/modules/hub/pubspec.lock +++ b/modules/legacy/modules/hub/pubspec.lock @@ -595,6 +595,13 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.2" + legacy_dashboard_shell: + dependency: "direct main" + description: + path: "../legacy_dashboard_shell" + relative: true + source: path + version: "0.0.1" legacy_shared: dependency: "direct main" description: diff --git a/modules/legacy/modules/hub/pubspec.yaml b/modules/legacy/modules/hub/pubspec.yaml index b1c41d9d..4618b474 100644 --- a/modules/legacy/modules/hub/pubspec.yaml +++ b/modules/legacy/modules/hub/pubspec.yaml @@ -34,6 +34,8 @@ dependencies: #modules dependencies go here dashboard_shell: path: ../../../../modules/dashboard_shell + legacy_dashboard_shell: + path: ../../modules/legacy_dashboard_shell #packages dependencies go here design_system: path: ../../../../packages/design_system diff --git a/modules/legacy/modules/hub/pubspec_overrides.yaml b/modules/legacy/modules/hub/pubspec_overrides.yaml index 04ccd0da..b15761e1 100644 --- a/modules/legacy/modules/hub/pubspec_overrides.yaml +++ b/modules/legacy/modules/hub/pubspec_overrides.yaml @@ -1,3 +1,4 @@ +# melos_managed_dependency_overrides: legacy_dashboard_shell # melos_managed_dependency_overrides: legacy_shared # melos_managed_dependency_overrides: design_system,fonts,navigation,sf_infrastructure,sf_localizations,utils,auth,dashboard_shell,home,notifications,sf_shared,profile dependency_overrides: @@ -11,6 +12,8 @@ dependency_overrides: path: ..\\..\\..\\..\\packages\\fonts home: path: ..\\..\\..\\home + legacy_dashboard_shell: + path: ..\\legacy_dashboard_shell legacy_shared: path: ..\\..\\packages\\legacy_shared navigation: diff --git a/modules/legacy/packages/legacy_shared/lib/src/components/menu_button.dart b/modules/legacy/packages/legacy_shared/lib/src/components/menu_button.dart new file mode 100644 index 00000000..a54cc17a --- /dev/null +++ b/modules/legacy/packages/legacy_shared/lib/src/components/menu_button.dart @@ -0,0 +1,64 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +class AppMenuButton extends StatelessWidget { + + final GestureTapCallback onPressed; + final IconData icon; + final bool negativeIcon; + final double? iconSize; + final String text; + final Color color; + + const AppMenuButton({ + required this.onPressed, + required this.icon, + this.negativeIcon = false, + this.iconSize, + required this.text, + required this.color, + }); + + @override + Widget build(BuildContext context) { + + return TextButton( + onPressed: onPressed, + style: ButtonStyle( + overlayColor: WidgetStatePropertyAll(Color(0xFFF7F7F7)) + ), + child: Row( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: negativeIcon + ? Colors.white + : color, + ), + height: SizeUtils.getByScreen(small: 52, big: 48), + width: SizeUtils.getByScreen(small: 52, big: 48), + child: Icon(icon, + size: iconSize ?? SizeUtils.getByScreen(small: 52, big: 48), + color: negativeIcon + ? color + : Colors.white, + weight: 30, + ), + ), + SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), + Expanded( + child: Text(text, + style: TextStyle( + fontSize: SizeUtils.getByScreen(small: 18, big: 19), + fontWeight: FontWeight.w500, + color: Color(0xFF4B4B4B) + ) + ) + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/modules/legacy/packages/legacy_shared/lib/src/components/section_button.dart b/modules/legacy/packages/legacy_shared/lib/src/components/section_button.dart new file mode 100644 index 00000000..8c65539d --- /dev/null +++ b/modules/legacy/packages/legacy_shared/lib/src/components/section_button.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:utils/utils.dart'; + +class SectionButton extends StatelessWidget { + + final GestureTapCallback onPressed; + final Widget icon; + final double? iconPadding; + final Widget body; + + const SectionButton({ + required this.onPressed, + required this.icon, + this.iconPadding, + required this.body, + }); + + @override + Widget build(BuildContext context) { + + return TextButton( + onPressed: onPressed, + style: ButtonStyle( + padding: WidgetStatePropertyAll(SizeUtils.getByScreen( + small: EdgeInsets.symmetric(horizontal: 22, vertical: 16), + big: EdgeInsets.symmetric(horizontal: 21, vertical: 12) + )), + backgroundColor: WidgetStatePropertyAll(Color(0xFFF7F7F7)), + foregroundColor: WidgetStatePropertyAll(Color(0xFF4B4B4B)), + shape: WidgetStatePropertyAll( + RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(SizeUtils.getByScreen(small: 12, big: 18))), + ), + ), + ), + child: Row( + children: [ + Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Colors.white, + ), + padding: EdgeInsets.all( + iconPadding ?? SizeUtils.getByScreen(small: 12, big: 16)), + child: icon, + ), + SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)), + Expanded( + child: body + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart b/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart index 08732649..80117dbb 100644 --- a/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart +++ b/modules/legacy/packages/legacy_shared/lib/src/widgets/layouts/page_layout.dart @@ -1,21 +1,24 @@ +import 'package:design_system/design_system.dart'; import 'package:flutter/material.dart'; -import 'package:utils/src/size_utils.dart'; +import 'package:utils/utils.dart'; -class PageLayout extends StatelessWidget{ +class LegacyPageLayout extends StatelessWidget{ final String title; final Widget body; final Widget? footer; final bool showEdit; final VoidCallback? onEditChange; + final ThemePort theme; - const PageLayout({ + const LegacyPageLayout({ super.key, required this.title, required this.body, this.footer, this.showEdit = false, - this.onEditChange + this.onEditChange, + required this.theme, }); @override @@ -37,7 +40,7 @@ class PageLayout extends StatelessWidget{ children: [ IconButton(onPressed: () {Navigator.pop(context);}, icon: Icon(Icons.arrow_back, - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), size: 32, ), padding: EdgeInsets.zero, @@ -45,7 +48,7 @@ class PageLayout extends StatelessWidget{ if (showEdit) DecoratedBox( decoration: BoxDecoration( - color: Color(0xFF588EA5), + color: theme.getColorFor(ThemeCode.legacyPrimary), shape: BoxShape.circle ), child: IconButton(onPressed: onEditChange, @@ -65,7 +68,7 @@ class PageLayout extends StatelessWidget{ fontSize: SizeUtils.getByScreen(small: 20, big: 19), fontWeight: FontWeight.w500, letterSpacing: 0, - color: Color(0xFF588EA5) + color: theme.getColorFor(ThemeCode.legacyPrimary) ), ) ) diff --git a/packages/design_system/lib/design_system.dart b/packages/design_system/lib/design_system.dart index 8e4c970d..f1581269 100644 --- a/packages/design_system/lib/design_system.dart +++ b/packages/design_system/lib/design_system.dart @@ -10,4 +10,4 @@ export 'src/buttons/primary_button.dart'; export 'src/buttons/secondary_button.dart'; export 'src/buttons/custom_text_button.dart'; export 'src/dropdowns/dropdown.dart'; -export 'src/dropdowns/country_prefix_picker.dart'; +export 'src/dropdowns/country_prefix_picker.dart'; \ No newline at end of file diff --git a/packages/design_system/lib/src/theme/theme_port.dart b/packages/design_system/lib/src/theme/theme_port.dart index ea346c1f..a0b4e0f3 100644 --- a/packages/design_system/lib/src/theme/theme_port.dart +++ b/packages/design_system/lib/src/theme/theme_port.dart @@ -20,6 +20,7 @@ enum ThemeCode { textTertiary, buttonPrimary, buttonSecondary, + legacyPrimary, } abstract class ThemePort { diff --git a/packages/design_system/lib/src/theme/theme_sf_adapter.dart b/packages/design_system/lib/src/theme/theme_sf_adapter.dart index 942139ae..06863e4f 100644 --- a/packages/design_system/lib/src/theme/theme_sf_adapter.dart +++ b/packages/design_system/lib/src/theme/theme_sf_adapter.dart @@ -13,6 +13,7 @@ class ThemeSfAdapter extends ThemePort { ThemeCode.textTertiary: Color(0xFFE0E0E0), ThemeCode.buttonPrimary: Color(0xFF329e95), ThemeCode.buttonSecondary: Color(0xFF4B4B4B), + ThemeCode.legacyPrimary: Color(0xFF588EA5), }; @override diff --git a/packages/sf_localizations/assets/l10n/en.json b/packages/sf_localizations/assets/l10n/en.json index 81cd554c..5284de92 100755 --- a/packages/sf_localizations/assets/l10n/en.json +++ b/packages/sf_localizations/assets/l10n/en.json @@ -178,5 +178,34 @@ "userRole": "Role: {role}", "copy": "copy", "deviceIdLabel": "ID: {deviceId}", - "regCodeLabel": "Registration code: {regCode}" + "regCodeLabel": "Registration code: {regCode}", + "deleteAccountBody1": "Canceling an account is an irreversible operation. Please confirm that all services related to the account have been properly managed.\n\nAfter canceling your account, you will no longer be able to use this account or recover any content or information you have added or linked (even if you use the same account to register and reuse), including, but not limited to:\n1. You will not be able to log in and use this account.\n2. Your personal information and account history will not be recovered.\n3. All records of third-party services you use through account linking or account binding cannot be recovered. You will no longer be able to log in and use the above services. Love, gold coins, third-party points, orders, tickets, and other coupons you have received will be considered abandoned and will not be used.\n\nPlease note that canceling your account does not mean that the account behavior and related responsibilities prior to the cancellation of this account are exempt or reduced.", + "deleteAccountBody2": "Clicking \"Request account cancellation\" means that you have read and agree to the above description.", + "requestCancelButton": "Request account cancellation", + "verifyAccount": "Verify account", + "requestCancelTitle": "Request account cancellation", + "requestCancelBody": "1. Account cancellation does not mean operational recovery, so please ensure that the account is no longer in use before operating it.\n2. Once an account cancellation request has been successfully submitted, the platform will delete all information related to your account within one hour.", + "deleteDeviceData": "Delete all information related to the {name} device", + "confirm": "Confirm", + "remoteConnection": "Remote connection", + "calendar": "Calendar", + "contacts": "Contacts", + "doNotDisturb": "Do not disturb", + "videoCall": "Video call", + "health": "Health", + "activityMeter": "Activity meter", + "rewards": "Rewards", + "callWatch": "Call watch", + "appsUse": "Apps use", + "appsSurveillance": "Apps surveillance", + "makeFriends": "Make friends", + "locateSF": "Play sound on device", + "locateSFBody1": "Locate your device with a sound.", + "locateSFBody2": "1. Press the Play Sound button to activate the sound on the device.\n2. Press OK.\n3. The device will play a sound.\n4. The device will start sounding after receiving the instructions.", + "locateSFAction": "Locate my SaveFamily", + "insertPhone": "Insert your phone number", + "call": "Call me", + "takePicture": "Take a picture", + "remoteCamera": "Remote Camera", + "remoteListening": "Remote Listening" } \ 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 b6d9d71f..176f142b 100644 --- a/packages/sf_localizations/assets/l10n/es.json +++ b/packages/sf_localizations/assets/l10n/es.json @@ -184,5 +184,26 @@ "requestCancelTitle": "Solicitud de cancelación de la cuenta", "requestCancelBody": "1. La cancelación de la cuenta no es la recuperación operacional, asegúrate de que antes de operar la cuenta ya no se utiliza.\n2. Enviado correctamente una cancelación de la cuenta de la aplicación, la plataforma se eliminará toda la información relacionada con tu cuenta dentro de 1 hora.", "deleteDeviceData": "Borrar toda la información relacionada con el dispositivo de {name}", - "confirm": "Confirmar" + "confirm": "Confirmar", + "remoteConnection": "Conexión remota", + "calendar": "Horario de actividades", + "contacts": "Agenda", + "doNotDisturb": "No molestar", + "videoCall": "Video llamada", + "health": "Salud", + "activityMeter": "Medidor de actividad", + "rewards": "Enviar recompensas", + "callWatch": "Llamar al reloj", + "appsUse": "Uso de las aplicaciones", + "appsSurveillance": "Supervisión de las aplicaciones", + "makeFriends": "Hacer amigos", + "locateSF": "Reproducir sonido en dispositivo", + "locateSFBody1": "Localiza tu dispositivo con un sonido.", + "locateSFBody2": "1. Pulsa el botón Reproducir Sonido para activar el sonido en el dispositivo.\n2. Pulsa OK\n3. El dispositivo reproducirá un sonido\n4. El dispositivo comenzará a sonar después de recibir las instrucciones", + "locateSFAction": "Ubica mi Savefamily", + "insertPhone": "Inserta tu número de teléfono", + "call": "Llámame", + "takePicture": "Tomar fotografía", + "remoteCamera": "Foto remota", + "remoteListening": "Escucha remota" } \ 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 70203512..123b86f9 100755 --- a/packages/sf_localizations/lib/src/generated/i18n.dart +++ b/packages/sf_localizations/lib/src/generated/i18n.dart @@ -184,35 +184,56 @@ class I18n { static const String enterSubject = 'enterSubject'; static const String enterMessage = 'enterMessage'; static const String sendEmail = 'sendEmail'; - static const String legacyPersonalData = 'personalData'; - static const String legacyChangePassword = 'changePassword'; - static const String legacyAddNewSF = 'addNewSF'; - static const String legacyLinkedDevices = 'linkedDevices'; - static const String legacyAppUsers = 'appUsers'; - static const String legacyPrivacyPolicy = 'privacyPolicy'; - static const String legacyLogOut = 'logOut'; + static const String personalData = 'personalData'; + static const String changePassword = 'changePassword'; + static const String addNewSF = 'addNewSF'; + static const String linkedDevices = 'linkedDevices'; + static const String appUsers = 'appUsers'; + static const String privacyPolicy = 'privacyPolicy'; + static const String logOut = 'logOut'; static const String passwordLabel = 'passwordLabel'; - static const String legacySubmit = 'submit'; - static const String legacySave = 'save'; - static const String legacyEditDeviceTitle = 'editDeviceTitle'; - static const String legacyName = 'name'; - static const String legacyDeleteDeviceDialog = 'deleteDeviceDialog'; - static const String legacyDeleteUserDialog = 'deleteUserDialog'; - static const String legacyCancel = 'cancel'; - static const String legacyDelete = 'delete'; - static const String legacyUserAccount = 'userAccount'; - static const String legacyUserRole = 'userRole'; - static const String legacyCopy = 'copy'; - static const String legacyDeviceIdLabel = 'deviceIdLabel'; - static const String legacyRegCodeLabel = 'regCodeLabel'; - static const String legacyRegCode = 'regCode'; - static const String legacyDeleteAccount = 'deleteAccount'; - static const String legacyDeleteAccountBody1 = 'deleteAccountBody1'; - static const String legacyDeleteAccountBody2 = 'deleteAccountBody2'; - static const String legacyRequestCancelButton = 'requestCancelButton'; - static const String legacyVerifyAccount = 'verifyAccount'; - static const String legacyRequestCancelTitle = 'requestCancelTitle'; - static const String legacyRequestCancelBody = 'requestCancelBody'; - static const String legacyDeleteDeviceData = 'deleteDeviceData'; - static const String legacyConfirm = 'confirm'; + static const String submit = 'submit'; + static const String save = 'save'; + static const String editDeviceTitle = 'editDeviceTitle'; + static const String name = 'name'; + static const String deleteDeviceDialog = 'deleteDeviceDialog'; + static const String deleteUserDialog = 'deleteUserDialog'; + static const String cancel = 'cancel'; + static const String delete = 'delete'; + static const String userAccount = 'userAccount'; + static const String userRole = 'userRole'; + static const String copy = 'copy'; + static const String deviceIdLabel = 'deviceIdLabel'; + static const String regCodeLabel = 'regCodeLabel'; + static const String regCode = 'regCode'; + static const String deleteAccount = 'deleteAccount'; + static const String deleteAccountBody1 = 'deleteAccountBody1'; + static const String deleteAccountBody2 = 'deleteAccountBody2'; + static const String requestCancelButton = 'requestCancelButton'; + static const String verifyAccount = 'verifyAccount'; + static const String requestCancelTitle = 'requestCancelTitle'; + static const String requestCancelBody = 'requestCancelBody'; + static const String deleteDeviceData = 'deleteDeviceData'; + static const String confirm = 'confirm'; + static const String remoteConnection = 'remoteConnection'; + static const String calendar = 'calendar'; + static const String contacts = 'contacts'; + static const String doNotDisturb = 'doNotDisturb'; + static const String videoCall = 'videoCall'; + static const String health = 'health'; + static const String activityMeter = 'activityMeter'; + static const String rewards = 'rewards'; + static const String callWatch = 'callWatch'; + static const String appsUse = 'appsUse'; + static const String appsSurveillance = 'appsSurveillance'; + static const String makeFriends = 'makeFriends'; + static const String locateSF = 'locateSF'; + static const String locateSFBody1 = 'locateSFBody1'; + static const String locateSFBody2 = 'locateSFBody2'; + static const String locateSFAction = 'locateSFAction'; + static const String insertPhone = 'insertPhone'; + static const String call = 'call'; + static const String takePicture = 'takePicture'; + static const String remoteCamera = 'remoteCamera'; + static const String remoteListening = 'remoteListening'; }