Skip to content

Commit

Permalink
Tweaks starter project (#3)
Browse files Browse the repository at this point in the history
* Add notes about keys for testing

* Add AddressScreen

* Tweaks main.dart

* Hardcode Android SDK version

* Rename VSCode configuration name

* Cleanup pubspec.yaml

* Cleanup address.dart

* Document AddressScreen
  • Loading branch information
bizz84 authored Feb 21, 2022
1 parent 816e2d1 commit 0070b90
Show file tree
Hide file tree
Showing 13 changed files with 189 additions and 14 deletions.
2 changes: 1 addition & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch (no flavor)",
"name": "Launch",
"request": "launch",
"type": "dart",
"cwd": "${workspaceFolder}/ecommerce_app",
Expand Down
2 changes: 1 addition & 1 deletion ecommerce_app/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"version": "0.2.0",
"configurations": [
{
"name": "Launch (no flavor)",
"name": "Launch",
"request": "launch",
"type": "dart",
"program": "lib/main.dart",
Expand Down
6 changes: 3 additions & 3 deletions ecommerce_app/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion flutter.compileSdkVersion
compileSdkVersion 31

compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
Expand All @@ -44,8 +44,8 @@ android {
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.ecommerce_app"
minSdkVersion flutter.minSdkVersion
targetSdkVersion flutter.targetSdkVersion
minSdkVersion 23
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
Expand Down
3 changes: 2 additions & 1 deletion ecommerce_app/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:async';

import 'package:ecommerce_app/src/app.dart';
import 'package:ecommerce_app/src/localization/string_hardcoded.dart';
import 'package:flutter/material.dart';

void main() async {
Expand All @@ -19,7 +20,7 @@ void main() async {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.red,
title: const Text('An error occurred'),
title: Text('An error occurred'.hardcoded),
),
body: Center(child: Text(details.toString())),
);
Expand Down
152 changes: 152 additions & 0 deletions ecommerce_app/lib/src/features/address/address_screen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import 'package:ecommerce_app/src/localization/string_hardcoded.dart';
import 'package:flutter/material.dart';
import 'package:ecommerce_app/src/common_widgets/primary_button.dart';
import 'package:ecommerce_app/src/common_widgets/responsive_scrollable_card.dart';
import 'package:ecommerce_app/src/constants/app_sizes.dart';

/// A page where the user can enter and submit all the address details.
/// * This page is not yet in use. We will add it to the checkout flows later.
class AddressScreen extends StatefulWidget {
const AddressScreen({Key? key, this.onSubmit}) : super(key: key);
final VoidCallback? onSubmit;

// * Keys for testing using find.byKey()
static const addressKey = Key('address');
static const townCityKey = Key('townCity');
static const stateKey = Key('state');
static const postalCodeKey = Key('postalCode');
static const countryKey = Key('country');
static const scrollableKey = Key('addressPageScrollable');

@override
_AddressPageState createState() => _AddressPageState();
}

class _AddressPageState extends State<AddressScreen> {
final _formKey = GlobalKey<FormState>();

final _addressController = TextEditingController();
final _cityController = TextEditingController();
final _stateController = TextEditingController();
final _postalCodeController = TextEditingController();
final _countryController = TextEditingController();

final _isLoading = false;

Future<void> _submit() async {
if (_formKey.currentState!.validate()) {
FocusScope.of(context).unfocus();
// TODO: uncomment and submit the address
// final address = Address(
// address: _addressController.value.text,
// city: _cityController.value.text,
// state: _stateController.value.text,
// postalCode: _postalCodeController.value.text,
// country: _countryController.value.text,
// );
// TODO: Only fire callback if submission is successful
widget.onSubmit?.call();
}
}

@override
Widget build(BuildContext context) {
return ResponsiveScrollableCard(
key: AddressScreen.scrollableKey,
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
AddressFormField(
formFieldKey: AddressScreen.addressKey,
controller: _addressController,
labelText: 'Address'.hardcoded,
keyboardType: TextInputType.streetAddress,
enabled: !_isLoading,
),
gapH8,
AddressFormField(
formFieldKey: AddressScreen.townCityKey,
controller: _cityController,
labelText: 'Town/City'.hardcoded,
keyboardType: TextInputType.streetAddress,
enabled: !_isLoading,
),
gapH8,
AddressFormField(
formFieldKey: AddressScreen.stateKey,
controller: _stateController,
labelText: 'State'.hardcoded,
keyboardType: TextInputType.streetAddress,
enabled: !_isLoading,
),
gapH8,
AddressFormField(
formFieldKey: AddressScreen.postalCodeKey,
controller: _postalCodeController,
labelText: 'Postal Code'.hardcoded,
keyboardType: TextInputType.streetAddress,
enabled: !_isLoading,
),
gapH8,
AddressFormField(
formFieldKey: AddressScreen.countryKey,
controller: _countryController,
labelText: 'Country'.hardcoded,
keyboardType: TextInputType.streetAddress,
enabled: !_isLoading,
),
gapH8,
PrimaryButton(
text: 'Submit'.hardcoded,
onPressed: _submit,
isLoading: _isLoading,
)
],
),
),
);
}
}

// Reusable address form field
class AddressFormField extends StatelessWidget {
const AddressFormField({
Key? key,
required this.controller,
required this.labelText,
this.keyboardType,
this.enabled = true,
this.formFieldKey,
}) : super(key: key);

/// Controller used to read out the value in the parent widget
final TextEditingController controller;
final String labelText;
final TextInputType? keyboardType;

/// Whether the text field is enabled or not
final bool enabled;

/// Key used in the widget tests
final Key? formFieldKey;

@override
Widget build(BuildContext context) {
return TextFormField(
key: formFieldKey,
controller: controller,
decoration: InputDecoration(
labelText: labelText,
enabled: enabled,
),
autocorrect: true,
textInputAction: TextInputAction.next,
keyboardType: keyboardType,
keyboardAppearance: Brightness.light,
validator: (value) =>
value?.isNotEmpty == true ? null : 'Can\'t be empty'.hardcoded,
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:ecommerce_app/src/features/checkout/payment/payment_page.dart';
import 'package:ecommerce_app/src/features/sign_in/email_password_sign_in_screen.dart';

/// The two sub-routes that are presented as part of the checkout flow.
/// TODO: add the address page as well (see [AddressScreen]).
enum CheckoutSubRoute { register, payment }

/// This is the root widget of the checkout flow, which is composed of 2 pages:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class MoreMenuButton extends StatelessWidget {
const MoreMenuButton({Key? key, this.user}) : super(key: key);
final AppUser? user;

// * Keys for testing using find.byKey()
static const signInKey = Key('menuSignIn');
static const ordersKey = Key('menuOrders');
static const accountKey = Key('menuAccount');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'package:ecommerce_app/src/constants/app_sizes.dart';
class ShoppingCartIcon extends StatelessWidget {
const ShoppingCartIcon({Key? key}) : super(key: key);

// * Keys for testing using find.byKey()
static const shoppingCartIconKey = Key('shopping-cart');

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class LeaveReviewForm extends StatefulWidget {
final String productId;
final Review? review;

// * Keys for testing using find.byKey()
static const reviewCommentKey = Key('reviewComment');

@override
Expand All @@ -50,9 +51,10 @@ class _LeaveReviewFormState extends State<LeaveReviewForm> {
@override
void initState() {
super.initState();
if (widget.review != null) {
_controller.text = widget.review!.comment;
_rating = widget.review!.score;
final review = widget.review;
if (review != null) {
_controller.text = review.comment;
_rating = review.score;
}
}

Expand All @@ -75,8 +77,7 @@ class _LeaveReviewFormState extends State<LeaveReviewForm> {
children: [
if (widget.review != null) ...[
Text(
'You reviewed this product before. You can edit your review.'
.hardcoded,
'You reviewed this product before. Submit again to edit.'.hardcoded,
textAlign: TextAlign.center,
),
gapH24,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class ProductCard extends StatelessWidget {
final Product product;
final VoidCallback? onPressed;

// * Keys for testing using find.byKey()
static const productCardKey = Key('product-card');

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class EmailPasswordSignInScreen extends StatelessWidget {
: super(key: key);
final EmailPasswordSignInFormType formType;

// * Keys for testing using find.byKey()
static const emailKey = Key('email');
static const passwordKey = Key('password');

Expand Down
16 changes: 16 additions & 0 deletions ecommerce_app/lib/src/models/address.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// Address information used for shipping.
class Address {
const Address({
required this.address,
required this.city,
required this.state,
required this.postalCode,
required this.country,
});

final String address;
final String city;
final String state;
final String postalCode;
final String country;
}
6 changes: 3 additions & 3 deletions ecommerce_app/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ dependencies:
flutter_lints: 1.0.4
flutter_localizations:
sdk: flutter
intl: 0.17.0 # Used for date and currency formatting
flutter_layout_grid: 1.0.3 # Used for content-sized items in the products grid layout
flutter_rating_bar: 4.0.0 # Used for the "leave a rating" feature
intl: 0.17.0
flutter_layout_grid: 1.0.3
flutter_rating_bar: 4.0.0

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit 0070b90

Please sign in to comment.