Fix translations and icons

Added page layout to customer service screens
This commit is contained in:
2026-02-16 11:20:33 +01:00
parent e581895246
commit f76a88a53c
9 changed files with 236 additions and 233 deletions

View File

@@ -2,26 +2,11 @@ import 'package:customer_service/src/presentation/state/contact_view_model.dart'
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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';
const Map<String, String> country = <String, String>{
'SPAIN': 'España',
'PORTUGAL': 'Portugal',
'FRANCE': 'France',
'ITALIA': 'Italia',
'GERMANY': 'Deutschland',
'OTHER': I18n.other,
};
const Map<String, String> channel = <String, String>{
'ONLINE_SHOP': I18n.channelOnline,
'AMAZON': I18n.channelAmazon,
'STORE': I18n.channelStore,
'OTHER': I18n.other,
};
class ContactScreen extends ConsumerWidget {
final NavigationContract navigationContract;
@@ -34,87 +19,88 @@ class ContactScreen extends ConsumerWidget {
final vm = ref.read(contactViewModelProvider.notifier);
final viewState = ref.watch(contactViewModelProvider);
return Scaffold(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
body: SafeArea(
child: Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 38, vertical: 14),
big: EdgeInsets.symmetric(horizontal: 36, vertical: 12)
),
child: SingleChildScrollView(
child: Column(
children: [
Stack(
children: [
SizedBox(
height: SizeUtils.getByScreen(small: 36, big: 36),
child: Align(
alignment: Alignment.centerLeft,
child: Icon(Icons.arrow_back, size: SizeUtils.getByScreen(small: 36, big: 34))
)
),
Center(child: Text(context.translate(I18n.contactTitle),
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 28, big: 27))))
],
final List<String> country = [
'España',
'Portugal',
'France',
'Italia',
'Deutschland',
context.translate(I18n.other),
];
final List<String> channel = [
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,
),
SizedBox(height: SizeUtils.getByScreen(small: 40, big: 38)),
CustomDropdown(
items: country.values.map(Text.new).toList(growable: false),
values: country.keys.toList(),
onChanged: (x){vm.setCountry(x);},
hint: 'Choose your country'
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomDropdown(
items: channel.values.map(Text.new).toList(growable: false),
values: channel.keys.toList(),
onChanged: (x){vm.setChannel(x);},
hint: 'Purchase channel'
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomTextField(
controller: vm.nameController,
hint: 'Enter your name',
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomTextField(
controller: vm.emailController,
keyboardType: TextInputType.emailAddress,
hint: 'Enter your email',
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomTextField(
controller: vm.subjectController,
hint: 'Your message subject',
),
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 17)),
CustomTextField(
controller: vm.bodyController,
keyboardType: TextInputType.multiline,
hint: 'Your message',
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,
),
),
],
SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)),
PrimaryButton(
onPressed: vm.sendEmail,
text: 'Send!',
color: theme.getColorFor(ThemeCode.buttonPrimary)
)
],
)
)
),
],
],
)),
),
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)
)
),
);

View File

@@ -2,6 +2,7 @@ import 'package:customer_service/src/presentation/contact_screen.dart';
import 'package:design_system/design_system.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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';
@@ -14,80 +15,66 @@ class CustomerServiceScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final theme = ref.watch(themePortProvider);
// final theme = ref.watch(themePortProvider);
return Scaffold(
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
body: SafeArea(
child: Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 18, vertical: 14),
big: EdgeInsets.symmetric(horizontal: 16, vertical: 12)
),
child: Column(
children: [
Stack(
children: [
SizedBox(
height: SizeUtils.getByScreen(small: 36, big: 36),
child: Align(
alignment: Alignment.centerLeft,
child: Icon(Icons.arrow_back, size: SizeUtils.getByScreen(small: 36, big: 34))
)
),
Center(child: Text(context.translate(I18n.customerService),
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 28, big: 27))))
],
),
SizedBox(height: SizeUtils.getByScreen(small: 40, big: 38)),
AppSectionButton(
onPressed: () async {
final Uri url = Uri.parse('https://www.savefamilygps.com/');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
icon: Icons.sunny,
text: "Visit our Website"
),
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)),
AppSectionButton(
onPressed: () async {
final Uri url = Uri.parse('https://savefamilygpshelp.zendesk.com/hc/es');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
icon: Icons.handshake_outlined,
text: "Can we help you?"
),
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)),
AppSectionButton(
return PageLayout(
title: context.translate(I18n.customerService),
body: Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 18),
big: EdgeInsets.symmetric(horizontal: 16)
),
child: Column(
children: [
SectionButton(
onPressed: () async {
final Uri url = Uri.parse('https://www.savefamilygps.com/');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
image: 'assets/images/ui/iso_sf.png',
text: context.translate(I18n.supportWebsite)
),
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)),
SectionButton(
onPressed: () async {
final Uri url = Uri.parse('https://savefamilygpshelp.zendesk.com/hc/es');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
icon: SFIcons.handshake,
text: context.translate(I18n.supportHelp)
),
SizedBox(height: SizeUtils.getByScreen(small: 10, big: 9)),
SectionButton(
onPressed: (){Navigator.push(context,
MaterialPageRoute(
builder: (_) => ContactScreen(navigationContract: navigationContract),
));},
MaterialPageRoute(
builder: (_) => ContactScreen(navigationContract: navigationContract),
));},
icon: Icons.email_outlined,
text: context.translate(I18n.contactTitle)
),
],
)
),
],
)
),
)
);
}
}
class AppSectionButton extends ConsumerWidget {
class SectionButton extends ConsumerWidget {
final GestureTapCallback onPressed;
final IconData icon;
final IconData? icon;
final String? image;
final String text;
const AppSectionButton({
const SectionButton({
required this.onPressed,
required this.icon,
this.icon,
this.image,
required this.text,
});
@@ -96,44 +83,49 @@ class AppSectionButton extends ConsumerWidget {
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),
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
)
)
),
],
),
)
),
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
)
)
),
],
),
)
);
}
}

View File

@@ -88,27 +88,37 @@ class ContactViewModel extends Notifier<ContactViewState> {
void _onBodyChanged() {
final text = bodyController.text;
if (text == state.body) return;
if (text == state.message) return;
state = state.copyWith(body: text, errorMessage: '');
state = state.copyWith(message: text, errorMessage: '');
}
void sendEmail() async {
final receiver = 'aitorarana@savefamilygps.com';
final receiver = 'info@savefamilygps.com';
//final name = state.name;
final name = state.name;
final country = state.country;
final channel = state.channel;
final sender = state.email;
final subject = state.subject;
final body = state.body;
final message = state.message;
if (sender.isEmpty) {
state = state.copyWith(errorMessage: I18n.errorEmailRequired);
return;
}
if (_isValidEmail(sender)) {
if (!_isValidEmail(sender)) {
state = state.copyWith(errorMessage: I18n.errorEmailInvalid);
return;
}
final body =
'country:$country\n'
'Purchase channel:$channel\n'
'name:$name\n'
'email:$sender\n'
'$message';
final Uri url = Uri.parse('mailto:$receiver?from=$sender&subject=$subject&body=$body');
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');

View File

@@ -10,7 +10,7 @@ abstract class ContactViewState with _$ContactViewState{
@Default('') String name,
@Default('') String email,
@Default('') String subject,
@Default('') String body,
@Default('') String message,
@Default('') String errorMessage,
@Default('') String emailError,
}) = _ContactViewState;

View File

@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
/// @nodoc
mixin _$ContactViewState {
String get country; String get channel; String get name; String get email; String get subject; String get body; String get errorMessage; String get emailError;
String get country; String get channel; String get name; String get email; String get subject; String get message; String get errorMessage; String get emailError;
/// Create a copy of ContactViewState
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@@ -25,16 +25,16 @@ $ContactViewStateCopyWith<ContactViewState> get copyWith => _$ContactViewStateCo
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactViewState&&(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)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.emailError, emailError) || other.emailError == emailError));
return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactViewState&&(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.message, message) || other.message == message)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.emailError, emailError) || other.emailError == emailError));
}
@override
int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,body,errorMessage,emailError);
int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,message,errorMessage,emailError);
@override
String toString() {
return 'ContactViewState(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, body: $body, errorMessage: $errorMessage, emailError: $emailError)';
return 'ContactViewState(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, message: $message, errorMessage: $errorMessage, emailError: $emailError)';
}
@@ -45,7 +45,7 @@ abstract mixin class $ContactViewStateCopyWith<$Res> {
factory $ContactViewStateCopyWith(ContactViewState value, $Res Function(ContactViewState) _then) = _$ContactViewStateCopyWithImpl;
@useResult
$Res call({
String country, String channel, String name, String email, String subject, String body, String errorMessage, String emailError
String country, String channel, String name, String email, String subject, String message, String errorMessage, String emailError
});
@@ -62,14 +62,14 @@ class _$ContactViewStateCopyWithImpl<$Res>
/// Create a copy of ContactViewState
/// 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,Object? errorMessage = null,Object? emailError = null,}) {
@pragma('vm:prefer-inline') @override $Res call({Object? country = null,Object? channel = null,Object? name = null,Object? email = null,Object? subject = null,Object? message = null,Object? errorMessage = null,Object? emailError = 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,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
as String,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
as String,
@@ -157,10 +157,10 @@ return $default(_that);case _:
/// }
/// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String country, String channel, String name, String email, String subject, String body, String errorMessage, String emailError)? $default,{required TResult orElse(),}) {final _that = this;
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String country, String channel, String name, String email, String subject, String message, String errorMessage, String emailError)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) {
case _ContactViewState() when $default != null:
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body,_that.errorMessage,_that.emailError);case _:
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.message,_that.errorMessage,_that.emailError);case _:
return orElse();
}
@@ -178,10 +178,10 @@ return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject
/// }
/// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String country, String channel, String name, String email, String subject, String body, String errorMessage, String emailError) $default,) {final _that = this;
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String country, String channel, String name, String email, String subject, String message, String errorMessage, String emailError) $default,) {final _that = this;
switch (_that) {
case _ContactViewState():
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body,_that.errorMessage,_that.emailError);case _:
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.message,_that.errorMessage,_that.emailError);case _:
throw StateError('Unexpected subclass');
}
@@ -198,10 +198,10 @@ return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject
/// }
/// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String country, String channel, String name, String email, String subject, String body, String errorMessage, String emailError)? $default,) {final _that = this;
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String country, String channel, String name, String email, String subject, String message, String errorMessage, String emailError)? $default,) {final _that = this;
switch (_that) {
case _ContactViewState() when $default != null:
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.body,_that.errorMessage,_that.emailError);case _:
return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject,_that.message,_that.errorMessage,_that.emailError);case _:
return null;
}
@@ -213,7 +213,7 @@ return $default(_that.country,_that.channel,_that.name,_that.email,_that.subject
class _ContactViewState implements ContactViewState {
const _ContactViewState({this.country = '', this.channel = '', this.name = '', this.email = '', this.subject = '', this.body = '', this.errorMessage = '', this.emailError = ''});
const _ContactViewState({this.country = '', this.channel = '', this.name = '', this.email = '', this.subject = '', this.message = '', this.errorMessage = '', this.emailError = ''});
@override@JsonKey() final String country;
@@ -221,7 +221,7 @@ class _ContactViewState implements ContactViewState {
@override@JsonKey() final String name;
@override@JsonKey() final String email;
@override@JsonKey() final String subject;
@override@JsonKey() final String body;
@override@JsonKey() final String message;
@override@JsonKey() final String errorMessage;
@override@JsonKey() final String emailError;
@@ -235,16 +235,16 @@ _$ContactViewStateCopyWith<_ContactViewState> get copyWith => __$ContactViewStat
@override
bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactViewState&&(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)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.emailError, emailError) || other.emailError == emailError));
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactViewState&&(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.message, message) || other.message == message)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.emailError, emailError) || other.emailError == emailError));
}
@override
int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,body,errorMessage,emailError);
int get hashCode => Object.hash(runtimeType,country,channel,name,email,subject,message,errorMessage,emailError);
@override
String toString() {
return 'ContactViewState(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, body: $body, errorMessage: $errorMessage, emailError: $emailError)';
return 'ContactViewState(country: $country, channel: $channel, name: $name, email: $email, subject: $subject, message: $message, errorMessage: $errorMessage, emailError: $emailError)';
}
@@ -255,7 +255,7 @@ abstract mixin class _$ContactViewStateCopyWith<$Res> implements $ContactViewSta
factory _$ContactViewStateCopyWith(_ContactViewState value, $Res Function(_ContactViewState) _then) = __$ContactViewStateCopyWithImpl;
@override @useResult
$Res call({
String country, String channel, String name, String email, String subject, String body, String errorMessage, String emailError
String country, String channel, String name, String email, String subject, String message, String errorMessage, String emailError
});
@@ -272,14 +272,14 @@ class __$ContactViewStateCopyWithImpl<$Res>
/// Create a copy of ContactViewState
/// 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,Object? errorMessage = null,Object? emailError = null,}) {
@override @pragma('vm:prefer-inline') $Res call({Object? country = null,Object? channel = null,Object? name = null,Object? email = null,Object? subject = null,Object? message = null,Object? errorMessage = null,Object? emailError = null,}) {
return _then(_ContactViewState(
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,message: null == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
as String,emailError: null == emailError ? _self.emailError : emailError // ignore: cast_nullable_to_non_nullable
as String,

View File

@@ -23,18 +23,29 @@ class PageLayout extends StatelessWidget{
children: [
Container(
padding: SizeUtils.getByScreen(
small: EdgeInsets.symmetric(horizontal: 22, vertical: 10),
big: EdgeInsets.symmetric(horizontal: 21, vertical: 8)
small: EdgeInsets.fromLTRB(22, 20, 22, 0),
big: EdgeInsets.fromLTRB(21, 16, 21, 0),
),
child: Stack(
children: [
IconButton(onPressed: () {Navigator.pop(context);},
icon: Icon(Icons.arrow_back)),
Center(
child: Text(title,
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 28, big: 27)
),
icon: Icon(Icons.arrow_back,
color: Color(0xFF588EA5),
size: 32,
),
padding: EdgeInsets.zero,
),
SizedBox(
height: 50,
child: Center(
child: Text(title.toUpperCase(),
style: TextStyle(
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
fontWeight: FontWeight.w500,
letterSpacing: 0,
color: Color(0xFF588EA5)
),
)
)
)
],

View File

@@ -144,6 +144,8 @@
"channelAmazon": "Amazon",
"channelStore": "Physical store",
"other": "Other",
"supportWebsite": "Visit our Website",
"supportHelp": "Can we help you?",
"contactTitle": "Contact us",
"selectCountry": "Choose your country",
"selectChannel": "Purchase channel",
@@ -151,8 +153,7 @@
"enterEmail": "Enter your email",
"enterSubject": "Your message subject",
"enterMessage": "Your message",
"sendEmail": "Send!"
"chat": "Chat",
"sendEmail": "Send!",
"personalData": "Personal Data",
"addNewSF": "Add a new SaveFamily",
"linkedDevices": "Linked Devices",

View File

@@ -140,19 +140,20 @@
"home": "Inicio",
"location": "Mapa",
"chat": "Chat",
"channelOnline": "Tienda online SF",
"channelOnline": "Tienda online de SF",
"channelAmazon": "Amazon",
"channelStore": "Tienda física",
"other": "Otro",
"contactTitle": "Contacta con nosotros",
"supportWebsite": "Visita nuestro sitio web",
"supportHelp": "¿Podemos ayudarte?",
"contactTitle": "Contáctanos",
"selectCountry": "Selecciona tu país",
"selectChannel": "Caal de compra",
"selectChannel": "Canal de compra",
"enterName": "Introduce tu nombre",
"enterEmail": "Introduce tu correo electrónico",
"enterSubject": "Asunto del mensaje",
"enterMessage": "Tu mensaje",
"sendEmail": "!Enviar!"
"chat": "Chat",
"sendEmail": "Enviar",
"personalData": "Datos Personales",
"addNewSF": "Añadir un nuevo SaveFamily",
"linkedDevices": "Dispositivos vinculados",

View File

@@ -174,6 +174,8 @@ class I18n {
static const String channelAmazon = 'channelAmazon';
static const String channelStore = 'channelStore';
static const String other = 'other';
static const String supportWebsite = 'supportWebsite';
static const String supportHelp = 'supportHelp';
static const String contactTitle = 'contactTitle';
static const String selectCountry = 'selectCountry';
static const String selectChannel = 'selectChannel';