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';
|
||||
|
||||
class DesignConfig {
|
||||
static const Color lightPrimaryColor3 = Color(0XFFF5FAFC);
|
||||
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(
|
||||
primaryColor: primaryColor,
|
||||
colorScheme: lightColorScheme,
|
||||
fontFamily: 'dana-fa',
|
||||
textTheme: const TextTheme(
|
||||
bodyText1: body1TextStyle,
|
||||
caption: captionTextStyle,
|
||||
),
|
||||
);
|
||||
|
||||
static const ColorScheme lightColorScheme = ColorScheme(
|
||||
|
|
@ -23,4 +35,18 @@ class DesignConfig {
|
|||
onError: Colors.white,
|
||||
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 {
|
||||
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/constants/assets.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/widgets/logos/didvan_horizontal_logo.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Splash extends StatefulWidget {
|
||||
|
|
@ -10,12 +11,23 @@ class Splash extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _SplashState extends State<Splash> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(
|
||||
const Duration(seconds: 2),
|
||||
() => Navigator.of(context).pushReplacementNamed(
|
||||
Routes.authenticaion,
|
||||
),
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(60),
|
||||
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_state.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
|
|
@ -14,6 +16,13 @@ class RouteGenerator {
|
|||
child: const Splash(),
|
||||
),
|
||||
);
|
||||
case Routes.authenticaion:
|
||||
return _materialPageRouteGenerator(
|
||||
ChangeNotifierProvider(
|
||||
create: (context) => AuthenticationState(),
|
||||
child: const Authentication(),
|
||||
),
|
||||
);
|
||||
default:
|
||||
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);
|
||||
}
|
||||
}
|
||||
13
pubspec.yaml
13
pubspec.yaml
|
|
@ -62,7 +62,8 @@ flutter:
|
|||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
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,7 +78,15 @@ flutter:
|
|||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
# fonts:
|
||||
fonts:
|
||||
- family: dana-fa
|
||||
fonts:
|
||||
- asset: lib/assets/fonts/dana-fa.ttf
|
||||
|
||||
- family: dana
|
||||
fonts:
|
||||
- asset: lib/assets/fonts/dana-fa.ttf
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
|
|
|
|||
Loading…
Reference in New Issue