// 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(); String serverUrl = ''; String baseUrl = ''; String token = 'your-auth-token'; // これが使用されている。 Future 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(); if (indexController.currentUser.isNotEmpty) { token = indexController.currentUser[0]['token'] ?? ''; print("Get token = $token"); }else{ token = ""; } return token; } Future> 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 teamsJson = json.decode(decodedResponse); List 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> 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 categoriesJson = json.decode(decodedResponse); List 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 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 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 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 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 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> 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 membersJson = json.decode(decodedResponse); return membersJson.map((json) => User.fromJson(json)).toList(); } else { throw Exception('Failed to load team members'); } } Future 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 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 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 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> getEntries() async { init(); getToken(); final response = await http.get( Uri.parse('$baseUrl/entries/'), headers: {'Authorization': 'Token $token'}, ); if (response.statusCode == 200) { List entriesJson = json.decode(response.body); return entriesJson.map((json) => Entry.fromJson(json)).toList(); } else { throw Exception('Failed to load entries'); } } Future> 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 eventsJson = json.decode(decodedResponse); return eventsJson.map((json) => Event.fromJson(json)).toList(); } else { throw Exception('Failed to load events'); } } Future 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 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 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'); } } }