dth-pingpong-mobileapp/lib/pages/login.dart

195 lines
6.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'home.dart';
import '../globals.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
final _displayNameController = TextEditingController();
bool _isLogin = true;
bool _isLoading = false;
Future<void> _handleAuth() async {
final email = _emailController.text.trim();
final password = _passwordController.text.trim();
final displayName = _displayNameController.text.trim();
// Input validation
if (email.isEmpty ||
password.isEmpty ||
(!_isLogin && displayName.isEmpty)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Please fill in all required fields.')),
);
return;
}
setState(() {
_isLoading = true;
});
try {
if (_isLogin) {
final token = await _login(email, password);
if (token != null) {
final prefs = await SharedPreferences.getInstance();
await prefs.setString('token', token);
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
} else {
final uid = await _register(email, password, displayName);
if (uid != null) {
setState(() {
_isLogin = true;
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Registration successful! Please login.')));
}
}
} catch (e) {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(content: Text(e.toString())));
} finally {
setState(() {
_isLoading = false;
});
}
}
Future<String?> _login(String email, String password) async {
final url = Uri.parse('$apiurl/login');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: json.encode({'email': email, 'password': password}),
);
if (response.statusCode == 200) {
final body = json.decode(response.body);
return body['uid'];
} else {
throw Exception('Login failed: ${response.body}');
}
}
Future<String?> _register(
String email, String password, String displayName) async {
final url = Uri.parse('$apiurl/register');
final response = await http.post(
url,
headers: {'Content-Type': 'application/json'},
body: json.encode({
'email': email,
'password': password,
'display_name': displayName,
}),
);
if (response.statusCode == 200) {
final body = json.decode(response.body);
return body['uid'];
} else {
throw Exception('Registration failed: ${response.body}');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_isLogin ? 'Login' : 'Register'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
TextField(
controller: _emailController,
decoration: InputDecoration(labelText: 'Email'),
),
TextField(
controller: _passwordController,
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
),
if (!_isLogin)
TextField(
controller: _displayNameController,
decoration: InputDecoration(labelText: 'Display Name'),
),
const SizedBox(height: 20),
if (_isLoading)
CircularProgressIndicator()
else
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: _handleAuth,
child: Text(_isLogin ? 'Login' : 'Register'),
),
ElevatedButton(
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
child: Text(_isLogin ? 'Register' : 'Back to Login'),
),
],
),
const Spacer(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
icon: Icon(FontAwesomeIcons.github),
onPressed: () async {
final url = Uri.parse(
'https://git.mercurio.moe/Mercury/dth-pingpong-mobileapp');
if (await canLaunchUrl(url)) {
await launchUrl(
url,
mode: LaunchMode
.externalApplication, // Ensures it opens in the browser
);
} else {
throw 'Could not launch $url';
}
}),
IconButton(
icon: Icon(FontAwesomeIcons.chartSimple),
onPressed: () async {
final url =
Uri.parse('https://kuma.mercurio.moe/status/dthpp');
if (await canLaunchUrl(url)) {
await launchUrl(
url,
mode: LaunchMode
.externalApplication, // Ensures it opens in the browser
);
} else {
throw 'Could not launch $url';
}
}),
],
),
],
),
),
);
}
}