mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 14:47:23 +00:00
auth UI and Api
This commit is contained in:
@ -1,32 +1,46 @@
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
|
||||
import 'package:syncrow_web/pages/auth/view/login_page.dart';
|
||||
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||
import 'package:syncrow_web/services/locator.dart';
|
||||
void main() {
|
||||
|
||||
Future<void> main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
initialSetup();
|
||||
runApp(const MyApp());
|
||||
initialSetup(); // Perform initial setup, e.g., dependency injection
|
||||
String res = await AuthBloc.getTokenAndValidate();
|
||||
runApp(MyApp(
|
||||
isLoggedIn: res,
|
||||
));
|
||||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
final dynamic isLoggedIn;
|
||||
const MyApp({
|
||||
super.key,
|
||||
required this.isLoggedIn,
|
||||
});
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
debugShowCheckedModeBanner: false,
|
||||
debugShowCheckedModeBanner: false, // Hide debug banner
|
||||
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
||||
dragDevices: {
|
||||
PointerDeviceKind.mouse,
|
||||
PointerDeviceKind.touch,
|
||||
PointerDeviceKind.stylus,
|
||||
PointerDeviceKind.unknown
|
||||
PointerDeviceKind.unknown,
|
||||
},
|
||||
),
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
useMaterial3: true,
|
||||
colorScheme: ColorScheme.fromSeed(
|
||||
seedColor: Colors.deepPurple), // Set up color scheme
|
||||
useMaterial3: true, // Enable Material 3
|
||||
),
|
||||
home: const LoginPage(),
|
||||
home: isLoggedIn == 'Success'?
|
||||
const HomePage()
|
||||
:
|
||||
const LoginPage(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,8 @@ import 'package:syncrow_web/pages/auth/model/login_with_email_model.dart';
|
||||
import 'package:syncrow_web/pages/auth/model/token.dart';
|
||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
||||
import 'package:syncrow_web/services/auth_api.dart';
|
||||
import 'package:syncrow_web/utils/constants/strings_manager.dart';
|
||||
import 'package:syncrow_web/utils/helpers/shared_preferences_helper.dart';
|
||||
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||
|
||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
@ -20,16 +22,16 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
on<StopTimerEvent>(_onStopTimer);
|
||||
on<UpdateTimerEvent>(_onUpdateTimer);
|
||||
on<PasswordVisibleEvent>(_passwordVisible);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////// forget password //////////////////////////////////
|
||||
final TextEditingController forgetEmailController = TextEditingController();
|
||||
final TextEditingController forgetPasswordController = TextEditingController();
|
||||
final TextEditingController forgetOtp = TextEditingController();
|
||||
final forgetFormKey = GlobalKey<FormState>();
|
||||
|
||||
Timer? _timer;
|
||||
int _remainingTime = 0;
|
||||
|
||||
@ -53,7 +55,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
|
||||
print("Timer finished"); // Debug print
|
||||
} else {
|
||||
add(UpdateTimerEvent(remainingTime: _remainingTime, isButtonEnabled: false));
|
||||
add(UpdateTimerEvent(
|
||||
remainingTime: _remainingTime, isButtonEnabled: false));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -67,40 +70,49 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
||||
try {
|
||||
emit(LoadingForgetState());
|
||||
bool response = await AuthenticationAPI.verifyOtp(
|
||||
email: forgetEmailController.text, otpCode: forgetOtp.text);
|
||||
if (response == true) {
|
||||
await AuthenticationAPI.forgetPassword(
|
||||
password: forgetPasswordController.text, email: forgetEmailController.text);
|
||||
password: forgetPasswordController.text,
|
||||
email: forgetEmailController.text);
|
||||
_timer?.cancel();
|
||||
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
||||
}
|
||||
emit(SuccessForgetState());
|
||||
} catch (failure) {
|
||||
print(failure);
|
||||
emit(FailureForgetState(error: failure.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
|
||||
emit(TimerState(
|
||||
isButtonEnabled: event.isButtonEnabled,
|
||||
remainingTime: event.remainingTime));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////// login /////////////////////////////////////
|
||||
final TextEditingController loginEmailController = TextEditingController();
|
||||
final TextEditingController loginPasswordController = TextEditingController();
|
||||
final loginFormKey = GlobalKey<FormState>();
|
||||
bool isChecked = false;
|
||||
bool obscureText = false;
|
||||
|
||||
bool obscureText = true;
|
||||
String newPassword = '';
|
||||
String maskedEmail = '';
|
||||
String otpCode = '';
|
||||
|
||||
static Token token = Token.emptyConstructor();
|
||||
static UserModel? user;
|
||||
bool showValidationMessage = false;
|
||||
|
||||
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
|
||||
emit(LoginLoading());
|
||||
if(isChecked) {
|
||||
if (isChecked) {
|
||||
try {
|
||||
if (event.username.isEmpty || event.password.isEmpty) {
|
||||
CustomSnackBar.displaySnackBar('Please enter your credentials');
|
||||
@ -113,8 +125,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
password: event.password,
|
||||
),
|
||||
);
|
||||
}
|
||||
catch (failure) {
|
||||
} catch (failure) {
|
||||
emit(const LoginFailure(error: 'Something went wrong'));
|
||||
// emit(LoginFailure(error: failure.toString()));
|
||||
return;
|
||||
@ -124,11 +135,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||
await storage.write(
|
||||
key: Token.loginAccessTokenKey, value: token.accessToken);
|
||||
|
||||
const FlutterSecureStorage().write(
|
||||
key: UserModel.userUuidKey,
|
||||
value: Token.decodeToken(token.accessToken)['uuid'].toString()
|
||||
);
|
||||
value: Token.decodeToken(token.accessToken)['uuid'].toString());
|
||||
user = UserModel.fromToken(token);
|
||||
loginEmailController.clear();
|
||||
loginPasswordController.clear();
|
||||
@ -136,18 +145,24 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
} else {
|
||||
emit(const LoginFailure(error: 'Something went wrong'));
|
||||
}
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
emit(const LoginFailure(error: 'Accept terms and condition'));
|
||||
}
|
||||
}
|
||||
|
||||
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,){
|
||||
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,) {
|
||||
emit(LoginLoading());
|
||||
isChecked = event.newValue!;
|
||||
emit(LoginInitial());
|
||||
}
|
||||
|
||||
checkOtpCode(ChangePasswordEvent event, Emitter<AuthState> emit,) async {
|
||||
emit(LoadingForgetState());
|
||||
await AuthenticationAPI.verifyOtp(
|
||||
email: forgetEmailController.text, otpCode: forgetOtp.text);
|
||||
emit(SuccessForgetState());
|
||||
}
|
||||
|
||||
void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> emit) {
|
||||
emit(LoginLoading());
|
||||
obscureText = !event.newValue!;
|
||||
@ -161,8 +176,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
||||
String? validatePassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Password is required';
|
||||
@ -192,8 +207,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
emit(LoadingForgetState());
|
||||
final nameError = validateEmail(forgetEmailController.text);
|
||||
if (nameError != null) {
|
||||
emit(FailureForgetState(error:nameError )) ;
|
||||
// CustomSnackBar.displaySnackBar(nameError);
|
||||
emit(FailureForgetState(error: nameError));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -210,7 +224,6 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter your password';
|
||||
}
|
||||
|
||||
List<String> validationErrors = [];
|
||||
|
||||
if (!RegExp(r'^(?=.*[a-z])').hasMatch(value)) {
|
||||
@ -230,73 +243,30 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
}
|
||||
|
||||
if (validationErrors.isNotEmpty) {
|
||||
return 'Password must contain at least:\n' + validationErrors.join('\n');
|
||||
return 'Password must contain at least:\n${validationErrors.join('\n')}';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
String? fullNameValidator(String? value) {
|
||||
if (value == null) return 'Full name is required';
|
||||
|
||||
final withoutExtraSpaces = value.replaceAll(RegExp(r"\s+"), ' ').trim();
|
||||
|
||||
if (withoutExtraSpaces.length < 2 || withoutExtraSpaces.length > 30) {
|
||||
return 'Full name must be between 2 and 30 characters long';
|
||||
}
|
||||
|
||||
// Test if it contains anything but alphanumeric spaces and single quote
|
||||
|
||||
if (RegExp(r"/[^ a-zA-Z0-9-\']/").hasMatch(withoutExtraSpaces)) {
|
||||
return 'Only alphanumeric characters, space, dash and single quote are allowed';
|
||||
}
|
||||
|
||||
final parts = withoutExtraSpaces.split(' ');
|
||||
|
||||
if (parts.length < 2) return 'Full name must contain first and last names';
|
||||
|
||||
if (parts.length > 3) return 'Full name can at most contain 3 parts';
|
||||
|
||||
if (parts.any((part) => part.length < 2 || part.length > 30)) {
|
||||
return 'Full name parts must be between 2 and 30 characters long';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
String? reEnterPasswordCheckForgetPass(String? value) {
|
||||
passwordValidator(value);
|
||||
if (newPassword == value) {
|
||||
return null;
|
||||
} else {
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
}
|
||||
|
||||
String? emailAddressValidator(String? value) {
|
||||
if (value != null && value.isNotEmpty && value != "") {
|
||||
if (checkValidityOfEmail(value)) {
|
||||
return null;
|
||||
} else {
|
||||
return 'Please enter a valid email';
|
||||
}
|
||||
} else {
|
||||
return 'Email address is required';
|
||||
}
|
||||
}
|
||||
|
||||
bool checkValidityOfEmail(String? email) {
|
||||
if (email != null) {
|
||||
return RegExp(
|
||||
r"^[a-zA-Z0-9]+([.!#$%&'*+/=?^_`{|}~-]?[a-zA-Z0-9]+)*@[a-zA-Z0-9]+([.-]?[a-zA-Z0-9]+)*\.[a-zA-Z0-9]{2,}$")
|
||||
.hasMatch(email);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
String maskEmail(String email) {
|
||||
final emailParts = email.split('@');
|
||||
if (emailParts.length != 2) return email;
|
||||
@ -324,4 +294,36 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||
];
|
||||
|
||||
|
||||
static Future<String> getTokenAndValidate() async {
|
||||
try {
|
||||
const storage = FlutterSecureStorage();
|
||||
final firstLaunch = await SharedPreferencesHelper.readBoolFromSP(StringsManager.firstLaunch) ?? true;
|
||||
if (firstLaunch) {
|
||||
storage.deleteAll();
|
||||
}
|
||||
await SharedPreferencesHelper.saveBoolToSP(StringsManager.firstLaunch, false);
|
||||
final value = await storage.read(key: Token.loginAccessTokenKey) ?? '';
|
||||
if (value.isEmpty) {
|
||||
return 'Token not found';
|
||||
}
|
||||
final tokenData = Token.decodeToken(value);
|
||||
if (tokenData.containsKey('exp')) {
|
||||
final exp = tokenData['exp'] ?? 0;
|
||||
final currentTime = DateTime.now().millisecondsSinceEpoch ~/ 1000;
|
||||
if (currentTime < exp) {
|
||||
return 'Success';
|
||||
} else {
|
||||
return 'expired';
|
||||
}
|
||||
} else {
|
||||
return 'Something went wrong';
|
||||
}
|
||||
} catch (_) {
|
||||
return 'Something went wrong';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -9,6 +9,8 @@ abstract class AuthState extends Equatable {
|
||||
|
||||
class LoginInitial extends AuthState {}
|
||||
|
||||
class AuthTokenLoading extends AuthState {}
|
||||
|
||||
class LoginLoading extends AuthState {}
|
||||
|
||||
class LoginSuccess extends AuthState {}
|
||||
@ -38,6 +40,7 @@ class InitialForgetState extends AuthState{}
|
||||
class LoadingForgetState extends AuthState{}
|
||||
|
||||
class SuccessForgetState extends AuthState{}
|
||||
|
||||
class PasswordVisibleState extends AuthState{}
|
||||
|
||||
class FailureForgetState extends AuthState {
|
||||
@ -58,8 +61,18 @@ class TimerState extends AuthState {
|
||||
}
|
||||
|
||||
|
||||
class AuthError extends AuthState {
|
||||
final String message;
|
||||
String? code;
|
||||
AuthError({required this.message, this.code});
|
||||
}
|
||||
|
||||
class AuthTokenError extends AuthError {
|
||||
AuthTokenError({required super.message, super.code});
|
||||
}
|
||||
class AuthSuccess extends AuthState {}
|
||||
|
||||
class AuthTokenSuccess extends AuthSuccess {}
|
||||
|
||||
|
||||
// class AuthState extends AuthState {}
|
||||
|
@ -9,7 +9,6 @@ import 'package:syncrow_web/pages/common/first_layer.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
class ForgetPasswordWebPage extends StatelessWidget {
|
||||
const ForgetPasswordWebPage({super.key});
|
||||
|
||||
@ -21,7 +20,11 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
||||
child: BlocConsumer<AuthBloc, AuthState>(
|
||||
listener: (context, state) {
|
||||
if (state is LoadingForgetState) {
|
||||
} else if (state is FailureForgetState) {
|
||||
|
||||
} else if (state is SuccessForgetState){
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
else if (state is FailureForgetState) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.error),
|
||||
@ -138,10 +141,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Account",
|
||||
style: smallTextStyle,
|
||||
),
|
||||
Text("Account",
|
||||
style: smallTextStyle,),
|
||||
SizedBox(
|
||||
width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
child: TextFormField(
|
||||
|
@ -287,108 +287,7 @@ class LoginWebPage extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(5.0),
|
||||
// child: SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Expanded(child: Image.asset(Assets.liftLine)),
|
||||
// Expanded(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(5.0),
|
||||
// child: Text('Or sign in with',
|
||||
// style: smallTextStyle.copyWith(fontSize: 10),
|
||||
// ),
|
||||
// )
|
||||
// ),
|
||||
// Expanded(child: Image.asset(Assets.rightLine)),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// decoration: containerDecoration,
|
||||
// child:InkWell(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// SvgPicture.asset(
|
||||
// Assets.google,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// const Flexible(
|
||||
// child: Text('Google',
|
||||
// style: TextStyle(color: Colors.black),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 10,),
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// decoration: containerDecoration,
|
||||
// child:InkWell(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// SvgPicture.asset(
|
||||
// Assets.facebook,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// const Flexible(
|
||||
// child: Text('Facebook',
|
||||
// style: TextStyle(color: Colors.black),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
//
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Don't you have an account? ",
|
||||
// style: TextStyle(color: Colors.white),
|
||||
// )),
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Sign up",
|
||||
// )),
|
||||
// ],
|
||||
// ),
|
||||
// )
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -403,3 +302,105 @@ class LoginWebPage extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.all(5.0),
|
||||
// child: SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Expanded(child: Image.asset(Assets.liftLine)),
|
||||
// Expanded(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(5.0),
|
||||
// child: Text('Or sign in with',
|
||||
// style: smallTextStyle.copyWith(fontSize: 10),
|
||||
// ),
|
||||
// )
|
||||
// ),
|
||||
// Expanded(child: Image.asset(Assets.rightLine)),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: Row(
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// decoration: containerDecoration,
|
||||
// child:InkWell(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// SvgPicture.asset(
|
||||
// Assets.google,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// const Flexible(
|
||||
// child: Text('Google',
|
||||
// style: TextStyle(color: Colors.black),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(width: 10,),
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// decoration: containerDecoration,
|
||||
// child:InkWell(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(8.0),
|
||||
// child: Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// SvgPicture.asset(
|
||||
// Assets.facebook,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// const Flexible(
|
||||
// child: Text('Facebook',
|
||||
// style: TextStyle(color: Colors.black),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// onTap: () {},
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
//
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// SizedBox(
|
||||
// width: MediaQuery.sizeOf(context).width * 0.2,
|
||||
// child: const Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.center,
|
||||
// children: [
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Don't you have an account? ",
|
||||
// style: TextStyle(color: Colors.white),
|
||||
// )),
|
||||
// Flexible(
|
||||
// child: Text(
|
||||
// "Sign up",
|
||||
// )),
|
||||
// ],
|
||||
// ),
|
||||
// )
|
@ -1,3 +1,5 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:syncrow_web/pages/auth/model/token.dart';
|
||||
import 'package:syncrow_web/services/api/http_service.dart';
|
||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||
@ -43,17 +45,23 @@ class AuthenticationAPI {
|
||||
return response;
|
||||
}
|
||||
|
||||
static Future checkOtp({ required var email}) async {
|
||||
static Future<bool> verifyOtp({ required String email, required String otpCode}) async {
|
||||
final response = await HTTPService().post(
|
||||
path: ApiEndpoints.sendOtp,
|
||||
path: ApiEndpoints.verifyOtp,
|
||||
body: {
|
||||
"email": email,
|
||||
"type": "VERIFICATION"
|
||||
"type": "VERIFICATION",
|
||||
"otpCode": otpCode
|
||||
},
|
||||
showServerMessage: true,
|
||||
expectedResponseModel: (json) {
|
||||
print('json===${json['message']}');
|
||||
if(json['message']=='Otp Verified Successfully'){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
@ -7,4 +7,5 @@ abstract class ApiEndpoints {
|
||||
static const String login = '$baseUrl/authentication/user/login';
|
||||
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
|
||||
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
|
||||
static const String verifyOtp = '$baseUrl/authentication/user/verify-otp';
|
||||
}
|
||||
|
43
lib/utils/constants/strings_manager.dart
Normal file
43
lib/utils/constants/strings_manager.dart
Normal file
@ -0,0 +1,43 @@
|
||||
class StringsManager {
|
||||
static const noRouteFound = 'No route found';
|
||||
static const noInternetConnection = 'No internet connection';
|
||||
static const String dashboard = 'Dashboard';
|
||||
static const String devices = 'Devices';
|
||||
static const String routine = 'Routines';
|
||||
static const String tapToRunRoutine = 'Tap to run routine';
|
||||
static const String wizard = 'Wizard';
|
||||
static const String active = 'Active';
|
||||
static const String current = 'Current';
|
||||
static const String frequency = 'Frequency';
|
||||
static const String energyUsage = 'Energy Usage';
|
||||
static const String totalConsumption = 'Total Consumption';
|
||||
static const String ACConsumption = 'AC Consumption';
|
||||
static const String units = 'Units';
|
||||
static const String emissions = 'Emissions';
|
||||
static const String reductions = 'Reductions';
|
||||
static const String winter = 'Winter';
|
||||
static const String winterMode = 'Winter Mode';
|
||||
static const String summer = 'Summer';
|
||||
static const String summerMode = 'Summer Mode';
|
||||
static const String on = 'ON';
|
||||
static const String off = 'OFF';
|
||||
static const String timer = 'Timer';
|
||||
static const String dimmerAndColor = "Dimmer & color";
|
||||
static const String recentlyUsed = "Recently used colors";
|
||||
static const String lightingModes = "Lighting modes";
|
||||
static const String doze = "Doze";
|
||||
static const String relax = "Relax";
|
||||
static const String reading = "Reading";
|
||||
static const String energizing = "Energizing";
|
||||
static const String createScene = 'Create Scene';
|
||||
static const String tapToRun = 'Launch: Tap - To - Run';
|
||||
static const String turnOffAllLights =
|
||||
'Example: turn off all lights in the with one tap.';
|
||||
static const String whenDeviceStatusChanges = 'When device status changes';
|
||||
static const String whenUnusualActivityIsDetected =
|
||||
'Example: when an unusual activity is detected.';
|
||||
static const String functions = "Functions";
|
||||
static const String firstLaunch = "firstLaunch";
|
||||
static const String deleteScene = 'Delete Scene';
|
||||
static const String deleteAutomation = 'Delete Automation';
|
||||
}
|
58
lib/utils/helpers/shared_preferences_helper.dart
Normal file
58
lib/utils/helpers/shared_preferences_helper.dart
Normal file
@ -0,0 +1,58 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class SharedPreferencesHelper {
|
||||
static saveStringToSP(String key, String value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(key, value);
|
||||
}
|
||||
|
||||
static saveBoolToSP(String key, bool value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool(key, value);
|
||||
}
|
||||
|
||||
static saveIntToSP(String key, int value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setInt(key, value);
|
||||
}
|
||||
|
||||
static saveDoubleToSP(String key, double value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setDouble(key, value);
|
||||
}
|
||||
|
||||
static saveStringListToSP(String key, List<String> value) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setStringList(key, value);
|
||||
}
|
||||
|
||||
static Future<String> readStringFromSP(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
String value = prefs.getString(key) ?? '';
|
||||
return value;
|
||||
}
|
||||
|
||||
static Future<bool?> readBoolFromSP(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
bool? value = prefs.getBool(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
static Future<int> readIntFromSP(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
int value = prefs.getInt(key) ?? 0;
|
||||
return value;
|
||||
}
|
||||
|
||||
static Future<List<String>> readStringListFromSP(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
List<String>? value = prefs.getStringList(key) ?? [];
|
||||
return value;
|
||||
}
|
||||
|
||||
static Future<bool> removeValueFromSP(String key) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(key);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -7,8 +7,10 @@ import Foundation
|
||||
|
||||
import flutter_secure_storage_macos
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
}
|
||||
|
68
pubspec.lock
68
pubspec.lock
@ -105,6 +105,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -392,6 +400,62 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.2"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: c3f888ba2d659f3e75f4686112cc1e71f46177f74452d40d8307edc332296ead
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "041be4d9d2dc6079cf342bc8b761b03787e3b71192d658220a56cac9c04a0294"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "671e7a931f55a08aa45be2a13fe7247f2a41237897df434b30d2012388191833"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.0"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "2ba0510d3017f91655b7543e9ee46d48619de2a2af38e5c790423f7007c7ccc1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: "3a293170d4d9403c3254ee05b84e62e8a9b3c5808ebd17de6a33fe9ea6457936"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "398084b47b7f92110683cac45c6dc4aae853db47e470e5ddcd52cab7f7196ab2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.0"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@ -497,10 +561,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
|
||||
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
version: "0.5.1"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -42,7 +42,7 @@ dependencies:
|
||||
dio: ^5.5.0+1
|
||||
get_it: ^7.6.7
|
||||
flutter_secure_storage: ^9.2.2
|
||||
|
||||
shared_preferences: ^2.3.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
@ -1,30 +0,0 @@
|
||||
// This is a basic Flutter widget test.
|
||||
//
|
||||
// To perform an interaction with a widget in your test, use the WidgetTester
|
||||
// utility in the flutter_test package. For example, you can send tap and scroll
|
||||
// gestures. You can also use WidgetTester to find child widgets in the widget
|
||||
// tree, read text, and verify that the values of widget properties are correct.
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import 'package:syncrow_web/main.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
|
||||
// Build our app and trigger a frame.
|
||||
await tester.pumpWidget(const MyApp());
|
||||
|
||||
// Verify that our counter starts at 0.
|
||||
expect(find.text('0'), findsOneWidget);
|
||||
expect(find.text('1'), findsNothing);
|
||||
|
||||
// Tap the '+' icon and trigger a frame.
|
||||
await tester.tap(find.byIcon(Icons.add));
|
||||
await tester.pump();
|
||||
|
||||
// Verify that our counter has incremented.
|
||||
expect(find.text('0'), findsNothing);
|
||||
expect(find.text('1'), findsOneWidget);
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user