Skip to content

Signup page optimizations #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ More details at [kilvish.in](https://kilvish.in)
- Due to sharing related changes, android & iOS specific code is written which had broken the web or MacOS builds.
- `flutter build apk --debug && flutter install --debug` will build & install apk in an already running emulator
- To run an Android emulator, install Android Studio & launch an emulator with the AVD manager
- To make it easier to launch emulator every time, add `/path/to/sdk/emulator` to PATH variable & run command `emulator -avd <name of emulator>`
- you can find SDK path from Android Studio -> Settings -> Appearance & Behavior -> Android SDK
- To give a short name to the emulator, launch AVD manager from Android Studio, click on the pencil/edit button of the emulator & give it a short name that you can pass to the emulator command above.

## Firebase Setup

Expand Down
15 changes: 15 additions & 0 deletions lib/common_widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,21 @@ Widget renderLabel(
)));
}

Widget renderSupportLabel(
{required String text,
Color color = inactiveColor,
double fontSize = smallFontSize,
double topSpacing = 0}) {
return Container(
margin: EdgeInsets.only(top: topSpacing),
child: Align(
alignment: Alignment.centerLeft,
child: Text(
text,
style: TextStyle(color: color, fontSize: fontSize),
)));
}

Widget renderHelperText({required String text}) {
return Container(
margin: const EdgeInsets.only(top: 5, bottom: 10),
Expand Down
79 changes: 52 additions & 27 deletions lib/signup_screen.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:async';

import 'package:cloud_functions/cloud_functions.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
Expand Down Expand Up @@ -34,6 +36,7 @@ class SignUpPageState extends State<SignUpPage> {
TextEditingController();
final _formKey = GlobalKey<FormState>();
bool sendOtpSuccess = false;
bool isOtpButtonEnabled = true;

@override
void initState() {
Expand Down Expand Up @@ -91,6 +94,14 @@ class SignUpPageState extends State<SignUpPage> {
super.dispose();
}

void removeFocusFromAllInputFields() {
_kilvishTextFocus.unfocus();
_phoneTextFocus.unfocus();
_emailTextFocus.unfocus();
_otpEmailTextFocus.unfocus();
_otpPhoneTextFocus.unfocus();
}

void allowFormSubmission(int stepNumber) {
setState(() {
_stepNumber = stepNumber + 1;
Expand Down Expand Up @@ -144,8 +155,8 @@ class SignUpPageState extends State<SignUpPage> {
),
SignupForm(
stepNumber: "1",
fieldLabel: "Setup Kilvish Id",
buttonLabel: "Get Started",
fieldLabel: "Kilvish Id",
supportLabel: "First time user ? Get a new id",
hint: "crime-master-gogo",
isActive: _stepNumber == 1 && (!sendOtpSuccess),
isOperationAllowedButNotActive: _stepNumber > 1,
Expand All @@ -155,10 +166,8 @@ class SignUpPageState extends State<SignUpPage> {
),
SignupForm(
stepNumber: "2",
fieldLabel:
(_stepNumber == 2) ? "Phone Number" : "Update Phone Number",
buttonLabel:
(_stepNumber == 2) ? "Get OTP" : "Get OTP for new number",
fieldLabel: "Phone Number",
supportLabel: "OTP will be sent on this number",
hint: "7019316063",
isActive: _stepNumber == 2 && (!sendOtpSuccess),
isOperationAllowedButNotActive: _stepNumber > 2,
Expand All @@ -169,14 +178,29 @@ class SignUpPageState extends State<SignUpPage> {
),
SignupForm(
stepNumber: "3",
fieldLabel: "Enter Email Id",
buttonLabel: "Send OTP",
hint: "admin@mail.com",
fieldLabel: "Email Id",
supportLabel:
"In future, you can receive OTP either on email or on phone",
buttonLabel: sendOtpSuccess
? (isOtpButtonEnabled ? "Re-requet OTP" : "Please wait ..")
: "Get OTP",
hint: "teja-finder@aaa.movie",
isActive: _stepNumber == 3 && (!sendOtpSuccess),
isOperationAllowedButNotActive: _stepNumber > 3,
buttonClickHandler: () {
removeFocusFromAllInputFields();
verifyUser();
setState(() {
_stepNumber = 4;
isOtpButtonEnabled = false;
});
Timer(const Duration(seconds: 10), () {
setState(() {
isOtpButtonEnabled = true;
});
});
},
buttonEnabled: isOtpButtonEnabled,
buttonVisible: true,
textFocus: _emailTextFocus,
controller: _emailTextEditingController,
Expand All @@ -193,8 +217,8 @@ class SignUpPageState extends State<SignUpPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
renderInputLabel("Phone OTP", _stepNumber == 4),
renderTextField(_otpPhoneTextEditingController,
"Enter Phone OTP", _otpPhoneTextFocus)
renderTextField(_otpPhoneTextEditingController, "xxxx",
_otpPhoneTextFocus)
],
)),
const SizedBox(width: 16),
Expand All @@ -204,8 +228,8 @@ class SignUpPageState extends State<SignUpPage> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
renderInputLabel("Email OTP", _stepNumber == 5),
renderTextField(_otpEmailTextEditingController,
"Enter Email OTP", _otpEmailTextFocus)
renderTextField(_otpEmailTextEditingController, "xxxx",
_otpEmailTextFocus)
],
)),
],
Expand Down Expand Up @@ -246,6 +270,7 @@ class SignUpPageState extends State<SignUpPage> {
minimumSize: const Size.fromHeight(50),
shape: greyBorderIfNeeded),
onPressed: () {
removeFocusFromAllInputFields();
verifyOtp();
},
child: const Text("Verify OTP",
Expand Down Expand Up @@ -348,7 +373,8 @@ String? genericFieldValidator(String? value) {
class SignupForm extends StatefulWidget {
final String stepNumber;
final String fieldLabel;
final String buttonLabel;
final String supportLabel;
final String? buttonLabel;
final String hint;
final bool isActive;
final bool isOperationAllowedButNotActive;
Expand All @@ -358,11 +384,13 @@ class SignupForm extends StatefulWidget {
final TextEditingController controller;
final TextInputAction textInputAction;
final bool buttonVisible;
final bool buttonEnabled;

const SignupForm({
required this.stepNumber,
required this.fieldLabel,
required this.buttonLabel,
required this.supportLabel,
this.buttonLabel,
required this.hint,
required this.isActive,
required this.isOperationAllowedButNotActive,
Expand All @@ -372,6 +400,7 @@ class SignupForm extends StatefulWidget {
required this.controller,
this.textInputAction = TextInputAction.next,
this.buttonVisible = false,
this.buttonEnabled = false,
super.key,
}) : fieldValidator = fieldvalidator ?? genericFieldValidator;

Expand All @@ -393,6 +422,7 @@ class SignupFormState extends State<SignupForm> {
child: Column(
children: [
renderInputLabel(),
renderSupportLabel(text: widget.supportLabel),
renderTextField(),
Visibility(
visible: widget.buttonVisible,
Expand All @@ -407,13 +437,15 @@ class SignupFormState extends State<SignupForm> {
],
),
]);

if (widget.isActive) {
//this will give focus to the active input field
widget.textFocus.requestFocus();
} else {
//this will give un focus to the in active input field
widget.textFocus.unfocus();
}

return uiWidget;
}

Expand Down Expand Up @@ -445,7 +477,6 @@ class SignupFormState extends State<SignupForm> {

Widget renderTextField() {
return TextFormField(
readOnly: !widget.isActive,
controller: widget.controller,
decoration: InputDecoration(
hintText: widget.isActive ? widget.hint : "",
Expand All @@ -456,27 +487,21 @@ class SignupFormState extends State<SignupForm> {
}

Widget renderFormSubmitButton() {
StadiumBorder? greyBorderIfNeeded = (widget.isOperationAllowedButNotActive)
StadiumBorder? greyBorderIfNeeded = (widget.buttonEnabled)
? const StadiumBorder(
side: BorderSide(color: primaryColor, width: 2),
)
: const StadiumBorder();
Color backgroundColor = (widget.isActive) ? primaryColor : inactiveColor;
Color backgroundColor =
(widget.buttonEnabled) ? primaryColor : inactiveColor;

return TextButton(
style: TextButton.styleFrom(
backgroundColor: backgroundColor,
minimumSize: const Size.fromHeight(50),
shape: greyBorderIfNeeded),
onPressed: widget.isActive
? () {
if (!widget.isActive && !widget.isOperationAllowedButNotActive) {
return denyFormSubmission();
}
widget.buttonClickHandler();
}
: null,
child: Text(widget.buttonLabel,
onPressed: widget.buttonEnabled ? widget.buttonClickHandler : null,
child: Text(widget.buttonLabel ?? "Click Me",
style: const TextStyle(color: Colors.white, fontSize: 15)),
);
}
Expand Down