D1APP-11 authentication (phone number)

This commit is contained in:
MohammadTaha Basiri 2021-12-08 15:24:03 +03:30
parent 7b9ed44f6b
commit cddda7d7e9
18 changed files with 425 additions and 5 deletions

Binary file not shown.

BIN
lib/assets/fonts/dana.ttf Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 272 KiB

View File

@ -1,11 +1,23 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class DesignConfig { class DesignConfig {
static const Color lightPrimaryColor3 = Color(0XFFF5FAFC);
static const Color primaryColor = Color(0XFF007EA7); static const Color primaryColor = Color(0XFF007EA7);
static const Color darkPrimaryColor2 = Color(0XFF1B3C59);
static const Color greyColor4 = Color(0XFFE0E0E0);
static const Color greyColor5 = Color(0XFFE0E0E0);
static const Color lightRedColor = Color(0XFFFFF8F8);
static final ThemeData lightTheme = ThemeData( static final ThemeData lightTheme = ThemeData(
primaryColor: primaryColor, primaryColor: primaryColor,
colorScheme: lightColorScheme, colorScheme: lightColorScheme,
fontFamily: 'dana-fa',
textTheme: const TextTheme(
bodyText1: body1TextStyle,
caption: captionTextStyle,
),
); );
static const ColorScheme lightColorScheme = ColorScheme( static const ColorScheme lightColorScheme = ColorScheme(
@ -23,4 +35,18 @@ class DesignConfig {
onError: Colors.white, onError: Colors.white,
brightness: Brightness.light, brightness: Brightness.light,
); );
static const TextStyle body1TextStyle = TextStyle(
fontSize: 14,
);
static const TextStyle captionTextStyle = TextStyle(
fontSize: 13,
);
static const BorderRadius lowBorderRadius = BorderRadius.all(
Radius.circular(8),
);
static final Border lightBorder = Border.all(color: DesignConfig.greyColor4);
static const Duration defaultAppDuration = Duration(milliseconds: 400);
} }

View File

@ -1,4 +1,9 @@
class Assets { class Assets {
static const String _basePath = 'lib/assets'; static const String _basePath = 'lib/assets';
static const String logoWithTitleAndDesc = _basePath + '/logo/logo-t-d.png'; static const String _baseImagesPath = _basePath + '/images';
static const String verticalLogoWithText =
_baseImagesPath + '/logo/logo-v-t.png';
static const String horizontalLogoWithText =
_baseImagesPath + '/logo/logo-h-t.png';
} }

View File

@ -0,0 +1,133 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/pages/authentication/widgets/authentication_app_bar.dart';
import 'package:didvan/widgets/didvan/button.dart';
import 'package:didvan/widgets/didvan/text_field.dart';
import 'package:didvan/widgets/logos/didvan_horizontal_logo.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class Authentication extends StatefulWidget {
const Authentication({Key? key}) : super(key: key);
@override
State<Authentication> createState() => _AuthenticationState();
}
class _AuthenticationState extends State<Authentication> {
final List<Widget> _pages = const [
PhoneNumberInput(),
PasswordInput(),
];
@override
Widget build(BuildContext context) {
return Scaffold(
body: Consumer<AuthenticationState>(
builder: (context, state, child) => AnimatedSwitcher(
duration: DesignConfig.defaultAppDuration,
child: _pages[state.currentPageIndex],
),
),
);
}
}
class PhoneNumberInput extends StatelessWidget {
const PhoneNumberInput({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final AuthenticationState state = context.read<AuthenticationState>();
return SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(20),
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(
top: 80,
left: 100,
right: 100,
bottom: 40,
),
child: DidvanVerticalLogo(),
),
DidvanTextField(
title: 'شماره موبایل',
textInputType: TextInputType.phone,
hintText: 'شماره موبایل',
onChanged: (value) {
state.phoneNumber = value;
},
),
const SizedBox(
height: 20,
),
DidvanButton(
title: 'ورود',
onPressed: () {
state.currentPageIndex = 1;
},
),
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 60),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: Theme.of(context).textTheme.caption,
children: [
const TextSpan(text: 'با ثبت نام و ورود به دیدوان،'),
TextSpan(
text: ' شرایط ',
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: Theme.of(context).primaryColor),
recognizer: TapGestureRecognizer()
..onTap = () {
//TODO: Needs implementaion
},
),
const TextSpan(text: 'و\n'),
TextSpan(
text: ' قوانین حریم خصوصی ',
style: Theme.of(context)
.textTheme
.caption!
.copyWith(color: Theme.of(context).primaryColor),
recognizer: TapGestureRecognizer()
..onTap = () {
//TODO: Needs implementaion
},
),
const TextSpan(text: 'را می‌پذیرم'),
],
),
),
),
const SizedBox(
height: 48,
),
],
),
),
);
}
}
class PasswordInput extends StatelessWidget {
const PasswordInput({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final AuthenticationState state = context.read<AuthenticationState>();
return Container();
}
}

View File

@ -0,0 +1,14 @@
import 'package:didvan/providers/core_provider.dart';
class AuthenticationState extends CoreProvier {
int _currentPageIndex = 0;
String phoneNumber = '';
String password = '';
set currentPageIndex(int value) {
_currentPageIndex = value;
notifyListeners();
}
int get currentPageIndex => _currentPageIndex;
}

View File

@ -0,0 +1,30 @@
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class AuthenticationAppBar extends StatelessWidget {
final String? title;
const AuthenticationAppBar({Key? key, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 12),
child: Row(
children: [
GestureDetector(
onTap: () => context.read<AuthenticationState>().currentPageIndex--,
child: const Icon(
Icons.arrow_back,
),
),
const SizedBox(
width: 20,
),
if (title != null) DidvanText(title!)
],
),
);
}
}

View File

@ -1,5 +1,6 @@
import 'package:didvan/config/design_config.dart'; import 'package:didvan/config/design_config.dart';
import 'package:didvan/constants/assets.dart'; import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/logos/didvan_horizontal_logo.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class Splash extends StatefulWidget { class Splash extends StatefulWidget {
@ -10,12 +11,23 @@ class Splash extends StatefulWidget {
} }
class _SplashState extends State<Splash> { class _SplashState extends State<Splash> {
@override
void initState() {
Future.delayed(
const Duration(seconds: 2),
() => Navigator.of(context).pushReplacementNamed(
Routes.authenticaion,
),
);
super.initState();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
padding: const EdgeInsets.all(60), padding: const EdgeInsets.all(60),
color: DesignConfig.lightColorScheme.background, color: DesignConfig.lightColorScheme.background,
child: Image.asset(Assets.logoWithTitleAndDesc), child: const DidvanVerticalLogo(),
); );
} }
} }

View File

@ -1,3 +1,5 @@
import 'package:didvan/pages/authentication/authentication.dart';
import 'package:didvan/pages/authentication/authentication_state.dart';
import 'package:didvan/pages/splash/splash.dart'; import 'package:didvan/pages/splash/splash.dart';
import 'package:didvan/pages/splash/splash_state.dart'; import 'package:didvan/pages/splash/splash_state.dart';
import 'package:didvan/routes/routes.dart'; import 'package:didvan/routes/routes.dart';
@ -14,6 +16,13 @@ class RouteGenerator {
child: const Splash(), child: const Splash(),
), ),
); );
case Routes.authenticaion:
return _materialPageRouteGenerator(
ChangeNotifierProvider(
create: (context) => AuthenticationState(),
child: const Authentication(),
),
);
default: default:
return _errorRoute(); return _errorRoute();
} }

View File

@ -0,0 +1,34 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanButton extends StatelessWidget {
final VoidCallback? onPressed;
final String? title;
const DidvanButton({Key? key, this.onPressed, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
width: double.infinity,
child: MaterialButton(
shape: const RoundedRectangleBorder(
borderRadius: DesignConfig.lowBorderRadius,
),
height: 48,
color: Theme.of(context).primaryColor,
onPressed: onPressed,
child: _childBuilder(),
),
);
}
Widget? _childBuilder() {
if (title != null) {
return DidvanText(
title!,
color: Colors.white,
);
}
}
}

View File

@ -0,0 +1,31 @@
import 'package:didvan/config/design_config.dart';
import 'package:flutter/material.dart';
class DidvanText extends StatelessWidget {
final TextStyle style;
final String text;
final Color? color;
final FontWeight? fontWeight;
final double? fontSize;
const DidvanText(
this.text, {
Key? key,
this.style = DesignConfig.body1TextStyle,
this.color,
this.fontSize,
this.fontWeight,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Text(
text,
style: style.copyWith(
color: color,
fontWeight: fontWeight,
fontSize: fontSize,
),
);
}
}

View File

@ -0,0 +1,106 @@
import 'package:didvan/config/design_config.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class DidvanTextField extends StatefulWidget {
final void Function(String value)? onChanged;
final bool enabled;
final TextAlign textAlign;
final String? title;
final String? hintText;
final dynamic initialValue;
final String? Function(String? value)? validator;
final TextInputType? textInputType;
const DidvanTextField({
Key? key,
this.onChanged,
this.enabled = true,
this.title,
this.hintText,
this.initialValue,
this.validator,
this.textInputType,
this.textAlign = TextAlign.right,
}) : super(key: key);
@override
State<DidvanTextField> createState() => _DidvanTextFieldState();
}
class _DidvanTextFieldState extends State<DidvanTextField> {
final FocusNode _focusNode = FocusNode();
final TextEditingController _controller = TextEditingController();
bool _hasError = false;
@override
void initState() {
_focusNode.addListener(() {
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.title != null) DidvanText(widget.title!),
if (widget.title != null) const SizedBox(height: 8),
Container(
padding: const EdgeInsets.symmetric(horizontal: 12),
decoration: BoxDecoration(
color: _fillColor(),
borderRadius: DesignConfig.lowBorderRadius,
border: Border.all(color: _borderColor()),
),
child: TextFormField(
textAlign: widget.textAlign,
keyboardType: widget.textInputType,
focusNode: _focusNode,
controller: _controller,
onChanged: _onChanged,
validator: _validator,
decoration: InputDecoration(
enabled: widget.enabled,
border: InputBorder.none,
hintText: widget.hintText,
hintStyle: Theme.of(context)
.textTheme
.bodyText1!
.copyWith(color: DesignConfig.greyColor5),
),
),
),
],
);
}
Color _borderColor() {
if (_focusNode.hasFocus) {
return Theme.of(context).primaryColor;
} else if (_hasError) {
return Theme.of(context).colorScheme.error;
}
return DesignConfig.greyColor4;
}
Color _fillColor() {
if (_focusNode.hasFocus) {
return DesignConfig.lightPrimaryColor3;
} else if (_hasError) {
return DesignConfig.lightRedColor;
}
return Theme.of(context).colorScheme.surface;
}
void _onChanged(String value) {
if (widget.onChanged != null) {
widget.onChanged!(value);
}
}
String? _validator(String? value) {}
}

View File

@ -0,0 +1,11 @@
import 'package:didvan/constants/assets.dart';
import 'package:flutter/material.dart';
class DidvanVerticalLogo extends StatelessWidget {
const DidvanVerticalLogo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Image.asset(Assets.verticalLogoWithText);
}
}

View File

@ -62,7 +62,8 @@ flutter:
# To add assets to your application, add an assets section, like this: # To add assets to your application, add an assets section, like this:
assets: assets:
- lib/assets/logo/logo-t-d.png - lib/assets/images/logo/logo-v-t.png
- lib/assets/images/logo/logo-h-t.png
@ -77,6 +78,14 @@ flutter:
# "family" key with the font family name, and a "fonts" key with a # "family" key with the font family name, and a "fonts" key with a
# list giving the asset and other descriptors for the font. For # list giving the asset and other descriptors for the font. For
# example: # example:
fonts:
- family: dana-fa
fonts:
- asset: lib/assets/fonts/dana-fa.ttf
- family: dana
fonts:
- asset: lib/assets/fonts/dana-fa.ttf
# fonts: # fonts:
# - family: Schyler # - family: Schyler
# fonts: # fonts: