チームまでは表示できた。表示と更新及びメンバー編集不可。エントリー以降も表示不可。
This commit is contained in:
15597
all_combined.txt
Normal file
15597
all_combined.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -34,7 +34,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
import 'pages/permission/permission.dart';
|
||||
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
Map<String, dynamic> deviceInfo = {};
|
||||
|
||||
@ -100,6 +100,7 @@ void restoreGame() async {
|
||||
pref.getBool("rogaining_counted") ?? false;
|
||||
DestinationController.ready_for_goal =
|
||||
pref.getBool("ready_for_goal") ?? false;
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,13 +151,39 @@ void main() async {
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
try {
|
||||
// ApiServiceを初期化
|
||||
//await Get.putAsync(() => ApiService().init());
|
||||
await initServices();
|
||||
|
||||
runApp(const ProviderScope(child: MyApp()));
|
||||
//runApp(HomePage()); // MyApp()からHomePage()に変更
|
||||
//runApp(const MyApp());
|
||||
}catch(e, stackTrace){
|
||||
print('Error during initialization: $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> initServices() async {
|
||||
print('Starting services ...');
|
||||
try {
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
print('All services started...');
|
||||
}catch(e){
|
||||
print('Error initializing ApiService: $e');
|
||||
}
|
||||
|
||||
try {
|
||||
Get.put(SettingsController());
|
||||
print('SettingsController initialized successfully');
|
||||
} catch (e) {
|
||||
print('Error initializing SettingsController: $e');
|
||||
}
|
||||
|
||||
print('All services started...');
|
||||
|
||||
}
|
||||
|
||||
Future<void> requestLocationPermission() async {
|
||||
try {
|
||||
|
||||
45
lib/model/category.dart
Normal file
45
lib/model/category.dart
Normal file
@ -0,0 +1,45 @@
|
||||
// lib/models/category.dart
|
||||
|
||||
class NewCategory {
|
||||
final int id;
|
||||
final String categoryName;
|
||||
final int categoryNumber;
|
||||
final Duration duration;
|
||||
final int numOfMember;
|
||||
final bool family;
|
||||
final bool female;
|
||||
|
||||
NewCategory({
|
||||
required this.id,
|
||||
required this.categoryName,
|
||||
required this.categoryNumber,
|
||||
required this.duration,
|
||||
required this.numOfMember,
|
||||
required this.family,
|
||||
required this.female,
|
||||
});
|
||||
|
||||
factory NewCategory.fromJson(Map<String, dynamic> json) {
|
||||
return NewCategory(
|
||||
id: json['id'] ?? 0,
|
||||
categoryName: json['category_name'] ?? 'Unknown Category',
|
||||
categoryNumber: json['category_number'] ?? 0,
|
||||
duration: Duration(seconds: json['duration'] ?? 0),
|
||||
numOfMember: json['num_of_member'] ?? 1,
|
||||
family: json['family'] ?? false,
|
||||
female: json['female'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'category_name': categoryName,
|
||||
'category_number': categoryNumber,
|
||||
'duration': duration.inSeconds,
|
||||
'num_of_member': numOfMember,
|
||||
'family': family,
|
||||
'female': female,
|
||||
};
|
||||
}
|
||||
}
|
||||
45
lib/model/entry.dart
Normal file
45
lib/model/entry.dart
Normal file
@ -0,0 +1,45 @@
|
||||
// lib/models/entry.dart
|
||||
import 'event.dart';
|
||||
import 'event.dart';
|
||||
import 'team.dart';
|
||||
import 'category.dart';
|
||||
|
||||
class Entry {
|
||||
final int id;
|
||||
final Team team;
|
||||
final Event event;
|
||||
final NewCategory category;
|
||||
final DateTime date;
|
||||
final String owner;
|
||||
|
||||
Entry({
|
||||
required this.id,
|
||||
required this.team,
|
||||
required this.event,
|
||||
required this.category,
|
||||
required this.date,
|
||||
required this.owner,
|
||||
});
|
||||
|
||||
factory Entry.fromJson(Map<String, dynamic> json) {
|
||||
return Entry(
|
||||
id: json['id'],
|
||||
team: Team.fromJson(json['team']),
|
||||
event: Event.fromJson(json['event']),
|
||||
category: NewCategory.fromJson(json['category']),
|
||||
date: DateTime.parse(json['date']),
|
||||
owner: json['owner'],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'team': team.toJson(),
|
||||
'event': event.toJson(),
|
||||
'category': category.toJson(),
|
||||
'date': date.toIso8601String(),
|
||||
'owner': owner,
|
||||
};
|
||||
}
|
||||
}
|
||||
33
lib/model/event.dart
Normal file
33
lib/model/event.dart
Normal file
@ -0,0 +1,33 @@
|
||||
// lib/models/event.dart
|
||||
|
||||
class Event {
|
||||
final int id;
|
||||
final String eventName;
|
||||
final DateTime startDatetime;
|
||||
final DateTime endDatetime;
|
||||
|
||||
Event({
|
||||
required this.id,
|
||||
required this.eventName,
|
||||
required this.startDatetime,
|
||||
required this.endDatetime,
|
||||
});
|
||||
|
||||
factory Event.fromJson(Map<String, dynamic> json) {
|
||||
return Event(
|
||||
id: json['id'],
|
||||
eventName: json['event_name'],
|
||||
startDatetime: DateTime.parse(json['start_datetime']),
|
||||
endDatetime: DateTime.parse(json['end_datetime']),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'event_name': eventName,
|
||||
'start_datetime': startDatetime.toIso8601String(),
|
||||
'end_datetime': endDatetime.toIso8601String(),
|
||||
};
|
||||
}
|
||||
}
|
||||
44
lib/model/team.dart
Normal file
44
lib/model/team.dart
Normal file
@ -0,0 +1,44 @@
|
||||
// lib/models/team.dart
|
||||
|
||||
import 'category.dart';
|
||||
import 'user.dart';
|
||||
|
||||
class Team {
|
||||
final int id;
|
||||
final String zekkenNumber;
|
||||
final String teamName;
|
||||
final NewCategory category;
|
||||
final User owner;
|
||||
|
||||
Team({
|
||||
required this.id,
|
||||
required this.zekkenNumber,
|
||||
required this.teamName,
|
||||
required this.category,
|
||||
required this.owner,
|
||||
});
|
||||
|
||||
factory Team.fromJson(Map<String, dynamic> json) {
|
||||
return Team(
|
||||
id: json['id'] ?? 0,
|
||||
zekkenNumber: json['zekken_number'] ?? 'Unknown',
|
||||
teamName: json['team_name'] ?? 'Unknown Team',
|
||||
category: json['category'] != null
|
||||
? NewCategory.fromJson(json['category'])
|
||||
: NewCategory(id: 0, categoryName: 'Unknown', categoryNumber: 0, duration: Duration.zero, numOfMember: 1, family: false, female: false),
|
||||
owner: json['owner'] != null
|
||||
? User.fromJson(json['owner'])
|
||||
: User(id: 0, email: 'unknown@example.com', firstname: 'Unknown', lastname: 'User', dateOfBirth: null, female: false, isActive: false),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'zekken_number': zekkenNumber,
|
||||
'team_name': teamName,
|
||||
'category': category.toJson(),
|
||||
'owner': owner.toJson(),
|
||||
};
|
||||
}
|
||||
}
|
||||
47
lib/model/user.dart
Normal file
47
lib/model/user.dart
Normal file
@ -0,0 +1,47 @@
|
||||
// lib/models/user.dart
|
||||
|
||||
class User {
|
||||
final int? id;
|
||||
final String? email;
|
||||
final String firstname;
|
||||
final String lastname;
|
||||
final DateTime? dateOfBirth;
|
||||
final bool female;
|
||||
final bool isActive;
|
||||
|
||||
User({
|
||||
this.id,
|
||||
this.email,
|
||||
required this.firstname,
|
||||
required this.lastname,
|
||||
this.dateOfBirth,
|
||||
required this.female,
|
||||
required this.isActive,
|
||||
});
|
||||
|
||||
factory User.fromJson(Map<String, dynamic> json) {
|
||||
return User(
|
||||
id: json['id'],
|
||||
email: json['email'],
|
||||
firstname: json['firstname'] ?? 'Unknown',
|
||||
lastname: json['lastname'] ?? 'Unknown',
|
||||
dateOfBirth: json['date_of_birth'] != null
|
||||
? DateTime.tryParse(json['date_of_birth'])
|
||||
: null,
|
||||
female: json['female'] ?? false,
|
||||
isActive: json['is_active'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'email': email,
|
||||
'firstname': firstname,
|
||||
'lastname': lastname,
|
||||
'date_of_birth': dateOfBirth?.toIso8601String(),
|
||||
'female': female,
|
||||
'is_active': isActive,
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -206,6 +206,22 @@ class DrawerPage extends StatelessWidget {
|
||||
width: 0,
|
||||
height: 0,
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.group),
|
||||
title: Text('チーム管理'),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Get.toNamed(AppPages.TEAM_LIST);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.event),
|
||||
title: Text('エントリー管理'),
|
||||
onTap: () {
|
||||
Get.back();
|
||||
Get.toNamed(AppPages.ENTRY_LIST);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.privacy_tip),
|
||||
title: Text("privacy".tr),
|
||||
|
||||
12
lib/pages/entry/entry_binding.dart
Normal file
12
lib/pages/entry/entry_binding.dart
Normal file
@ -0,0 +1,12 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/entry/entry_controller.dart';
|
||||
import 'package:rogapp/pages/team/member_controller.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class EntryBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<ApiService>(() => ApiService());
|
||||
Get.lazyPut<EntryController>(() => EntryController());
|
||||
}
|
||||
}
|
||||
155
lib/pages/entry/entry_controller.dart
Normal file
155
lib/pages/entry/entry_controller.dart
Normal file
@ -0,0 +1,155 @@
|
||||
// lib/entry/entry_controller.dart
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/model/entry.dart';
|
||||
import 'package:rogapp/model/event.dart';
|
||||
import 'package:rogapp/model/team.dart';
|
||||
import 'package:rogapp/model/category.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class EntryController extends GetxController {
|
||||
late final ApiService _apiService;
|
||||
|
||||
final entries = <Entry>[].obs;
|
||||
final events = <Event>[].obs;
|
||||
final teams = <Team>[].obs;
|
||||
final categories = <NewCategory>[].obs;
|
||||
|
||||
final selectedEvent = Rx<Event?>(null);
|
||||
final selectedTeam = Rx<Team?>(null);
|
||||
final selectedCategory = Rx<NewCategory?>(null);
|
||||
final selectedDate = Rx<DateTime?>(null);
|
||||
|
||||
final currentEntry = Rx<Entry?>(null);
|
||||
|
||||
@override
|
||||
void onInit() async{
|
||||
super.onInit();
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
_apiService = Get.find<ApiService>();
|
||||
|
||||
try {
|
||||
await Future.wait([
|
||||
fetchEntries(),
|
||||
fetchEvents(),
|
||||
fetchTeams(),
|
||||
fetchCategories(),
|
||||
]);
|
||||
if (Get.arguments != null && Get.arguments['entry'] != null) {
|
||||
currentEntry.value = Get.arguments['entry'];
|
||||
_initializeEntryData();
|
||||
}
|
||||
Get.putAsync(() => ApiService().init());
|
||||
}catch(e){
|
||||
print('Error initializing data: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void _initializeEntryData() {
|
||||
if (currentEntry.value != null) {
|
||||
selectedEvent.value = currentEntry.value!.event;
|
||||
selectedTeam.value = currentEntry.value!.team;
|
||||
selectedCategory.value = currentEntry.value!.category;
|
||||
selectedDate.value = currentEntry.value!.date;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchEntries() async {
|
||||
try {
|
||||
final fetchedEntries = await _apiService.getEntries();
|
||||
entries.assignAll(fetchedEntries);
|
||||
} catch (e) {
|
||||
print('Error fetching entries: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchEvents() async {
|
||||
try {
|
||||
final fetchedEvents = await _apiService.getEvents();
|
||||
events.assignAll(fetchedEvents);
|
||||
} catch (e) {
|
||||
print('Error fetching events: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchTeams() async {
|
||||
try {
|
||||
final fetchedTeams = await _apiService.getTeams();
|
||||
teams.assignAll(fetchedTeams);
|
||||
} catch (e) {
|
||||
print('Error fetching teams: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchCategories() async {
|
||||
try {
|
||||
final fetchedCategories = await _apiService.getCategories();
|
||||
categories.assignAll(fetchedCategories);
|
||||
} catch (e) {
|
||||
print('Error fetching categories: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createEntry() async {
|
||||
if (selectedEvent.value == null || selectedTeam.value == null ||
|
||||
selectedCategory.value == null || selectedDate.value == null) {
|
||||
Get.snackbar('Error', 'Please fill all fields');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final newEntry = await _apiService.createEntry(
|
||||
selectedTeam.value!.id,
|
||||
selectedEvent.value!.id,
|
||||
selectedCategory.value!.id,
|
||||
selectedDate.value!,
|
||||
);
|
||||
entries.add(newEntry);
|
||||
Get.back();
|
||||
} catch (e) {
|
||||
print('Error creating entry: $e');
|
||||
Get.snackbar('Error', 'Failed to create entry');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateEntry() async {
|
||||
if (currentEntry.value == null) return;
|
||||
try {
|
||||
final updatedEntry = await _apiService.updateEntry(
|
||||
currentEntry.value!.id,
|
||||
selectedEvent.value!.id,
|
||||
selectedCategory.value!.id,
|
||||
selectedDate.value!,
|
||||
);
|
||||
final index = entries.indexWhere((entry) => entry.id == updatedEntry.id);
|
||||
if (index != -1) {
|
||||
entries[index] = updatedEntry;
|
||||
}
|
||||
Get.back();
|
||||
} catch (e) {
|
||||
print('Error updating entry: $e');
|
||||
Get.snackbar('Error', 'Failed to update entry');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntry() async {
|
||||
if (currentEntry.value == null) return;
|
||||
try {
|
||||
await _apiService.deleteEntry(currentEntry.value!.id);
|
||||
entries.removeWhere((entry) => entry.id == currentEntry.value!.id);
|
||||
Get.back();
|
||||
} catch (e) {
|
||||
print('Error deleting entry: $e');
|
||||
Get.snackbar('Error', 'Failed to delete entry');
|
||||
}
|
||||
}
|
||||
|
||||
void updateEvent(Event? value) => selectedEvent.value = value;
|
||||
void updateTeam(Team? value) => selectedTeam.value = value;
|
||||
void updateCategory(NewCategory? value) => selectedCategory.value = value;
|
||||
void updateDate(DateTime value) => selectedDate.value = value;
|
||||
|
||||
bool isOwner() {
|
||||
// Implement logic to check if the current user is the owner of the entry
|
||||
return true; // Placeholder
|
||||
}
|
||||
}
|
||||
62
lib/pages/entry/entry_detail_page.dart
Normal file
62
lib/pages/entry/entry_detail_page.dart
Normal file
@ -0,0 +1,62 @@
|
||||
// lib/pages/entry/entry_detail_page.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/entry/entry_controller.dart';
|
||||
|
||||
class EntryDetailPage extends GetView<EntryController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Map<String, dynamic> arguments = Get.arguments ?? {};
|
||||
final mode = Get.arguments['mode'] as String? ?? 'new';
|
||||
final entry = Get.arguments['entry'];
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(mode == 'new' ? 'エントリー登録' : 'エントリー詳細'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Obx(() => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
DropdownButtonFormField(
|
||||
decoration: InputDecoration(labelText: 'イベント'),
|
||||
value: controller.selectedEvent.value,
|
||||
items: controller.events.map((event) => DropdownMenuItem(
|
||||
value: event,
|
||||
child: Text(event.eventName),
|
||||
)).toList(),
|
||||
onChanged: (value) => controller.updateEvent(value),
|
||||
),
|
||||
DropdownButtonFormField(
|
||||
decoration: InputDecoration(labelText: 'チーム'),
|
||||
value: controller.selectedTeam.value,
|
||||
items: controller.teams.map((team) => DropdownMenuItem(
|
||||
value: team,
|
||||
child: Text(team.teamName),
|
||||
)).toList(),
|
||||
onChanged: (value) => controller.updateTeam(value),
|
||||
),
|
||||
DropdownButtonFormField(
|
||||
decoration: InputDecoration(labelText: 'カテゴリ'),
|
||||
value: controller.selectedCategory.value,
|
||||
items: controller.categories.map((category) => DropdownMenuItem(
|
||||
value: category,
|
||||
child: Text(category.categoryName),
|
||||
)).toList(),
|
||||
onChanged: (value) => controller.updateCategory(value),
|
||||
),
|
||||
// 日付選択ウィジェットを追加
|
||||
if (mode == 'edit' && controller.isOwner())
|
||||
ElevatedButton(
|
||||
child: Text('エントリーを削除'),
|
||||
onPressed: () => controller.deleteEntry(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
35
lib/pages/entry/entry_list_page.dart
Normal file
35
lib/pages/entry/entry_list_page.dart
Normal file
@ -0,0 +1,35 @@
|
||||
// lib/pages/entry/entry_list_page.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/entry/entry_controller.dart';
|
||||
import 'package:rogapp/routes/app_pages.dart';
|
||||
|
||||
class EntryListPage extends GetView<EntryController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('エントリー管理'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () => Get.toNamed(AppPages.ENTRY_DETAIL, arguments: {'mode': 'new'}),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Obx(() => ListView.builder(
|
||||
itemCount: controller.entries.length,
|
||||
itemBuilder: (context, index) {
|
||||
final entry = controller.entries[index];
|
||||
return ListTile(
|
||||
title: Text(entry.event?.eventName ?? 'イベント未設定'),
|
||||
subtitle: Text('${entry.team?.teamName ?? 'チーム未設定'} - ${entry.category?.categoryName ?? 'カテゴリ未設定'}'),
|
||||
trailing: Text(entry.date?.toString().substring(0, 10) ?? '日付未設定'),
|
||||
onTap: () => Get.toNamed(AppPages.ENTRY_DETAIL, arguments: {'mode': 'edit', 'entry': entry}),
|
||||
);
|
||||
},
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,8 @@ import 'package:rogapp/utils/database_helper.dart';
|
||||
import 'package:rogapp/widgets/debug_widget.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
import '../../main.dart';
|
||||
|
||||
|
||||
@ -190,11 +192,19 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
||||
WidgetsBinding.instance?.addObserver(this);
|
||||
_startLocationService(); // アプリ起動時にLocationServiceを開始する
|
||||
|
||||
initializeApiService();
|
||||
|
||||
print('IndexController onInit called'); // デバッグ用の出力を追加
|
||||
|
||||
}
|
||||
|
||||
|
||||
Future<void> initializeApiService() async {
|
||||
if (currentUser.isNotEmpty) {
|
||||
// 既にログインしている場合
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
// 必要に応じて追加の初期化処理
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void checkPermission()
|
||||
@ -314,9 +324,9 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
||||
|
||||
// 要検討:エラーハンドリングが行われていますが、エラーメッセージをローカライズすることを検討してください。
|
||||
//
|
||||
void login(String email, String password, BuildContext context) {
|
||||
void login(String email, String password, BuildContext context) async{
|
||||
|
||||
AuthService.login(email, password).then((value) {
|
||||
AuthService.login(email, password).then((value) async {
|
||||
print("------- logged in user details ######## $value ###### --------");
|
||||
if (value.isNotEmpty) {
|
||||
logManager.addOperationLog("User logged in : ${value}.");
|
||||
@ -324,6 +334,11 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
||||
// Navigator.pop(context);
|
||||
print("--------- user details login ----- $value");
|
||||
changeUser(value);
|
||||
|
||||
// ログイン成功後、api_serviceを初期化
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
|
||||
|
||||
} else {
|
||||
logManager.addOperationLog("User failed login : ${email} , ${password}.");
|
||||
isLoading.value = false;
|
||||
|
||||
11
lib/pages/team/member_binding.dart
Normal file
11
lib/pages/team/member_binding.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/team/member_controller.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class MemberBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<ApiService>(() => ApiService());
|
||||
Get.lazyPut<MemberController>(() => MemberController());
|
||||
}
|
||||
}
|
||||
105
lib/pages/team/member_controller.dart
Normal file
105
lib/pages/team/member_controller.dart
Normal file
@ -0,0 +1,105 @@
|
||||
// lib/controllers/member_controller.dart
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/model/user.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class MemberController extends GetxController {
|
||||
late final ApiService _apiService;
|
||||
|
||||
final int teamId = 0;
|
||||
final member = Rx<User?>(null);
|
||||
final email = ''.obs;
|
||||
final firstname = ''.obs;
|
||||
final lastname = ''.obs;
|
||||
final dateOfBirth = Rx<DateTime?>(null);
|
||||
|
||||
@override
|
||||
void onInit() async{
|
||||
super.onInit();
|
||||
await Get.putAsync(() => ApiService().init());
|
||||
_apiService = Get.find<ApiService>();
|
||||
if (Get.arguments != null && Get.arguments['member'] != null) {
|
||||
member.value = Get.arguments['member'];
|
||||
_initializeMemberData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _initializeMemberData() {
|
||||
if (member.value != null) {
|
||||
email.value = member.value!.email ?? '';
|
||||
firstname.value = member.value!.firstname ?? '';
|
||||
lastname.value = member.value!.lastname ?? '';
|
||||
dateOfBirth.value = member.value!.dateOfBirth;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createMember(int teamId) async {
|
||||
try {
|
||||
final newMember = await _apiService.createTeamMember(
|
||||
teamId,
|
||||
email.value,
|
||||
firstname.value,
|
||||
lastname.value,
|
||||
dateOfBirth.value,
|
||||
);
|
||||
member.value = newMember;
|
||||
} catch (e) {
|
||||
print('Error creating member: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateMember() async {
|
||||
if (member.value == null) return;
|
||||
int? memberId = member.value?.id;
|
||||
try {
|
||||
final updatedMember = await _apiService.updateTeamMember(
|
||||
teamId,
|
||||
memberId!,
|
||||
firstname.value,
|
||||
lastname.value,
|
||||
dateOfBirth.value,
|
||||
);
|
||||
member.value = updatedMember;
|
||||
} catch (e) {
|
||||
print('Error updating member: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteMember() async {
|
||||
if (member.value == null) return;
|
||||
int? memberId = member.value?.id;
|
||||
try {
|
||||
await _apiService.deleteTeamMember(teamId,memberId!);
|
||||
member.value = null;
|
||||
Get.back();
|
||||
} catch (e) {
|
||||
print('Error deleting member: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> resendInvitation() async {
|
||||
if (member.value == null || member.value!.email == null) return;
|
||||
int? memberId = member.value?.id;
|
||||
try {
|
||||
await _apiService.resendMemberInvitation(memberId!);
|
||||
Get.snackbar('Success', 'Invitation resent successfully');
|
||||
} catch (e) {
|
||||
print('Error resending invitation: $e');
|
||||
Get.snackbar('Error', 'Failed to resend invitation');
|
||||
}
|
||||
}
|
||||
|
||||
void updateEmail(String value) => email.value = value;
|
||||
void updateFirstname(String value) => firstname.value = value;
|
||||
void updateLastname(String value) => lastname.value = value;
|
||||
void updateDateOfBirth(DateTime value) => dateOfBirth.value = value;
|
||||
|
||||
String getMemberStatus() {
|
||||
if (member.value == null) return '';
|
||||
if (member.value!.email == null) return '未登録';
|
||||
if (member.value!.isActive) return '承認済';
|
||||
return '招待中';
|
||||
}
|
||||
}
|
||||
55
lib/pages/team/member_detail_page.dart
Normal file
55
lib/pages/team/member_detail_page.dart
Normal file
@ -0,0 +1,55 @@
|
||||
// lib/pages/team/member_detail_page.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/team/member_controller.dart';
|
||||
|
||||
class MemberDetailPage extends GetView<MemberController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mode = Get.arguments['mode'];
|
||||
final member = Get.arguments['member'];
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(mode == 'new' ? 'メンバー追加' : 'メンバー詳細'),
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (mode == 'edit' && member.email != null)
|
||||
Text('Email: ${member.email}'),
|
||||
if (mode == 'new' || (mode == 'edit' && member.email == null))
|
||||
TextField(
|
||||
decoration: InputDecoration(labelText: 'Email'),
|
||||
onChanged: (value) => controller.updateEmail(value),
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(labelText: '姓'),
|
||||
onChanged: (value) => controller.updateLastname(value),
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(labelText: '名'),
|
||||
onChanged: (value) => controller.updateFirstname(value),
|
||||
),
|
||||
// 誕生日選択ウィジェットを追加
|
||||
if (mode == 'edit')
|
||||
Text('ステータス: ${controller.getMemberStatus()}'),
|
||||
if (mode == 'edit' && controller.getMemberStatus() == '招待中')
|
||||
ElevatedButton(
|
||||
child: Text('招待メールを再送信'),
|
||||
onPressed: () => controller.resendInvitation(),
|
||||
),
|
||||
if (mode == 'edit')
|
||||
ElevatedButton(
|
||||
child: Text('メンバーから除外'),
|
||||
onPressed: () => controller.deleteMember(),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
11
lib/pages/team/team_binding.dart
Normal file
11
lib/pages/team/team_binding.dart
Normal file
@ -0,0 +1,11 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/team/team_controller.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class TeamBinding extends Bindings {
|
||||
@override
|
||||
void dependencies() {
|
||||
Get.lazyPut<ApiService>(() => ApiService());
|
||||
Get.lazyPut<TeamController>(() => TeamController());
|
||||
}
|
||||
}
|
||||
117
lib/pages/team/team_controller.dart
Normal file
117
lib/pages/team/team_controller.dart
Normal file
@ -0,0 +1,117 @@
|
||||
// lib/controllers/team_controller.dart
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/model/team.dart';
|
||||
import 'package:rogapp/model/category.dart';
|
||||
import 'package:rogapp/model/user.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class TeamController extends GetxController {
|
||||
late final ApiService _apiService;
|
||||
|
||||
|
||||
final teams = <Team>[].obs;
|
||||
final categories = <NewCategory>[].obs;
|
||||
final teamMembers = <User>[].obs;
|
||||
|
||||
final selectedCategory = Rx<NewCategory?>(null);
|
||||
final currentUser = Rx<User?>(null);
|
||||
|
||||
final isLoading = true.obs;
|
||||
final error = RxString('');
|
||||
|
||||
@override
|
||||
void onInit() async{
|
||||
super.onInit();
|
||||
try {
|
||||
//await Get.putAsync(() => ApiService().init());
|
||||
_apiService = Get.find<ApiService>();
|
||||
|
||||
await Future.wait([
|
||||
fetchTeams(),
|
||||
fetchCategories(),
|
||||
getCurrentUser(),
|
||||
]);
|
||||
|
||||
}catch(e){
|
||||
print("Team Controller error: $e");
|
||||
}finally{
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Future<void> fetchTeams() async {
|
||||
try {
|
||||
final fetchedTeams = await _apiService.getTeams();
|
||||
teams.assignAll(fetchedTeams);
|
||||
} catch (e) {
|
||||
print('Error fetching teams: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchCategories() async {
|
||||
try {
|
||||
final fetchedCategories = await _apiService.getCategories();
|
||||
categories.assignAll(fetchedCategories);
|
||||
} catch (e) {
|
||||
print('Error fetching categories: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> getCurrentUser() async {
|
||||
try {
|
||||
final user = await _apiService.getCurrentUser();
|
||||
currentUser.value = user;
|
||||
} catch (e) {
|
||||
print('Error getting current user: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createTeam(String teamName, int categoryId) async {
|
||||
try {
|
||||
final newTeam = await _apiService.createTeam(teamName, categoryId);
|
||||
teams.add(newTeam);
|
||||
} catch (e) {
|
||||
print('Error creating team: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateTeam(int teamId, String teamName, int categoryId) async {
|
||||
try {
|
||||
final updatedTeam = await _apiService.updateTeam(teamId, teamName, categoryId);
|
||||
final index = teams.indexWhere((team) => team.id == teamId);
|
||||
if (index != -1) {
|
||||
teams[index] = updatedTeam;
|
||||
}
|
||||
} catch (e) {
|
||||
print('Error updating team: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteTeam(int teamId) async {
|
||||
try {
|
||||
await _apiService.deleteTeam(teamId);
|
||||
teams.removeWhere((team) => team.id == teamId);
|
||||
} catch (e) {
|
||||
print('Error deleting team: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchTeamMembers(int teamId) async {
|
||||
try {
|
||||
final members = await _apiService.getTeamMembers(teamId);
|
||||
teamMembers.assignAll(members);
|
||||
} catch (e) {
|
||||
print('Error fetching team members: $e');
|
||||
}
|
||||
}
|
||||
|
||||
void updateTeamName(String value) {
|
||||
// Update local state
|
||||
}
|
||||
|
||||
void updateCategory(NewCategory? value) {
|
||||
selectedCategory.value = value;
|
||||
}
|
||||
}
|
||||
69
lib/pages/team/team_detail_page.dart
Normal file
69
lib/pages/team/team_detail_page.dart
Normal file
@ -0,0 +1,69 @@
|
||||
// lib/pages/team/team_detail_page.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/team/team_controller.dart';
|
||||
import 'package:rogapp/routes/app_pages.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class TeamDetailPage extends GetView<TeamController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mode = Get.arguments['mode'];
|
||||
final team = Get.arguments['team'];
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(mode == 'new' ? '新規チーム作成' : 'チーム詳細'),
|
||||
actions: [
|
||||
if (mode == 'edit')
|
||||
IconButton(
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () => Get.toNamed(AppPages.MEMBER_DETAIL, arguments: {'mode': 'new', 'teamId': team.id}),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextField(
|
||||
decoration: InputDecoration(labelText: 'チーム名'),
|
||||
onChanged: (value) => controller.updateTeamName(value),
|
||||
),
|
||||
DropdownButtonFormField(
|
||||
decoration: InputDecoration(labelText: 'カテゴリ'),
|
||||
value: controller.selectedCategory.value,
|
||||
items: controller.categories.map((category) => DropdownMenuItem(
|
||||
value: category,
|
||||
child: Text(category.categoryName),
|
||||
)).toList(),
|
||||
onChanged: (value) => controller.updateCategory(value),
|
||||
),
|
||||
if (mode == 'edit')
|
||||
Text('ゼッケン番号: ${team.zekkenNumber}'),
|
||||
Obx(() {
|
||||
final currentUser = controller.currentUser.value;
|
||||
return Text('所有者: ${currentUser?.email ?? "未設定"}');
|
||||
}),
|
||||
SizedBox(height: 20),
|
||||
Text('メンバーリスト', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
|
||||
Expanded(
|
||||
child: Obx(() => ListView.builder(
|
||||
itemCount: controller.teamMembers.length,
|
||||
itemBuilder: (context, index) {
|
||||
final member = controller.teamMembers[index];
|
||||
return ListTile(
|
||||
title: Text('${member.lastname}, ${member.firstname}'),
|
||||
onTap: () => Get.toNamed(AppPages.MEMBER_DETAIL, arguments: {'mode': 'edit', 'member': member}),
|
||||
);
|
||||
},
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
54
lib/pages/team/team_list_page.dart
Normal file
54
lib/pages/team/team_list_page.dart
Normal file
@ -0,0 +1,54 @@
|
||||
// lib/pages/team/team_list_page.dart
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rogapp/pages/team/team_controller.dart';
|
||||
import 'package:rogapp/routes/app_pages.dart';
|
||||
import 'package:rogapp/services/api_service.dart';
|
||||
|
||||
class TeamListPage extends GetView<TeamController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('チーム管理'),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.add),
|
||||
onPressed: () => Get.toNamed(AppPages.TEAM_DETAIL, arguments: {'mode': 'new'}),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: FutureBuilder(
|
||||
future: Get.putAsync(() => ApiService().init()),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
return Obx(() {
|
||||
if (controller.isLoading.value) {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
} else if (controller.error.value.isNotEmpty) {
|
||||
return Center(child: Text('エラー: ${controller.error.value}'));
|
||||
} else {
|
||||
return ListView.builder(
|
||||
itemCount: controller.teams.length,
|
||||
itemBuilder: (context, index) {
|
||||
final team = controller.teams[index];
|
||||
return ListTile(
|
||||
title: Text(team.teamName),
|
||||
subtitle: Text('${team.category.categoryName} - ${team.zekkenNumber}'),
|
||||
trailing: Text('メンバー: (メンバー数表示予定)'),
|
||||
onTap: () => Get.toNamed(AppPages.TEAM_DETAIL, arguments: {'mode': 'edit', 'team': team}),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
return Center(child: CircularProgressIndicator());
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -28,6 +28,15 @@ import 'package:rogapp/spa/spa_binding.dart';
|
||||
import 'package:rogapp/spa/spa_page.dart';
|
||||
import 'package:rogapp/widgets/permission_handler_screen.dart';
|
||||
|
||||
import 'package:rogapp/pages/team/team_binding.dart';
|
||||
import 'package:rogapp/pages/team/team_list_page.dart';
|
||||
import 'package:rogapp/pages/team/team_detail_page.dart';
|
||||
import 'package:rogapp/pages/team/member_binding.dart';
|
||||
import 'package:rogapp/pages/team/member_detail_page.dart';
|
||||
import 'package:rogapp/pages/entry/entry_list_page.dart';
|
||||
import 'package:rogapp/pages/entry/entry_detail_page.dart';
|
||||
import 'package:rogapp/pages/entry/entry_binding.dart';
|
||||
|
||||
part 'app_routes.dart';
|
||||
|
||||
class AppPages {
|
||||
@ -56,6 +65,11 @@ class AppPages {
|
||||
static const GPS = Routes.GPS;
|
||||
static const SETTINGS = Routes.SETTINGS;
|
||||
static const DEBUG = Routes.DEBUG;
|
||||
static const TEAM_LIST = Routes.TEAM_LIST;
|
||||
static const TEAM_DETAIL = Routes.TEAM_DETAIL;
|
||||
static const MEMBER_DETAIL = Routes.MEMBER_DETAIL;
|
||||
static const ENTRY_LIST = Routes.ENTRY_LIST;
|
||||
static const ENTRY_DETAIL = Routes.ENTRY_DETAIL;
|
||||
|
||||
static final routes = [
|
||||
GetPage(
|
||||
@ -127,6 +141,31 @@ class AppPages {
|
||||
page: () => DebugPage(),
|
||||
binding: DebugBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: Routes.TEAM_LIST,
|
||||
page: () => TeamListPage(),
|
||||
binding: TeamBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: Routes.TEAM_DETAIL,
|
||||
page: () => TeamDetailPage(),
|
||||
binding: TeamBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: Routes.MEMBER_DETAIL,
|
||||
page: () => MemberDetailPage(),
|
||||
binding: MemberBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: Routes.ENTRY_LIST,
|
||||
page: () => EntryListPage(),
|
||||
binding: EntryBinding(),
|
||||
),
|
||||
GetPage(
|
||||
name: Routes.ENTRY_DETAIL,
|
||||
page: () => EntryDetailPage(),
|
||||
binding: EntryBinding(),
|
||||
),
|
||||
|
||||
];
|
||||
|
||||
|
||||
@ -28,4 +28,10 @@ abstract class Routes {
|
||||
static const GPS = '/gp';
|
||||
static const SETTINGS = '/settings';
|
||||
static const DEBUG = '/debug';
|
||||
|
||||
static const TEAM_LIST = '/team-list';
|
||||
static const TEAM_DETAIL = '/team-detail';
|
||||
static const MEMBER_DETAIL = '/member-detail';
|
||||
static const ENTRY_LIST = '/entry-list';
|
||||
static const ENTRY_DETAIL = '/entry-detail';
|
||||
}
|
||||
|
||||
474
lib/services/api_service.dart
Normal file
474
lib/services/api_service.dart
Normal file
@ -0,0 +1,474 @@
|
||||
// lib/services/api_service.dart
|
||||
import 'package:get/get.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:rogapp/model/entry.dart';
|
||||
import 'package:rogapp/model/event.dart';
|
||||
import 'package:rogapp/model/team.dart';
|
||||
import 'package:rogapp/model/category.dart';
|
||||
import 'package:rogapp/model/user.dart';
|
||||
import 'package:rogapp/pages/index/index_controller.dart';
|
||||
import '../utils/const.dart';
|
||||
|
||||
|
||||
class ApiService extends GetxService{
|
||||
static ApiService get to => Get.find<ApiService>();
|
||||
String serverUrl = '';
|
||||
String baseUrl = '';
|
||||
String token = 'your-auth-token'; // これが使用されている。
|
||||
|
||||
Future<void> init() async {
|
||||
try {
|
||||
// ここで必要な初期化処理を行う
|
||||
serverUrl = ConstValues.currentServer();
|
||||
baseUrl = '$serverUrl/api';
|
||||
//await Future.delayed(Duration(seconds: 2)); // 仮の遅延(実際の初期化処理に置き換えてください)
|
||||
print('ApiService initialized successfully');
|
||||
} catch(e) {
|
||||
print('Error in ApiService initialization: $e');
|
||||
rethrow; // エラーを再スローして、呼び出し元で処理できるようにする
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
このメソッドは以下のように動作します:
|
||||
|
||||
まず、渡された type パラメータに基づいて、どのクラスのフィールドを扱っているかを判断します。
|
||||
次に、クラス内で fieldName に対応する期待される型を返します。
|
||||
クラスや フィールド名が予期されていないものである場合、'Unknown' または 'Unknown Type' を返します。
|
||||
|
||||
このメソッドを ApiService クラスに追加することで、_printDataComparison メソッドは各フィールドの期待される型を正確に表示できるようになります。
|
||||
さらに、このメソッドを使用することで、API レスポンスのデータ型が期待と異なる場合に簡単に検出できるようになります。例えば、Category クラスの duration フィールドが整数型(秒数)で期待されているのに対し、API が文字列を返した場合、すぐに問題を特定できます。
|
||||
注意点として、API のレスポンス形式が変更された場合や、新しいフィールドが追加された場合は、このメソッドも更新する必要があります。そのため、API の変更とクライアントサイドのコードの同期を保つことが重要です。
|
||||
*/
|
||||
|
||||
String getToken()
|
||||
{
|
||||
// IndexControllerの初期化を待つ
|
||||
final indexController = Get.find<IndexController>();
|
||||
|
||||
if (indexController.currentUser.isNotEmpty) {
|
||||
token = indexController.currentUser[0]['token'] ?? '';
|
||||
print("Get token = $token");
|
||||
}else{
|
||||
token = "";
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
Future<List<Team>> getTeams() async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/teams/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// UTF-8でデコード
|
||||
final decodedResponse = utf8.decode(response.bodyBytes);
|
||||
print('User Response body: $decodedResponse');
|
||||
List<dynamic> teamsJson = json.decode(decodedResponse);
|
||||
|
||||
List<Team> teams = [];
|
||||
for (var teamJson in teamsJson) {
|
||||
print('\nTeam Data:');
|
||||
_printDataComparison(teamJson, Team);
|
||||
teams.add(Team.fromJson(teamJson));
|
||||
}
|
||||
return teams;
|
||||
} else {
|
||||
throw Exception('Failed to load teams. Status code: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
print('Error in getTeams: $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Future<List<NewCategory>> getCategories() async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/categories/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final decodedResponse = utf8.decode(response.bodyBytes);
|
||||
print('User Response body: $decodedResponse');
|
||||
List<dynamic> categoriesJson = json.decode(decodedResponse);
|
||||
|
||||
List<NewCategory> categories = [];
|
||||
for (var categoryJson in categoriesJson) {
|
||||
print('\nCategory Data:');
|
||||
_printDataComparison(categoryJson, NewCategory);
|
||||
categories.add(NewCategory.fromJson(categoryJson));
|
||||
}
|
||||
|
||||
return categories;
|
||||
} else {
|
||||
throw Exception(
|
||||
'Failed to load categories. Status code: ${response.statusCode}');
|
||||
}
|
||||
}catch(e, stackTrace){
|
||||
print('Error in getCategories: $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> getCurrentUser() async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
try {
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/user/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final decodedResponse = utf8.decode(response.bodyBytes);
|
||||
print('User Response body: $decodedResponse');
|
||||
final jsonData = json.decode(decodedResponse);
|
||||
|
||||
print('\nUser Data Comparison:');
|
||||
_printDataComparison(jsonData, User);
|
||||
|
||||
return User.fromJson(jsonData);
|
||||
} else {
|
||||
throw Exception('Failed to get current user. Status code: ${response.statusCode}');
|
||||
}
|
||||
} catch (e, stackTrace) {
|
||||
print('Error in getCurrentUser: $e');
|
||||
print('Stack trace: $stackTrace');
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
void _printDataComparison(Map<String, dynamic> data, Type expectedType) {
|
||||
print('Field\t\t| Expected Type\t| Actual Type\t| Actual Value');
|
||||
print('------------------------------------------------------------');
|
||||
data.forEach((key, value) {
|
||||
String expectedFieldType = _getExpectedFieldType(expectedType, key);
|
||||
_printComparison(key, expectedFieldType, value);
|
||||
});
|
||||
}
|
||||
|
||||
String _getExpectedFieldType(Type type, String fieldName) {
|
||||
// This method should return the expected type for each field based on the class definition
|
||||
// You might need to implement this based on your class structures
|
||||
|
||||
switch (type) {
|
||||
case NewCategory:
|
||||
switch (fieldName) {
|
||||
case 'id': return 'int';
|
||||
case 'category_name': return 'String';
|
||||
case 'category_number': return 'int';
|
||||
case 'duration': return 'int (seconds)';
|
||||
case 'num_of_member': return 'int';
|
||||
case 'family': return 'bool';
|
||||
case 'female': return 'bool';
|
||||
default: return 'Unknown';
|
||||
}
|
||||
case Team:
|
||||
switch (fieldName) {
|
||||
case 'id': return 'int';
|
||||
case 'zekken_number': return 'String';
|
||||
case 'team_name': return 'String';
|
||||
case 'category': return 'NewCategory (Object)';
|
||||
case 'owner': return 'User (Object)';
|
||||
default: return 'Unknown';
|
||||
}
|
||||
case User:
|
||||
switch (fieldName) {
|
||||
case 'id': return 'int';
|
||||
case 'email': return 'String';
|
||||
case 'firstname': return 'String';
|
||||
case 'lastname': return 'String';
|
||||
case 'date_of_birth': return 'String (ISO8601)';
|
||||
case 'female': return 'bool';
|
||||
case 'is_active': return 'bool';
|
||||
default: return 'Unknown';
|
||||
}
|
||||
default:
|
||||
return 'Unknown Type';
|
||||
}
|
||||
}
|
||||
|
||||
void _printComparison(String fieldName, String expectedType, dynamic actualValue) {
|
||||
String actualType = actualValue?.runtimeType.toString() ?? 'null';
|
||||
String displayValue = actualValue.toString();
|
||||
if (displayValue.length > 50) {
|
||||
displayValue = '${displayValue.substring(0, 47)}...';
|
||||
}
|
||||
print('$fieldName\t\t| $expectedType\t\t| $actualType\t\t| $displayValue');
|
||||
}
|
||||
|
||||
Future<Team> createTeam(String teamName, int categoryId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/teams/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'team_name': teamName,
|
||||
'category': categoryId,
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return Team.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to create team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Team> updateTeam(int teamId, String teamName, int categoryId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.put(
|
||||
Uri.parse('$baseUrl/teams/$teamId/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'team_name': teamName,
|
||||
'category': categoryId,
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Team.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to update team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteTeam(int teamId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.delete(
|
||||
Uri.parse('$baseUrl/teams/$teamId/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode != 204) {
|
||||
throw Exception('Failed to delete team');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<User>> getTeamMembers(int teamId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/teams/$teamId/members/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final decodedResponse = utf8.decode(response.bodyBytes);
|
||||
print('User Response body: $decodedResponse');
|
||||
List<dynamic> membersJson = json.decode(decodedResponse);
|
||||
|
||||
return membersJson.map((json) => User.fromJson(json)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to load team members');
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> createTeamMember(int teamId, String email, String firstname, String lastname, DateTime? dateOfBirth) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/teams/$teamId/members/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'email': email,
|
||||
'firstname': firstname,
|
||||
'lastname': lastname,
|
||||
'date_of_birth': dateOfBirth?.toIso8601String(),
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return User.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to create team member');
|
||||
}
|
||||
}
|
||||
|
||||
Future<User> updateTeamMember(int teamId,int memberId, String firstname, String lastname, DateTime? dateOfBirth) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.put(
|
||||
Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'firstname': firstname,
|
||||
'lastname': lastname,
|
||||
'date_of_birth': dateOfBirth?.toIso8601String(),
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return User.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to update team member');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteTeamMember(int teamId,int memberId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.delete(
|
||||
Uri.parse('$baseUrl/teams/$teamId/members/$memberId/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode != 204) {
|
||||
throw Exception('Failed to delete team member');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> resendMemberInvitation(int memberId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/members/$memberId/resend-invitation/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to resend invitation');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Entry>> getEntries() async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/entries/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
List<dynamic> entriesJson = json.decode(response.body);
|
||||
return entriesJson.map((json) => Entry.fromJson(json)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to load entries');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Event>> getEvents() async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.get(
|
||||
Uri.parse('$baseUrl/new-events/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final decodedResponse = utf8.decode(response.bodyBytes);
|
||||
print('Response body: $decodedResponse');
|
||||
List<dynamic> eventsJson = json.decode(decodedResponse);
|
||||
|
||||
return eventsJson.map((json) => Event.fromJson(json)).toList();
|
||||
} else {
|
||||
throw Exception('Failed to load events');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Entry> createEntry(int teamId, int eventId, int categoryId, DateTime date) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.post(
|
||||
Uri.parse('$baseUrl/entry/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'team': teamId,
|
||||
'event': eventId,
|
||||
'category': categoryId,
|
||||
'date': date.toIso8601String(),
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 201) {
|
||||
return Entry.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to create entry');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Entry> updateEntry(int entryId, int eventId, int categoryId, DateTime date) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.put(
|
||||
Uri.parse('$baseUrl/entry/$entryId/'),
|
||||
headers: {
|
||||
'Authorization': 'Token $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode({
|
||||
'event': eventId,
|
||||
'category': categoryId,
|
||||
'date': date.toIso8601String(),
|
||||
}),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return Entry.fromJson(json.decode(response.body));
|
||||
} else {
|
||||
throw Exception('Failed to update entry');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntry(int entryId) async {
|
||||
init();
|
||||
getToken();
|
||||
|
||||
final response = await http.delete(
|
||||
Uri.parse('$baseUrl/entry/$entryId/'),
|
||||
headers: {'Authorization': 'Token $token'},
|
||||
);
|
||||
|
||||
if (response.statusCode != 204) {
|
||||
throw Exception('Failed to delete entry');
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@
|
||||
|
||||
class ConstValues{
|
||||
static const container_svr = "http://container.intranet.sumasen.net:8100";
|
||||
static const server_uri = "https://rogaining.sumasen.net";
|
||||
static const server_uri = "https://rogaining.intranet.sumasen.net";
|
||||
static const dev_server = "http://localhost:8100";
|
||||
static const dev_ip_server = "http://192.168.8.100:8100";
|
||||
static const dev_home_ip_server = "http://172.20.10.9:8100";
|
||||
|
||||
Reference in New Issue
Block a user