D1APP-11 authentication (phone number)
This commit is contained in:
parent
7b9ed44f6b
commit
cddda7d7e9
Binary file not shown.
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 |
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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';
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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!)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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) {}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
pubspec.yaml
11
pubspec.yaml
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue