1)User Login api Integrate

2)Forgot Password api Integrate
3)Change Password api Integrate and ChangePassword UI Create
This commit is contained in:
saritabirare 2024-08-27 15:57:28 +05:30
parent 37e8ebbe30
commit 7aa59ca145
7 changed files with 292 additions and 5 deletions

View File

@ -2,7 +2,7 @@ import 'package:cheminova/screens/splash_screen.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
void main() {
void main()async{
runApp(const MyApp());
}
@ -12,6 +12,7 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: SplashScreen(),
);
}

View File

@ -0,0 +1,181 @@
import 'package:cheminova/widgets/custom_button.dart';
import 'package:cheminova/widgets/input_field.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import '../../utils/show_snackbar.dart';
import 'controller/auth_controller.dart';
class ChangePasswordScreen extends StatefulWidget {
const ChangePasswordScreen({super.key});
@override
State<ChangePasswordScreen> createState() => _ChangePasswordScreenState();
}
class _ChangePasswordScreenState extends State<ChangePasswordScreen> {
final authController = Get.put(AuthController());
void dispose() {
authController.currentpassController.dispose();
authController.newpassController.dispose();
authController.confirmpassController.dispose();
super.dispose();
}
void validateAndChangePassword() async {
String oldPassword = authController.currentpassController.text.trim();
String newPassword = authController.newpassController.text.trim();
String confirmPassword = authController.confirmpassController.text.trim();
if (newPassword.isEmpty || confirmPassword.isEmpty || oldPassword.isEmpty) {
showSnackbar('All fields are required');
return;
}
if (newPassword.length < 8) {
showSnackbar('Password must be at least 8 characters long');
return;
}
if (!RegExp(r'[!@#$%^&*(),.?":{}|<>]').hasMatch(newPassword)) {
showSnackbar('Password must contain at least one special character');
return;
}
if (newPassword != confirmPassword) {
showSnackbar('New Password and Confirm Password do not match');
return;
}
authController.changePassword();
}
@override
Widget build(BuildContext context) {
return Scaffold(
extendBodyBehindAppBar: true,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
leading: GestureDetector(
onTap: () => Get.back(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SizedBox(
width: 20,
height: 20,
child: SvgPicture.asset('assets/svg/menu.svg')),
),
),
actions: [
GestureDetector(
onTap: () => Get.back(),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: SvgPicture.asset('assets/svg/back_arrow.svg'),
),
),
],
),
body: Stack(
alignment: Alignment.topCenter,
children: [
Container(
decoration: const BoxDecoration(
image: DecorationImage(
fit: BoxFit.cover,
image: AssetImage(
'assets/images/image_1.png',
),
),
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(50.0),
bottomRight: Radius.circular(50.0),
),
),
child: SizedBox(
width: Get.width,
height: Get.height * 0.7,
),
),
Center(
child: SingleChildScrollView(
child: Card(
margin: const EdgeInsets.symmetric(horizontal: 24),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(19),
side: const BorderSide(color: Color(0xFFFDFDFD)),
),
color: const Color(0xFFB4D1E5).withOpacity(0.9),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
Container(
padding: const EdgeInsets.only(bottom: 10),
alignment: Alignment.centerLeft,
child: Text(
'Change Password',
style: GoogleFonts.getFont(
'Roboto',
fontWeight: FontWeight.w500,
fontSize: 30,
height: 1.2,
),
),
),
InputField(
hintText: "Current Password",
labelText: "Current Password",
controller: authController.currentpassController,
obscureText: true,
keyboardType: TextInputType.text,
),
const SizedBox(height: 15),
InputField(
hintText: "New Password",
labelText: "New Password",
obscureText: true,
controller: authController.newpassController,
keyboardType: TextInputType.text,
),
const SizedBox(height: 15),
InputField(
hintText: "Confirm Password",
labelText: "Confirm Password",
obscureText: true,
controller: authController.confirmpassController,
keyboardType: TextInputType.text,
),
const SizedBox(height: 30),
CustomButton(
text: "RESET PASSWORD",
onPressed: () async {
validateAndChangePassword();
},
isLoading: authController.isLoading.value,
)
],
),
),
),
),
),
],
),
);
}
}

View File

@ -2,6 +2,7 @@ import 'package:cheminova/screens/authentication/controller/auth_service.dart';
import 'package:cheminova/screens/home_screen.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';
class AuthController extends GetxController {
final authService = AuthService();
@ -9,6 +10,10 @@ class AuthController extends GetxController {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
TextEditingController phoneController = TextEditingController();
TextEditingController currentpassController = TextEditingController();
TextEditingController newpassController = TextEditingController();
TextEditingController confirmpassController = TextEditingController();
RxBool isLoading = false.obs;
Future<void> login() async {
@ -23,4 +28,53 @@ class AuthController extends GetxController {
Get.offAll(() => const HomeScreen());
}
}
Future<void> forgotpass() async{
isLoading.value = true;
final response = await authService.forgotPassword(
{
'email': emailController.text,
}
);
isLoading.value = false;
update();
if(response != null){
}
}
Future<void> changePassword() async {
isLoading.value = true;
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
if (token != null) {
final response = await authService.changePassword(
{
'oldPassword': currentpassController.text,
'newPassword': newpassController.text,
'confirmPassword': confirmpassController.text,
},
token: token, // Pass the token here
);
print("tokemn ,$token");
isLoading.value = false;
update();
if (response != null) {
Get.snackbar('Success', 'Password changed successfully');
} else {
Get.snackbar('Error', 'Failed to change password');
}
} else {
isLoading.value = false;
update();
Get.snackbar('Error', 'Token not found. Please login again.');
}
}
}

View File

@ -5,7 +5,7 @@ class AuthService {
Future<Map<String, dynamic>?> login(Map<String, dynamic> data) async {
try {
final response = await commonApiService<Map<String, dynamic>>(
url: '/api/territorymanager/login',
url: '/api/v1/user/login/',
method: 'POST',
body: data,
fromJson: (json) => json, // Simply return the JSON map as is
@ -16,4 +16,41 @@ class AuthService {
}
return null;
}
Future<Map<String, dynamic>?> forgotPassword(Map<String, dynamic> data) async {
try {
final response = await commonApiService<Map<String, dynamic>>(
url: '/api/v1/user/password/forgot',
method: 'POST',
body: data,
fromJson: (json) => json, // Simply return the JSON map as is
);
return response;
} catch (e) {
showSnackbar(e.toString());
}
return null;
}
Future<Map<String, dynamic>?> changePassword(Map<String, dynamic> data, {required String token}) async {
try {
final response = await commonApiService<Map<String, dynamic>>(
url: '/api/v1/user/password/update',
method: 'PUT',
body: data,
fromJson: (json) => json, // Simply return the JSON map as is
additionalHeaders: { // Pass the token here
'Authorization': 'Bearer $token',
},
);
return response;
} catch (e) {
showSnackbar(e.toString());
}
return null;
}
}

View File

@ -5,6 +5,8 @@ import 'package:flutter_svg/svg.dart';
import 'package:get/get.dart';
import 'package:google_fonts/google_fonts.dart';
import 'controller/auth_controller.dart';
class ForgetPasswordScreen extends StatefulWidget {
const ForgetPasswordScreen({super.key});
@ -15,6 +17,7 @@ class ForgetPasswordScreen extends StatefulWidget {
class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
final userNameController = TextEditingController();
final passwordController = TextEditingController();
final authController = Get.put(AuthController());
@override
Widget build(BuildContext context) {
return Scaffold(
@ -125,7 +128,11 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
),
),
const SizedBox(height: 30),
CustomButton(text: "Send", onPressed: () {}),
CustomButton(text: "Send",
onPressed: () => authController.forgotpass(),
isLoading: authController.isLoading.value,
),
],
),
),

View File

@ -11,6 +11,7 @@ Future<BodyType?> commonApiService<BodyType>({
Map<String, dynamic> body = const {},
File? imageFile,
bool isformData = true,
Map<String, String>? additionalHeaders,
required BodyType Function(Map<String, dynamic>) fromJson,
}) async {
try {
@ -31,6 +32,9 @@ Future<BodyType?> commonApiService<BodyType>({
headers['Authorization'] = 'Bearer $token';
}
if (additionalHeaders != null) {
headers.addAll(additionalHeaders);
}
Options options = Options(headers: headers);
FormData formData = FormData.fromMap(body);
@ -60,7 +64,7 @@ Future<BodyType?> commonApiService<BodyType>({
print("response of $url : $response");
if (url == "/api/territorymanager/login" &&
if (url == "/api/v1/user/login/" &&
response.data['token'] != null) {
prefs.setString('token', response.data['token']);
}

View File

@ -1,4 +1,5 @@
import 'package:cheminova/controller/home_controller.dart';
import 'package:cheminova/screens/authentication/change_password_screen.dart';
import 'package:cheminova/screens/authentication/login_screen.dart';
import 'package:cheminova/screens/home_screen.dart';
import 'package:flutter/material.dart';
@ -64,7 +65,9 @@ class _MyDrawerState extends State<MyDrawer> {
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Change Password'),
onTap: () {},
onTap: () {
Get.to(ChangePasswordScreen());
},
),
ListTile(
leading: const Icon(Icons.exit_to_app),