チームまでは表示できた。表示と更新及びメンバー編集不可。エントリー以降も表示不可。
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 'package:permission_handler/permission_handler.dart';
|
||||||
|
|
||||||
import 'pages/permission/permission.dart';
|
import 'pages/permission/permission.dart';
|
||||||
|
import 'package:rogapp/services/api_service.dart';
|
||||||
|
|
||||||
Map<String, dynamic> deviceInfo = {};
|
Map<String, dynamic> deviceInfo = {};
|
||||||
|
|
||||||
@ -100,6 +100,7 @@ void restoreGame() async {
|
|||||||
pref.getBool("rogaining_counted") ?? false;
|
pref.getBool("rogaining_counted") ?? false;
|
||||||
DestinationController.ready_for_goal =
|
DestinationController.ready_for_goal =
|
||||||
pref.getBool("ready_for_goal") ?? false;
|
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(const ProviderScope(child: MyApp()));
|
||||||
//runApp(HomePage()); // MyApp()からHomePage()に変更
|
//runApp(HomePage()); // MyApp()からHomePage()に変更
|
||||||
//runApp(const MyApp());
|
//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 {
|
Future<void> requestLocationPermission() async {
|
||||||
try {
|
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,
|
width: 0,
|
||||||
height: 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(
|
ListTile(
|
||||||
leading: const Icon(Icons.privacy_tip),
|
leading: const Icon(Icons.privacy_tip),
|
||||||
title: Text("privacy".tr),
|
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:rogapp/widgets/debug_widget.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'package:rogapp/services/api_service.dart';
|
||||||
|
|
||||||
import '../../main.dart';
|
import '../../main.dart';
|
||||||
|
|
||||||
|
|
||||||
@ -190,11 +192,19 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
WidgetsBinding.instance?.addObserver(this);
|
WidgetsBinding.instance?.addObserver(this);
|
||||||
_startLocationService(); // アプリ起動時にLocationServiceを開始する
|
_startLocationService(); // アプリ起動時にLocationServiceを開始する
|
||||||
|
|
||||||
|
initializeApiService();
|
||||||
|
|
||||||
print('IndexController onInit called'); // デバッグ用の出力を追加
|
print('IndexController onInit called'); // デバッグ用の出力を追加
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> initializeApiService() async {
|
||||||
|
if (currentUser.isNotEmpty) {
|
||||||
|
// 既にログインしている場合
|
||||||
|
await Get.putAsync(() => ApiService().init());
|
||||||
|
// 必要に応じて追加の初期化処理
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
void checkPermission()
|
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 ###### --------");
|
print("------- logged in user details ######## $value ###### --------");
|
||||||
if (value.isNotEmpty) {
|
if (value.isNotEmpty) {
|
||||||
logManager.addOperationLog("User logged in : ${value}.");
|
logManager.addOperationLog("User logged in : ${value}.");
|
||||||
@ -324,6 +334,11 @@ class IndexController extends GetxController with WidgetsBindingObserver {
|
|||||||
// Navigator.pop(context);
|
// Navigator.pop(context);
|
||||||
print("--------- user details login ----- $value");
|
print("--------- user details login ----- $value");
|
||||||
changeUser(value);
|
changeUser(value);
|
||||||
|
|
||||||
|
// ログイン成功後、api_serviceを初期化
|
||||||
|
await Get.putAsync(() => ApiService().init());
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logManager.addOperationLog("User failed login : ${email} , ${password}.");
|
logManager.addOperationLog("User failed login : ${email} , ${password}.");
|
||||||
isLoading.value = false;
|
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/spa/spa_page.dart';
|
||||||
import 'package:rogapp/widgets/permission_handler_screen.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';
|
part 'app_routes.dart';
|
||||||
|
|
||||||
class AppPages {
|
class AppPages {
|
||||||
@ -56,6 +65,11 @@ class AppPages {
|
|||||||
static const GPS = Routes.GPS;
|
static const GPS = Routes.GPS;
|
||||||
static const SETTINGS = Routes.SETTINGS;
|
static const SETTINGS = Routes.SETTINGS;
|
||||||
static const DEBUG = Routes.DEBUG;
|
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 = [
|
static final routes = [
|
||||||
GetPage(
|
GetPage(
|
||||||
@ -127,6 +141,31 @@ class AppPages {
|
|||||||
page: () => DebugPage(),
|
page: () => DebugPage(),
|
||||||
binding: DebugBinding(),
|
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 GPS = '/gp';
|
||||||
static const SETTINGS = '/settings';
|
static const SETTINGS = '/settings';
|
||||||
static const DEBUG = '/debug';
|
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{
|
class ConstValues{
|
||||||
static const container_svr = "http://container.intranet.sumasen.net:8100";
|
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_server = "http://localhost:8100";
|
||||||
static const dev_ip_server = "http://192.168.8.100:8100";
|
static const dev_ip_server = "http://192.168.8.100:8100";
|
||||||
static const dev_home_ip_server = "http://172.20.10.9:8100";
|
static const dev_home_ip_server = "http://172.20.10.9:8100";
|
||||||
|
|||||||
Reference in New Issue
Block a user