Skip to content

Commit

Permalink
fix: Contact us page (#129)
Browse files Browse the repository at this point in the history
## Description

- Complete Contacts Us form with form validation.
- Form internationalization in both French and English
- Solves issue #28 


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ] ✨ New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [x] 🗑️ Chore


## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read and ran all relevant commands as specififed in the Running
Tests section of the [Contributor Guide].
- [x] The title of the PR follows the [Conventional Commits] guideline
- [x] My local branch follows the naming standards in the [Deepsource
Branch Naming Convention] or [Biodiversity Branch Naming Convention]
- [x] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated `pubspec.yaml` with an appropriate new version according
to the [pub versioning philosophy],
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [ ] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [ ] All existing and new tests are passing.


[Contributor Guide]:
https://github.com/FlutterPlaza/.github/blob/main/CONTRIBUTING.md
[Conventional Commits]:
https://www.conventionalcommits.org/en/v1.0.0-beta.4/
[pub versioning philosophy]: https://dart.dev/tools/pub/versioning
[Biodiversity Branch Naming Convention]: https://bit.ly/3DyYSwM
[Deepsource Branch Naming Convention]: https://bit.ly/3Y08Gs4
  • Loading branch information
jeffrey0606 authored Mar 16, 2023
2 parents f839dcf + 3024645 commit a4b1b46
Show file tree
Hide file tree
Showing 17 changed files with 700 additions and 79 deletions.
4 changes: 4 additions & 0 deletions assets/fpb-assets/Cross.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/fpb-assets/email_success.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions lib/assets/fpb_svg.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ class SvgNames {
static String google = '${path}google.svg';
static String facebook = '${path}facebook.svg';
static String twitter = '${path}twitter.svg';
static String error = '${path}Cross.svg';
}
2 changes: 2 additions & 0 deletions lib/contact_us/contact_us_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'view/contact_us_screen.dart';
export 'view/contact_us_success_screen.dart';
163 changes: 163 additions & 0 deletions lib/contact_us/view/contact_us_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
// ignore_for_file: body_might_complete_normally_nullable

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:fpb/assets/fpb_svg.dart';
import 'package:fpb/contact_us/contact_us_screen.dart';
import 'package:fpb/contact_us/view/widgets/message_textfield.dart';
import 'package:fpb/core/presentation/widget/fpb_button.dart';
import 'package:fpb/core/presentation/widget/fpb_text_form_field.dart';
import 'package:fpb/core/shared/helpers/extensions.dart';
import 'package:fpb/l10n/l10n.dart';
import 'package:fpb/router/app_route.gr.dart';
import 'package:fpb/sign_in/view/sign_in_page.dart';

class ContactUsScreen extends StatefulWidget {
const ContactUsScreen({super.key});

@override
State<ContactUsScreen> createState() => _ContactUsScreenState();
}

class _ContactUsScreenState extends State<ContactUsScreen> {
final _formKey = GlobalKey<FormState>();
final nameController = TextEditingController();
final emailController = TextEditingController();
String errorText = '';
//IconData errorIcon;
double errorContainerHeight = 0.0;

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final theme = Theme.of(context);
//final style = theme.textTheme;

return LayoutBuilder(
builder: (context, box) {
return Scaffold(
resizeToAvoidBottomInset: true,
body: Stack(children: [
BubblesTopBackGround(
cts: box,
svgName: SvgNames.authBackground,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: box.maxHeight * .75,
width: box.maxWidth,
decoration: BoxDecoration(
color: theme.colorScheme.background,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Padding(
padding: EdgeInsets.only(
top: box.maxHeight * .025,
left: box.maxHeight * .025,
right: box.maxHeight * .025,
bottom: box.maxHeight * .005),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
PageTitle(
title: l10n.contactUsTitle,
box: box,
),
SizedBox(
height: 0.015 * box.maxHeight,
),
Flexible(
child: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: [
FpbTextFormField(
onChanged: (value) {
setState(() {});
},
textController: nameController,
label: l10n.contactUsNameTextFieldLabel,
hint: l10n.contactUsNameTextFieldHintText,
box: box,
validator: (val) {
if (val!.isEmpty) {
return 'Field is required';
} else if (val.isValidName) {
return null;
} else {
return l10n.contactUsNameErrorText;
}
},
),
SizedBox(
height: box.maxHeight * .03,
),
FpbTextFormField(
onChanged: (value) {
setState(() {});
},
textController: emailController,
label: l10n.signInEmailTextFieldLabel,
hint: l10n.signInEmailTextFieldHintText,
box: box,
validator: (val) {
if (val!.isEmpty) {
return 'Field is required';
} else if (val.isValidEmail) {
return null;
} else {
return l10n.contactUsEmailErrorText;
}
},
),
SizedBox(
height: box.maxHeight * .03,
),
MessageTextField(
theme: theme,
box: box,
validator: (val) {
if (val!.isEmpty) {
return 'Field is required';
} else if (val.length > 30 &&
val.length < 500) {
return null;
} else {
return l10n
.contactUsMessageTextFieldErrorText;
}
},
),
],
),
),
),
),
SizedBox(
height: box.maxHeight * .05,
),
FpbButton(
label: l10n.contactUsSubmitBtnLabel,
onTap: () {
if (_formKey.currentState!.validate()) {
context.router.push(
ContactUsSuccessRoute()
);
} else {}
})
]),
),
),
)
]));
},
);
}
}
79 changes: 79 additions & 0 deletions lib/contact_us/view/contact_us_success_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:fpb/assets/fpb_svg.dart';
import 'package:fpb/contact_us/view/widgets/contact_us_success_btn.dart';
import 'package:fpb/contact_us/view/widgets/contact_us_success_image.dart';
import 'package:fpb/contact_us/view/widgets/contact_us_success_texts.dart';
import 'package:fpb/l10n/l10n.dart';
import 'package:fpb/sign_in/view/sign_in_page.dart';

class ContactUsSuccessScreen extends StatelessWidget {
const ContactUsSuccessScreen({super.key, });

@override
Widget build(BuildContext context) {
final l10n = context.l10n;
final theme = Theme.of(context);
final style = theme.textTheme;
//final colors = theme.colorScheme;

return LayoutBuilder(
builder: (context, box){
return Scaffold(
resizeToAvoidBottomInset: false,
body: Stack(children: [
BubblesTopBackGround(
cts: box,
svgName: SvgNames.authBackground,
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
height: box.maxHeight * .75,
width: box.maxWidth,
decoration: BoxDecoration(
color: theme.colorScheme.background,
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Padding(
padding: EdgeInsets.only(
top: box.maxHeight * .025,
left: box.maxHeight * .025,
right: box.maxHeight * .025,
bottom: box.maxHeight * .005),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,

children: [
SizedBox(
height: box.maxHeight * .1,
),
ContactUsSuccessImageWidget(box: box),
SizedBox(
height: box.maxHeight * .0001,
),
ContactUsSuccessTexts(

l10n: l10n, style: style, box: box),
SizedBox(
height: box.maxHeight * .15,
),
ContactUsSuccessBtn(
style: style,
box: box,
backgroundColor: theme.colorScheme.background,
borderColor: theme.colorScheme.secondary,
text: l10n.contactUsSuccessBtnText,
textColor: theme.colorScheme.secondary,
)
],
),
),
))
]),
);
});
}
}
47 changes: 47 additions & 0 deletions lib/contact_us/view/widgets/contact_us_success_btn.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import 'package:flutter/material.dart';

class ContactUsSuccessBtn extends StatelessWidget {
const ContactUsSuccessBtn(
{super.key,
required this.style,
required this.box,
required this.backgroundColor,
required this.borderColor,
required this.text,
required this.textColor});

final TextTheme style;
final BoxConstraints box;
final Color textColor;
final Color backgroundColor;
final String text;
final Color borderColor;

@override
Widget build(BuildContext context) {
return Container(
height: box.maxHeight * .06,
width: box.maxWidth,
child: ElevatedButton(
style: ButtonStyle(
foregroundColor: MaterialStateProperty.all(textColor),
elevation: MaterialStateProperty.all(0),
textStyle: MaterialStateProperty.all(style.titleMedium),
backgroundColor: MaterialStateProperty.all(
backgroundColor,
),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
box.maxHeight * .015,
))),
side: MaterialStateProperty.all(BorderSide(
color: borderColor,
))),
onPressed: () {},
child: Text(
text,
),
),
);
}
}
19 changes: 19 additions & 0 deletions lib/contact_us/view/widgets/contact_us_success_image.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import 'package:flutter/material.dart';

class ContactUsSuccessImageWidget extends StatelessWidget {
const ContactUsSuccessImageWidget({
super.key,
required this.box,
});

final BoxConstraints box;

@override
Widget build(BuildContext context) {
return Image.asset(
'assets/fpb-assets/email_success.png',
width: box.maxWidth * .3,
height: 0.15 * box.maxHeight,
);
}
}
37 changes: 37 additions & 0 deletions lib/contact_us/view/widgets/contact_us_success_texts.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import 'package:flutter/material.dart';
import 'package:fpb/l10n/l10n.dart';

class ContactUsSuccessTexts extends StatelessWidget {
const ContactUsSuccessTexts({
super.key,
required this.l10n,
required this.style,
required this.box,
});

final AppLocalizations l10n;
final TextTheme style;
final BoxConstraints box;

@override
Widget build(BuildContext context) {
return Column(
children: [
Text(
l10n.contactUsSuccessTitle,
maxLines: 2,
textAlign: TextAlign.center,
style: style.titleLarge,
),
SizedBox(
height: box.maxHeight * .025,
),
Text(
l10n.contactUsSuccessText,
maxLines: 3,
textAlign: TextAlign.center,
style: style.titleMedium),
],
);
}
}
Loading

0 comments on commit a4b1b46

Please sign in to comment.