This commit is contained in:
2025-04-17 23:32:39 +09:00
commit 5b719b6766
105 changed files with 25653 additions and 0 deletions
+351
View File
@@ -0,0 +1,351 @@
import apiClient from './api';
/**
* 관리자 API 서비스
*/
const adminService = {
/**
* 모든 클럽 목록 조회
* @returns {Promise} - 클럽 목록
*/
getClubs() {
return apiClient.get('/api/admin/clubs');
},
/**
* 모든 클럽 조회
* @returns {Promise} - 클럽 목록
*/
getAllClubs() {
return apiClient.get('/api/admin/clubs');
},
/**
* 특정 클럽 조회
* @param {Number} id - 클럽 ID
* @returns {Promise} - 클럽 정보
*/
getClubById(id) {
return apiClient.get(`/api/admin/clubs/${id}`);
},
/**
* 클럽 정보 업데이트
* @param {Number} id - 클럽 ID
* @param {Object} clubData - 업데이트할 클럽 정보
* @returns {Promise} - 업데이트된 클럽 정보
*/
updateClub(id, clubData) {
return apiClient.put(`/api/admin/clubs/${id}`, clubData);
},
/**
* 클럽 삭제
* @param {Number} id - 클럽 ID
* @returns {Promise} - 삭제 결과
*/
deleteClub(id) {
return apiClient.delete(`/api/admin/clubs/${id}`);
},
/**
* 클럽 멤버 조회
* @param {Number} id - 클럽 ID
* @returns {Promise} - 클럽 멤버 목록
*/
getClubMembers(id) {
return apiClient.get(`/api/admin/clubs/${id}/members`);
},
/**
* 클럽 멤버 추가
* @param {Number} id - 클럽 ID
* @param {Object} memberData - 멤버 정보
* @returns {Promise} - 추가된 멤버 정보
*/
addClubMember(id, memberData) {
return apiClient.post(`/api/admin/clubs/${id}/members`, memberData);
},
/**
* 클럽 멤버 정보 업데이트
* @param {Number} clubId - 클럽 ID
* @param {Number} memberId - 멤버 ID
* @param {Object} memberData - 업데이트할 멤버 정보
* @returns {Promise} - 업데이트된 멤버 정보
*/
updateClubMember(clubId, memberId, memberData) {
return apiClient.put(`/api/admin/clubs/${clubId}/members/${memberId}`, memberData);
},
/**
* 클럽 회원 삭제
* @param {Number} clubId - 클럽 ID
* @param {Number} memberId - 멤버 ID
* @returns {Promise} - 삭제 결과
*/
deleteClubMember(clubId, memberId) {
return apiClient.delete(`/api/admin/clubs/${clubId}/members/${memberId}`);
},
/**
* 모든 사용자 조회
* @returns {Promise} - 사용자 목록
*/
getAllUsers() {
return apiClient.get('/api/admin/users');
},
/**
* 특정 사용자 조회
* @param {Number} id - 사용자 ID
* @returns {Promise} - 사용자 정보
*/
getUserById(id) {
return apiClient.get(`/api/admin/users/${id}`);
},
/**
* 사용자 정보 업데이트
* @param {Number} id - 사용자 ID
* @param {Object} userData - 업데이트할 사용자 정보
* @returns {Promise} - 업데이트된 사용자 정보
*/
updateUser(id, userData) {
return apiClient.put(`/api/admin/users/${id}`, userData);
},
/**
* 사용자 삭제
* @param {Number} id - 사용자 ID
* @returns {Promise} - 삭제 결과
*/
deleteUser(id) {
return apiClient.delete(`/api/admin/users/${id}`);
},
/**
* 모든 이벤트 조회
* @returns {Promise} - 이벤트 목록
*/
getAllEvents() {
return apiClient.get('/api/admin/events');
},
/**
* 특정 이벤트 조회
* @param {Number} id - 이벤트 ID
* @returns {Promise} - 이벤트 정보
*/
getEventById(id) {
return apiClient.get(`/api/admin/events/${id}`);
},
/**
* 새 이벤트 생성
* @param {Object} eventData - 이벤트 정보
* @returns {Promise} - 생성된 이벤트 정보
*/
createEvent(eventData) {
return apiClient.post('/api/admin/events', eventData);
},
/**
* 이벤트 정보 업데이트
* @param {Number} id - 이벤트 ID
* @param {Object} eventData - 업데이트할 이벤트 정보
* @returns {Promise} - 업데이트된 이벤트 정보
*/
updateEvent(id, eventData) {
return apiClient.put(`/api/admin/events/${id}`, eventData);
},
/**
* 이벤트 삭제
* @param {Number} id - 이벤트 ID
* @returns {Promise} - 삭제 결과
*/
deleteEvent(id) {
return apiClient.delete(`/api/admin/events/${id}`);
},
/**
* 이벤트 참가자 목록 조회
* @param {Number} eventId - 이벤트 ID
* @returns {Promise} - 참가자 목록
*/
getEventParticipants(eventId) {
return apiClient.get(`/api/admin/events/${eventId}/participants`);
},
/**
* 이벤트 참가자 추가
* @param {Number} eventId - 이벤트 ID
* @param {Number} userId - 사용자 ID
* @returns {Promise} - 추가된 참가자 정보
*/
addEventParticipant(eventId, userId) {
return apiClient.post(`/api/admin/events/${eventId}/participants`, { userId });
},
/**
* 이벤트 참가자 상태 업데이트
* @param {Number} eventId - 이벤트 ID
* @param {Number} participantId - 참가자 ID
* @param {String} status - 새로운 상태
* @returns {Promise} - 업데이트된 참가자 정보
*/
updateEventParticipantStatus(eventId, participantId, status) {
return apiClient.put(`/api/admin/events/${eventId}/participants/${participantId}`, { status });
},
/**
* 이벤트 참가자 제거
* @param {Number} eventId - 이벤트 ID
* @param {Number} participantId - 참가자 ID
* @returns {Promise} - 제거 결과
*/
removeEventParticipant(eventId, participantId) {
return apiClient.delete(`/api/admin/events/${eventId}/participants/${participantId}`);
},
/**
* 구독 플랜 목록 조회
* @returns {Promise} - 구독 플랜 목록
*/
getPlans() {
return apiClient.get('/api/admin/subscriptions/plans');
},
/**
* 특정 구독 플랜 조회
* @param {Number} id - 구독 플랜 ID
* @returns {Promise} - 구독 플랜 정보
*/
getPlanById(id) {
return apiClient.get(`/api/admin/subscriptions/plans/${id}`);
},
/**
* 새 구독 플랜 생성
* @param {Object} planData - 구독 플랜 정보
* @returns {Promise} - 생성된 구독 플랜 정보
*/
createPlan(planData) {
return apiClient.post('/api/admin/subscriptions/plans', planData);
},
/**
* 구독 플랜 정보 업데이트
* @param {Number} id - 구독 플랜 ID
* @param {Object} planData - 업데이트할 구독 플랜 정보
* @returns {Promise} - 업데이트된 구독 플랜 정보
*/
updatePlan(id, planData) {
return apiClient.put(`/api/admin/subscriptions/plans/${id}`, planData);
},
/**
* 구독 플랜 삭제
* @param {Number} id - 구독 플랜 ID
* @returns {Promise} - 삭제 결과
*/
deletePlan(id) {
return apiClient.delete(`/api/admin/subscriptions/plans/${id}`);
},
/**
* 모든 구독 목록 조회
* @returns {Promise} - 구독 목록
*/
getSubscriptions() {
return apiClient.get('/api/admin/subscriptions');
},
/**
* 구독 플랜의 구독 목록 조회
* @param {Number} planId - 구독 플랜 ID
* @returns {Promise} - 구독 목록
*/
getPlanSubscriptions(planId) {
return apiClient.get(`/api/admin/subscriptions/plans/${planId}/subscriptions`);
},
/**
* 모든 기능 목록 조회
* @returns {Promise} - 기능 목록
*/
getFeatures() {
return apiClient.get('/api/admin/features');
},
/**
* 새 구독 생성
* @param {Object} subscriptionData - 구독 정보
* @returns {Promise} - 생성된 구독 정보
*/
createSubscription(subscriptionData) {
return apiClient.post('/api/admin/subscriptions', subscriptionData);
},
/**
* 구독 정보 업데이트
* @param {Number} id - 구독 ID
* @param {Object} subscriptionData - 업데이트할 구독 정보
* @returns {Promise} - 업데이트된 구독 정보
*/
updateSubscription(id, subscriptionData) {
return apiClient.put(`/api/admin/subscriptions/${id}`, subscriptionData);
},
/**
* 구독 삭제
* @param {Number} id - 구독 ID
* @returns {Promise} - 삭제 결과
*/
deleteSubscription(id) {
return apiClient.delete(`/api/admin/subscriptions/${id}`);
},
/**
* 대시보드 데이터 조회
* @returns {Promise} - 대시보드 데이터
*/
getDashboardData() {
return apiClient.get('/api/admin/dashboard');
},
/**
* 최근 활동 조회
* @returns {Promise} - 최근 활동 목록
*/
getRecentActivities() {
return apiClient.get('/api/admin/activities/recent');
},
/**
* 통계 데이터 조회
* @returns {Promise} - 통계 데이터
*/
getStatistics() {
return apiClient.get('/api/admin/statistics');
},
/**
* 클럽 기능 관리
* @param {Number} clubId - 클럽 ID
* @param {Object} features - 클럽 기능 정보
* @returns {Promise} - 클럽 기능 정보
*/
manageClubFeatures: async (clubId, features) => {
try {
const response = await apiClient.put(`/api/admin/clubs/${clubId}/features`, { features });
return response.data;
} catch (error) {
console.error('클럽 기능 관리 중 오류:', error);
throw error;
}
}
};
export default adminService;
+46
View File
@@ -0,0 +1,46 @@
import axios from 'axios';
// 환경 변수에서 API URL을 가져오거나 기본값 사용
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:3030';
// axios 인스턴스 생성
const apiClient = axios.create({
baseURL: API_URL,
headers: {
'Content-Type': 'application/json',
},
timeout: 10000
});
// 요청 인터셉터 - 토큰 추가
apiClient.interceptors.request.use(
(config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
// 응답 인터셉터 - 에러 처리
apiClient.interceptors.response.use(
(response) => {
return response;
},
(error) => {
// 401 에러 (인증 실패) 처리
if (error.response && error.response.status === 401) {
// 로컬 스토리지에서 토큰 제거
localStorage.removeItem('token');
// 로그인 페이지로 리디렉션
window.location.href = '/login';
}
return Promise.reject(error);
}
);
export default apiClient;
+51
View File
@@ -0,0 +1,51 @@
import apiClient from './api';
/**
* 인증 관련 API 서비스
*/
const authService = {
/**
* 로그인
* @param {Object} credentials - 로그인 정보 (이메일, 비밀번호)
* @returns {Promise} - 로그인 결과
*/
login(credentials) {
return apiClient.post('/api/auth/login', credentials);
},
/**
* 회원가입
* @param {Object} userData - 사용자 정보
* @returns {Promise} - 회원가입 결과
*/
register(userData) {
return apiClient.post('/api/auth/register', userData);
},
/**
* 현재 사용자 정보 조회
* @returns {Promise} - 사용자 정보
*/
getCurrentUser() {
return apiClient.get('/api/auth/me');
},
/**
* 비밀번호 변경
* @param {Object} passwordData - 비밀번호 변경 정보
* @returns {Promise} - 비밀번호 변경 결과
*/
changePassword(passwordData) {
return apiClient.post('/api/auth/change-password', passwordData);
},
/**
* 로그아웃
*/
logout() {
localStorage.removeItem('token');
localStorage.removeItem('user');
}
};
export default authService;
+109
View File
@@ -0,0 +1,109 @@
import apiClient from './api';
/**
* 클럽 관련 API 서비스
*/
const clubService = {
/**
* 모든 클럽 조회
* @returns {Promise} - 클럽 목록
*/
getAllClubs() {
return apiClient.get('/api/club');
},
/**
* 특정 클럽 조회
* @param {Number} id - 클럽 ID
* @returns {Promise} - 클럽 정보
*/
getClubById(id) {
return apiClient.post(`/api/club`, { clubId: id });
},
/**
* 새 클럽 생성
* @param {Object} clubData - 클럽 정보
* @returns {Promise} - 생성된 클럽 정보
*/
createClub(clubData) {
return apiClient.post('/api/club/create', clubData);
},
/**
* 클럽 정보 업데이트
* @param {Number} id - 클럽 ID
* @param {Object} clubData - 업데이트할 클럽 정보
* @returns {Promise} - 업데이트된 클럽 정보
*/
updateClub(id, clubData) {
return apiClient.put(`/api/club`, { clubId: id, ...clubData });
},
/**
* 클럽 삭제
* @param {Number} id - 클럽 ID
* @returns {Promise} - 삭제 결과
*/
deleteClub(id) {
return apiClient.delete(`/api/club`, { clubId: id });
},
/**
* 클럽 회원 목록 조회
* @param {Number} clubId - 클럽 ID
* @returns {Promise} - 회원 목록
*/
getClubMembers(clubId) {
return apiClient.post('/api/club/members', { clubId });
},
/**
* 클럽 회원 추가
* @param {Number} clubId - 클럽 ID
* @param {Object} memberData - 회원 정보
* @returns {Promise} - 추가된 회원 정보
*/
addClubMember(clubId, memberData) {
return apiClient.post('/api/club/members/add', {
clubId,
...memberData
});
},
/**
* 클럽 회원 정보 수정
* @param {Number} clubId - 클럽 ID
* @param {Number} memberId - 회원 ID
* @param {Object} memberData - 수정할 회원 정보
* @returns {Promise} - 수정된 회원 정보
*/
updateClubMember(clubId, memberId, memberData) {
return apiClient.post('/api/club/members/update', {
clubId,
memberId,
...memberData
});
},
/**
* 클럽 회원 삭제
* @param {Number} clubId - 클럽 ID
* @param {Number} memberId - 회원 ID
* @returns {Promise} - 삭제 결과
*/
deleteClubMember(clubId, memberId) {
return apiClient.post('/api/club/members/delete', { clubId, memberId });
},
/**
* 클럽 회원 통계 조회
* @param {Number} clubId - 클럽 ID
* @returns {Promise} - 회원 통계 정보
*/
getMemberStats(clubId) {
return apiClient.post('/api/club/members/stats', { clubId });
}
};
export default clubService;
+370
View File
@@ -0,0 +1,370 @@
import apiClient from './api';
import dayjs from 'dayjs';
/**
* 이벤트 서비스 - 이벤트 관련 API 호출을 처리하는 서비스
*/
export default {
/**
* 모든 이벤트 목록 가져오기
* @param {number} clubId - 클럽 ID
* @returns {Promise<Array>} 이벤트 목록
*/
async getEvents(clubId) {
if (!clubId) {
throw new Error('클럽 ID가 필요합니다.');
}
try {
const response = await apiClient.post('/api/club/events', { clubId });
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 특정 이벤트 상세 정보 가져오기
* @param {number} id - 이벤트 ID
* @returns {Promise<Object>} 이벤트 상세 정보
*/
async getEventById(id) {
if (!id) {
throw new Error('이벤트 ID가 필요합니다.');
}
try {
const response = await apiClient.get(`/api/club/events/${id}`);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 새 이벤트 추가
* @param {Object} event - 이벤트 객체
* @returns {Promise<Object>} 생성된 이벤트 객체
*/
async createEvent(event) {
if (!event) {
throw new Error('이벤트 객체가 필요합니다.');
}
try {
const formattedEvent = {
...event,
startDate: dayjs(event.startDate).format('YYYY-MM-DD'),
endDate: event.endDate ? dayjs(event.endDate).format('YYYY-MM-DD') : null
};
const response = await apiClient.post('/api/club/events/create', formattedEvent);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 기존 이벤트 수정
* @param {Object} event - 수정할 이벤트 객체
* @returns {Promise<Object>} 수정된 이벤트 객체
*/
async updateEvent(event) {
if (!event) {
throw new Error('이벤트 객체가 필요합니다.');
}
try {
const formattedEvent = {
...event,
startDate: dayjs(event.startDate).format('YYYY-MM-DD'),
endDate: dayjs(event.endDate).format('YYYY-MM-DD')
};
const response = await apiClient.put(`/api/club/events/${event.id}`, formattedEvent);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 이벤트 삭제
* @param {number} clubId - 클럽 ID
* @param {number} id - 삭제할 이벤트 ID
* @returns {Promise<void>}
*/
async deleteEvent(clubId, id) {
if (!clubId || !id) {
throw new Error('클럽 ID와 이벤트 ID가 필요합니다.');
}
try {
await apiClient.delete(`/api/club/events/${id}`, {
data: { clubId }
});
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 이벤트 참가자 목록 조회
* @param {number} eventId - 이벤트 ID
* @returns {Promise<Array>} 참가자 목록
*/
async getEventParticipants(eventId) {
if (!eventId) {
throw new Error('이벤트 ID가 필요합니다.');
}
try {
const response = await apiClient.post(`/api/club/events/${eventId}/participants/list`, {
eventId,
clubId: localStorage.getItem('clubId')
});
return response.data.participants;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 이벤트 참가자 추가
* @param {number} eventId - 이벤트 ID
* @param {Object} participant - 참가자 정보
* @returns {Promise<Object>} 추가된 참가자 정보
*/
async addEventParticipant(eventId, participant) {
if (!eventId || !participant) {
throw new Error('이벤트 ID와 참가자 정보가 필요합니다.');
}
try {
const response = await apiClient.post(`/api/club/events/${eventId}/participants`, participant);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 참가자 정보 수정
* @param {number} eventId - 이벤트 ID
* @param {Object} participant - 수정할 참가자 정보
* @returns {Promise<Object>} 수정된 참가자 정보
*/
async updateEventParticipant(eventId, participant) {
if (!eventId || !participant) {
throw new Error('이벤트 ID와 참가자 정보가 필요합니다.');
}
try {
const response = await apiClient.put(`/api/club/events/${eventId}/participants`, participant);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 참가자 제거
* @param {number} eventId - 이벤트 ID
* @param {Object} participant - 제거할 참가자 정보
* @returns {Promise<void>}
*/
async removeEventParticipant(eventId, participant) {
if (!eventId || !participant) {
throw new Error('이벤트 ID와 참가자 정보가 필요합니다.');
}
try {
await apiClient.delete(`/api/club/events/${eventId}/participants`, {
data: participant
});
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 참가자 상태 수정
* @param {number} eventId - 이벤트 ID
* @param {number} userId - 사용자 ID
* @param {string} status - 변경할 상태
* @returns {Promise<Object>} 수정된 참가자 정보
*/
async updateParticipantStatus(eventId, userId, status) {
if (!eventId || !userId || !status) {
throw new Error('이벤트 ID, 사용자 ID, 상태가 필요합니다.');
}
try {
const response = await apiClient.put(`/api/club/events/${eventId}/participants/${userId}/status`, { status });
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
/**
* 점수 조회
* @param {number} eventId - 이벤트 ID
* @returns {Promise<Array>} 점수 목록
*/
async getEventScores(eventId) {
if (!eventId) {
throw new Error('이벤트 ID가 필요합니다.');
}
try {
const response = await apiClient.get(`/api/club/events/${eventId}/scores`);
return response.data;
} catch (error) {
throw new Error(error.response?.data?.message || '점수 조회 중 오류가 발생했습니다.');
}
},
/**
* 점수 등록
* @param {number} eventId - 이벤트 ID
* @param {Object} scoreData - 점수 정보
* @returns {Promise<Object>} 등록된 점수 정보
*/
async addScore(eventId, scoreData) {
if (!eventId || !scoreData) {
throw new Error('이벤트 ID와 점수 정보가 필요합니다.');
}
try {
const response = await apiClient.post(`/api/club/events/${eventId}/scores`, {
participantId: scoreData.participantId,
teamNumber: scoreData.teamNumber,
gameNumber: scoreData.gameNumber,
score: scoreData.score,
handicap: scoreData.handicap
});
return response.data;
} catch (error) {
throw new Error(error.response?.data?.message || '점수 등록 중 오류가 발생했습니다.');
}
},
/**
* 점수 수정
* @param {number} eventId - 이벤트 ID
* @param {number} scoreId - 점수 ID
* @param {Object} scoreData - 수정할 점수 정보
* @returns {Promise<Object>} 수정된 점수 정보
*/
async updateScore(eventId, scoreId, scoreData) {
if (!eventId || !scoreId || !scoreData) {
throw new Error('이벤트 ID, 점수 ID, 점수 정보가 필요합니다.');
}
if (scoreData.gameNumber === undefined || scoreData.gameNumber === null ||
scoreData.score === undefined || scoreData.score === null) {
throw new Error('게임 번호와 점수는 필수입니다.');
}
try {
// URL 파라미터 문자열로 변환
const url = `/api/club/events/${String(eventId)}/scores/${String(scoreId)}`;
const payload = {
gameNumber: Number(scoreData.gameNumber),
score: scoreData.score !== null ? Number(scoreData.score) : undefined,
handicap: scoreData.handicap !== null ? Number(scoreData.handicap) : 0
};
console.log('Updating score:', {
url,
eventId,
scoreId,
payload
});
const response = await apiClient.put(url, payload);
return response.data;
} catch (error) {
console.error('Score update error:', {
error: error.response?.data,
status: error.response?.status,
statusText: error.response?.statusText
});
throw new Error(error.response?.data?.message || '점수 수정 중 오류가 발생했습니다.');
}
},
/**
* 점수 삭제
* @param {number} eventId - 이벤트 ID
* @param {number} scoreId - 점수 ID
* @returns {Promise<void>}
*/
async deleteScore(eventId, scoreId) {
if (!eventId || !scoreId) {
throw new Error('이벤트 ID와 점수 ID가 필요합니다.');
}
try {
const response = await apiClient.delete(`/api/club/events/${eventId}/scores/${scoreId}`);
return response.data;
} catch (error) {
throw new Error(error.response?.data?.message || '점수 삭제 중 오류가 발생했습니다.');
}
},
/**
* 참가자의 모든 점수 삭제
* @param {number} eventId - 이벤트 ID
* @param {number} participantId - 참가자 ID
* @returns {Promise<Object>} 삭제 결과
*/
async deleteParticipantScores(eventId, participantId) {
if (!eventId || !participantId) {
throw new Error('이벤트 ID와 참가자 ID가 필요합니다.');
}
try {
const response = await apiClient.delete(`/api/club/events/${eventId}/participants/${participantId}/scores`);
return response.data;
} catch (error) {
if (error.response && error.response.data && error.response.data.message) {
throw new Error(error.response.data.message);
}
throw error;
}
},
};
+80
View File
@@ -0,0 +1,80 @@
import apiClient from './apiClient';
/**
* 점수 관리 서비스
*/
export default {
/**
* 모임의 점수 데이터 가져오기
* @param {number} meetingId - 모임 ID
* @returns {Promise} - API 응답
*/
async getMeetingScores(meetingId) {
return apiClient.get(`/meetings/${meetingId}/scores`);
},
/**
* 점수 저장하기
* @param {number} meetingId - 모임 ID
* @param {Array} scores - 점수 데이터 배열
* @returns {Promise} - API 응답
*/
async saveScores(meetingId, scores) {
return apiClient.post(`/meetings/${meetingId}/scores`, { scores });
},
/**
* 특정 참가자의 점수 이력 가져오기
* @param {number} memberId - 회원 ID
* @param {number} limit - 가져올 이력 수
* @returns {Promise} - API 응답
*/
async getMemberScoreHistory(memberId, limit = 5) {
return apiClient.get(`/members/${memberId}/scores/history`, { params: { limit } });
},
/**
* 점수 내보내기
* @param {number} meetingId - 모임 ID
* @param {string} format - 내보내기 형식 (xlsx, csv, pdf)
* @param {Array} content - 내보낼 내용 배열
* @returns {Promise} - API 응답 (파일 다운로드)
*/
async exportScores(meetingId, format, content) {
return apiClient.get(`/meetings/${meetingId}/scores/export`, {
params: { format, content: content.join(',') },
responseType: 'blob'
});
},
/**
* 팀별 점수 가져오기
* @param {number} meetingId - 모임 ID
* @returns {Promise} - API 응답
*/
async getTeamScores(meetingId) {
return apiClient.get(`/meetings/${meetingId}/scores/teams`);
},
/**
* 개인 순위 가져오기
* @param {number} meetingId - 모임 ID
* @param {string} type - 순위 유형 (scratch, handicap)
* @param {string} game - 게임 코드 (all, game1, game2, ...)
* @returns {Promise} - API 응답
*/
async getIndividualRankings(meetingId, type = 'handicap', game = 'all') {
return apiClient.get(`/meetings/${meetingId}/scores/rankings/individual`, {
params: { type, game }
});
},
/**
* 팀 순위 가져오기
* @param {number} meetingId - 모임 ID
* @returns {Promise} - API 응답
*/
async getTeamRankings(meetingId) {
return apiClient.get(`/meetings/${meetingId}/scores/rankings/teams`);
}
};
+83
View File
@@ -0,0 +1,83 @@
import { io } from 'socket.io-client';
import { API_URL } from '../config';
// Socket.IO 서버 URL (API_URL에서 '/api' 부분 제거)
const SOCKET_URL = API_URL.replace('/api', '');
// Socket.IO 클라이언트 인스턴스
let socket;
// Socket.IO 연결 설정
export const initSocket = () => {
if (socket) return socket;
socket = io(SOCKET_URL, {
autoConnect: false,
reconnection: true,
reconnectionAttempts: 5,
reconnectionDelay: 3000
});
// 연결 이벤트 핸들러
socket.on('connect', () => {
console.log('Socket.IO 서버에 연결되었습니다.');
// 사용자 인증 정보 전송
const token = localStorage.getItem('token');
if (token) {
try {
const payload = JSON.parse(atob(token.split('.')[1]));
socket.emit('authenticate', { id: payload.id });
} catch (error) {
console.error('토큰 파싱 오류:', error);
}
}
});
// 연결 오류 이벤트 핸들러
socket.on('connect_error', (error) => {
console.error('Socket.IO 연결 오류:', error);
});
// 연결 해제 이벤트 핸들러
socket.on('disconnect', (reason) => {
console.log('Socket.IO 연결이 해제되었습니다:', reason);
});
return socket;
};
// Socket.IO 연결
export const connectSocket = () => {
if (!socket) initSocket();
if (!socket.connected) socket.connect();
};
// Socket.IO 연결 해제
export const disconnectSocket = () => {
if (socket && socket.connected) socket.disconnect();
};
// 이벤트 리스너 등록
export const onEvent = (event, callback) => {
if (!socket) initSocket();
socket.on(event, callback);
};
// 이벤트 리스너 제거
export const offEvent = (event, callback) => {
if (!socket) return;
if (callback) {
socket.off(event, callback);
} else {
socket.off(event);
}
};
export default {
initSocket,
connectSocket,
disconnectSocket,
onEvent,
offEvent
};
+70
View File
@@ -0,0 +1,70 @@
import apiClient from './api';
/**
* 사용자 관련 API 서비스
*/
const userService = {
/**
* 모든 사용자 조회
* @returns {Promise} - 사용자 목록
*/
getAllUsers() {
return apiClient.get('/users/all');
},
/**
* 특정 사용자 조회
* @param {Number} id - 사용자 ID
* @returns {Promise} - 사용자 정보
*/
getUserById(id) {
return apiClient.get(`/users/${id}`);
},
/**
* 사용자 정보 업데이트
* @param {Number} id - 사용자 ID
* @param {Object} userData - 업데이트할 사용자 정보
* @returns {Promise} - 업데이트된 사용자 정보
*/
updateUser(id, userData) {
return apiClient.put(`/users/${id}`, userData);
},
/**
* 사용자 프로필 조회
* @returns {Promise} - 사용자 프로필 정보
*/
getUserProfile() {
return apiClient.get('/users/profile');
},
/**
* 사용자 프로필 업데이트
* @param {Object} profileData - 업데이트할 프로필 정보
* @returns {Promise} - 업데이트된 프로필 정보
*/
updateUserProfile(profileData) {
return apiClient.put('/users/profile', profileData);
},
/**
* 사용자 참가 이벤트 조회
* @param {Number} id - 사용자 ID
* @returns {Promise} - 이벤트 목록
*/
getUserEvents(id) {
return apiClient.get(`/users/${id}/events`);
},
/**
* 사용자 클럽 멤버십 조회
* @param {Number} id - 사용자 ID
* @returns {Promise} - 클럽 멤버십 목록
*/
getUserClubs(id) {
return apiClient.get(`/users/${id}/clubs`);
}
};
export default userService;