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/gestures.dart';
|
||||||
import 'package:flutter/material.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/auth/view/login_page.dart';
|
||||||
|
import 'package:syncrow_web/pages/home/view/home_page.dart';
|
||||||
import 'package:syncrow_web/services/locator.dart';
|
import 'package:syncrow_web/services/locator.dart';
|
||||||
void main() {
|
|
||||||
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
initialSetup();
|
initialSetup(); // Perform initial setup, e.g., dependency injection
|
||||||
runApp(const MyApp());
|
String res = await AuthBloc.getTokenAndValidate();
|
||||||
|
runApp(MyApp(
|
||||||
|
isLoggedIn: res,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
class MyApp extends StatelessWidget {
|
class MyApp extends StatelessWidget {
|
||||||
const MyApp({super.key});
|
final dynamic isLoggedIn;
|
||||||
|
const MyApp({
|
||||||
|
super.key,
|
||||||
|
required this.isLoggedIn,
|
||||||
|
});
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false, // Hide debug banner
|
||||||
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
scrollBehavior: const MaterialScrollBehavior().copyWith(
|
||||||
dragDevices: {
|
dragDevices: {
|
||||||
PointerDeviceKind.mouse,
|
PointerDeviceKind.mouse,
|
||||||
PointerDeviceKind.touch,
|
PointerDeviceKind.touch,
|
||||||
PointerDeviceKind.stylus,
|
PointerDeviceKind.stylus,
|
||||||
PointerDeviceKind.unknown
|
PointerDeviceKind.unknown,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
colorScheme: ColorScheme.fromSeed(
|
||||||
useMaterial3: true,
|
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/token.dart';
|
||||||
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
import 'package:syncrow_web/pages/auth/model/user_model.dart';
|
||||||
import 'package:syncrow_web/services/auth_api.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';
|
import 'package:syncrow_web/utils/snack_bar.dart';
|
||||||
|
|
||||||
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
||||||
@ -20,16 +22,16 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
on<StopTimerEvent>(_onStopTimer);
|
on<StopTimerEvent>(_onStopTimer);
|
||||||
on<UpdateTimerEvent>(_onUpdateTimer);
|
on<UpdateTimerEvent>(_onUpdateTimer);
|
||||||
on<PasswordVisibleEvent>(_passwordVisible);
|
on<PasswordVisibleEvent>(_passwordVisible);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
////////////////////////////// forget password //////////////////////////////////
|
////////////////////////////// forget password //////////////////////////////////
|
||||||
final TextEditingController forgetEmailController = TextEditingController();
|
final TextEditingController forgetEmailController = TextEditingController();
|
||||||
final TextEditingController forgetPasswordController = TextEditingController();
|
final TextEditingController forgetPasswordController = TextEditingController();
|
||||||
final TextEditingController forgetOtp = TextEditingController();
|
final TextEditingController forgetOtp = TextEditingController();
|
||||||
final forgetFormKey = GlobalKey<FormState>();
|
final forgetFormKey = GlobalKey<FormState>();
|
||||||
|
|
||||||
Timer? _timer;
|
Timer? _timer;
|
||||||
int _remainingTime = 0;
|
int _remainingTime = 0;
|
||||||
|
|
||||||
@ -53,7 +55,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
|
add(const UpdateTimerEvent(remainingTime: 0, isButtonEnabled: true));
|
||||||
print("Timer finished"); // Debug print
|
print("Timer finished"); // Debug print
|
||||||
} else {
|
} 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 {
|
ChangePasswordEvent event, Emitter<AuthState> emit) async {
|
||||||
try {
|
try {
|
||||||
emit(LoadingForgetState());
|
emit(LoadingForgetState());
|
||||||
await AuthenticationAPI.forgetPassword(
|
bool response = await AuthenticationAPI.verifyOtp(
|
||||||
password: forgetPasswordController.text, email: forgetEmailController.text);
|
email: forgetEmailController.text, otpCode: forgetOtp.text);
|
||||||
|
if (response == true) {
|
||||||
|
await AuthenticationAPI.forgetPassword(
|
||||||
|
password: forgetPasswordController.text,
|
||||||
|
email: forgetEmailController.text);
|
||||||
|
_timer?.cancel();
|
||||||
|
emit(const TimerState(isButtonEnabled: true, remainingTime: 0));
|
||||||
|
}
|
||||||
emit(SuccessForgetState());
|
emit(SuccessForgetState());
|
||||||
} catch (failure) {
|
} catch (failure) {
|
||||||
print(failure);
|
|
||||||
emit(FailureForgetState(error: failure.toString()));
|
emit(FailureForgetState(error: failure.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
|
void _onUpdateTimer(UpdateTimerEvent event, Emitter<AuthState> emit) {
|
||||||
emit(TimerState(
|
emit(TimerState(
|
||||||
isButtonEnabled: event.isButtonEnabled,
|
isButtonEnabled: event.isButtonEnabled,
|
||||||
remainingTime: event.remainingTime));
|
remainingTime: event.remainingTime));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////// login /////////////////////////////////////
|
///////////////////////////////////// login /////////////////////////////////////
|
||||||
final TextEditingController loginEmailController = TextEditingController();
|
final TextEditingController loginEmailController = TextEditingController();
|
||||||
final TextEditingController loginPasswordController = TextEditingController();
|
final TextEditingController loginPasswordController = TextEditingController();
|
||||||
final loginFormKey = GlobalKey<FormState>();
|
final loginFormKey = GlobalKey<FormState>();
|
||||||
bool isChecked = false;
|
bool isChecked = false;
|
||||||
bool obscureText = false;
|
bool obscureText = true;
|
||||||
|
|
||||||
String newPassword = '';
|
String newPassword = '';
|
||||||
String maskedEmail = '';
|
String maskedEmail = '';
|
||||||
String otpCode = '';
|
String otpCode = '';
|
||||||
|
|
||||||
static Token token = Token.emptyConstructor();
|
static Token token = Token.emptyConstructor();
|
||||||
static UserModel? user;
|
static UserModel? user;
|
||||||
bool showValidationMessage = false;
|
bool showValidationMessage = false;
|
||||||
|
|
||||||
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
|
void _login(LoginButtonPressed event, Emitter<AuthState> emit) async {
|
||||||
emit(LoginLoading());
|
emit(LoginLoading());
|
||||||
if(isChecked) {
|
if (isChecked) {
|
||||||
try {
|
try {
|
||||||
if (event.username.isEmpty || event.password.isEmpty) {
|
if (event.username.isEmpty || event.password.isEmpty) {
|
||||||
CustomSnackBar.displaySnackBar('Please enter your credentials');
|
CustomSnackBar.displaySnackBar('Please enter your credentials');
|
||||||
@ -113,8 +125,7 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
password: event.password,
|
password: event.password,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
} catch (failure) {
|
||||||
catch (failure) {
|
|
||||||
emit(const LoginFailure(error: 'Something went wrong'));
|
emit(const LoginFailure(error: 'Something went wrong'));
|
||||||
// emit(LoginFailure(error: failure.toString()));
|
// emit(LoginFailure(error: failure.toString()));
|
||||||
return;
|
return;
|
||||||
@ -124,11 +135,9 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
FlutterSecureStorage storage = const FlutterSecureStorage();
|
FlutterSecureStorage storage = const FlutterSecureStorage();
|
||||||
await storage.write(
|
await storage.write(
|
||||||
key: Token.loginAccessTokenKey, value: token.accessToken);
|
key: Token.loginAccessTokenKey, value: token.accessToken);
|
||||||
|
|
||||||
const FlutterSecureStorage().write(
|
const FlutterSecureStorage().write(
|
||||||
key: UserModel.userUuidKey,
|
key: UserModel.userUuidKey,
|
||||||
value: Token.decodeToken(token.accessToken)['uuid'].toString()
|
value: Token.decodeToken(token.accessToken)['uuid'].toString());
|
||||||
);
|
|
||||||
user = UserModel.fromToken(token);
|
user = UserModel.fromToken(token);
|
||||||
loginEmailController.clear();
|
loginEmailController.clear();
|
||||||
loginPasswordController.clear();
|
loginPasswordController.clear();
|
||||||
@ -136,18 +145,24 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
} else {
|
} else {
|
||||||
emit(const LoginFailure(error: 'Something went wrong'));
|
emit(const LoginFailure(error: 'Something went wrong'));
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
emit(const LoginFailure(error: 'Accept terms and condition'));
|
emit(const LoginFailure(error: 'Accept terms and condition'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,){
|
checkBoxToggle(CheckBoxEvent event, Emitter<AuthState> emit,) {
|
||||||
emit(LoginLoading());
|
emit(LoginLoading());
|
||||||
isChecked = event.newValue!;
|
isChecked = event.newValue!;
|
||||||
emit(LoginInitial());
|
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) {
|
void _passwordVisible(PasswordVisibleEvent event, Emitter<AuthState> emit) {
|
||||||
emit(LoginLoading());
|
emit(LoginLoading());
|
||||||
obscureText = !event.newValue!;
|
obscureText = !event.newValue!;
|
||||||
@ -161,8 +176,8 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
|
||||||
|
|
||||||
|
/////////////////////////////////////VALIDATORS/////////////////////////////////////
|
||||||
String? validatePassword(String? value) {
|
String? validatePassword(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Password is required';
|
return 'Password is required';
|
||||||
@ -192,25 +207,23 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
emit(LoadingForgetState());
|
emit(LoadingForgetState());
|
||||||
final nameError = validateEmail(forgetEmailController.text);
|
final nameError = validateEmail(forgetEmailController.text);
|
||||||
if (nameError != null) {
|
if (nameError != null) {
|
||||||
emit(FailureForgetState(error:nameError )) ;
|
emit(FailureForgetState(error: nameError));
|
||||||
// CustomSnackBar.displaySnackBar(nameError);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? validateRegion(String? value) {
|
String? validateRegion(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please select a region';
|
return 'Please select a region';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String? passwordValidator(String? value) {
|
String? passwordValidator(String? value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Please enter your password';
|
return 'Please enter your password';
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> validationErrors = [];
|
List<String> validationErrors = [];
|
||||||
|
|
||||||
if (!RegExp(r'^(?=.*[a-z])').hasMatch(value)) {
|
if (!RegExp(r'^(?=.*[a-z])').hasMatch(value)) {
|
||||||
@ -230,73 +243,30 @@ class AuthBloc extends Bloc<AuthEvent, AuthState> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (validationErrors.isNotEmpty) {
|
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;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
String? fullNameValidator(String? value) {
|
String? fullNameValidator(String? value) {
|
||||||
if (value == null) return 'Full name is required';
|
if (value == null) return 'Full name is required';
|
||||||
|
|
||||||
final withoutExtraSpaces = value.replaceAll(RegExp(r"\s+"), ' ').trim();
|
final withoutExtraSpaces = value.replaceAll(RegExp(r"\s+"), ' ').trim();
|
||||||
|
|
||||||
if (withoutExtraSpaces.length < 2 || withoutExtraSpaces.length > 30) {
|
if (withoutExtraSpaces.length < 2 || withoutExtraSpaces.length > 30) {
|
||||||
return 'Full name must be between 2 and 30 characters long';
|
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)) {
|
if (RegExp(r"/[^ a-zA-Z0-9-\']/").hasMatch(withoutExtraSpaces)) {
|
||||||
return 'Only alphanumeric characters, space, dash and single quote are allowed';
|
return 'Only alphanumeric characters, space, dash and single quote are allowed';
|
||||||
}
|
}
|
||||||
|
|
||||||
final parts = withoutExtraSpaces.split(' ');
|
final parts = withoutExtraSpaces.split(' ');
|
||||||
|
|
||||||
if (parts.length < 2) return 'Full name must contain first and last names';
|
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.length > 3) return 'Full name can at most contain 3 parts';
|
||||||
|
|
||||||
if (parts.any((part) => part.length < 2 || part.length > 30)) {
|
if (parts.any((part) => part.length < 2 || part.length > 30)) {
|
||||||
return 'Full name parts must be between 2 and 30 characters long';
|
return 'Full name parts must be between 2 and 30 characters long';
|
||||||
}
|
}
|
||||||
return null;
|
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) {
|
String maskEmail(String email) {
|
||||||
final emailParts = email.split('@');
|
final emailParts = email.split('@');
|
||||||
if (emailParts.length != 2) return email;
|
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 LoginInitial extends AuthState {}
|
||||||
|
|
||||||
|
class AuthTokenLoading extends AuthState {}
|
||||||
|
|
||||||
class LoginLoading extends AuthState {}
|
class LoginLoading extends AuthState {}
|
||||||
|
|
||||||
class LoginSuccess extends AuthState {}
|
class LoginSuccess extends AuthState {}
|
||||||
@ -38,6 +40,7 @@ class InitialForgetState extends AuthState{}
|
|||||||
class LoadingForgetState extends AuthState{}
|
class LoadingForgetState extends AuthState{}
|
||||||
|
|
||||||
class SuccessForgetState extends AuthState{}
|
class SuccessForgetState extends AuthState{}
|
||||||
|
|
||||||
class PasswordVisibleState extends AuthState{}
|
class PasswordVisibleState extends AuthState{}
|
||||||
|
|
||||||
class FailureForgetState 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 {}
|
// 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/color_manager.dart';
|
||||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||||
import 'package:syncrow_web/utils/style.dart';
|
import 'package:syncrow_web/utils/style.dart';
|
||||||
|
|
||||||
class ForgetPasswordWebPage extends StatelessWidget {
|
class ForgetPasswordWebPage extends StatelessWidget {
|
||||||
const ForgetPasswordWebPage({super.key});
|
const ForgetPasswordWebPage({super.key});
|
||||||
|
|
||||||
@ -21,7 +20,11 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
child: BlocConsumer<AuthBloc, AuthState>(
|
child: BlocConsumer<AuthBloc, AuthState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is LoadingForgetState) {
|
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(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(state.error),
|
content: Text(state.error),
|
||||||
@ -138,10 +141,8 @@ class ForgetPasswordWebPage extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text("Account",
|
||||||
"Account",
|
style: smallTextStyle,),
|
||||||
style: smallTextStyle,
|
|
||||||
),
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.sizeOf(context).width * 0.2,
|
width: MediaQuery.sizeOf(context).width * 0.2,
|
||||||
child: TextFormField(
|
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/pages/auth/model/token.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
import 'package:syncrow_web/utils/constants/api_const.dart';
|
import 'package:syncrow_web/utils/constants/api_const.dart';
|
||||||
@ -43,17 +45,23 @@ class AuthenticationAPI {
|
|||||||
return response;
|
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(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.sendOtp,
|
path: ApiEndpoints.verifyOtp,
|
||||||
body: {
|
body: {
|
||||||
"email": email,
|
"email": email,
|
||||||
"type": "VERIFICATION"
|
"type": "VERIFICATION",
|
||||||
|
"otpCode": otpCode
|
||||||
},
|
},
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
|
print('json===${json['message']}');
|
||||||
|
if(json['message']=='Otp Verified Successfully'){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,5 @@ abstract class ApiEndpoints {
|
|||||||
static const String login = '$baseUrl/authentication/user/login';
|
static const String login = '$baseUrl/authentication/user/login';
|
||||||
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
|
static const String forgetPassword = '$baseUrl/authentication/user/forget-password';
|
||||||
static const String sendOtp = '$baseUrl/authentication/user/send-otp';
|
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 flutter_secure_storage_macos
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
|
import shared_preferences_foundation
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
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"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.2"
|
||||||
|
file:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: file
|
||||||
|
sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "7.0.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -392,6 +400,62 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.2"
|
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:
|
sky_engine:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description: flutter
|
description: flutter
|
||||||
@ -497,10 +561,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: web
|
name: web
|
||||||
sha256: d43c1d6b787bf0afad444700ae7f4db8827f701bc61c255ac8d328c6f4d52062
|
sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "0.5.1"
|
||||||
win32:
|
win32:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -42,7 +42,7 @@ dependencies:
|
|||||||
dio: ^5.5.0+1
|
dio: ^5.5.0+1
|
||||||
get_it: ^7.6.7
|
get_it: ^7.6.7
|
||||||
flutter_secure_storage: ^9.2.2
|
flutter_secure_storage: ^9.2.2
|
||||||
|
shared_preferences: ^2.3.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
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