Commit 88191ddc authored by Ilham Maulana's avatar Ilham Maulana 💻

feat: login form as admin

parent b5bd4c78
...@@ -64,6 +64,39 @@ class AuthProvider with ChangeNotifier { ...@@ -64,6 +64,39 @@ class AuthProvider with ChangeNotifier {
} }
} }
Future<void> signInAsAdmin(String username, String password) async {
try {
final response = await http.post(
Uri.parse('$baseUrl/librarians/auth/login'),
body: jsonEncode({'username': username, 'password': password}),
headers: {'Content-Type': 'application/json'},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
await storeAccessToken(Token.fromJson(data)!.key);
final token = await getAccessToken();
if (token != null) {
isLoggedIn = true;
}
debugPrint("Login successful $token");
} else if (response.statusCode == 401) {
invalidUsernameOrPassword = true;
debugPrint("Login failed: ${response.statusCode} ${response.body}");
} else {
final code = response.statusCode;
debugPrint("Login failed $code");
}
notifyListeners();
} catch (error) {
debugPrint("Login failed $error");
}
}
Future<void> signOut() async { Future<void> signOut() async {
final token = await getAccessToken(); final token = await getAccessToken();
......
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:library_app/src/providers/auth_provider.dart'; import 'package:library_app/src/providers/auth_provider.dart';
import 'package:library_app/src/widgets/forms/admin_login_form.dart';
import 'package:library_app/src/widgets/forms/login_form.dart'; import 'package:library_app/src/widgets/forms/login_form.dart';
import 'package:library_app/src/widgets/forms/profile_edit_form.dart'; import 'package:library_app/src/widgets/forms/profile_edit_form.dart';
...@@ -10,14 +11,25 @@ import 'package:provider/provider.dart'; ...@@ -10,14 +11,25 @@ import 'package:provider/provider.dart';
class FormScreen extends StatelessWidget { class FormScreen extends StatelessWidget {
final String title; final String title;
final Widget body; final Widget body;
const FormScreen({super.key, required this.title, required this.body}); final List<Widget>? action;
final bool? withBackButton;
const FormScreen({
super.key,
required this.title,
required this.body,
this.action,
this.withBackButton,
});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool withBack = withBackButton != null ? withBackButton! : true;
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text(title), title: Text(title),
leading: const BackButton(), leading: withBack ? const BackButton() : null,
actions: action,
), ),
body: ListView( body: ListView(
children: [ children: [
...@@ -41,12 +53,36 @@ class LoginScreen extends StatelessWidget { ...@@ -41,12 +53,36 @@ class LoginScreen extends StatelessWidget {
String title = "Login"; String title = "Login";
return FormScreen( return FormScreen(
withBackButton: false,
title: title, title: title,
action: [
IconButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const AdminLoginScreen(),
));
},
icon: const Icon(Icons.admin_panel_settings_rounded))
],
body: const LoginForm(), body: const LoginForm(),
); );
} }
} }
class AdminLoginScreen extends StatelessWidget {
const AdminLoginScreen({super.key});
@override
Widget build(BuildContext context) {
String title = "Admin Login";
return FormScreen(
title: title,
body: const AdminLoginForm(),
);
}
}
class SignUpScreen extends StatelessWidget { class SignUpScreen extends StatelessWidget {
const SignUpScreen({super.key}); const SignUpScreen({super.key});
......
import 'package:flutter/material.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 AdminLoginForm extends StatefulWidget {
const AdminLoginForm({super.key});
@override
State<AdminLoginForm> createState() => _AdminLoginForm();
}
class _AdminLoginForm extends State<AdminLoginForm> {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final usernameController = TextEditingController();
final passwordController = TextEditingController();
bool passwordVisible = false;
@override
void initState() {
super.initState();
passwordVisible = true;
}
@override
void dispose() {
usernameController.dispose();
passwordController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
const String formText = "Login As Admin";
return Consumer<AuthProvider>(builder: (context, authProvider, child) {
final isInvalid = authProvider.invalidUsernameOrPassword;
return Column(
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0),
child: Icon(
Icons.admin_panel_settings_rounded,
size: 160.0,
),
),
const Text(
formText,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
Container(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 20.0),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFormField(
controller: usernameController,
decoration: const InputDecoration(
hintText: "Enter your Username",
labelText: "Username",
suffixIcon: Icon(Icons.supervised_user_circle),
),
validator: (String? value) {
if (value == null || value.isEmpty) {
return "Please enter your username";
} else {
return null;
}
},
),
TextFormField(
controller: passwordController,
obscureText: passwordVisible,
decoration: InputDecoration(
hintText: "Enter your Password",
labelText: "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,
),
Visibility(
visible: isInvalid,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Theme.of(context).highlightColor,
),
margin: const EdgeInsets.symmetric(vertical: 20.0),
padding: const EdgeInsets.symmetric(
horizontal: 10.0, vertical: 8.0),
child: const Text("Invalid username or password"),
),
),
const SizedBox(
height: 20.0,
),
Column(
children: [
SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: () {
if (_formKey.currentState!.validate()) {}
authProvider.signInAsAdmin(
usernameController.text,
passwordController.text,
);
},
child: const Text("Submit"),
),
),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Sign Up"),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const SignUpScreen(),
),
);
},
),
),
SizedBox(
width: double.infinity,
child: TextButton(
child: const Text("Forgot Password"),
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const ResetPasswordScreen(),
));
},
),
),
],
),
],
),
),
)
],
);
});
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment