first commit

This commit is contained in:
2026-02-07 15:57:09 +07:00
commit 157096f164
1153 changed files with 415766 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:mobile_pos/Screens/Authentication/forgot%20password/repo/forgot_pass_repo.dart';
import 'package:mobile_pos/generated/l10n.dart' as lang;
import '../../../GlobalComponents/glonal_popup.dart';
import '../../../constant.dart';
import '../Sign Up/verify_email.dart';
import '../Wedgets/check_email_for_otp_popup.dart';
class ForgotPassword extends StatefulWidget {
const ForgotPassword({
Key? key,
}) : super(key: key);
@override
State<ForgotPassword> createState() => _ForgotPasswordState();
}
class _ForgotPasswordState extends State<ForgotPassword> {
final _formKey = GlobalKey<FormState>();
bool isClicked = false;
final TextEditingController _emailController = TextEditingController();
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final _theme = Theme.of(context);
TextTheme textTheme = Theme.of(context).textTheme;
return GlobalPopup(
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
titleSpacing: 16,
backgroundColor: kWhite,
surfaceTintColor: kWhite,
centerTitle: true,
title: Text(
// 'Forgot Password',
lang.S.of(context).forgotPassword,
style: textTheme.titleMedium?.copyWith(fontSize: 18),
),
),
body: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 20.0, 16.0, 0.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
// 'Forgot Password',
lang.S.of(context).forgotPassword,
style: textTheme.titleMedium?.copyWith(fontSize: 24.0),
),
const SizedBox(height: 8.0),
Text(
//'Reset password by using your email or phone number',
lang.S.of(context).reset,
style: textTheme.bodyMedium?.copyWith(color: kGreyTextColor, fontSize: 16),
textAlign: TextAlign.center,
),
const SizedBox(height: 24.0),
TextFormField(
controller: _emailController,
keyboardType: TextInputType.emailAddress,
decoration: kInputDecoration.copyWith(
// labelText: 'Email',
labelText: lang.S.of(context).lableEmail,
// hintText: 'Enter email address',
hintText: lang.S.of(context).hintEmail,
),
validator: (value) {
if (value == null || value.isEmpty) {
//return 'Email can\'t be empty';
return lang.S.of(context).emailCannotBeEmpty;
} else if (!value.contains('@')) {
// return 'Please enter a valid email';
return lang.S.of(context).pleaseEnterAValidEmail;
}
return null;
},
),
const SizedBox(height: 24.0),
ElevatedButton(
style: OutlinedButton.styleFrom(
maximumSize: const Size(double.infinity, 48),
minimumSize: const Size(double.infinity, 48),
disabledBackgroundColor: _theme.colorScheme.primary.withValues(alpha: 0.15),
),
onPressed: () async {
if (isClicked) {
return;
}
if (_formKey.currentState?.validate() ?? false) {
isClicked = true;
EasyLoading.show();
ForgotPassRepo repo = ForgotPassRepo();
if (await repo.forgotPass(email: _emailController.text, context: context)) {
if (await checkEmailForCodePupUp(
email: _emailController.text, context: context, textTheme: textTheme)) {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => VerifyEmail(
email: _emailController.text,
isFormForgotPass: true,
),
),
);
}
} else {
isClicked = false;
}
}
},
child: Text(
lang.S.of(context).continueE,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: _theme.textTheme.bodyMedium?.copyWith(
color: _theme.colorScheme.primaryContainer,
fontWeight: FontWeight.w600,
fontSize: 16,
),
),
),
],
),
),
),
),
);
}
}

View File

@@ -0,0 +1,102 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:http/http.dart' as http;
import '../../../../Const/api_config.dart';
class ForgotPassRepo {
Future<bool> forgotPass({required String email, required BuildContext context}) async {
final url = Uri.parse('${APIConfig.url}/send-reset-code');
final body = {
'email': email,
};
final headers = {
'Accept': 'application/json',
};
try {
final response = await http.post(url, headers: headers, body: body);
final responseData = jsonDecode(response.body);
EasyLoading.dismiss();
if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['message'])));
return true;
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['message'])));
}
} catch (error) {
print(error);
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Network error: Please try again')));
} finally {}
return false;
}
Future<bool> verifyOTPForgotPass({required String email, required String otp, required BuildContext context}) async {
final url = Uri.parse('${APIConfig.url}/verify-reset-code');
final body = {
'email': email,
'code': otp,
};
final headers = {
'Accept': 'application/json',
};
try {
final response = await http.post(url, headers: headers, body: body);
final responseData = jsonDecode(response.body);
print(response.body);
EasyLoading.dismiss();
if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['message'])));
return true;
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['error'])));
}
} catch (error) {
print(error);
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Network error: Please try again')));
} finally {}
return false;
}
Future<bool> resetPass({required String email, required String password, required BuildContext context}) async {
final url = Uri.parse('${APIConfig.url}/password-reset');
final body = {
'email': email,
"password": password,
};
final headers = {
'Accept': 'application/json',
};
try {
final response = await http.post(url, headers: headers, body: body);
final responseData = jsonDecode(response.body);
EasyLoading.dismiss();
if (response.statusCode == 200) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['message'])));
return true;
} else {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(responseData['message'])));
}
} catch (error) {
print(error);
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Network error: Please try again')));
} finally {}
return false;
}
}

View File

@@ -0,0 +1,165 @@
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_feather_icons/flutter_feather_icons.dart';
import 'package:mobile_pos/Screens/Authentication/forgot%20password/repo/forgot_pass_repo.dart';
import 'package:mobile_pos/generated/l10n.dart' as lang;
import '../../../GlobalComponents/glonal_popup.dart';
import '../../../constant.dart';
class SetNewPassword extends StatefulWidget {
const SetNewPassword({super.key, required this.email});
final String email;
@override
State<SetNewPassword> createState() => _SetNewPasswordState();
}
class _SetNewPasswordState extends State<SetNewPassword> {
final _formKey = GlobalKey<FormState>();
bool isClicked = false;
final TextEditingController _passwordController = TextEditingController();
final TextEditingController _confirmPasswordController = TextEditingController();
bool showPassword = true;
bool showConfirmPassword = true;
@override
void dispose() {
_passwordController.dispose();
_confirmPasswordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
TextTheme textTheme = Theme.of(context).textTheme;
return GlobalPopup(
child: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
surfaceTintColor: kWhite,
backgroundColor: kWhite,
centerTitle: true,
titleSpacing: 16,
title: Text(
lang.S.of(context).createNewPassword,
//'Create New Password',
style: textTheme.titleMedium?.copyWith(fontSize: 18),
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.fromLTRB(16.0, 20.0, 16.0, 0.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text(
lang.S.of(context).setUpNewPassword,
// 'Set Up New Password',
style: textTheme.titleMedium?.copyWith(fontSize: 24.0),
),
const SizedBox(height: 8.0),
Text(
lang.S.of(context).resetPassword,
//'Reset your password to recovery and log in your account',
style: textTheme.bodyMedium?.copyWith(color: kGreyTextColor, fontSize: 16), textAlign: TextAlign.center,
),
const SizedBox(height: 24.0),
TextFormField(
controller: _passwordController,
keyboardType: TextInputType.text,
obscureText: showPassword,
decoration: kInputDecoration.copyWith(
// border: const OutlineInputBorder(),
hintText: '********',
//labelText: 'New Password',
labelText: lang.S.of(context).newPassword,
suffixIcon: IconButton(
onPressed: () {
setState(() {
showPassword = !showPassword;
});
},
icon: Icon(
showPassword ? FeatherIcons.eyeOff : FeatherIcons.eye,
color: kGreyTextColor,
),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
//return 'Password can\'t be empty';
return lang.S.of(context).passwordCannotBeEmpty;
} else if (value.length < 6) {
//return 'Please enter a bigger password';
return lang.S.of(context).pleaseEnterABiggerPassword;
}
return null;
},
),
const SizedBox(height: 20.0),
TextFormField(
controller: _confirmPasswordController,
keyboardType: TextInputType.text,
obscureText: showConfirmPassword,
decoration: kInputDecoration.copyWith(
border: const OutlineInputBorder(),
//labelText: 'Confirm Password',
labelText: lang.S.of(context).confirmPassword,
hintText: '********',
suffixIcon: IconButton(
onPressed: () {
setState(() {
showConfirmPassword = !showConfirmPassword;
});
},
icon: Icon(
showConfirmPassword ? FeatherIcons.eyeOff : FeatherIcons.eye,
color: kGreyTextColor,
),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
//return 'Password can\'t be empty';
return lang.S.of(context).passwordCannotBeEmpty;
} else if (value != _passwordController.text) {
//return 'Passwords do not match';
return lang.S.of(context).passwordsDoNotMatch;
}
return null;
},
),
const SizedBox(height: 24.0),
ElevatedButton(
onPressed: () async {
if (isClicked) {
return;
}
if (_formKey.currentState?.validate() ?? false) {
isClicked = true;
EasyLoading.show();
ForgotPassRepo repo = ForgotPassRepo();
if (await repo.resetPass(email: widget.email, password: _confirmPasswordController.text, context: context)) {
Navigator.pop(context);
} else {
isClicked = false;
}
}
},
child: Text(lang.S.of(context).save),
//'Save',
),
],
),
),
),
),
),
);
}
}