Done login routine

This commit is contained in:
Andrew 2023-04-08 03:51:25 +07:00
commit f9b1b25e91
20 changed files with 983 additions and 0 deletions

View file

@ -0,0 +1,52 @@
import 'package:animated_background/animated_background.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
class CheckupPage extends StatefulWidget {
const CheckupPage({super.key});
@override
State<StatefulWidget> createState() => _CheckupPageState();
}
class _CheckupPageState extends State<CheckupPage>
with TickerProviderStateMixin {
@override
void initState() {
super.initState();
final accessToken = GetStorage().read<String?>("accessToken");
WidgetsBinding.instance.addPostFrameCallback((_) {
if (accessToken == null) {
Get.offAllNamed("/login");
} else {
Get.offAllNamed("/home");
}
});
}
@override
Widget build(BuildContext context) {
return AnimatedBackground(
behaviour: RandomParticleBehaviour(),
vsync: this,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Checking credentials...',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 16),
const SizedBox.square(
dimension: 32,
child: CircularProgressIndicator(),
),
],
),
),
);
}
}

33
lib/pages/home_page.dart Normal file
View file

@ -0,0 +1,33 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
State<StatefulWidget> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Home Page',
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
Get.offNamed("/login");
},
child: const Text('Login'),
),
],
),
);
}
}

145
lib/pages/login_page.dart Normal file
View file

@ -0,0 +1,145 @@
import 'dart:async';
import 'package:animated_background/animated_background.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get_storage/get_storage.dart';
import 'package:tuuli_app/api/api_client.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<StatefulWidget> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> with TickerProviderStateMixin {
final _formKey = GlobalKey<FormState>();
final apiClient = ApiClient.fromString("http://127.0.0.1:8000");
var submitted = false;
final loginController = TextEditingController();
final passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
final screenSize = MediaQuery.of(context).size;
final formWidth = screenSize.width <= 600 ? screenSize.width : 300.0;
return Stack(
children: [
AnimatedBackground(
behaviour: RandomParticleBehaviour(),
vsync: this,
child: const SizedBox.square(
dimension: 0,
),
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
LimitedBox(
maxWidth: formWidth,
child: Container(
color: Colors.black.withAlpha(100),
padding: const EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
controller: loginController,
enabled: !submitted,
decoration: const InputDecoration(
labelText: 'Login',
hintText: 'Enter your login',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your Login';
}
return null;
},
),
TextFormField(
controller: passwordController,
obscureText: true,
enabled: !submitted,
decoration: const InputDecoration(
labelText: 'Password',
hintText: 'Enter your password',
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your password';
}
return null;
},
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: submitted ? null : _submit,
child: const Text('Login'),
),
],
),
),
),
),
],
),
],
);
}
Future<void> _submit() async {
if (!_formKey.currentState!.validate()) {
return;
}
setState(() {
submitted = true;
});
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Trying to login...'),
),
);
final response = await apiClient.login(
loginController.text.trim(),
passwordController.text.trim(),
);
response.unfold((data) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Login successful'),
),
);
GetStorage()
.write("accessToken", data.accessToken)
.then((value) => GetStorage().save());
Timer(1.seconds, () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
WidgetsBinding.instance.addPostFrameCallback((_) {
Get.offAllNamed("/home");
});
});
}, (error) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(error.toString()),
),
);
setState(() {
submitted = false;
});
});
}
}

View file

@ -0,0 +1,21 @@
import 'package:animated_background/animated_background.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/scheduler/ticker.dart';
class NotFoundPage extends StatelessWidget {
const NotFoundPage({super.key});
@override
Widget build(BuildContext context) {
return AnimatedBackground(
behaviour: RandomParticleBehaviour(),
vsync: Scaffold.of(context),
child: Center(
child: Text(
'Page not found',
style: Theme.of(context).textTheme.headlineMedium,
),
),
);
}
}