chore: clean up flutter analyze warnings

Highlights:
- Add publish_to: 'none' to legacy pubspec.yaml files                                                      - Replace print() with dart:developer log() in Treezor SDK
- Add !context.mounted guards in async callbacks (defensive bug fix)                                                       - Add super.key to widget constructors
- Remove redundant @Default(null) from device_model                                     - Fix implementation_imports in legacy_auth datasources                                        - Add ignore comments for scaffolding code
- Add missing shared_preferences dependency in splash module                                                                                                            Mostly code quality improvements, with one defensive bug fix              context.mounted) and one missing dependency fix (shared_preferences).
This commit is contained in:
2026-04-06 22:21:22 +02:00
parent b63b06ef14
commit 3d267aff37
66 changed files with 504 additions and 490 deletions

View File

@@ -1,8 +1,6 @@
library account;
export 'src/features/account_settings/account_settings_builder.dart';
export 'src/features/personal_data/personal_data_builder.dart';
export 'src/features/change_password/change_password_builder.dart';
export 'src/features/linked_devices/linked_devices_builder.dart';
export 'src/features/app_users/app_users_builder.dart';
export 'src/features/delete_account/delete_account_builder.dart';
export 'src/features/delete_account/delete_account_builder.dart';

View File

@@ -1,4 +1,3 @@
import 'package:legacy_shared/legacy_shared.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:sf_shared/sf_shared.dart';

View File

@@ -58,7 +58,8 @@ class AppUserCard extends ConsumerWidget {
final bool isEditing;
const AppUserCard({
required this.user,
super.key, required this.user,
required this.isEditing,
});

View File

@@ -222,6 +222,7 @@ class _SaveSection extends ConsumerWidget {
child: PrimaryButton(
onPressed: () async {
await vm.submit();
if (!context.mounted) return;
final errorMessage = ref.read(
changePasswordViewModelProvider.select((s)=>s.errorMessage)

View File

@@ -7,9 +7,10 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:sf_shared/sf_shared.dart';
final changePasswordViewModelProvider =
NotifierProvider.autoDispose<ChangePasswordViewModel, ChangePasswordViewState>(
ChangePasswordViewModel.new,
);
NotifierProvider.autoDispose<
ChangePasswordViewModel,
ChangePasswordViewState
>(ChangePasswordViewModel.new);
class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
late final ChangePasswordUseCase _changePasswordUseCase;
@@ -38,21 +39,15 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
}
void toggleCurrentPasswordVisibility() {
state = state.copyWith(
showCurrentPassword: !state.showCurrentPassword
);
state = state.copyWith(showCurrentPassword: !state.showCurrentPassword);
}
void toggleNewPasswordVisibility() {
state = state.copyWith(
showNewPassword: !state.showNewPassword
);
state = state.copyWith(showNewPassword: !state.showNewPassword);
}
void toggleRepeatedPasswordVisibility() {
state = state.copyWith(
showRepeatedPassword: !state.showRepeatedPassword
);
state = state.copyWith(showRepeatedPassword: !state.showRepeatedPassword);
}
void _onNewPasswordChanged() {
@@ -60,10 +55,7 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
if (value == state.newPassword) return;
state = state.copyWith(
newPassword: value,
errorMessage: ''
);
state = state.copyWith(newPassword: value, errorMessage: '');
}
void _onRepeatPasswordChanged() {
@@ -71,45 +63,41 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
if (value == state.repeatPassword) return;
state = state.copyWith(
repeatPassword: value,
errorMessage: ''
);
state = state.copyWith(repeatPassword: value, errorMessage: '');
}
bool _validateForm() {
final _upperRegex = RegExp(r'[A-Z]');
final _digitRegex = RegExp(r'[0-9]');
final _specialRegex =
RegExp(r'[!@#$%^&*(),.?":{}|<>\-_+=\[\]\\\/~`]');
final upperRegex = RegExp(r'[A-Z]');
final digitRegex = RegExp(r'[0-9]');
final specialRegex = RegExp(r'[!@#$%^&*(),.?":{}|<>\-_+=\[\]\\\/~`]');
final password = state.newPassword.trim();
if (password.isEmpty){
if (password.isEmpty) {
state = state.copyWith(errorMessage: 'errorMessageNewPasswordIsEmpty');
return false;
}
if (state.repeatPassword.trim().isEmpty){
if (state.repeatPassword.trim().isEmpty) {
state = state.copyWith(errorMessage: 'errorMessageRepeatPasswordIsEmpty');
return false;
}
if (password != state.repeatPassword.trim()){
if (password != state.repeatPassword.trim()) {
state = state.copyWith(errorMessage: 'errorMessagePasswordsDontMatch');
return false;
}
if (password.length < 8){
if (password.length < 8) {
state = state.copyWith(errorMessage: 'errorPasswordMinLength');
return false;
}
if (!_upperRegex.hasMatch(password)) {
if (!upperRegex.hasMatch(password)) {
state = state.copyWith(errorMessage: 'errorPasswordUppercase');
return false;
}
if (!_digitRegex.hasMatch(password)) {
if (!digitRegex.hasMatch(password)) {
state = state.copyWith(errorMessage: 'errorPasswordDigits');
return false;
}
if (!_specialRegex.hasMatch(password)) {
if (!specialRegex.hasMatch(password)) {
state = state.copyWith(errorMessage: 'errorPasswordSpecial');
return false;
}
@@ -117,10 +105,7 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
}
ChangePasswordRequestEntity _toRequest() {
return ChangePasswordRequestEntity(
password: state.newPassword.trim(),
);
return ChangePasswordRequestEntity(password: state.newPassword.trim());
}
Future<void> submit() async {
@@ -128,20 +113,17 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
if (!_validateForm()) return;
try {
state = state.copyWith(
isLoading: true,
isComplete: false
);
state = state.copyWith(isLoading: true, isComplete: false);
final user = await ref.read(userInfoProvider.future);
final request = _toRequest();
await _changePasswordUseCase.changePassword(userId: user.id, request: request);
state = state.copyWith(
isLoading: false,
isComplete: true
await _changePasswordUseCase.changePassword(
userId: user.id,
request: request,
);
state = state.copyWith(isLoading: false, isComplete: true);
} catch (e) {
if (!ref.mounted) return;
_finishWithError(message: e.toString());
@@ -163,6 +145,5 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
repeatPasswordController.removeListener(_onRepeatPasswordChanged);
repeatPasswordController.dispose();
}
}
}

View File

@@ -7,18 +7,13 @@ import 'package:navigation/navigation_contract.dart';
import 'package:sf_localizations/sf_localizations.dart';
import 'package:utils/utils.dart';
class ConfirmDialog extends ConsumerWidget{
class ConfirmDialog extends ConsumerWidget {
final NavigationContract navigationContract;
const ConfirmDialog({
super.key,
required this.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);
@@ -36,16 +31,16 @@ class ConfirmDialog extends ConsumerWidget{
theme: theme,
toggleDeleteDevice: viewModel.toggleDeleteDevice,
deviceNames: state.deviceNames,
onCancel: (){
onCancel: () {
viewModel.resetConfirmStep();
Navigator.pop(context);
},
onSubmit: () async {
viewModel.deleteAccount();
if (!context.mounted) return;
final isComplete = ref.read(
deleteAccountViewModelProvider.select((s)=>s.isComplete)
deleteAccountViewModelProvider.select((s) => s.isComplete),
);
if (isComplete) {
navigationContract.goTo(AppRoutes.login);
@@ -59,7 +54,6 @@ class ConfirmDialog extends ConsumerWidget{
}
class _VerifyAccountStep extends StatelessWidget {
final String email;
final TextEditingController passwordController;
final String errorMessage;
@@ -88,26 +82,29 @@ class _VerifyAccountStep extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(context.translate(I18n.verifyAccount),
style: TextStyle(
fontWeight: FontWeight.w500
),
Text(
context.translate(I18n.verifyAccount),
style: TextStyle(fontWeight: FontWeight.w500),
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)),
Text('${context.translate(I18n.email)}: ${email}'),
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,
))
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)
@@ -122,32 +119,36 @@ class _VerifyAccountStep extends StatelessWidget {
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,
)),
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,
)),
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<String> deviceNames;
@@ -177,58 +178,68 @@ class _ConfirmRequestStep extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(height: SizeUtils.getByScreen(small: 14, big: 12)),
Text(context.translate(I18n.requestCancelTitle),
style: TextStyle(
fontWeight: FontWeight.w500
),
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<Widget>.generate(deviceNames.length, (int index) =>
CheckboxListTile(
contentPadding: EdgeInsets.zero,
title: Text(context.translate(I18n.deleteDeviceData,
args: {'name': deviceNames[index]}
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
Text(
context.translate(I18n.requestCancelBody),
style: TextStyle(height: 1.5),
),
style: TextStyle(height: 0),
SizedBox(height: SizeUtils.getByScreen(small: 12, big: 10)),
...List<Widget>.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);
},
),
),
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,
)),
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,
)),
Expanded(
child: PrimaryButton(
onPressed: onSubmit,
text: context.translate(I18n.confirm),
color: theme.getColorFor(ThemeCode.legacyPrimary),
height: 50,
radius: 25,
),
),
],
)
),
],
),
);
}
}
}

View File

@@ -9,7 +9,7 @@ import 'package:utils/utils.dart';
class EditLinkedDeviceScreen extends ConsumerWidget {
const EditLinkedDeviceScreen();
const EditLinkedDeviceScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -100,6 +100,7 @@ class _SaveSection extends ConsumerWidget{
PrimaryButton(
onPressed: () async {
await vm.updateDevice();
if (!context.mounted) return;
final errorMessage = ref.read(
linkedDevicesViewModelProvider.select((s) => s.errorMessage)

View File

@@ -13,8 +13,9 @@ class DeleteDeviceDialog extends ConsumerWidget {
final DeviceEntity device;
const DeleteDeviceDialog({
super.key,
required this.navigationContract,
required this.device
required this.device,
});
@override
@@ -51,6 +52,7 @@ class DeleteDeviceDialog extends ConsumerWidget {
Expanded(child: PrimaryButton(
onPressed: () async {
await vm.deleteDevice(device);
if (!context.mounted) return;
final isComplete = ref.read(
linkedDevicesViewModelProvider.select((s)=>s.isComplete)

View File

@@ -1,5 +1,6 @@
name: account
description: "A new Flutter project."
publish_to: 'none'
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43

View File

@@ -1,3 +1,5 @@
// ignore_for_file: non_constant_identifier_names
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:control_panel/src/core/domain/entities/address_entity.dart';
import 'package:control_panel/src/core/domain/entities/network_entity.dart';
@@ -7,7 +9,8 @@ part 'latest_positions_response_model.freezed.dart';
part 'latest_positions_response_model.g.dart';
@freezed
abstract class LatestPositionsResponseModel with _$LatestPositionsResponseModel {
abstract class LatestPositionsResponseModel
with _$LatestPositionsResponseModel {
const factory LatestPositionsResponseModel({
required List<LatestPositionsItemResponseModel> items,
}) = _LatestPositionsResponseModel;
@@ -40,37 +43,43 @@ abstract class LatestPositionsItemResponseModel
required bool frequentPlace,
}) = _LatestPositionsItemResponseModel;
factory LatestPositionsItemResponseModel.fromJson(Map<String, dynamic> json) =>
_$LatestPositionsItemResponseModelFromJson(json);
factory LatestPositionsItemResponseModel.fromJson(
Map<String, dynamic> json,
) => _$LatestPositionsItemResponseModelFromJson(json);
}
extension LatestPositionsResponseModelMapper on LatestPositionsResponseModel {
List<PositionEntity> toEntity() {
return items.map((LatestPositionsItemResponseModel item) => PositionEntity(
id: item.id,
deviceIdentificator: item.deviceIdentificator,
latitude: item.latitude,
longitude: item.longitude,
hpe: item.hpe,
ncell: item.ncell,
type: item.type,
steps: item.steps,
address: item.address?.toEntity(),
createdAt: item.createdAt,
positionDate: item.positionDate,
positionDateOriginal: item.positionDateOriginal,
frequentPlaceName: item.frequentPlaceName,
message: item.message,
networks: item.networks.map((n)=>n.toEntity()).toList(),
ignore: item.ignore,
suspect: item.suspect,
frequentPlace: item.frequentPlace,
)).toList();
return items
.map(
(LatestPositionsItemResponseModel item) => PositionEntity(
id: item.id,
deviceIdentificator: item.deviceIdentificator,
latitude: item.latitude,
longitude: item.longitude,
hpe: item.hpe,
ncell: item.ncell,
type: item.type,
steps: item.steps,
address: item.address?.toEntity(),
createdAt: item.createdAt,
positionDate: item.positionDate,
positionDateOriginal: item.positionDateOriginal,
frequentPlaceName: item.frequentPlaceName,
message: item.message,
networks: item.networks.map((n) => n.toEntity()).toList(),
ignore: item.ignore,
suspect: item.suspect,
frequentPlace: item.frequentPlace,
),
)
.toList();
}
}
@freezed
abstract class LatestPositionsAddressResponseModel with _$LatestPositionsAddressResponseModel {
abstract class LatestPositionsAddressResponseModel
with _$LatestPositionsAddressResponseModel {
const factory LatestPositionsAddressResponseModel({
String? street,
String? city,
@@ -79,11 +88,13 @@ abstract class LatestPositionsAddressResponseModel with _$LatestPositionsAddress
String? country,
}) = _LatestPositionsAddressResponseModel;
factory LatestPositionsAddressResponseModel.fromJson(Map<String, dynamic> json) =>
_$LatestPositionsAddressResponseModelFromJson(json);
factory LatestPositionsAddressResponseModel.fromJson(
Map<String, dynamic> json,
) => _$LatestPositionsAddressResponseModelFromJson(json);
}
extension LatestPositionsAddressResponseModelMapper on LatestPositionsAddressResponseModel {
extension LatestPositionsAddressResponseModelMapper
on LatestPositionsAddressResponseModel {
AddressEntity toEntity() {
return AddressEntity(
street: street,
@@ -96,23 +107,22 @@ extension LatestPositionsAddressResponseModelMapper on LatestPositionsAddressRes
}
@freezed
abstract class LatestPositionsNetworkResponseModel with _$LatestPositionsNetworkResponseModel {
abstract class LatestPositionsNetworkResponseModel
with _$LatestPositionsNetworkResponseModel {
const factory LatestPositionsNetworkResponseModel({
required String SSID,
required String BSSID,
required String signal,
}) = _LatestPositionsNetworkResponseModel;
factory LatestPositionsNetworkResponseModel.fromJson(Map<String, dynamic> json) =>
_$LatestPositionsNetworkResponseModelFromJson(json);
factory LatestPositionsNetworkResponseModel.fromJson(
Map<String, dynamic> json,
) => _$LatestPositionsNetworkResponseModelFromJson(json);
}
extension LatestPositionsNetworkResponseModelMapper on LatestPositionsNetworkResponseModel {
extension LatestPositionsNetworkResponseModelMapper
on LatestPositionsNetworkResponseModel {
NetworkEntity toEntity() {
return NetworkEntity(
SSID: SSID,
BSSID: BSSID,
signal: signal,
);
return NetworkEntity(SSID: SSID, BSSID: BSSID, signal: signal);
}
}
}

View File

@@ -1,3 +1,5 @@
// ignore_for_file: non_constant_identifier_names
import 'package:freezed_annotation/freezed_annotation.dart';
part 'network_entity.freezed.dart';

View File

@@ -1,3 +1 @@
library customer_service;
export 'src/customer_service_builder.dart';

View File

@@ -23,24 +23,26 @@ class ContactScreen extends ConsumerWidget {
title: context.translate(I18n.contactTitle),
body: Padding(
padding: EdgeInsets.symmetric(
horizontal: SizeUtils.getByScreen(small: 38, big: 36)
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(),
],
),
),
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),
);
@@ -48,12 +50,10 @@ class ContactScreen extends ConsumerWidget {
}
class _CountrySection extends ConsumerWidget {
const _CountrySection();
@override
Widget build(BuildContext context, WidgetRef ref) {
final List<String> countries = [
'España',
'Portugal',
@@ -66,20 +66,20 @@ class _CountrySection extends ConsumerWidget {
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)
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<String> channels = [
context.translate(I18n.channelOnline),
context.translate(I18n.channelAmazon),
@@ -90,20 +90,20 @@ class _ChannelSection extends ConsumerWidget {
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)
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(
@@ -114,12 +114,10 @@ class _NameSection extends ConsumerWidget {
}
class _EmailSection extends ConsumerWidget {
const _EmailSection();
@override
Widget build(BuildContext context, WidgetRef ref) {
final vm = ref.read(contactViewModelProvider.notifier);
return CustomTextField(
@@ -131,12 +129,10 @@ class _EmailSection extends ConsumerWidget {
}
class _SubjectSection extends ConsumerWidget {
const _SubjectSection();
@override
Widget build(BuildContext context, WidgetRef ref) {
final vm = ref.read(contactViewModelProvider.notifier);
return CustomTextField(
@@ -147,16 +143,12 @@ class _SubjectSection extends ConsumerWidget {
}
class _MessageSection extends ConsumerWidget {
final VoidCallback onSubmit;
const _MessageSection({
required this.onSubmit,
});
const _MessageSection({required this.onSubmit});
@override
Widget build(BuildContext context, WidgetRef ref) {
final vm = ref.read(contactViewModelProvider.notifier);
return CustomTextField(
@@ -170,12 +162,10 @@ class _MessageSection extends ConsumerWidget {
}
class _ErrorMessageSection extends ConsumerWidget {
const _ErrorMessageSection();
@override
Widget build(BuildContext context, WidgetRef ref) {
final viewState = ref.watch(contactViewModelProvider);
if (viewState.errorMessage.isNotEmpty) {
@@ -192,34 +182,31 @@ class _ErrorMessageSection extends ConsumerWidget {
),
],
);
} else return SizedBox.shrink();
} else {
return SizedBox.shrink();
}
}
}
class _SendSection extends ConsumerWidget {
final VoidCallback onSend;
const _SendSection({
required this.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)
big: EdgeInsets.symmetric(horizontal: 36, vertical: 12),
),
child: PrimaryButton(
onPressed: onSend,
text: context.translate(I18n.sendEmail),
color: theme.getColorFor(ThemeCode.buttonPrimary)
)
color: theme.getColorFor(ThemeCode.buttonPrimary),
),
);
}
}
}

View File

@@ -1,5 +1,6 @@
name: customer_service
description: "A new Flutter project."
publish_to: 'none'
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43

View File

@@ -1,5 +1,3 @@
library functions;
export 'src/features/device_management/device_management_builder.dart';
export 'src/features/contacts/contacts_builder.dart';
export 'src/features/contacts/edit_contact_builder.dart';
@@ -12,4 +10,4 @@ export 'src/features/activity_meter/activity_meter_builder.dart';
export 'src/features/apps_use/apps_use_builder.dart';
export 'src/features/volume_control/volume_control_builder.dart';
export 'src/features/call_history/call_history_builder.dart';
export 'src/features/background_image/background_image_builder.dart';
export 'src/features/background_image/background_image_builder.dart';

View File

@@ -134,7 +134,7 @@ class _NewContactDialogState extends ConsumerState<NewContactDialog> {
name: _nameController.text,
phone: _phoneController.text,
);
if (success && mounted) Navigator.pop(context);
if (success && context.mounted) Navigator.pop(context);
},
text: context.translate(I18n.save),
color: theme.getColorFor(ThemeCode.legacyPrimary),

View File

@@ -3,7 +3,6 @@ import 'dart:async';
import 'package:device_management/src/core/providers/pictures_repository_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
import 'package:device_management/src/features/remote_connection/presentation/state/remote_connection_view_state.dart';
import 'package:legacy_shared/legacy_shared.dart';

View File

@@ -7,7 +7,7 @@ import 'package:device_management/src/features/remote_connection/presentation/st
import 'package:utils/utils.dart';
class ShowPictureDialog extends ConsumerWidget {
const ShowPictureDialog();
const ShowPictureDialog({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {

View File

@@ -7,7 +7,7 @@ import 'package:sf_localizations/sf_localizations.dart';
import 'package:utils/utils.dart';
class SpyCallDialog extends ConsumerWidget {
const SpyCallDialog();
const SpyCallDialog({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {

View File

@@ -1,5 +1,6 @@
name: device_management
description: "A new Flutter project."
publish_to: 'none'
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43

View File

@@ -1,5 +1,5 @@
import 'package:legacy_auth/src/core/data/models/two_fa_secret_response_model.dart';
import 'package:legacy_shared/src/utils/dio_error_mapper.dart';
import 'package:legacy_shared/legacy_shared.dart';
import 'package:sf_infrastructure/sf_infrastructure.dart';
import 'auth_remote_datasource.dart';

View File

@@ -1,5 +1,4 @@
import 'package:legacy_auth/src/core/data/datasource/device_setup_remote_datasource.dart';
import 'package:legacy_shared/src/utils/dio_error_mapper.dart';
import 'package:legacy_shared/legacy_shared.dart';
import 'package:sf_infrastructure/sf_infrastructure.dart';

View File

@@ -1,7 +1,7 @@
import 'package:sf_infrastructure/sf_infrastructure.dart';
import 'package:legacy_auth/src/core/data/datasource/login_remote_datasource.dart';
import 'package:legacy_auth/src/core/data/models/login_response_model.dart';
import 'package:legacy_shared/src/utils/dio_error_mapper.dart';
import 'package:legacy_shared/legacy_shared.dart';
class LegacyLoginRemoteDatasourceImpl implements LegacyLoginRemoteDatasource {
const LegacyLoginRemoteDatasourceImpl(this._repository);

View File

@@ -1,6 +1,6 @@
import 'package:legacy_auth/src/core/data/models/sign_up_request_model.dart';
import 'package:legacy_auth/src/core/data/models/sign_up_response_model.dart';
import 'package:legacy_shared/src/utils/dio_error_mapper.dart';
import 'package:legacy_shared/legacy_shared.dart';
import 'package:sf_infrastructure/sf_infrastructure.dart';
import 'sign_up_remote_datasource.dart';

View File

@@ -44,6 +44,7 @@ class LegacyScanWatchStepScreen extends ConsumerWidget {
MaterialPageRoute(builder: (_) => const LegacyQrScannerScreen()),
);
if (result == null || result.isEmpty) return;
if (!context.mounted) return;
vm.onWatchQrScanned(result);
showActivationCodeDialog(context);
},

View File

@@ -4,6 +4,7 @@ import 'package:legacy_auth/src/features/link_phone/domain/use_cases/link_phone_
class LegacyLinkPhoneUseCaseImpl implements LegacyLinkPhoneUseCase {
LegacyLinkPhoneUseCaseImpl(this._repository);
// ignore: unused_field
final LegacyAuthRepository _repository;
@override

View File

@@ -117,6 +117,7 @@ class LegacyRequestRecoveryScreen extends ConsumerWidget {
child: PrimaryButton(
onPressed: () async {
await viewModel.requestRecovery();
if (!context.mounted) return;
final updatedState = ref.read(
legacyRecoverPasswordViewModelProvider,
);

View File

@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:legacy_auth/src/core/domain/repositories/sign_up_repository.dart';
import 'package:legacy_auth/src/core/providers/sign_up_repository_provider.dart';
import 'package:legacy_shared/src/utils/dio_error_mapper.dart';
import 'package:legacy_shared/legacy_shared.dart';
import 'package:legacy_auth/src/core/utils/text_format_utils.dart';
import 'package:legacy_auth/src/features/sign_up/domain/entities/address_entity.dart';
import 'package:legacy_auth/src/features/sign_up/domain/entities/sign_up_request_entity.dart';
@@ -90,8 +90,6 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
repeatPasswordController = TextEditingController(text: s.repeatPassword);
}
void _syncField(
String text, {
required String current,
@@ -107,14 +105,9 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
required LegacyAddressViewState Function() updateAddress,
}) {
if (text == current) return;
state = state.copyWith(
address: updateAddress(),
errorMessage: '',
);
state = state.copyWith(address: updateAddress(), errorMessage: '');
}
void _addListeners() {
firstNameController.addListener(_onFirstNameChanged);
lastNameController.addListener(_onLastNameChanged);
@@ -144,10 +137,8 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
_syncField(
firstNameController.text,
current: state.firstName,
update: () => state.copyWith(
firstName: firstNameController.text,
errorMessage: '',
),
update: () =>
state.copyWith(firstName: firstNameController.text, errorMessage: ''),
);
}
@@ -156,10 +147,8 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
_syncField(
lastNameController.text,
current: state.lastName,
update: () => state.copyWith(
lastName: lastNameController.text,
errorMessage: '',
),
update: () =>
state.copyWith(lastName: lastNameController.text, errorMessage: ''),
);
}
@@ -176,22 +165,22 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
}
void _onDocumentTypeChanged() => _syncField(
documentTypeController.text,
current: state.documentType,
update: () => state.copyWith(
documentType: documentTypeController.text,
errorMessage: '',
),
);
documentTypeController.text,
current: state.documentType,
update: () => state.copyWith(
documentType: documentTypeController.text,
errorMessage: '',
),
);
void _onRelationshipChanged() => _syncField(
relationshipController.text,
current: state.relationType,
update: () => state.copyWith(
relationType: relationshipController.text,
errorMessage: '',
),
);
relationshipController.text,
current: state.relationType,
update: () => state.copyWith(
relationType: relationshipController.text,
errorMessage: '',
),
);
void _onPlaceOfBirthChanged() {
toCapitalizedController(placeOfBirthController);
@@ -206,13 +195,13 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
}
void _onBirthCountryChanged() => _syncField(
birthCountryController.text,
current: state.birthCountry,
update: () => state.copyWith(
birthCountry: birthCountryController.text,
errorMessage: '',
),
);
birthCountryController.text,
current: state.birthCountry,
update: () => state.copyWith(
birthCountry: birthCountryController.text,
errorMessage: '',
),
);
void _onPhoneChanged() {
final text = phoneController.text;
@@ -325,11 +314,11 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
}
void _onAddressCountryChanged() => _syncAddressField(
addressCountryController.text,
current: state.address.country,
updateAddress: () =>
state.address.copyWith(country: addressCountryController.text),
);
addressCountryController.text,
current: state.address.country,
updateAddress: () =>
state.address.copyWith(country: addressCountryController.text),
);
void _onAddressPostCodeChanged() {
final text = addressPostCodeController.text.trim();
@@ -353,8 +342,6 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
}
}
void next() {
if (state.isLoading) return;
@@ -386,8 +373,6 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
);
}
void updateDialCode(String dialCode) {
state = state.copyWith(dialCode: dialCode);
}
@@ -449,8 +434,6 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
state = state.copyWith(isShowPassword: !state.isShowPassword);
}
bool _validateStep0() {
final emailErr = emailErrorFor(state.email);
final phoneErr = phoneErrorFor(state.phone);
@@ -544,8 +527,6 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
bool _validateForm() =>
_validateStep0() && _validateStep1() && _validateStep2();
Future<bool> signUp() async {
if (state.isLoading) return false;
if (!_validateForm()) return false;
@@ -573,13 +554,11 @@ class LegacySignUpViewModel extends Notifier<LegacySignUpViewState>
if (!ref.mounted) return false;
final msg = formatErrorMessage(e);
final errorMsg =
msg == 'BadRequest' ? I18n.errorEmailAlreadyRegistered : msg;
final errorMsg = msg == 'BadRequest'
? I18n.errorEmailAlreadyRegistered
: msg;
state = state.copyWith(
isLoading: false,
errorMessage: errorMsg,
);
state = state.copyWith(isLoading: false, errorMessage: errorMsg);
return false;
}
}

View File

@@ -1,3 +1,5 @@
// ignore_for_file: non_constant_identifier_names
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:location/src/core/domain/entities/frequent_place_entity.dart';

View File

@@ -4,5 +4,6 @@ import 'package:sf_infrastructure/sf_infrastructure.dart';
class SettingsRemoteDatasourceImpl implements SettingsRemoteDatasource {
SettingsRemoteDatasourceImpl(this._repository);
// ignore: unused_field
final QuestiaRepository _repository;
}

View File

@@ -4,5 +4,6 @@ import 'package:settings/src/core/domain/repositories/settings_repository.dart';
class SettingsRepositoryImpl implements SettingsRepository {
const SettingsRepositoryImpl(this._remote);
// ignore: unused_field
final SettingsRemoteDatasource _remote;
}

View File

@@ -5,6 +5,7 @@ import 'shutdown_use_case.dart';
class ShutdownUseCaseImpl implements ShutdownUseCase {
ShutdownUseCaseImpl(this._repository);
// ignore: unused_field
final SettingsRepository _repository;
@override

View File

@@ -47,7 +47,6 @@ class _OptionsSection extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final state = ref.watch(remoteManagementViewModelProvider);
final vm = ref.read(remoteManagementViewModelProvider.notifier);
return SingleChildScrollView(
@@ -63,6 +62,7 @@ class _OptionsSection extends ConsumerWidget {
message: context.translate(I18n.remoteTurnOffConfirm),
onConfirm: () async {
await vm.shutdown();
if (!context.mounted) return;
final errorMessage = ref.read(
remoteManagementViewModelProvider.select((s)=>s.errorMessage)

View File

@@ -10,7 +10,8 @@ class ConfirmDialog extends ConsumerWidget {
final VoidCallback onConfirm;
const ConfirmDialog({
required this.title,
super.key, required this.title,
required this.message,
required this.onConfirm,
});

View File

@@ -6,6 +6,7 @@ class SyncClockUseCaseImpl implements SyncClockUseCase {
SyncClockUseCaseImpl(this._repository);
// ignore: unused_field
final SettingsRepository _repository;
@override

View File

@@ -1,4 +1,3 @@
import 'package:flutter/material.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'sync_clock_view_state.freezed.dart';

View File

@@ -37,6 +37,7 @@ class SyncClockScreen extends ConsumerWidget {
}
}
// ignore: unused_element
class _OptionsSection extends ConsumerWidget {
const _OptionsSection();

View File

@@ -1,5 +1,6 @@
name: settings
description: "A new Flutter project."
publish_to: 'none'
# The following defines the version and build number for your application.
# A version number is three numbers separated by dots, like 1.2.43

View File

@@ -1,5 +1,3 @@
library legacy_shared;
export 'src/providers/map_style_provider.dart';
export 'src/providers/selected_device_provider.dart';
export 'src/widgets/layouts/page_layout.dart';
@@ -17,4 +15,4 @@ export 'src/providers/commands_repository_provider.dart';
export 'src/domain/repositories/devices_repository.dart';
export 'src/providers/devices_repository_provider.dart';
export 'src/data/datasources/device_settings_update_datasource.dart';
export 'src/providers/device_settings_update_provider.dart';
export 'src/providers/device_settings_update_provider.dart';

View File

@@ -1,9 +1,7 @@
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;
@@ -12,6 +10,7 @@ class AppMenuButton extends StatelessWidget {
final Color color;
const AppMenuButton({
super.key,
required this.onPressed,
required this.icon,
this.negativeIcon = false,
@@ -22,43 +21,40 @@ class AppMenuButton extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TextButton(
onPressed: onPressed,
style: ButtonStyle(
overlayColor: WidgetStatePropertyAll(Color(0xFFF7F7F7))
overlayColor: WidgetStatePropertyAll(Color(0xFFF7F7F7)),
),
child: Row(
children: [
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
color: negativeIcon
? Colors.white
: color,
color: negativeIcon ? Colors.white : color,
),
height: SizeUtils.getByScreen(small: 52, big: 48),
width: SizeUtils.getByScreen(small: 52, big: 48),
child: Icon(icon,
child: Icon(
icon,
size: iconSize ?? SizeUtils.getByScreen(small: 52, big: 48),
color: negativeIcon
? color
: Colors.white,
color: negativeIcon ? color : Colors.white,
weight: 30,
),
),
SizedBox(width: SizeUtils.getByScreen(small: 16, big: 15)),
Expanded(
child: Text(text,
child: Text(
text,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 18, big: 19),
fontWeight: FontWeight.w500,
color: Color(0xFF4B4B4B)
)
)
)
color: Color(0xFF4B4B4B),
),
),
),
],
),
);
}
}
}

View File

@@ -9,7 +9,8 @@ class SectionButton extends StatelessWidget {
final Widget body;
const SectionButton({
required this.onPressed,
super.key, required this.onPressed,
required this.icon,
this.iconPadding,
required this.body,

View File

@@ -723,7 +723,7 @@ packages:
source: path
version: "0.0.1"
sf_localizations:
dependency: "direct overridden"
dependency: "direct main"
description:
path: "../../../../packages/sf_localizations"
relative: true

View File

@@ -1,5 +1,6 @@
name: legacy_shared
description: "A new Flutter project."
publish_to: 'none'
version: 0.0.1
homepage:
@@ -30,6 +31,7 @@ dependencies:
freezed: ^3.2.3
json_annotation: ^4.9.0
json_serializable: ^6.11.2
sf_localizations: ^0.0.1
dev_dependencies:
flutter_test:

View File

@@ -24,7 +24,6 @@ class ScanStrapAndWatchStepScreen extends ConsumerWidget {
final textPrimary = theme.getColorFor(ThemeCode.textPrimary);
final vm = ref.read(deviceSetupViewModelProvider.notifier);
final state = ref.watch(deviceSetupViewModelProvider);
return SingleChildScrollView(
child: Column(

View File

@@ -11,7 +11,6 @@ class SuccessStepScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
final state = ref.watch(deviceSetupViewModelProvider);
final vm = ref.read(deviceSetupViewModelProvider.notifier);
return Column(
mainAxisSize: MainAxisSize.max,

View File

@@ -4,6 +4,7 @@ import 'package:auth/src/features/link_phone/domain/use_cases/link_phone_use_cas
class LinkPhoneUseCaseImpl implements LinkPhoneUseCase {
LinkPhoneUseCaseImpl(this._repository);
// ignore: unused_field
final AuthRepository _repository;
@override

View File

@@ -312,6 +312,7 @@ class _SignInSection extends ConsumerWidget {
}
}
// ignore: unused_element
class _OrContinueWith extends StatelessWidget {
const _OrContinueWith({required this.theme});
final ThemePort theme;
@@ -334,6 +335,7 @@ class _OrContinueWith extends StatelessWidget {
}
}
// ignore: unused_element
class _SocialButtons extends ConsumerWidget {
const _SocialButtons({required this.theme});
final ThemePort theme;

View File

@@ -117,6 +117,7 @@ class RequestRecoveryScreen extends ConsumerWidget {
child: PrimaryButton(
onPressed: () async {
await viewModel.requestRecovery();
if (!context.mounted) return;
final updatedState = ref.read(
recoverPasswordViewModelProvider,
);

View File

@@ -28,11 +28,20 @@ class ExtractScreen extends ConsumerWidget {
ref.listen(extractViewModelProvider(childId), (prev, next) {
if (next.success && !(prev?.success ?? false)) {
showTopSnackbar(context, message: context.translate(I18n.walletMoveSuccess), type: MessageType.success);
showTopSnackbar(
context,
message: context.translate(I18n.walletMoveSuccess),
type: MessageType.success,
);
navigation.goBack();
}
if (next.errorMessage.isNotEmpty && next.errorMessage != (prev?.errorMessage ?? '')) {
showTopSnackbar(context, message: context.translate(I18n.walletMoveError), type: MessageType.error);
if (next.errorMessage.isNotEmpty &&
next.errorMessage != (prev?.errorMessage ?? '')) {
showTopSnackbar(
context,
message: context.translate(I18n.walletMoveError),
type: MessageType.error,
);
}
});
@@ -53,8 +62,37 @@ class ExtractScreen extends ConsumerWidget {
return WalletManagementLayout(
childName: childName,
balance: availableBalance,
cardColors: cardColorsFor(theme: theme, carrierGenre: viewState.device?.carrierGenre, cardStatus: cardStatus),
cardColors: cardColorsFor(
theme: theme,
carrierGenre: viewState.device?.carrierGenre,
cardStatus: cardStatus,
),
navigation: navigation,
footer: FooterContainer(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
primaryColor: theme.getColorFor(ThemeCode.buttonPrimary),
primaryText: viewState.isSubmitting
? context.translate(I18n.walletMoveProcessing)
: context.translate(I18n.sendMessageAndBlock),
onPrimaryPressed: viewState.isSubmitting
? null
: () {
final amount = double.tryParse(
viewModel.amountController.text.trim(),
);
if (amount == null || amount <= 0) {
showTopSnackbar(
context,
message: context.translate(I18n.walletMoveAmountRequired),
type: MessageType.warning,
);
return;
}
viewModel.submit();
},
cancelText: context.translate(I18n.cancel),
onCancelPressed: () => navigation.goBack(),
),
children: [
SectionContainer(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
@@ -95,9 +133,10 @@ class ExtractScreen extends ConsumerWidget {
context.translate(
I18n.allowanceBalanceAfter,
args: {
'amount': (availableBalance -
(double.tryParse(viewState.amount) ?? 0))
.toStringAsFixed(2),
'amount':
(availableBalance -
(double.tryParse(viewState.amount) ?? 0))
.toStringAsFixed(2),
},
),
),
@@ -131,7 +170,10 @@ class ExtractScreen extends ConsumerWidget {
Align(
alignment: Alignment.topLeft,
child: Text(
context.translate(I18n.extractMessageLabel, args: {'name': childName}),
context.translate(
I18n.extractMessageLabel,
args: {'name': childName},
),
style: TextStyle(fontSize: 14, letterSpacing: 0),
),
),
@@ -146,7 +188,10 @@ class ExtractScreen extends ConsumerWidget {
children: [
Icon(Icons.info_outline, size: 16),
Text(
context.translate(I18n.allowanceMaxChars, args: {'count': '150'}),
context.translate(
I18n.allowanceMaxChars,
args: {'count': '150'},
),
style: TextStyle(fontSize: 14, letterSpacing: 0),
),
],
@@ -156,25 +201,6 @@ class ExtractScreen extends ConsumerWidget {
],
),
],
footer: FooterContainer(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
primaryColor: theme.getColorFor(ThemeCode.buttonPrimary),
primaryText: viewState.isSubmitting
? context.translate(I18n.walletMoveProcessing)
: context.translate(I18n.sendMessageAndBlock),
onPrimaryPressed: viewState.isSubmitting
? null
: () {
final amount = double.tryParse(viewModel.amountController.text.trim());
if (amount == null || amount <= 0) {
showTopSnackbar(context, message: context.translate(I18n.walletMoveAmountRequired), type: MessageType.warning);
return;
}
viewModel.submit();
},
cancelText: context.translate(I18n.cancel),
onCancelPressed: () => navigation.goBack(),
),
);
}
}

View File

@@ -44,8 +44,13 @@ class GoalsScreen extends ConsumerWidget {
return WalletManagementLayout(
childName: childName,
balance: availableBalance,
cardColors: cardColorsFor(theme: theme, carrierGenre: viewState.device?.carrierGenre, cardStatus: cardStatus),
cardColors: cardColorsFor(
theme: theme,
carrierGenre: viewState.device?.carrierGenre,
cardStatus: cardStatus,
),
navigation: navigation,
footer: Container(),
children: [
SectionContainer(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
@@ -86,7 +91,6 @@ class GoalsScreen extends ConsumerWidget {
childId: childId,
),
],
footer: Container(),
);
}
}
@@ -123,7 +127,7 @@ class SavingsBlockState extends ConsumerState<SavingsBlock> {
Widget build(BuildContext context) {
final theme = ref.watch(themePortProvider);
var emptyBlock = ({fullPlan}) => Container(
Container emptyBlock({fullPlan}) => Container(
padding: EdgeInsets.all(24),
decoration: BoxDecoration(
color: theme.getColorFor(ThemeCode.backgroundPrimary),
@@ -213,7 +217,7 @@ class SavingsBlockState extends ConsumerState<SavingsBlock> {
),
);
var editBlock = ({create, index}) => Column(
Column editBlock({create, index}) => Column(
spacing: 24,
children: [
CustomTextField(
@@ -292,7 +296,10 @@ class SavingsBlockState extends ConsumerState<SavingsBlock> {
children: [
Icon(Icons.info_outline, size: 16),
Text(
context.translate(I18n.allowanceMaxChars, args: {'count': '150'}),
context.translate(
I18n.allowanceMaxChars,
args: {'count': '150'},
),
style: TextStyle(fontSize: 14, letterSpacing: 0),
),
],
@@ -492,7 +499,9 @@ class SavingsBlockState extends ConsumerState<SavingsBlock> {
ThemeCode.textSecondary,
),
),
Center(child: Text(context.translate(I18n.goalsSaved))),
Center(
child: Text(context.translate(I18n.goalsSaved)),
),
if (!showAdd[index])
TextButton(
style: ButtonStyle(
@@ -637,7 +646,7 @@ class TasksBlockState extends ConsumerState<TasksBlock> {
final theme = ref.watch(themePortProvider);
final viewModel = ref.read(goalsViewModelProvider(widget.childId).notifier);
final emptyBlock = ({fullPlan}) => Container(
Container emptyBlock({fullPlan}) => Container(
padding: EdgeInsets.all(24),
decoration: BoxDecoration(
color: theme.getColorFor(ThemeCode.backgroundPrimary),
@@ -818,7 +827,9 @@ class TasksBlockState extends ConsumerState<TasksBlock> {
children: [
Expanded(
child: Text(
context.translate(I18n.goalsRewardForCompletion),
context.translate(
I18n.goalsRewardForCompletion,
),
style: TextStyle(
fontSize: 16,
letterSpacing: 0,
@@ -854,14 +865,18 @@ class TasksBlockState extends ConsumerState<TasksBlock> {
Align(
alignment: Alignment.topLeft,
child: Text(
context.translate(I18n.goalsTasksCompletedMessagePrefix),
context.translate(
I18n.goalsTasksCompletedMessagePrefix,
),
style: TextStyle(fontSize: 14, letterSpacing: 0),
),
),
Align(
alignment: Alignment.topLeft,
child: Text(
context.translate(I18n.goalsTasksCompletedMessage),
context.translate(
I18n.goalsTasksCompletedMessage,
),
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,

View File

@@ -188,17 +188,13 @@ class WalletItem extends ConsumerWidget {
Widget _buildGenderAvatar(String? carrierGenre, double size) {
final IconData icon;
final Color color;
switch (carrierGenre) {
case 'M':
icon = Icons.face;
color = const Color(0xFF64B5F6);
case 'F':
icon = Icons.face_3;
color = const Color(0xFFF48FB1);
default:
icon = Icons.face_2;
color = const Color(0xFF90A4AE);
}
return CircleAvatar(
radius: size / 2,
@@ -209,6 +205,8 @@ class WalletItem extends ConsumerWidget {
}
class PhotoDialog extends ConsumerWidget {
const PhotoDialog({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);

View File

@@ -20,6 +20,7 @@ dependencies:
path: ../../packages/sf_infrastructure
sf_shared:
path: ../../packages/sf_shared
shared_preferences: ^2.5.5
dev_dependencies:
flutter_test:
sdk: flutter