feat: login view
This commit is contained in:
parent
0a347f5e6d
commit
9475767021
|
@ -1,17 +1,22 @@
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class ButtonBack extends StatelessWidget {
|
class ButtonBack extends StatelessWidget {
|
||||||
const ButtonBack({super.key});
|
final EdgeInsets? margin;
|
||||||
|
const ButtonBack({super.key, this.margin});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SizedBox(
|
return Container(
|
||||||
|
margin: margin ?? EdgeInsets.all(0),
|
||||||
width: SizeConfig.width * 0.1,
|
width: SizeConfig.width * 0.1,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
style: IconButton.styleFrom(
|
style: IconButton.styleFrom(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
shape: const CircleBorder()
|
shape: const CircleBorder(
|
||||||
|
side: BorderSide(color: ColorPalette.slate200)
|
||||||
|
)
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
|
|
@ -95,6 +95,8 @@ class TextFormView extends StatelessWidget {
|
||||||
name,
|
name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
// color: ColorPalette.greyLight,
|
// color: ColorPalette.greyLight,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -112,6 +114,8 @@ class TextFormView extends StatelessWidget {
|
||||||
name,
|
name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: const SizedBox(),
|
: const SizedBox(),
|
||||||
|
|
|
@ -73,7 +73,6 @@ class ColorPalette {
|
||||||
static const Color chathamsBlue = Color(0xFF285BB9);
|
static const Color chathamsBlue = Color(0xFF285BB9);
|
||||||
static const Color background = Color(0xFFDADADA);
|
static const Color background = Color(0xFFDADADA);
|
||||||
static const Color backgroundBlueLight = Color(0xFFEBF3FD);
|
static const Color backgroundBlueLight = Color(0xFFEBF3FD);
|
||||||
static const Color slate500 = Color(0xFF64748B);
|
|
||||||
static const Color blue50 = Color(0xFFEFF6FF);
|
static const Color blue50 = Color(0xFFEFF6FF);
|
||||||
static const Color blue200 = Color(0xFFBFDBFE);
|
static const Color blue200 = Color(0xFFBFDBFE);
|
||||||
static const Color slate50 = Color(0xFFF8FAFC);
|
static const Color slate50 = Color(0xFFF8FAFC);
|
||||||
|
|
94
lib/features/auth/login/view/login_view.dart
Normal file
94
lib/features/auth/login/view/login_view.dart
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_back.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view/password_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view/phone_number_view.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart';
|
||||||
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class LoginView extends StatefulWidget {
|
||||||
|
const LoginView({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LoginView> createState() => _LoginViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LoginViewState extends State<LoginView> {
|
||||||
|
int currentPage = 0;
|
||||||
|
PageController pageController = PageController(initialPage: 0);
|
||||||
|
TextEditingController phoneNumberController = TextEditingController();
|
||||||
|
TextEditingController passwordController = TextEditingController();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// TODO: implement dispose
|
||||||
|
pageController.dispose();
|
||||||
|
phoneNumberController.dispose();
|
||||||
|
passwordController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ChangeNotifierProvider(
|
||||||
|
create: (context) => LoginViewModel(),
|
||||||
|
child: WillPopScope(
|
||||||
|
onWillPop: () async {
|
||||||
|
if(currentPage == 1){
|
||||||
|
currentPage--;
|
||||||
|
pageController.jumpToPage(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
child: Scaffold(
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
appBar: AppBar(
|
||||||
|
toolbarHeight: 70,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
surfaceTintColor: Colors.white,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
title: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ButtonBack(),
|
||||||
|
const Text('Sign Up'),
|
||||||
|
SizedBox(
|
||||||
|
width: SizeConfig.width * 0.1,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
shape: const RoundedRectangleBorder(
|
||||||
|
side: BorderSide(color: ColorPalette.slate200)
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: PageView(
|
||||||
|
controller: pageController,
|
||||||
|
children: [
|
||||||
|
PhoneNumberView(nextStep: nextStep, controller: phoneNumberController),
|
||||||
|
PasswordView(nextStep: nextStep, controller: passwordController)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nextStep() {
|
||||||
|
if(pageController.page == 0){
|
||||||
|
currentPage++;
|
||||||
|
pageController.jumpToPage(1);
|
||||||
|
}else{
|
||||||
|
routePush(context, page: BottomNavigationView(), routeType: RouteType.pushRemove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
lib/features/auth/login/view/password_view.dart
Normal file
80
lib/features/auth/login/view/password_view.dart
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view_model/login_view_model.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
class PasswordView extends StatelessWidget {
|
||||||
|
final void Function() nextStep;
|
||||||
|
final TextEditingController controller;
|
||||||
|
const PasswordView({super.key, required this.nextStep, required this.controller});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Consumer<LoginViewModel>(
|
||||||
|
builder: (context, provider, child) {
|
||||||
|
return Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
height: SizeConfig.height,
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Enter your phone number', fontSize: 24),
|
||||||
|
SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
TextFormView(
|
||||||
|
name: 'Password',
|
||||||
|
ctrl: controller,
|
||||||
|
obscureText: !provider.showPassword,
|
||||||
|
prefix: SizedBox(
|
||||||
|
width: 16,
|
||||||
|
),
|
||||||
|
suffixIcon: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
provider.changeShowPassword();
|
||||||
|
},
|
||||||
|
child: Icon(
|
||||||
|
provider.showPassword
|
||||||
|
? Icons.visibility_outlined
|
||||||
|
: Icons.visibility_off_outlined,
|
||||||
|
color: ColorPalette.greyDarker,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: EdgeInsets.all(0)
|
||||||
|
),
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Forget the password?',
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.primary,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 16,
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Confirm',
|
||||||
|
heightWrapContent: true,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
marginVertical: 0,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
onPressed: nextStep,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
111
lib/features/auth/login/view/phone_number_view.dart
Normal file
111
lib/features/auth/login/view/phone_number_view.dart
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
import 'package:cims_apps/application/assets/path_assets.dart';
|
||||||
|
import 'package:cims_apps/application/component/button/button_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_form/text_form_view.dart';
|
||||||
|
import 'package:cims_apps/application/component/text_title/text_title.dart';
|
||||||
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
|
class PhoneNumberView extends StatelessWidget {
|
||||||
|
final void Function() nextStep;
|
||||||
|
final TextEditingController controller;
|
||||||
|
const PhoneNumberView({super.key, required this.nextStep, required this.controller});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
width: SizeConfig.width,
|
||||||
|
height: SizeConfig.height,
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const TextTitle(title: 'Enter your phone number', fontSize: 24),
|
||||||
|
SizedBox(
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
TextFormView(
|
||||||
|
name: 'Phone Number',
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
ctrl: controller,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.deny(RegExp(r'^0'))
|
||||||
|
],
|
||||||
|
prefixIcon: Container(
|
||||||
|
width: SizeConfig.width * .23,
|
||||||
|
padding:
|
||||||
|
const EdgeInsets.symmetric(horizontal: 16.0),
|
||||||
|
margin: const EdgeInsets.only(right: 16),
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
color: ColorPalette.grey,
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(8),
|
||||||
|
bottomLeft: Radius.circular(8),
|
||||||
|
)),
|
||||||
|
child: const Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ImageView(
|
||||||
|
image: PathAssets.iconFlag,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'+62',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.slate800,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
validator: (value) {
|
||||||
|
if (value!.isEmpty) {
|
||||||
|
return 'Phone number must be filled';
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
height: 32,
|
||||||
|
),
|
||||||
|
ButtonView(
|
||||||
|
name: 'Next',
|
||||||
|
heightWrapContent: true,
|
||||||
|
width: SizeConfig.width,
|
||||||
|
marginVertical: 0,
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
|
onPressed: nextStep,
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Don't have an account yet?",
|
||||||
|
style: TextStyle(
|
||||||
|
color: ColorPalette.slate500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
'Sign Up',
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.primary
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
10
lib/features/auth/login/view_model/login_view_model.dart
Normal file
10
lib/features/auth/login/view_model/login_view_model.dart
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
class LoginViewModel extends ChangeNotifier {
|
||||||
|
bool showPassword = false;
|
||||||
|
|
||||||
|
void changeShowPassword() {
|
||||||
|
showPassword = !showPassword;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
}
|
|
@ -515,9 +515,15 @@ class _HomeViewState extends State<HomeView> {
|
||||||
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
color: ColorPalette.colorSwitchButtonActive
|
color: ColorPalette.green100
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
article.type,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: ColorPalette.green500
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: Text(article.type),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import 'package:cims_apps/application/component/image/image_view.dart';
|
||||||
import 'package:cims_apps/application/theme/color_palette.dart';
|
import 'package:cims_apps/application/theme/color_palette.dart';
|
||||||
import 'package:cims_apps/core/route/route.dart';
|
import 'package:cims_apps/core/route/route.dart';
|
||||||
import 'package:cims_apps/core/utils/size_config.dart';
|
import 'package:cims_apps/core/utils/size_config.dart';
|
||||||
|
import 'package:cims_apps/features/auth/login/view/login_view.dart';
|
||||||
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
import 'package:cims_apps/features/auth/registration/view/registration_view.dart';
|
||||||
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
import 'package:cims_apps/features/bottom_navigation_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -70,7 +71,7 @@ class DashboardPublicView extends StatelessWidget {
|
||||||
width: SizeConfig.width * .43,
|
width: SizeConfig.width * .43,
|
||||||
height: SizeConfig.height * .06,
|
height: SizeConfig.height * .06,
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
routePush(context, page: const BottomNavigationView());
|
routePush(context, page: const LoginView());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ButtonView(
|
ButtonView(
|
||||||
|
|
|
@ -28,6 +28,7 @@ class MyApp extends StatelessWidget {
|
||||||
titleTextStyle: TextStyle(
|
titleTextStyle: TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
|
fontFamily: 'Manrope',
|
||||||
color: ColorPalette.slate800,
|
color: ColorPalette.slate800,
|
||||||
)),
|
)),
|
||||||
fontFamily: 'Manrope',
|
fontFamily: 'Manrope',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user