Files
rog_app/lib/pages/login/login_page.dart
2024-08-07 14:24:05 +09:00

397 lines
15 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/widgets/helper_dialog.dart';
import 'package:rogapp/services/api_service.dart';
import 'package:package_info_plus/package_info_plus.dart';
// 要検討:ログインボタンとサインアップボタンの配色を見直すことを検討してください。現在の配色では、ボタンの役割がわかりにくい可能性があります。
// エラーメッセージをローカライズすることを検討してください。
// ログイン処理中にエラーが発生した場合のエラーハンドリングを追加することをお勧めします。
//
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
//class LoginPage extends StatelessWidget {
final IndexController indexController = Get.find<IndexController>();
final ApiService apiService = Get.find<ApiService>();
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
bool _obscureText = true;
String _version = ''; // バージョン情報を保持する変数
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
showHelperDialog(
'参加するにはユーザー登録が必要です。サインアップからユーザー登録してください。',
'login_page'
);
});
_getVersionInfo(); // バージョン情報を取得
}
// バージョン情報を取得するメソッド
Future<void> _getVersionInfo() async {
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
setState(() {
_version = packageInfo.version;
});
}
void _showResetPasswordDialog() {
TextEditingController resetEmailController = TextEditingController();
Get.dialog(
AlertDialog(
title: Text('パスワードのリセット'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('パスワードをリセットするメールアドレスを入力してください。'),
SizedBox(height: 10),
TextField(
controller: resetEmailController,
decoration: InputDecoration(
labelText: 'メールアドレス',
border: OutlineInputBorder(),
),
),
],
),
actions: [
TextButton(
child: Text('キャンセル'),
onPressed: () => Get.back(),
),
ElevatedButton(
child: Text('リセット'),
onPressed: () async {
if (resetEmailController.text.isNotEmpty) {
bool success = await apiService.resetPassword(resetEmailController.text);
Get.back();
if (success) {
Get.dialog(
AlertDialog(
title: Text('パスワードリセット'),
content: Text('パスワードリセットメールを送信しました。メールのリンクからパスワードを設定してください。'),
actions: [
TextButton(
child: Text('OK'),
onPressed: () => Get.back(),
),
],
),
);
} else {
Get.snackbar('エラー', 'パスワードリセットに失敗しました。もう一度お試しください。',
snackPosition: SnackPosition.BOTTOM);
}
}
},
),
],
),
);
}
//LoginPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.white,
automaticallyImplyLeading: false,
),
body: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: indexController.currentUser.isEmpty
? SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Column(
children: [
Column(
children: [
Container(
height: MediaQuery.of(context).size.height / 6,
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/login_image.jpg'))),
),
const SizedBox(
height: 5,
),
// バージョン情報を表示
Text(
'Version: $_version',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Column(
children: [
makeInput(
label: "email".tr, controller: emailController),
makePasswordInput(
label: "password".tr,
controller: passwordController,
obscureText: _obscureText,
onToggleVisibility: () {
setState(() {
_obscureText = !_obscureText;
});
}),
],
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 40),
child: Container(
padding: const EdgeInsets.only(top: 3, left: 3),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(40),
),
child: Obx(
(() => indexController.isLoading.value == true
? MaterialButton(
minWidth: double.infinity,
height: 60,
onPressed: () {},
color: Colors.grey[400],
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(40)),
child: const CircularProgressIndicator(),
)
: Column(
children: [
MaterialButton(
minWidth: double.infinity,
height: 40,
onPressed: () async {
if (emailController.text.isEmpty ||
passwordController
.text.isEmpty) {
Get.snackbar(
"no_values".tr,
"email_and_password_required"
.tr,
backgroundColor: Colors.red,
colorText: Colors.white,
icon: const Icon(
Icons
.assistant_photo_outlined,
size: 40.0,
color: Colors.blue),
snackPosition:
SnackPosition.TOP,
duration: const Duration(
seconds: 3),
);
return;
}
indexController.isLoading.value =
true;
indexController.login(
emailController.text,
passwordController.text,
context);
},
color: Colors.indigoAccent[400],
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(40)),
child: Text(
"login".tr,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: Colors.white70),
),
),
const SizedBox(
height: 5.0,
),
MaterialButton(
minWidth: double.infinity,
height: 36,
onPressed: () {
Get.toNamed(AppPages.REGISTER);
},
color: Colors.redAccent,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(40)),
child: Text(
"sign_up".tr,
style: const TextStyle(
fontWeight: FontWeight.w600,
fontSize: 16,
color: Colors.white70),
),
),
],
)),
),
)),
const SizedBox(
height: 3,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: _showResetPasswordDialog,
child: Text(
"forgot_password".tr,
style: TextStyle(color: Colors.blue),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"app_developed_by_gifu_dx".tr,
style: const TextStyle(
overflow: TextOverflow.ellipsis,
fontSize: 10.0),
),
),
),
],
),
const Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Flexible(
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text(
"※第8回と第9回は、岐阜県の令和年度「清流の国ぎふ」SDGs推進ネットワーク連携促進補助金を受けています",
style: TextStyle(
fontSize: 10.0,
),
),
),
),
],
),
],
),
],
),
)
: TextButton(
onPressed: () {
indexController.logout();
Get.offAllNamed(AppPages.LOGIN);
},
child: const Text("Already Logged in, Click to logout"),
),
),
);
}
}
Widget makePasswordInput({
required String label,
required TextEditingController controller,
required bool obscureText,
required VoidCallback onToggleVisibility,
}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(
fontSize: 15, fontWeight: FontWeight.w400, color: Colors.black87),
),
const SizedBox(height: 5),
TextField(
controller: controller,
obscureText: obscureText,
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey[400]!),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: Colors.grey[400]!),
),
suffixIcon: IconButton(
icon: Icon(
obscureText ? Icons.visibility : Icons.visibility_off,
color: Colors.grey,
),
onPressed: onToggleVisibility,
),
),
),
const SizedBox(height: 30.0)
],
);
}
Widget makeInput(
{label, required TextEditingController controller, obsureText = false}) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: const TextStyle(
fontSize: 15, fontWeight: FontWeight.w400, color: Colors.black87),
),
const SizedBox(
height: 5,
),
TextField(
controller: controller,
obscureText: obsureText,
decoration: InputDecoration(
contentPadding:
const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: (Colors.grey[400])!,
),
),
border: OutlineInputBorder(
borderSide: BorderSide(color: (Colors.grey[400])!),
),
),
),
const SizedBox(
height: 30.0,
)
],
);
}