Files
bowlingManager/mobile/lib/services/admin_service.dart
T
2025-08-01 16:45:26 +09:00

359 lines
10 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../config/api_config.dart';
import '../models/admin_model.dart';
/// 관리자 기능 관련 서비스
class AdminService extends ChangeNotifier {
final String _baseUrl = ApiConfig.baseUrl;
final String _token;
final String _clubId;
List<MemberRole> _memberRoles = [];
ClubSettings? _clubSettings;
UserRole _currentUserRole = UserRole.member;
AdminPermission _currentUserPermissions = AdminPermission();
bool _isLoading = false;
String? _error;
AdminService(this._token, this._clubId) {
_initialize();
}
// 게터
List<MemberRole> get memberRoles => _memberRoles;
ClubSettings? get clubSettings => _clubSettings;
UserRole get currentUserRole => _currentUserRole;
AdminPermission get currentUserPermissions => _currentUserPermissions;
bool get isLoading => _isLoading;
String? get error => _error;
// 권한 확인 게터
bool get canManageMembers => _currentUserPermissions.canManageMembers;
bool get canManageEvents => _currentUserPermissions.canManageEvents;
bool get canManageScores => _currentUserPermissions.canManageScores;
bool get canManageSettings => _currentUserPermissions.canManageSettings;
bool get canManageSubscription => _currentUserPermissions.canManageSubscription;
bool get canManageRoles => _currentUserPermissions.canManageRoles;
bool get canViewFinancials => _currentUserPermissions.canViewFinancials;
bool get canExportData => _currentUserPermissions.canExportData;
/// 초기화 (현재 사용자 권한 및 클럽 설정 로드)
Future<void> _initialize() async {
await Future.wait([
fetchCurrentUserRole(),
fetchClubSettings(),
]);
}
/// 현재 사용자의 역할 및 권한 조회
Future<void> fetchCurrentUserRole() async {
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/clubs/$_clubId/my-role'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final memberRole = MemberRole.fromJson(data);
_currentUserRole = memberRole.role;
_currentUserPermissions = memberRole.permissions;
} else {
// 기본값: 일반 회원
_currentUserRole = UserRole.member;
_currentUserPermissions = AdminPermission.fromRole(UserRole.member);
_error = '사용자 역할 정보를 불러오는데 실패했습니다. (${response.statusCode})';
}
} catch (e) {
_error = '사용자 역할 정보를 불러오는데 실패했습니다: $e';
// 기본값: 일반 회원
_currentUserRole = UserRole.member;
_currentUserPermissions = AdminPermission.fromRole(UserRole.member);
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 내 모든 회원의 역할 정보 조회
Future<void> fetchMemberRoles() async {
if (!canManageRoles) {
_error = '역할 관리 권한이 없습니다.';
notifyListeners();
return;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/clubs/$_clubId/roles'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
final List<dynamic> data = jsonDecode(response.body);
_memberRoles = data.map((role) => MemberRole.fromJson(role)).toList();
} else {
_error = '회원 역할 정보를 불러오는데 실패했습니다. (${response.statusCode})';
}
} catch (e) {
_error = '회원 역할 정보를 불러오는데 실패했습니다: $e';
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 회원 역할 변경
Future<bool> updateMemberRole(String memberId, UserRole newRole) async {
if (!canManageRoles) {
_error = '역할 관리 권한이 없습니다.';
notifyListeners();
return false;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.put(
Uri.parse('$_baseUrl/api/clubs/$_clubId/members/$memberId/role'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
body: jsonEncode({
'role': newRole.toString().split('.').last,
}),
);
if (response.statusCode == 200) {
// 역할 목록 갱신
await fetchMemberRoles();
return true;
} else {
_error = '회원 역할 변경에 실패했습니다. (${response.statusCode})';
return false;
}
} catch (e) {
_error = '회원 역할 변경에 실패했습니다: $e';
return false;
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 설정 조회
Future<void> fetchClubSettings() async {
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/clubs/$_clubId/settings'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_clubSettings = ClubSettings.fromJson(data);
} else {
_error = '클럽 설정을 불러오는데 실패했습니다. (${response.statusCode})';
}
} catch (e) {
_error = '클럽 설정을 불러오는데 실패했습니다: $e';
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 설정 업데이트
Future<bool> updateClubSettings(ClubSettings updatedSettings) async {
if (!canManageSettings) {
_error = '설정 관리 권한이 없습니다.';
notifyListeners();
return false;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.put(
Uri.parse('$_baseUrl/api/clubs/$_clubId/settings'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
body: jsonEncode(updatedSettings.toJson()),
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
_clubSettings = ClubSettings.fromJson(data);
notifyListeners();
return true;
} else {
_error = '클럽 설정 업데이트에 실패했습니다. (${response.statusCode})';
return false;
}
} catch (e) {
_error = '클럽 설정 업데이트에 실패했습니다: $e';
return false;
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 로고 업로드
Future<bool> uploadClubLogo(String filePath) async {
if (!canManageSettings) {
_error = '설정 관리 권한이 없습니다.';
notifyListeners();
return false;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
// 파일 업로드 로직 구현 (multipart/form-data)
// 실제 구현 시 http.MultipartRequest 사용
// 성공 시 설정 업데이트
await fetchClubSettings();
return true;
} catch (e) {
_error = '클럽 로고 업로드에 실패했습니다: $e';
return false;
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 데이터 내보내기
Future<String?> exportClubData(String dataType) async {
if (!canExportData) {
_error = '데이터 내보내기 권한이 없습니다.';
notifyListeners();
return null;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/clubs/$_clubId/export/$dataType'),
headers: {
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
// 다운로드 URL 또는 데이터 반환
final data = jsonDecode(response.body);
return data['downloadUrl'] ?? data['data'];
} else {
_error = '데이터 내보내기에 실패했습니다. (${response.statusCode})';
return null;
}
} catch (e) {
_error = '데이터 내보내기에 실패했습니다: $e';
return null;
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 클럽 통계 및 분석 데이터 조회
Future<Map<String, dynamic>?> fetchClubAnalytics() async {
if (!canViewFinancials) {
_error = '통계 조회 권한이 없습니다.';
notifyListeners();
return null;
}
_isLoading = true;
_error = null;
notifyListeners();
try {
final response = await http.get(
Uri.parse('$_baseUrl/api/clubs/$_clubId/analytics'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
return data;
} else {
_error = '클럽 통계 데이터를 불러오는데 실패했습니다. (${response.statusCode})';
return null;
}
} catch (e) {
_error = '클럽 통계 데이터를 불러오는데 실패했습니다: $e';
return null;
} finally {
_isLoading = false;
notifyListeners();
}
}
/// 특정 권한이 있는지 확인
bool hasPermission(String permissionName) {
switch (permissionName) {
case 'manageMembers':
return _currentUserPermissions.canManageMembers;
case 'manageEvents':
return _currentUserPermissions.canManageEvents;
case 'manageScores':
return _currentUserPermissions.canManageScores;
case 'manageSettings':
return _currentUserPermissions.canManageSettings;
case 'manageSubscription':
return _currentUserPermissions.canManageSubscription;
case 'manageRoles':
return _currentUserPermissions.canManageRoles;
case 'viewFinancials':
return _currentUserPermissions.canViewFinancials;
case 'exportData':
return _currentUserPermissions.canExportData;
default:
return false;
}
}
}