Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
L
library-app-flutter
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Ilham Maulana
library-app-flutter
Commits
5b790690
Commit
5b790690
authored
Jul 31, 2024
by
Ilham Maulana
💻
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: reset pasword confirm by pin sended with email
parent
99c75c17
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
328 additions
and
74 deletions
+328
-74
auth_provider.dart
lib/src/providers/auth_provider.dart
+55
-1
form_screen.dart
lib/src/screens/form_screen.dart
+14
-0
reset_password_form.dart
lib/src/widgets/forms/reset_password_form.dart
+259
-73
No files found.
lib/src/providers/auth_provider.dart
View file @
5b790690
...
...
@@ -5,7 +5,6 @@ import 'package:http/http.dart' as http;
import
'package:library_app/src/models/token.dart'
;
import
'package:library_app/src/models/user.dart'
;
// Flutter: make memberLoans adjustable to be filtered to near outstanding loan and overdued loan
class
AuthProvider
with
ChangeNotifier
{
String
baseUrl
=
'http://localhost:8000/api/v1'
;
...
...
@@ -18,6 +17,10 @@ class AuthProvider with ChangeNotifier {
bool
filterByUpcoming
=
false
;
bool
filterByOverdued
=
false
;
int
?
userIdResetPw
;
bool
resetPasswordTokenSended
=
false
;
bool
resetPasswordSucced
=
false
;
Future
<
void
>
signIn
(
String
username
,
String
password
)
async
{
try
{
final
response
=
await
http
.
post
(
...
...
@@ -161,6 +164,57 @@ class AuthProvider with ChangeNotifier {
}
}
Future
<
void
>
resetPassword
(
String
email
)
async
{
try
{
final
response
=
await
http
.
post
(
Uri
.
parse
(
'
$baseUrl
/reset-password/request-token'
),
body:
jsonEncode
({
"email"
:
email
}),
headers:
{
'Content-Type'
:
'application/json'
},
);
if
(
response
.
statusCode
==
200
)
{
final
data
=
jsonDecode
(
response
.
body
);
resetPasswordTokenSended
=
true
;
userIdResetPw
=
data
[
"user_id_reset_pw"
];
}
else
{
debugPrint
(
'Error reset user password:
${response.statusCode}
,
${response.body}
'
);
}
notifyListeners
();
}
catch
(
error
)
{
debugPrint
(
"Error reset user password:
$error
"
);
}
}
Future
<
void
>
confirmResetPassword
(
int
pin
,
String
password1
,
String
password2
)
async
{
final
body
=
jsonEncode
({
"pin"
:
pin
,
"password1"
:
password1
,
"password2"
:
password2
,
});
try
{
final
response
=
await
http
.
post
(
Uri
.
parse
(
'
$baseUrl
/reset-password/confirm'
),
body:
body
,
headers:
{
'Content-Type'
:
'application/json'
},
);
if
(
response
.
statusCode
==
200
)
{
resetPasswordSucced
=
true
;
}
else
{
debugPrint
(
'Error confirm reset user password:
${response.statusCode}
,
${response.body}
'
);
}
notifyListeners
();
}
catch
(
error
)
{
debugPrint
(
"Error confirm reset user password:
$error
"
);
}
}
Future
<
void
>
getMemberLoan
()
async
{
String
url
=
'
$baseUrl
/members/
${user?.accountId}
/loans/'
;
if
(
filterByUpcoming
)
{
...
...
lib/src/screens/form_screen.dart
View file @
5b790690
...
...
@@ -75,6 +75,20 @@ class ResetPasswordScreen extends StatelessWidget {
}
}
class
ConfirmResetPasswordScreen
extends
StatelessWidget
{
const
ConfirmResetPasswordScreen
({
super
.
key
});
@override
Widget
build
(
BuildContext
context
)
{
String
title
=
"Reset Password"
;
return
FormScreen
(
title:
title
,
body:
const
ConfirmResetPasswordForm
(),
);
}
}
class
ProfileEditScreen
extends
StatelessWidget
{
const
ProfileEditScreen
({
super
.
key
,
...
...
lib/src/widgets/forms/reset_password_form.dart
View file @
5b790690
import
'package:flutter/material.dart'
;
import
'package:flutter_svg/flutter_svg.dart'
;
import
'package:library_app/src/providers/auth_provider.dart'
;
import
'package:library_app/src/screens/form_screen.dart'
;
import
'package:provider/provider.dart'
;
class
ResetPasswordForm
extends
StatefulWidget
{
const
ResetPasswordForm
({
super
.
key
});
...
...
@@ -10,93 +13,276 @@ class ResetPasswordForm extends StatefulWidget {
class
_ResetPasswordForm
extends
State
<
ResetPasswordForm
>
{
final
GlobalKey
<
FormState
>
_formKey
=
GlobalKey
<
FormState
>();
bool
passwordVisible
=
false
;
@override
void
initState
()
{
super
.
initState
();
passwordVisible
=
true
;
}
final
emailController
=
TextEditingController
();
@override
Widget
build
(
BuildContext
context
)
{
const
String
title
=
"Reset Password"
;
const
String
formText
=
"Confirm your email to continue reset password"
;
return
Column
(
children:
[
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20.0
,
vertical:
20.0
),
child:
Column
(
children:
[
SvgPicture
.
asset
(
"assets/images/reset_password_image.svg"
,
semanticsLabel:
title
,
width:
200
,
),
const
SizedBox
(
height:
10.0
,
return
Consumer
<
AuthProvider
>(
builder:
(
context
,
authProvider
,
child
)
{
return
Column
(
children:
[
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20.0
,
vertical:
20.0
),
child:
Column
(
children:
[
SvgPicture
.
asset
(
"assets/images/reset_password_image.svg"
,
semanticsLabel:
title
,
width:
200
,
),
const
SizedBox
(
height:
10.0
,
),
const
Text
(
formText
,
style:
TextStyle
(
fontSize:
20
,
fontWeight:
FontWeight
.
bold
),
textAlign:
TextAlign
.
center
,
),
],
),
),
Form
(
key:
_formKey
,
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
30.0
,
vertical:
30.0
,
),
const
Text
(
formText
,
style:
TextStyle
(
fontSize:
20
,
fontWeight:
FontWeight
.
bold
),
textAlign:
TextAlign
.
center
,
child:
Container
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
TextFormField
(
controller:
emailController
,
decoration:
const
InputDecoration
(
hintText:
"Enter your Email"
,
labelText:
"Email"
,
suffixIcon:
Icon
(
Icons
.
email_rounded
),
),
validator:
(
String
?
value
)
{
if
(
value
==
null
||
value
.
isEmpty
)
{
return
"Please enter your email"
;
}
else
if
(!
value
.
contains
(
"@"
))
{
return
"Email should include '@'"
;
}
return
null
;
},
),
// Flutter, iwant to go to ConfirmResetPasswordScreen after authProvider.resetPassword succeed with response 200
Container
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
20.0
,
),
child:
Column
(
children:
[
SizedBox
(
width:
double
.
infinity
,
child:
FilledButton
(
onPressed:
()
{
if
(
_formKey
.
currentState
!.
validate
())
{}
authProvider
.
resetPassword
(
emailController
.
text
)
.
then
(
(
response
)
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
=>
const
ConfirmResetPasswordScreen
(),
),
);
},
).
catchError
(
(
error
)
{
debugPrint
(
'Exception:
$error
'
);
},
);
},
child:
const
Text
(
"Submit"
),
),
),
],
),
)
],
),
),
],
),
),
Form
(
key:
_formKey
,
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
30.0
,
vertical:
30.0
,
),
child:
Container
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
TextFormField
(
decoration:
const
InputDecoration
(
hintText:
"Enter your Email"
,
labelText:
"Email"
,
suffixIcon:
Icon
(
Icons
.
email_rounded
),
)
],
);
});
}
}
class
ConfirmResetPasswordForm
extends
StatefulWidget
{
const
ConfirmResetPasswordForm
({
super
.
key
});
@override
State
<
ConfirmResetPasswordForm
>
createState
()
=>
_ConfirmResetPasswordForm
();
}
class
_ConfirmResetPasswordForm
extends
State
<
ConfirmResetPasswordForm
>
{
final
GlobalKey
<
FormState
>
_formKey
=
GlobalKey
<
FormState
>();
final
pinController
=
TextEditingController
();
final
password1Controller
=
TextEditingController
();
final
password2Controller
=
TextEditingController
();
bool
passwordVisible
=
false
;
@override
Widget
build
(
BuildContext
context
)
{
const
String
title
=
"Confirm Reset Password Pin"
;
const
String
formText
=
"Enter the pin that we just sent to your email"
;
return
Consumer
<
AuthProvider
>(
builder:
(
context
,
authProvider
,
child
)
{
return
Column
(
children:
[
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20.0
,
vertical:
20.0
),
child:
Column
(
children:
[
SvgPicture
.
asset
(
"assets/images/reset_password_image.svg"
,
semanticsLabel:
title
,
width:
200
,
),
const
SizedBox
(
height:
10.0
,
),
const
Text
(
formText
,
style:
TextStyle
(
fontSize:
20
,
fontWeight:
FontWeight
.
bold
),
textAlign:
TextAlign
.
center
,
),
],
),
),
Form
(
key:
_formKey
,
child:
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
30.0
,
vertical:
30.0
,
),
child:
Container
(
padding:
const
EdgeInsets
.
all
(
10.0
),
child:
Column
(
mainAxisAlignment:
MainAxisAlignment
.
center
,
children:
<
Widget
>[
TextFormField
(
controller:
pinController
,
decoration:
const
InputDecoration
(
hintText:
"Enter your confirmation pin"
,
labelText:
"confirmation pin"
,
suffixIcon:
Icon
(
Icons
.
password
),
),
),
validator:
(
String
?
value
)
{
if
(
value
==
null
||
value
.
isEmpty
)
{
return
"Please enter your email"
;
}
else
if
(!
value
.
contains
(
"@"
))
{
return
"Email should include '@'"
;
}
return
null
;
},
),
Container
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
20.0
,
TextFormField
(
controller:
password1Controller
,
obscureText:
passwordVisible
,
decoration:
InputDecoration
(
hintText:
"Enter your new Password"
,
labelText:
"New Password"
,
suffixIcon:
IconButton
(
icon:
Icon
(
passwordVisible
?
Icons
.
visibility
:
Icons
.
visibility_off
),
onPressed:
()
{
setState
(
()
{
passwordVisible
=
!
passwordVisible
;
},
);
},
),
),
validator:
(
String
?
value
)
{
if
(
value
==
null
||
value
.
isEmpty
)
{
return
"Please enter your password"
;
}
else
{
return
null
;
}
},
keyboardType:
TextInputType
.
visiblePassword
,
),
child:
Column
(
children:
[
SizedBox
(
width:
double
.
infinity
,
child:
FilledButton
(
onPressed:
()
{
if
(
_formKey
.
currentState
!.
validate
())
{}
},
child:
const
Text
(
"Submit"
),
),
TextFormField
(
controller:
password2Controller
,
obscureText:
passwordVisible
,
decoration:
InputDecoration
(
hintText:
"Confirm your new Password"
,
labelText:
"Confirm new Password"
,
suffixIcon:
IconButton
(
icon:
Icon
(
passwordVisible
?
Icons
.
visibility
:
Icons
.
visibility_off
),
onPressed:
()
{
setState
(
()
{
passwordVisible
=
!
passwordVisible
;
},
);
},
),
],
),
validator:
(
String
?
value
)
{
if
(
value
==
null
||
value
.
isEmpty
)
{
return
"Please enter your password"
;
}
else
{
return
null
;
}
},
keyboardType:
TextInputType
.
visiblePassword
,
),
)
],
Container
(
padding:
const
EdgeInsets
.
symmetric
(
vertical:
20.0
,
),
child:
Column
(
children:
[
SizedBox
(
width:
double
.
infinity
,
child:
FilledButton
(
onPressed:
()
{
if
(
_formKey
.
currentState
!.
validate
())
{}
authProvider
.
confirmResetPassword
(
int
.
parse
(
pinController
.
text
),
password1Controller
.
text
,
password2Controller
.
text
,
)
.
then
(
(
response
)
{
Navigator
.
of
(
context
).
push
(
MaterialPageRoute
(
builder:
(
context
)
=>
const
LoginScreen
(),
),
);
},
).
catchError
(
(
error
)
{
debugPrint
(
'Exception:
$error
'
);
},
);
},
child:
const
Text
(
"Submit"
),
),
),
],
),
)
],
),
),
),
)
,
)
],
);
)
],
);
}
);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment