Semi Final 7th Aug 2024

This commit is contained in:
2024-08-07 14:24:05 +09:00
parent 66ade1fe09
commit 347861e5a1
23 changed files with 342 additions and 160 deletions

View File

@ -398,11 +398,11 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 488; CURRENT_PROJECT_VERSION = 493;
DEVELOPMENT_TEAM = UMNEWT25JR; DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.8; FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 488; FLUTTER_BUILD_NUMBER = 493;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness";
@ -411,7 +411,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 4.8.8; MARKETING_VERSION = 4.8.13;
PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -539,11 +539,11 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 488; CURRENT_PROJECT_VERSION = 493;
DEVELOPMENT_TEAM = UMNEWT25JR; DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.8; FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 488; FLUTTER_BUILD_NUMBER = 493;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness";
@ -552,7 +552,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 4.8.8; MARKETING_VERSION = 4.8.13;
PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";
@ -571,11 +571,11 @@
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 488; CURRENT_PROJECT_VERSION = 493;
DEVELOPMENT_TEAM = UMNEWT25JR; DEVELOPMENT_TEAM = UMNEWT25JR;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
FLUTTER_BUILD_NAME = 4.8.8; FLUTTER_BUILD_NAME = 4.8.13;
FLUTTER_BUILD_NUMBER = 488; FLUTTER_BUILD_NUMBER = 493;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ"; INFOPLIST_KEY_CFBundleDisplayName = "岐阜ナビ";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness"; INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.healthcare-fitness";
@ -584,7 +584,7 @@
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
MARKETING_VERSION = 4.8.8; MARKETING_VERSION = 4.8.13;
PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi; PRODUCT_BUNDLE_IDENTIFIER = com.dvox.gifunavi;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = ""; PROVISIONING_PROFILE_SPECIFIER = "";

View File

@ -11,6 +11,7 @@ import 'package:geolocator/geolocator.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
//import 'package:vm_service/vm_service.dart'; //import 'package:vm_service/vm_service.dart';
//import 'package:dart_vm_info/dart_vm_info.dart'; //import 'package:dart_vm_info/dart_vm_info.dart';
import 'package:timezone/data/latest.dart' as tz;
import 'package:rogapp/pages/settings/settings_controller.dart'; import 'package:rogapp/pages/settings/settings_controller.dart';
@ -152,6 +153,8 @@ void main() async {
*/ */
try { try {
tz.initializeTimeZones();
// ApiServiceを初期化 // ApiServiceを初期化
//await Get.putAsync(() => ApiService().init()); //await Get.putAsync(() => ApiService().init());
await initServices(); await initServices();

View File

@ -239,6 +239,7 @@ class CameraPage extends StatelessWidget {
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
shape: const CircleBorder(), shape: const CircleBorder(),
padding: const EdgeInsets.all(20), padding: const EdgeInsets.all(20),
foregroundColor: Colors.white,
backgroundColor: destinationController.photos.isEmpty backgroundColor: destinationController.photos.isEmpty
? Colors.red ? Colors.red
: Colors.grey[300], : Colors.grey[300],
@ -294,7 +295,10 @@ class CameraPage extends StatelessWidget {
? settingGoal.value == false ? settingGoal.value == false
? ElevatedButton( ? ElevatedButton(
style: style:
ElevatedButton.styleFrom(backgroundColor: Colors.red), ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.red
),
onPressed: () async { onPressed: () async {
// print( // print(
// "----- user isss ${indexController.currentUser[0]} -----"); // "----- user isss ${indexController.currentUser[0]} -----");
@ -339,7 +343,7 @@ class CameraPage extends StatelessWidget {
isgoal: true); isgoal: true);
} else { } else {
//print("---- status ${value['status']} ---- "); //print("---- status ${value['status']} ---- ");
Get.snackbar("目標が追加されていません", "please_try_again", Get.snackbar(value["detail"], "ERROR",
backgroundColor: Colors.green, backgroundColor: Colors.green,
colorText: Colors.white colorText: Colors.white
); );
@ -455,6 +459,7 @@ class CameraPage extends StatelessWidget {
style: ElevatedButton.styleFrom(backgroundColor: Colors.red), style: ElevatedButton.styleFrom(backgroundColor: Colors.red),
onPressed: () async { onPressed: () async {
// print( // print(
// "##### current destination ${indexController.currentDestinationFeature[0].sub_loc_id} #######"); // "##### current destination ${indexController.currentDestinationFeature[0].sub_loc_id} #######");
await destinationController.makeCheckin( await destinationController.makeCheckin(
indexController.currentDestinationFeature[0], indexController.currentDestinationFeature[0],

View File

@ -255,18 +255,17 @@ class DrawerPage extends StatelessWidget {
Get.back(); // ドロワーを閉じる Get.back(); // ドロワーを閉じる
Get.toNamed(Routes.SETTINGS); Get.toNamed(Routes.SETTINGS);
}, },
),
//ListTile(
// leading: const Icon(Icons.developer_mode),
// title: const Text('open_settings'),
// onTap: () {
// Get.back(); // ドロワーを閉じる
// Get.toNamed('/debug'); // デバッグ画面に遷移
// },
//),
),
/*
ListTile(
leading: const Icon(Icons.developer_mode),
title: const Text('open_settings'),
onTap: () {
Get.back(); // ドロワーを閉じる
Get.toNamed('/debug'); // デバッグ画面に遷移
},
),
*/
// ListTile( // ListTile(
// leading: const Icon(Icons.router), // leading: const Icon(Icons.router),

View File

@ -9,6 +9,8 @@ import 'package:rogapp/model/category.dart';
import 'package:rogapp/services/api_service.dart'; import 'package:rogapp/services/api_service.dart';
import '../index/index_controller.dart'; import '../index/index_controller.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
class EntryController extends GetxController { class EntryController extends GetxController {
late ApiService _apiService; late ApiService _apiService;
@ -92,8 +94,10 @@ class EntryController extends GetxController {
void updateTeam(Team? value) => selectedTeam.value = value; void updateTeam(Team? value) => selectedTeam.value = value;
void updateCategory(NewCategory? value) => selectedCategory.value = value; void updateCategory(NewCategory? value) => selectedCategory.value = value;
void updateDate(DateTime value) => selectedDate.value = value; //void updateDate(DateTime value) => selectedDate.value = value;
void updateDate(DateTime value) {
selectedDate.value = tz.TZDateTime.from(value, tz.getLocation('Asia/Tokyo'));
}
/* /*
void updateDate(DateTime value){ void updateDate(DateTime value){
selectedDate.value = DateFormat('yyyy-MM-dd').format(value!) as DateTime?; selectedDate.value = DateFormat('yyyy-MM-dd').format(value!) as DateTime?;
@ -201,6 +205,7 @@ class EntryController extends GetxController {
selectedEvent.value!.id, selectedEvent.value!.id,
selectedCategory.value!.id, selectedCategory.value!.id,
selectedDate.value!, selectedDate.value!,
currentEntry.value!.zekkenNumber,
); );
final index = entries.indexWhere((entry) => entry.id == updatedEntry.id); final index = entries.indexWhere((entry) => entry.id == updatedEntry.id);
if (index != -1) { if (index != -1) {

View File

@ -8,6 +8,9 @@ import 'package:rogapp/model/category.dart';
import 'package:rogapp/model/team.dart'; import 'package:rogapp/model/team.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
class EntryDetailPage extends GetView<EntryController> { class EntryDetailPage extends GetView<EntryController> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -70,7 +73,7 @@ class EntryDetailPage extends GetView<EntryController> {
title: Text('日付'), title: Text('日付'),
subtitle: Text( subtitle: Text(
controller.selectedDate.value != null controller.selectedDate.value != null
? DateFormat('yyyy-MM-dd').format(controller.selectedDate.value!) ? DateFormat('yyyy-MM-dd').format(tz.TZDateTime.from(controller.selectedDate.value!, tz.getLocation('Asia/Tokyo')))
: '日付を選択してください', : '日付を選択してください',
), ),
onTap: () async { onTap: () async {
@ -78,14 +81,22 @@ class EntryDetailPage extends GetView<EntryController> {
Get.snackbar('Error', 'Please select an event first'); Get.snackbar('Error', 'Please select an event first');
return; return;
} }
final tz.TZDateTime now = tz.TZDateTime.now(tz.getLocation('Asia/Tokyo'));
final tz.TZDateTime eventStart = tz.TZDateTime.from(controller.selectedEvent.value!.startDatetime, tz.getLocation('Asia/Tokyo'));
final tz.TZDateTime eventEnd = tz.TZDateTime.from(controller.selectedEvent.value!.endDatetime, tz.getLocation('Asia/Tokyo'));
final tz.TZDateTime initialDate = controller.selectedDate.value != null
? tz.TZDateTime.from(controller.selectedDate.value!, tz.getLocation('Asia/Tokyo'))
: (now.isAfter(eventStart) ? now : eventStart);
final DateTime? picked = await showDatePicker( final DateTime? picked = await showDatePicker(
context: context, context: context,
initialDate: controller.selectedDate.value ?? controller.selectedEvent.value!.startDatetime, initialDate: initialDate,
firstDate: controller.selectedEvent.value!.startDatetime, firstDate: eventStart,
lastDate: controller.selectedEvent.value!.endDatetime, lastDate: eventEnd,
); );
if (picked != null) { if (picked != null) {
controller.updateDate(picked); controller.updateDate(tz.TZDateTime.from(picked, tz.getLocation('Asia/Tokyo')));
} }
}, },
), ),
@ -96,6 +107,7 @@ class EntryDetailPage extends GetView<EntryController> {
onPressed: () => controller.createEntry(), onPressed: () => controller.createEntry(),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
foregroundColor: Colors.white,
minimumSize: Size(double.infinity, 50), minimumSize: Size(double.infinity, 50),
), ),
) )
@ -108,6 +120,7 @@ class EntryDetailPage extends GetView<EntryController> {
onPressed: () => controller.deleteEntry(), onPressed: () => controller.deleteEntry(),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red, backgroundColor: Colors.red,
foregroundColor: Colors.white,
minimumSize: Size(0, 50), minimumSize: Size(0, 50),
), ),
), ),
@ -119,6 +132,7 @@ class EntryDetailPage extends GetView<EntryController> {
onPressed: () => controller.updateEntry(), onPressed: () => controller.updateEntry(),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.lightBlue, backgroundColor: Colors.lightBlue,
foregroundColor: Colors.white,
minimumSize: Size(0, 50), minimumSize: Size(0, 50),
), ),
), ),

View File

@ -5,6 +5,7 @@ import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:rogapp/pages/entry/entry_controller.dart'; import 'package:rogapp/pages/entry/entry_controller.dart';
import 'package:rogapp/routes/app_pages.dart'; import 'package:rogapp/routes/app_pages.dart';
import 'package:timezone/timezone.dart' as tz;
class EntryListPage extends GetView<EntryController> { class EntryListPage extends GetView<EntryController> {
@override @override
@ -12,6 +13,12 @@ class EntryListPage extends GetView<EntryController> {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
title: Text('エントリー管理'), title: Text('エントリー管理'),
actions: [
IconButton(
icon: Icon(Icons.add),
onPressed: () => Get.toNamed(AppPages.ENTRY_DETAIL, arguments: {'mode': 'new'}),
),
],
), ),
body: Obx(() { body: Obx(() {
if (controller.entries.isEmpty) { if (controller.entries.isEmpty) {
@ -54,7 +61,8 @@ class EntryListPage extends GetView<EntryController> {
if (date == null) { if (date == null) {
return '日時未設定'; return '日時未設定';
} }
return DateFormat('yyyy-MM-dd').format(date); final jstDate = tz.TZDateTime.from(date, tz.getLocation('Asia/Tokyo'));
return DateFormat('yyyy-MM-dd').format(jstDate);
} }
} }

View File

@ -4,6 +4,8 @@ import 'package:rogapp/pages/index/index_controller.dart';
import 'package:rogapp/pages/destination/destination_controller.dart'; import 'package:rogapp/pages/destination/destination_controller.dart';
import 'package:rogapp/services/api_service.dart'; import 'package:rogapp/services/api_service.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:timezone/timezone.dart' as tz;
import 'package:timezone/data/latest.dart' as tz;
class EventEntriesController extends GetxController { class EventEntriesController extends GetxController {
final ApiService _apiService = Get.find<ApiService>(); final ApiService _apiService = Get.find<ApiService>();
@ -14,9 +16,12 @@ class EventEntriesController extends GetxController {
final filteredEntries = <Entry>[].obs; final filteredEntries = <Entry>[].obs;
final showTodayEntries = true.obs; final showTodayEntries = true.obs;
static bool _timezoneInitialized = false;
@override @override
void onInit() { void onInit() {
super.onInit(); super.onInit();
_initializeTimezone();
// DestinationControllerが登録されていない場合に備えて、lazyPutを使用 // DestinationControllerが登録されていない場合に備えて、lazyPutを使用
Get.lazyPut<DestinationController>(() => DestinationController(), fenix: true); Get.lazyPut<DestinationController>(() => DestinationController(), fenix: true);
_destinationController = Get.find<DestinationController>(); _destinationController = Get.find<DestinationController>();
@ -24,6 +29,13 @@ class EventEntriesController extends GetxController {
fetchEntries(); fetchEntries();
} }
void _initializeTimezone() {
if (!_timezoneInitialized) {
tz.initializeTimeZones();
_timezoneInitialized = true;
}
}
Future<void> fetchEntries() async { Future<void> fetchEntries() async {
try { try {
final fetchedEntries = await _apiService.getEntries(); final fetchedEntries = await _apiService.getEntries();
@ -44,6 +56,16 @@ class EventEntriesController extends GetxController {
} }
void filterEntriesForToday() { void filterEntriesForToday() {
final now = tz.TZDateTime.now(tz.getLocation('Asia/Tokyo'));
filteredEntries.assignAll(entries.where((entry) {
final entryDate = tz.TZDateTime.from(entry.date!, tz.getLocation('Asia/Tokyo'));
return entryDate.year == now.year &&
entryDate.month == now.month &&
entryDate.day == now.day;
}));
}
void filterEntriesForToday_old() {
final now = DateTime.now(); final now = DateTime.now();
filteredEntries.assignAll(entries.where((entry) => filteredEntries.assignAll(entries.where((entry) =>
entry.date?.year == now.year && entry.date?.year == now.year &&
@ -66,10 +88,12 @@ class EventEntriesController extends GetxController {
} }
Future<void> joinEvent(Entry entry) async { Future<void> joinEvent(Entry entry) async {
final now = DateTime.now(); //final now = DateTime.now();
bool isToday = entry.date?.year == now.year && final now = tz.TZDateTime.now(tz.getLocation('Asia/Tokyo'));
entry.date?.month == now.month && final entryDate = tz.TZDateTime.from(entry.date!, tz.getLocation('Asia/Tokyo'));
entry.date?.day == now.day; bool isToday = entryDate.year == now.year &&
entryDate.month == now.month &&
entryDate.day == now.day;
_indexController.setReferenceMode(!isToday); _indexController.setReferenceMode(!isToday);
_indexController.setSelectedEventName(entry.event.eventName); _indexController.setSelectedEventName(entry.event.eventName);

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:rogapp/pages/entry/event_entries_controller.dart'; import 'package:rogapp/pages/entry/event_entries_controller.dart';
import 'package:timezone/timezone.dart' as tz;
class EventEntriesPage_old extends GetView<EventEntriesController> { class EventEntriesPage_old extends GetView<EventEntriesController> {
@override @override
@ -96,7 +97,8 @@ class EventEntriesPage extends GetView<EventEntriesController> {
if (date == null) { if (date == null) {
return '日時未設定'; return '日時未設定';
} }
return DateFormat('yyyy-MM-dd').format(date); final jstDate = tz.TZDateTime.from(date, tz.getLocation('Asia/Tokyo'));
return DateFormat('yyyy-MM-dd').format(jstDate);
} }
} }

View File

@ -489,7 +489,23 @@ class IndexController extends GetxController with WidgetsBindingObserver {
// //
void register(String email, String password, String password2, BuildContext context) { void register(String email, String password, String password2, BuildContext context) {
AuthService.register(email, password,password2).then((value) { AuthService.register(email, password,password2).then((value) {
if (value.isNotEmpty) { if (value is Map && value.containsKey("error")) {
String err_message = value["error"];
debugPrint("ユーザー登録失敗:${email}, ${password},${err_message}");
logManager.addOperationLog("User failed to register new account : ${email} , ${password} ,${err_message}.");
isLoading.value = false;
Get.snackbar(
'user_registration_failed_please_try_again'.tr, // ユーザー登録に失敗しました。
err_message,
backgroundColor: Colors.red,
colorText: Colors.white,
icon: const Icon(Icons.error, size: 40.0, color: Colors.blue),
snackPosition: SnackPosition.TOP,
duration: const Duration(seconds: 3),
//backgroundColor: Colors.yellow,
//icon:Image(image:AssetImage("assets/images/dora.png"))
);
}else{
debugPrint("ユーザー登録成功:${email}, ${password}"); debugPrint("ユーザー登録成功:${email}, ${password}");
logManager.addOperationLog("User tried to register new account : ${email} , ${password} ."); logManager.addOperationLog("User tried to register new account : ${email} , ${password} .");
@ -508,22 +524,7 @@ class IndexController extends GetxController with WidgetsBindingObserver {
); );
//Navigator.pop(context); //Navigator.pop(context);
Get.toNamed(AppPages.INDEX); Get.toNamed(AppPages.LOGIN);
} else {
debugPrint("ユーザー登録失敗:${email}, ${password}");
logManager.addOperationLog("User failed to register new account : ${email} , ${password} .");
isLoading.value = false;
Get.snackbar(
'failed'.tr, // 失敗
'user_registration_failed_please_try_again'.tr, // ユーザー登録に失敗しました。
backgroundColor: Colors.red,
colorText: Colors.white,
icon: const Icon(Icons.error, size: 40.0, color: Colors.blue),
snackPosition: SnackPosition.TOP,
duration: const Duration(seconds: 3),
//backgroundColor: Colors.yellow,
//icon:Image(image:AssetImage("assets/images/dora.png"))
);
} }
}); });
} }

View File

@ -36,24 +36,50 @@ class _IndexPageState extends State<IndexPage> {
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
//checkEntryAndShowHelper(); //checkLoginAndShowDialog();
}); });
} }
/* void checkLoginAndShowDialog() {
void checkEntryAndShowHelper() async { if (indexController.currentUser.isEmpty) {
final hasEntry = await checkIfUserHasEntry(); // この関数は実装する必要があります showDialog(
if (!hasEntry) { context: context,
showHelperDialog( barrierDismissible: false,
context, builder: (BuildContext context) {
'イベントに参加するには、チーム登録・メンバー登録及びエントリーが必要になります。', return AlertDialog(
'entry_helper', title: Text('ログインが必要です'),
showDoNotShowAgain: true, content: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('1) ログインされていません。ロゲに参加するにはログインが必要です。'),
SizedBox(height: 10),
Text('2) ログイン後、個人情報入力、チーム登録、エントリー登録を行なってください。'),
SizedBox(height: 10),
Text('3) エントリー登録は場所と日にちごとに行なってください。'),
],
),
actions: [
TextButton(
child: Text('キャンセル'),
onPressed: () {
Navigator.of(context).pop();
},
),
ElevatedButton(
child: Text('ログイン'),
onPressed: () {
Navigator.of(context).pop();
Get.toNamed(AppPages.LOGIN);
},
),
],
);
},
); );
} }
} }
*/
// class IndexPage extends GetView<IndexController> { // class IndexPage extends GetView<IndexController> {
// IndexPage({Key? key}) : super(key: key); // IndexPage({Key? key}) : super(key: key);

View File

@ -5,6 +5,8 @@ import 'package:rogapp/routes/app_pages.dart';
import 'package:rogapp/widgets/helper_dialog.dart'; import 'package:rogapp/widgets/helper_dialog.dart';
import 'package:rogapp/services/api_service.dart'; import 'package:rogapp/services/api_service.dart';
import 'package:package_info_plus/package_info_plus.dart';
// 要検討:ログインボタンとサインアップボタンの配色を見直すことを検討してください。現在の配色では、ボタンの役割がわかりにくい可能性があります。 // 要検討:ログインボタンとサインアップボタンの配色を見直すことを検討してください。現在の配色では、ボタンの役割がわかりにくい可能性があります。
// エラーメッセージをローカライズすることを検討してください。 // エラーメッセージをローカライズすることを検討してください。
// ログイン処理中にエラーが発生した場合のエラーハンドリングを追加することをお勧めします。 // ログイン処理中にエラーが発生した場合のエラーハンドリングを追加することをお勧めします。
@ -22,6 +24,7 @@ class _LoginPageState extends State<LoginPage> {
TextEditingController emailController = TextEditingController(); TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController(); TextEditingController passwordController = TextEditingController();
bool _obscureText = true; bool _obscureText = true;
String _version = ''; // バージョン情報を保持する変数
@override @override
void initState() { void initState() {
@ -32,6 +35,15 @@ class _LoginPageState extends State<LoginPage> {
'login_page' 'login_page'
); );
}); });
_getVersionInfo(); // バージョン情報を取得
}
// バージョン情報を取得するメソッド
Future<void> _getVersionInfo() async {
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
setState(() {
_version = packageInfo.version;
});
} }
void _showResetPasswordDialog() { void _showResetPasswordDialog() {
@ -124,6 +136,14 @@ class _LoginPageState extends State<LoginPage> {
const SizedBox( const SizedBox(
height: 5, height: 5,
), ),
// バージョン情報を表示
Text(
'Version: $_version',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
], ],
), ),
Padding( Padding(

View File

@ -89,6 +89,7 @@ class _RegisterPageState extends State<RegisterPage> {
ElevatedButton( ElevatedButton(
onPressed: _handleRegister, onPressed: _handleRegister,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.redAccent, backgroundColor: Colors.redAccent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(40)),
minimumSize: const Size(double.infinity, 60), minimumSize: const Size(double.infinity, 60),
@ -165,7 +166,7 @@ class _RegisterPageState extends State<RegisterPage> {
context context
); );
// 登録が成功したと仮定し、ログインページに遷移 // 登録が成功したと仮定し、ログインページに遷移
Get.offNamed(AppPages.LOGIN); //Get.offNamed(AppPages.LOGIN);
} catch (error) { } catch (error) {
_showErrorSnackbar("registration_error".tr, error.toString()); _showErrorSnackbar("registration_error".tr, error.toString());
} finally { } finally {

View File

@ -91,6 +91,7 @@ class MemberController extends GetxController {
lastname.value = value; lastname.value = value;
} }
Future<bool> saveMember() async { Future<bool> saveMember() async {
if (!_validateInputs()) return false; if (!_validateInputs()) return false;
@ -139,8 +140,8 @@ class MemberController extends GetxController {
return '${lastname.value} ${firstname.value}'.trim(); return '${lastname.value} ${firstname.value}'.trim();
} }
Future<void> updateMember() async { Future<bool> updateMember() async {
if (member.value == null) return; if (member.value == null) return false;
int? memberId = member.value?.id; int? memberId = member.value?.id;
try { try {
final updatedMember = await _apiService.updateTeamMember( final updatedMember = await _apiService.updateTeamMember(
@ -152,15 +153,17 @@ class MemberController extends GetxController {
female.value, female.value,
); );
member.value = updatedMember; member.value = updatedMember;
return true;
} catch (e) { } catch (e) {
print('Error updating member: $e'); print('Error updating member: $e');
return false;
} }
} }
Future<void> deleteMember() async { Future<bool> deleteMember() async {
if (member.value == null || member.value!.id == null) { if (member.value == null || member.value!.id == null) {
Get.snackbar('エラー', 'メンバー情報が不正です', snackPosition: SnackPosition.BOTTOM); Get.snackbar('エラー', 'メンバー情報が不正です', snackPosition: SnackPosition.BOTTOM);
return; return false;
} }
try { try {
@ -168,11 +171,14 @@ class MemberController extends GetxController {
await _apiService.deleteTeamMember(teamId, member.value!.id!); await _apiService.deleteTeamMember(teamId, member.value!.id!);
Get.snackbar('成功', 'メンバーが削除されました', snackPosition: SnackPosition.BOTTOM); Get.snackbar('成功', 'メンバーが削除されました', snackPosition: SnackPosition.BOTTOM);
member.value = null; member.value = null;
isLoading.value = false;
return true;
} catch (e) { } catch (e) {
print('Error deleting member: $e'); print('Error deleting member: $e');
Get.snackbar('エラー', 'メンバーの削除に失敗しました: ${e.toString()}', snackPosition: SnackPosition.BOTTOM); Get.snackbar('エラー', 'メンバーの削除に失敗しました: ${e.toString()}', snackPosition: SnackPosition.BOTTOM);
} finally {
isLoading.value = false; isLoading.value = false;
return false;
} }
} }
@ -251,10 +257,10 @@ class MemberController extends GetxController {
yearsFromSchoolStart--; yearsFromSchoolStart--;
} }
if (yearsFromSchoolStart < 0) return '未就学'; if (yearsFromSchoolStart < 7) return '未就学';
if (yearsFromSchoolStart < 6) return '${yearsFromSchoolStart + 1}'; if (yearsFromSchoolStart < 13) return '${yearsFromSchoolStart - 6}';
if (yearsFromSchoolStart < 9) return '${yearsFromSchoolStart - 5}'; if (yearsFromSchoolStart < 16) return '${yearsFromSchoolStart - 12}';
if (yearsFromSchoolStart < 12) return '${yearsFromSchoolStart - 8}'; if (yearsFromSchoolStart < 19) return '${yearsFromSchoolStart - 15}';
return '成人'; return '成人';
} }

View File

@ -7,6 +7,8 @@ import 'package:intl/intl.dart'; // この行を追加
import 'package:flutter_localizations/flutter_localizations.dart'; // 追加 import 'package:flutter_localizations/flutter_localizations.dart'; // 追加
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:rogapp/routes/app_pages.dart';
class MemberDetailPage extends StatefulWidget { class MemberDetailPage extends StatefulWidget {
@override @override
_MemberDetailPageState createState() => _MemberDetailPageState(); _MemberDetailPageState createState() => _MemberDetailPageState();
@ -34,15 +36,18 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
} }
void _initializeControllers() { void _initializeControllers() {
_firstNameController = TextEditingController(text: controller.firstname.value); _firstNameController =
_lastNameController = TextEditingController(text: controller.lastname.value); TextEditingController(text: controller.firstname.value);
_lastNameController =
TextEditingController(text: controller.lastname.value);
_emailController = TextEditingController(text: controller.email.value); _emailController = TextEditingController(text: controller.email.value);
controller.firstname.listen((value) { controller.firstname.listen((value) {
if (_firstNameController.text != value) { if (_firstNameController.text != value) {
_firstNameController.value = TextEditingValue( _firstNameController.value = TextEditingValue(
text: value, text: value,
selection: TextSelection.fromPosition(TextPosition(offset: value.length)), selection: TextSelection.fromPosition(
TextPosition(offset: value.length)),
); );
} }
}); });
@ -51,7 +56,8 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
if (_lastNameController.text != value) { if (_lastNameController.text != value) {
_lastNameController.value = TextEditingValue( _lastNameController.value = TextEditingValue(
text: value, text: value,
selection: TextSelection.fromPosition(TextPosition(offset: value.length)), selection: TextSelection.fromPosition(
TextPosition(offset: value.length)),
); );
} }
}); });
@ -60,12 +66,71 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
if (_emailController.text != value) { if (_emailController.text != value) {
_emailController.value = TextEditingValue( _emailController.value = TextEditingValue(
text: value, text: value,
selection: TextSelection.fromPosition(TextPosition(offset: value.length)), selection: TextSelection.fromPosition(
TextPosition(offset: value.length)),
); );
} }
}); });
} }
Future<void> _handleSaveAndNavigateBack() async {
bool success = await controller.saveMember();
if (success) {
Get.until((route) => Get.currentRoute == AppPages.TEAM_DETAIL);
// スナックバーが表示されるのを待つ
await Future.delayed(Duration(seconds: 1));
// 現在のスナックバーを安全に閉じる
if (Get.isSnackbarOpen) {
await Get.closeCurrentSnackbar();
}
// リストページに戻る
//Get.until((route) => Get.currentRoute == '/team');
// または、リストページの具体的なルート名がある場合は以下を使用
// Get.offNamed('/team');
}
}
Future<void> _handleDeleteAndNavigateBack() async {
final confirmed = await Get.dialog<bool>(
AlertDialog(
title: Text('確認'),
content: Text('このメンバーを削除してもよろしいですか?'),
actions: [
TextButton(
child: Text('キャンセル'),
onPressed: () => Get.back(result: false),
),
TextButton(
child: Text('削除'),
onPressed: () => Get.back(result: true),
),
],
),
);
if (confirmed == true) {
bool success = await controller.deleteMember();
if (success) {
// リストページに戻る
//Get.offNamed(result: true);
Get.until((route) => Get.currentRoute == AppPages.TEAM_DETAIL);
// スナックバーが表示されるのを待つ
await Future.delayed(Duration(seconds: 1));
// 現在のスナックバーを安全に閉じる
if (Get.isSnackbarOpen) {
await Get.closeCurrentSnackbar();
}
}
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final mode = Get.arguments['mode'] as String; final mode = Get.arguments['mode'] as String;
@ -109,17 +174,9 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
children: [ children: [
if (mode == 'new') if (mode == 'new')
TextFormField( TextFormField(
controller: _emailController,
onChanged: (value) => controller.updateEmail(value),
decoration: InputDecoration(labelText: 'メールアドレス'), decoration: InputDecoration(labelText: 'メールアドレス'),
//onChanged: (value) => controller.email.value = value,
onChanged: (value) {
controller.email.value = value;
// カーソル位置を更新
emailController.selection = TextSelection.fromPosition(
TextPosition(offset: value.length),
);
},
controller: emailController,
//controller: TextEditingController(text: controller.email.value),
keyboardType: TextInputType.emailAddress, // メールアドレス用のキーボードを表示 keyboardType: TextInputType.emailAddress, // メールアドレス用のキーボードを表示
autocorrect: false, // 自動修正を無効化 autocorrect: false, // 自動修正を無効化
enableSuggestions: false, enableSuggestions: false,
@ -129,16 +186,20 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
else else
Text('メールアドレス: ${controller.email.value}'), Text('メールアドレス: ${controller.email.value}'),
if (controller.email.value.isEmpty || mode == 'edit') ...[ if (controller.email.value.isEmpty || controller.isDummyEmail || mode == 'edit') ...[
TextFormField( TextFormField(
decoration: InputDecoration(labelText: ''), decoration: InputDecoration(labelText: ''),
onChanged: (value) => controller.lastname.value = value, controller: _lastNameController,
controller: TextEditingController(text: controller.lastname.value), onChanged: (value) => controller.updateLastName(value),
//controller: TextEditingController(text: controller.lastname.value),
), ),
TextFormField( TextFormField(
decoration: InputDecoration(labelText: ''), decoration: InputDecoration(labelText: ''),
onChanged: (value) => controller.firstname.value = value, controller: _firstNameController,
controller: TextEditingController(text: controller.firstname.value), //onChanged: (value) => controller.firstname.value = value,
onChanged: (value) => controller.updateFirstName(value),
//controller: TextEditingController(text: controller.firstname.value),
), ),
// 生年月日 // 生年月日
if (controller.isDummyEmail || !controller.isOver18()) if (controller.isDummyEmail || !controller.isOver18())
@ -178,28 +239,7 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
children: [ children: [
ElevatedButton( ElevatedButton(
child: Text('削除'), child: Text('削除'),
onPressed: () async { onPressed: _handleDeleteAndNavigateBack,
final confirmed = await Get.dialog<bool>(
AlertDialog(
title: Text('確認'),
content: Text('このメンバーを削除してもよろしいですか?'),
actions: [
TextButton(
child: Text('キャンセル'),
onPressed: () => Get.back(result: false),
),
TextButton(
child: Text('削除'),
onPressed: () => Get.back(result: true),
),
],
),
);
if (confirmed == true) {
await controller.deleteMember();
Get.back(result: true);
}
},
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.red, backgroundColor: Colors.red,
foregroundColor: Colors.white, foregroundColor: Colors.white,
@ -216,10 +256,7 @@ class _MemberDetailPageState extends State<MemberDetailPage> {
), ),
ElevatedButton( ElevatedButton(
child: Text('保存・招待'), child: Text('保存・招待'),
onPressed: () async { onPressed: _handleSaveAndNavigateBack,
await controller.saveMember();
Get.back(result: true);
},
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.green, backgroundColor: Colors.green,
foregroundColor: Colors.white, foregroundColor: Colors.white,

View File

@ -175,9 +175,9 @@ class _TeamDetailPageState extends State<TeamDetailPage> {
AppPages.MEMBER_DETAIL, AppPages.MEMBER_DETAIL,
arguments: {'mode': 'edit', 'member': member, 'teamId': controller.selectedTeam.value?.id}, arguments: {'mode': 'edit', 'member': member, 'teamId': controller.selectedTeam.value?.id},
); );
if (result == true) {
await controller.fetchTeamMembers(controller.selectedTeam.value!.id); await controller.fetchTeamMembers(controller.selectedTeam.value!.id);
}
}, },
); );
}, },

View File

@ -363,7 +363,7 @@ class ApiService extends GetxService{
}), }),
); );
if (response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
final decodedResponse = utf8.decode(response.bodyBytes); final decodedResponse = utf8.decode(response.bodyBytes);
return User.fromJson(json.decode(decodedResponse)); return User.fromJson(json.decode(decodedResponse));
} else { } else {
@ -511,6 +511,8 @@ class ApiService extends GetxService{
return Entry.fromJson(json.decode(decodedResponse)); return Entry.fromJson(json.decode(decodedResponse));
} else { } else {
final decodedResponse = utf8.decode(response.bodyBytes);
print("decodedResponse = $decodedResponse");
throw Exception('Failed to create entry'); throw Exception('Failed to create entry');
} }
} }
@ -552,7 +554,7 @@ class ApiService extends GetxService{
} }
Future<Entry> updateEntry(int entryId, int teamId, int eventId, int categoryId, DateTime date) async { Future<Entry> updateEntry(int entryId, int teamId, int eventId, int categoryId, DateTime date,int zekken_number) async {
init(); init();
getToken(); getToken();
@ -572,6 +574,7 @@ class ApiService extends GetxService{
'event': eventId, 'event': eventId,
'category': categoryId, 'category': categoryId,
'date': formattedDate, 'date': formattedDate,
'zekken_number': zekken_number,
}), }),
); );
@ -580,6 +583,9 @@ class ApiService extends GetxService{
return Entry.fromJson(json.decode(decodedResponse)); return Entry.fromJson(json.decode(decodedResponse));
} else { } else {
final decodedResponse = utf8.decode(response.bodyBytes);
final blk = json.decode(decodedResponse);
throw Exception('Failed to update entry'); throw Exception('Failed to update entry');
} }
} }

View File

@ -164,9 +164,10 @@ class AuthService {
}, },
body: jsonEncode(<String, String>{'email': email, 'password': password, 'password2': password2}), body: jsonEncode(<String, String>{'email': email, 'password': password, 'password2': password2}),
); );
//print(response.body);
if (response.statusCode == 201) {
cats = json.decode(utf8.decode(response.bodyBytes)); cats = json.decode(utf8.decode(response.bodyBytes));
print("result=$cats");
if (response.statusCode == 201) {
}else{
} }
return cats; return cats;
} }

View File

@ -202,6 +202,7 @@ class ExternalService {
colorText: Colors.white colorText: Colors.white
); );
} }
} }
} else { } else {
Get.snackbar("サーバーエラーがおきました", "サーバーと通信できませんでした", Get.snackbar("サーバーエラーがおきました", "サーバーと通信できませんでした",
@ -273,7 +274,8 @@ class ExternalService {
Get.find<DestinationController>(); Get.find<DestinationController>();
// チームIDを取得 // チームIDを取得
int teamId = indexController.currentUser[0]["user"]["team"]["id"];
//int teamId = indexController.currentUser[0]["user"]["team"]["id"];
debugPrint("== goal Rogaining =="); debugPrint("== goal Rogaining ==");
@ -283,7 +285,7 @@ class ExternalService {
id: 1, id: 1,
team_name: teamname, team_name: teamname,
event_code: eventcode, event_code: eventcode,
user_id: teamId, //userId, user_id: userId, // 中身はteamid
cp_number: -1, cp_number: -1,
checkintime: DateTime.now().toUtc().microsecondsSinceEpoch, checkintime: DateTime.now().toUtc().microsecondsSinceEpoch,
image: image, image: image,
@ -305,7 +307,7 @@ class ExternalService {
}, },
// 'id', 'user', 'goalimage', 'goaltime', 'team_name', 'event_code','cp_number' // 'id', 'user', 'goalimage', 'goaltime', 'team_name', 'event_code','cp_number'
body: jsonEncode(<String, String>{ body: jsonEncode(<String, String>{
'user': teamId.toString(), //userId.toString(), 'user': userId.toString(), //userId.toString(),
'team_name': teamname, 'team_name': teamname,
'event_code': eventcode, 'event_code': eventcode,
'goaltime': goalTime, 'goaltime': goalTime,
@ -318,6 +320,7 @@ class ExternalService {
String url = '$serverUrl/gifuroge/goal_from_rogapp'; String url = '$serverUrl/gifuroge/goal_from_rogapp';
//print('++++++++$url'); //print('++++++++$url');
if (response.statusCode == 201) { if (response.statusCode == 201) {
try {
Map<String, dynamic> res = json.decode(utf8.decode(response.bodyBytes)); Map<String, dynamic> res = json.decode(utf8.decode(response.bodyBytes));
// print('----_res : $res ----'); // print('----_res : $res ----');
// print('---- image url ${res["goalimage"]} ----'); // print('---- image url ${res["goalimage"]} ----');
@ -331,7 +334,8 @@ class ExternalService {
'event_code': eventcode, 'event_code': eventcode,
'goal_time': goalTime, 'goal_time': goalTime,
'image': res["goalimage"].toString().replaceAll( 'image': res["goalimage"].toString().replaceAll(
'http://localhost:8100', serverUrl) //'http://rogaining.sumasen.net') 'http://localhost:8100', serverUrl)
//'http://rogaining.sumasen.net')
}), }),
); );
String rec = jsonEncode(<String, String>{ String rec = jsonEncode(<String, String>{
@ -340,12 +344,18 @@ class ExternalService {
'goal_time': goalTime, 'goal_time': goalTime,
'image': res["goalimage"] 'image': res["goalimage"]
.toString() .toString()
.replaceAll('http://localhost:8100', serverUrl) //'http://rogaining.sumasen.net') .replaceAll('http://localhost:8100', serverUrl)
//'http://rogaining.sumasen.net')
}); });
//print("-- json -- $rec"); //print("-- json -- $rec");
//print('----- response2 is $response2 --------'); //print('----- response2 is $response2 --------');
if (response2.statusCode == 200) { if (response2.statusCode == 200) {
res2 = json.decode(utf8.decode(response2.bodyBytes)); res2 = json.decode(utf8.decode(response2.bodyBytes));
} else {
res2 = json.decode(utf8.decode(response2.bodyBytes));
}
} catch(e){
print( "Error {$e}" );
} }
} }
//} //}

View File

@ -250,7 +250,10 @@ class BottomSheetNew extends GetView<BottomSheetController> {
//goal //goal
return ElevatedButton( return ElevatedButton(
style: ElevatedButton.styleFrom(backgroundColor: Colors.red), style: ElevatedButton.styleFrom(
foregroundColor: Colors.white,
backgroundColor: Colors.red
),
onPressed: destinationController.rogainingCounted.value == true && onPressed: destinationController.rogainingCounted.value == true &&
destinationController.distanceToStart() <= 500 && destinationController.distanceToStart() <= 500 &&
(destination.cp == 0 || destination.cp == -2|| destination.cp == -1) && (destination.cp == 0 || destination.cp == -2|| destination.cp == -1) &&

View File

@ -92,6 +92,8 @@ class _LoginPageState extends State<LoginPage> {
//LoginPage({Key? key}) : super(key: key); //LoginPage({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(

View File

@ -1266,6 +1266,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "2.0.0"
timezone:
dependency: "direct main"
description:
name: timezone
sha256: "2236ec079a174ce07434e89fcd3fcda430025eb7692244139a9cf54fdcf1fc7d"
url: "https://pub.dev"
source: hosted
version: "0.9.4"
transparent_image: transparent_image:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -15,7 +15,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
# Read more about iOS versioning at # Read more about iOS versioning at
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
version: 4.8.6+486 version: 4.8.13+493
environment: environment:
sdk: ">=3.2.0 <4.0.0" sdk: ">=3.2.0 <4.0.0"
@ -41,6 +41,7 @@ dependencies:
geolocator: ^10.1.0 geolocator: ^10.1.0
permission_handler: ^11.3.1 permission_handler: ^11.3.1
logging: ^1.0.2 logging: ^1.0.2
timezone: ^0.9.1
# flutter_dev_tools: ^0.0.2 # flutter_dev_tools: ^0.0.2
# permission_handler: ^11.1.0 <== older # permission_handler: ^11.1.0 <== older