Files
rog_app/lib/pages/register/user_detail_page.dart

264 lines
9.1 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:gifunavi/model/user.dart';
import 'package:gifunavi/routes/app_pages.dart';
import 'package:gifunavi/services/api_service.dart';
import 'package:gifunavi/pages/index/index_controller.dart';
import 'package:intl/intl.dart';
import 'package:gifunavi/widgets/custom_date_picker.dart'; // 追加: 日付フォーマット用
class UserDetailsEditPage extends StatefulWidget {
const UserDetailsEditPage({super.key});
@override
_UserDetailsEditPageState createState() => _UserDetailsEditPageState();
}
class _UserDetailsEditPageState extends State<UserDetailsEditPage> {
final _formKey = GlobalKey<FormState>();
final IndexController indexController = Get.find<IndexController>();
late User _user;
final TextEditingController _firstnameController = TextEditingController();
final TextEditingController _lastnameController = TextEditingController();
final TextEditingController _dateOfBirthController = TextEditingController();
late bool _female;
@override
void initState() {
super.initState();
_user = User.fromJson(indexController.currentUser[0]['user']);
_firstnameController.text = _user.firstname;
_lastnameController.text = _user.lastname;
_dateOfBirthController.text = _user.dateOfBirth != null
? '${_user.dateOfBirth!.year}/${_user.dateOfBirth!.month.toString().padLeft(2, '0')}/${_user.dateOfBirth!.day.toString().padLeft(2, '0')}'
: '';
_female = _user.female;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('個人情報の修正'),
automaticallyImplyLeading: false,
),
body: Form(
key: _formKey,
child: ListView(
padding: const EdgeInsets.all(16.0),
children: [
TextFormField(
controller: _lastnameController,
decoration: const InputDecoration(
labelText: '',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '姓を入力してください';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _firstnameController,
decoration: const InputDecoration(
labelText: '',
border: OutlineInputBorder(),
),
validator: (value) {
if (value == null || value.isEmpty) {
return '名を入力してください';
}
return null;
},
),
const SizedBox(height: 16),
TextFormField(
controller: _dateOfBirthController,
decoration: InputDecoration(
labelText: '生年月日 (YYYY/MM/DD)',
border: const OutlineInputBorder(),
hintText: 'YYYY/MM/DD',
suffixIcon: IconButton(
icon: const Icon(Icons.calendar_today),
onPressed: () => _selectDate(context),
),
),
keyboardType: TextInputType.number, // <=datetime,
onChanged: (value) {
// スラッシュを除去
value = value.replaceAll('/', '');
if (value.length <= 8) {
String formattedValue = '';
// 年の処理4桁
if (value.length >= 4) {
formattedValue += '${value.substring(0, 4)}/';
value = value.substring(4);
} else {
formattedValue += value;
value = '';
}
// 月の処理2桁
if (value.length >= 2) {
formattedValue += '${value.substring(0, 2)}/';
value = value.substring(2);
} else if (value.isNotEmpty) {
formattedValue += value;
value = '';
}
// 残りの日付
formattedValue += value;
// 末尾のスラッシュを削除
if (formattedValue.endsWith('/')) {
formattedValue = formattedValue.substring(0, formattedValue.length - 1);
}
_dateOfBirthController.value = TextEditingValue(
text: formattedValue,
selection: TextSelection.collapsed(offset: formattedValue.length),
);
}
},
validator: (value) {
if (value == null || value.isEmpty) {
return '生年月日を入力してください';
}
if (!RegExp(r'^\d{4}/\d{2}/\d{2}$').hasMatch(value)) {
return '正しい形式で入力してください (YYYY/MM/DD)';
}
final date = DateTime.tryParse(value.replaceAll('/', '-'));
if (date == null) {
return '有効な日付を入力してください';
}
if (date.isAfter(DateTime.now())) {
return '未来の日付は入力できません';
}
return null;
},
),
const SizedBox(height: 16),
SwitchListTile(
title: const Text('性別'),
subtitle: Text(_female ? '女性' : '男性'),
value: _female,
onChanged: (bool value) {
setState(() {
_female = value;
});
},
),
const SizedBox(height: 16),
TextFormField(
initialValue: _user.email,
decoration: const InputDecoration(
labelText: 'メールアドレス',
border: OutlineInputBorder(),
),
enabled: false,
),
const SizedBox(height: 16),
SwitchListTile(
title: const Text('アクティブ状態'),
value: _user.isActive,
onChanged: null,
),
const SizedBox(height: 32),
ElevatedButton(
onPressed: _updateUserDetails,
child: const Text('更新'),
),
],
),
),
);
}
// 日付選択用の関数を追加
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDialog<DateTime>(
context: context,
builder: (BuildContext context) {
return CustomDatePicker(
initialDate: _user.dateOfBirth ?? DateTime.now(),
firstDate: DateTime(1900),
lastDate: DateTime.now(),
currentDateText: _dateOfBirthController.text,
);
},
);
if (picked != null) {
setState(() {
_dateOfBirthController.text = DateFormat('yyyy/MM/dd').format(picked);
});
}
}
void _updateUserDetails() async {
if (_formKey.currentState!.validate()) {
final dateOfBirth = DateTime.tryParse(_dateOfBirthController.text.replaceAll('/', '-'));
if (dateOfBirth == null || dateOfBirth.isAfter(DateTime.now())) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('生年月日が無効です', style: TextStyle(color: Colors.red))),
);
return;
}
// 13歳以上かどうかをチェック
final now = DateTime.now();
final age = now.year - dateOfBirth.year -
(now.month > dateOfBirth.month ||
(now.month == dateOfBirth.month && now.day >= dateOfBirth.day) ? 0 : 1);
if (age < 13) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('13歳未満の方は登録できません', style: TextStyle(color: Colors.red))),
);
return;
}
User updatedUser = User(
id: _user.id,
email: _user.email,
firstname: _firstnameController.text,
lastname: _lastnameController.text,
dateOfBirth: dateOfBirth,
female: _female,
isActive: _user.isActive,
);
try {
bool success = await ApiService.updateUserDetail(updatedUser, indexController.currentUser[0]['token']);
if (success) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('個人情報が更新されました')),
);
indexController.updateCurrentUser(updatedUser);
Get.offAllNamed(AppPages.INDEX);
//Get.back();
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('更新に失敗しました', style: TextStyle(color: Colors.red))),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('エラーが発生しました: $e', style: const TextStyle(color: Colors.red))),
);
}
}
}
}