integrated web and qr code login

feature/passo/PASSO-#1-Sync-data-from-device-to-postgre-and-vice-versa
rodolfobacuinjr 2023-01-23 16:23:20 +08:00
parent 226899893f
commit 692d080e25
11 changed files with 282 additions and 215 deletions

View File

@ -14,6 +14,7 @@ part 'user_state.dart';
class UserBloc extends Bloc<UserEvent, UserState> {
UserData? _userData;
VersionInfo? _versionInfo;
UserBloc() : super(UserInitial()) {
// this event is called when opening the app to check if
// there is new app version
@ -21,13 +22,17 @@ class UserBloc extends Bloc<UserEvent, UserState> {
try {
emit(SplashScreen());
VersionInfo versionInfo = await AuthService.instance.getVersionInfo();
emit(VersionLoaded(versionInfo: versionInfo));
_versionInfo = versionInfo;
emit(VersionLoaded(versionInfo: _versionInfo));
} catch (e) {
emit(UserError(
message: e.toString(),
));
}
});
on<LoadVersion>((event, emit) {
emit(VersionLoaded(versionInfo: _versionInfo));
});
on<UserLogin>((event, emit) async {
try {
UserData? userData = await AuthService.instance
@ -38,6 +43,16 @@ class UserBloc extends Bloc<UserEvent, UserState> {
emit(UserError(message: e.toString()));
}
});
on<UuidLogin>((event, emit) async {
try {
UserData? userData = await AuthService.instance
.qrLogin(uuid: event.uuid, password: event.password);
_userData = userData;
emit(UserLoggedIn(userData: _userData));
} catch (e) {
emit(UserError(message: e.toString()));
}
});
on<LoadLoggedInUser>((event, emit) {
emit(UserLoggedIn(userData: _userData));
});

View File

@ -15,6 +15,8 @@ class UserLogin extends UserEvent {
final String? username;
final String? password;
UserLogin({this.username, this.password});
@override
List<Object> get props => [username!, password!];
}
class LoadLoggedInUser extends UserEvent {
@ -25,3 +27,13 @@ class LoadLoggedInUser extends UserEvent {
class GetUuid extends UserEvent {
GetUuid();
}
class LoadVersion extends UserEvent {}
class UuidLogin extends UserEvent {
final String? uuid;
final String? password;
UuidLogin({this.uuid, this.password});
@override
List<Object> get props => [uuid!, password!];
}

View File

@ -16,8 +16,8 @@ import '../../../theme-data.dart/colors.dart';
import '../../../widgets/splash_screen.dart';
import './components/cover-image.dart';
class Profile extends StatelessWidget {
const Profile({super.key});
class BasicInfo extends StatelessWidget {
const BasicInfo({super.key});
@override
Widget build(BuildContext context) {

View File

@ -20,7 +20,6 @@ class _DrawerScreenState extends State<DrawerScreen> {
Widget build(BuildContext context) {
return BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
print("drawer screen" + state.toString());
if (state is UserLoggedIn) {
return ZoomDrawer(
controller: zoomDrawerController,

View File

@ -52,13 +52,13 @@ class _MenuScreenState extends State<MenuScreen> {
),
),
),
getTile(FontAwesome5.user, "Basic Info", 'profile', context,
getTile(FontAwesome5.user, "Basic Info", '/basic-info', context,
widget.userData!),
const Divider(),
getTile(FontAwesome5.user_circle, "Profile",
'/SelfAddressScreen', context, widget.userData!),
'/profile', context, widget.userData!),
const Divider(),
getTile(FontAwesome5.life_ring, "Request SOS", 'request-sos',
getTile(FontAwesome5.life_ring, "Request SOS", '/request-sos',
context, widget.userData!),
const Divider(),
Expanded(

View File

@ -23,7 +23,7 @@ Widget getTile(
context.goNamed("login");
});
} else {
context.goNamed(route,extra: userData);
Navigator.pushNamed(context, route);
}
},
);

View File

@ -44,15 +44,12 @@ class _UniT2LoginState extends State<UniT2Login> {
body: ProgressHUD(
child: BlocConsumer<UserBloc, UserState>(listener: (context, state) {
if (state is UserLoggedIn) {
print("login" + state.toString());
final progress = ProgressHUD.of(context);
progress!.dismiss();
Navigator.pushReplacementNamed(context, '/module-screen');
Navigator.pushReplacementNamed(context, '/module-screen');
}
if (state is UuidLoaded) {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return QRLogin();
}));
Navigator.pushNamed(context, '/qr-login');
}
}, builder: (context, state) {
if (state is VersionLoaded) {
@ -126,8 +123,6 @@ class _UniT2LoginState extends State<UniT2Login> {
name: 'password',
validator: FormBuilderValidators.required(
errorText: passwordRequired),
// initialValue: state.password,
onChanged: (value) {
value!.isEmpty
? setState(() {

View File

@ -4,12 +4,14 @@ import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:flutter_svg/svg.dart';
import 'package:fluttericon/font_awesome5_icons.dart';
import 'package:fluttericon/font_awesome_icons.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
import 'package:go_router/go_router.dart';
import 'package:unit2/theme-data.dart/btn-style.dart';
import 'package:unit2/widgets/error_state.dart';
import 'package:unit2/widgets/wave.dart';
import '../../../bloc/bloc/user_bloc.dart';
@ -32,206 +34,225 @@ class _QRLoginState extends State<QRLogin> {
final _formKey = GlobalKey<FormBuilderState>();
@override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
backgroundColor: primary,
elevation: 0,
automaticallyImplyLeading: true,
title: const Text("Login via QR"),
centerTitle: true,
),
body: BlocBuilder<UserBloc, UserState>(
builder: (context, state) {
print(state);
if (state is UuidLoaded) {
return Center(
child: Text(state.uuid),
);
return WillPopScope(
onWillPop: ()async{
context.read<UserBloc>().add(LoadVersion());
return true;
},
child: SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: true,
appBar: AppBar(
backgroundColor: primary,
elevation: 0,
title: const Text("Login via QR"),
centerTitle: true,
),
body: ProgressHUD(
child: BlocConsumer<UserBloc, UserState>(
listener: (context,state){
if (state is UserLoggedIn) {
final progress = ProgressHUD.of(context);
progress!.dismiss();
Navigator.pushReplacementNamed(context, '/module-screen');
}
return SingleChildScrollView(
child: Stack(
children: [
Positioned(
bottom: 0,
child: WaveReverse(height: blockSizeVertical * 8)),
Container(
height: screenHeight * .90,
padding: const EdgeInsets.symmetric(horizontal: 15),
child: FormBuilder(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/svgs/logo.svg',
height: blockSizeVertical * 12,
allowDrawingOutsideViewBox: true,
color: primary,
),
const SizedBox(
height: 12,
),
Text(unitApp,
style: TextStyle(
fontSize: blockSizeVertical * 5,
fontWeight: FontWeight.w800,
letterSpacing: .2,
height: 1,
color: Colors.black87)),
const SizedBox(
height: 15,
),
Text(
"Enter your password",
style: TextStyle(
fontSize: blockSizeVertical * 1.5,
height: 1.5,
fontWeight: FontWeight.w600),
),
const SizedBox(
height: 15,
),
// Password
FormBuilderTextField(
name: 'password',
validator: registerPasswordValidator,
// initialValue: state.password,
onChanged: (value) {
value!.isEmpty
? setState(() {
showSuffixIcon = false;
})
: setState(() {
showSuffixIcon = true;
});
},
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration: loginTextFieldStyle().copyWith(
suffixIcon: Visibility(
visible: showSuffixIcon,
child: _showPassword
? IconButton(
icon: Icon(FontAwesome5.eye_slash,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color),
onPressed: () {
setState(() {
_showPassword = false;
});
},
)
: IconButton(
onPressed: () {
setState(() {
_showPassword = true;
});
},
icon: Icon(FontAwesome5.eye,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color)),
},
builder: (context, state) {
if (state is UuidLoaded) {
return SingleChildScrollView(
child: Stack(
children: [
Positioned(
bottom: 0,
child: WaveReverse(height: blockSizeVertical * 8)),
Container(
height: screenHeight * .90,
padding: const EdgeInsets.symmetric(horizontal: 15),
child: FormBuilder(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SvgPicture.asset(
'assets/svgs/logo.svg',
height: blockSizeVertical * 12,
allowDrawingOutsideViewBox: true,
color: primary,
),
prefixIcon: const Icon(Icons.lock),
labelText: "Password",
hintText: enterPassword),
obscureText: _showPassword ? true : false,
const SizedBox(
height: 12,
),
Text(unitApp,
style: TextStyle(
fontSize: blockSizeVertical * 5,
fontWeight: FontWeight.w800,
letterSpacing: .2,
height: 1,
color: Colors.black87)),
const SizedBox(
height: 15,
),
Text(
"Enter your password",
style: TextStyle(
fontSize: blockSizeVertical * 1.5,
height: 1.5,
fontWeight: FontWeight.w600),
),
const SizedBox(
height: 15,
),
// Password
FormBuilderTextField(
name: 'password',
validator: registerPasswordValidator,
// initialValue: state.password,
onChanged: (value) {
value!.isEmpty
? setState(() {
showSuffixIcon = false;
})
: setState(() {
showSuffixIcon = true;
});
},
autofocus: false,
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black87),
decoration: loginTextFieldStyle().copyWith(
suffixIcon: Visibility(
visible: showSuffixIcon,
child: _showPassword
? IconButton(
icon: Icon(FontAwesome5.eye_slash,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color),
onPressed: () {
setState(() {
_showPassword = false;
});
},
)
: IconButton(
onPressed: () {
setState(() {
_showPassword = true;
});
},
icon: Icon(FontAwesome5.eye,
size: 24,
color: Theme.of(context)
.textTheme
.displayLarge
?.color)),
),
prefixIcon: const Icon(Icons.lock),
labelText: "Password",
hintText: enterPassword),
obscureText: _showPassword ? true : false,
),
const SizedBox(
height: 15,
),
// FormBuilderTextField(
// name: 'confirmPassword',
// validator: registerPasswordValidator,
// // initialValue: state.password,
// onChanged: (value) {
// value!.isEmpty
// ? setState(() {
// showSuffixIcon = false;
// })
// : setState(() {
// showSuffixIcon = true;
// });
// },
// autofocus: false,
// style: const TextStyle(
// fontWeight: FontWeight.bold, color: Colors.black87),
// decoration: loginTextFieldStyle().copyWith(
// suffixIcon: Visibility(
// visible: showSuffixIcon,
// child: _showPassword
// ? IconButton(
// icon: Icon(FontAwesome5.eye_slash,
// size: 24,
// color: Theme.of(context)
// .textTheme
// .displayLarge
// ?.color),
// onPressed: () {
// setState(() {
// _showPassword = false;
// });
// },
// )
// : IconButton(
// onPressed: () {
// setState(() {
// _showPassword = true;
// });
// },
// icon: Icon(FontAwesome5.eye,
// size: 24,
// color: Theme.of(context)
// .textTheme
// .displayLarge
// ?.color)),
// ),
// prefixIcon: const Icon(Icons.lock),
// labelText: confirmPassword,
// hintText: enterConfirmPassword),
// obscureText: _showPassword ? true : false,
// ),
const SizedBox(
height: 15,
),
SizedBox(
width: double.infinity,
height: blockSizeVertical * 6,
child: ElevatedButton(
style: secondaryBtnStyle(
second, Colors.transparent, primary),
onPressed: () {
if (_formKey.currentState!
.saveAndValidate()) {
final progress =
ProgressHUD.of(context);
progress?.showWithText(
'Logging in...',
);
context.read<UserBloc>().add(UuidLogin(uuid: state.uuid,password: _formKey.currentState!.value['password']));
// BlocProvider.of<UserBloc>(context)
// .add(UserLogin(
// username: _formKey
// .currentState!.value['username'],
// password: _formKey
// .currentState!.value['password'],
// ));
}
},
child: const Text(submit)),
)
],
),
),
const SizedBox(
height: 15,
),
// FormBuilderTextField(
// name: 'confirmPassword',
// validator: registerPasswordValidator,
// // initialValue: state.password,
// onChanged: (value) {
// value!.isEmpty
// ? setState(() {
// showSuffixIcon = false;
// })
// : setState(() {
// showSuffixIcon = true;
// });
// },
// autofocus: false,
// style: const TextStyle(
// fontWeight: FontWeight.bold, color: Colors.black87),
// decoration: loginTextFieldStyle().copyWith(
// suffixIcon: Visibility(
// visible: showSuffixIcon,
// child: _showPassword
// ? IconButton(
// icon: Icon(FontAwesome5.eye_slash,
// size: 24,
// color: Theme.of(context)
// .textTheme
// .displayLarge
// ?.color),
// onPressed: () {
// setState(() {
// _showPassword = false;
// });
// },
// )
// : IconButton(
// onPressed: () {
// setState(() {
// _showPassword = true;
// });
// },
// icon: Icon(FontAwesome5.eye,
// size: 24,
// color: Theme.of(context)
// .textTheme
// .displayLarge
// ?.color)),
// ),
// prefixIcon: const Icon(Icons.lock),
// labelText: confirmPassword,
// hintText: enterConfirmPassword),
// obscureText: _showPassword ? true : false,
// ),
const SizedBox(
height: 15,
),
SizedBox(
width: double.infinity,
height: blockSizeVertical * 6,
child: ElevatedButton(
style: secondaryBtnStyle(
second, Colors.transparent, primary),
onPressed: () {
if (_formKey.currentState!
.saveAndValidate()) {
BlocProvider.of<UserBloc>(context)
.add(UserLogin(
username: _formKey
.currentState!.value['username'],
password: _formKey
.currentState!.value['password'],
));
}
},
child: const Text(submit)),
)
],
),
),
],
),
),
],
),
);
},
);
}if(state is UserError){
return ErrorState(message: state.message,);
}
return Container();
},
),
),
),
),
);

View File

@ -58,4 +58,22 @@ class AuthService {
}
return userData!;
}
Future<UserData> qrLogin({String? uuid, String? password})async{
Map <String,String> body ={'uuid':uuid!,'password':password!};
Map<String, String> baseHeaders = {
'Content-Type': 'application/json'
};
String path = Url.instance.authentication();
UserData? userData;
try{
http.Response response = await Request.instance.postRequest(path: path,param: {},headers: baseHeaders,body: body);
if(response.statusCode == 200){
Map data = jsonDecode(response.body);
userData = UserData.fromJson(data['data']);
}
}catch(e){
throw (e.toString());
}
return userData!;
}
}

View File

@ -1,11 +1,11 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:unit2/bloc/bloc/user_bloc.dart';
import 'package:unit2/screens/unit2/login/login.dart';
import 'package:unit2/utils/global_context.dart';
import '../screens/unit2/basic-info/basic-info.dart';
import '../screens/unit2/homepage.dart/components/drawer-screen.dart';
import '../screens/unit2/login/qr_login.dart';
class AppRouter {
Route onGenerateRoute(RouteSettings routeSettings) {
@ -18,11 +18,18 @@ class AppRouter {
return const UniT2Login();
});
case '/module-screen':
BlocProvider.of<UserBloc>( NavigationService.navigatorKey.currentContext!).add(LoadLoggedInUser());
// BlocProvider.of<UserBloc>( NavigationService.navigatorKey.currentContext!).add(LoadLoggedInUser());
return MaterialPageRoute(builder: (_) {
return const DrawerScreen();
});
case '/basic-info':
return MaterialPageRoute(builder: (_){
return const BasicInfo();
});
case '/qr-login':
return MaterialPageRoute(builder: (_){
return const QRLogin();
});
default:
return MaterialPageRoute(builder: (context) {
return Container();