diff --git a/backend/controllers/clubController.js b/backend/controllers/clubController.js
index d03b69c..515ff48 100644
--- a/backend/controllers/clubController.js
+++ b/backend/controllers/clubController.js
@@ -198,8 +198,7 @@ exports.createClub = async (req, res) => {
// 클럽 정보 업데이트
exports.updateClub = async (req, res) => {
try {
- const { id, name, location, description, contact, ownerEmail, status } = req.body;
- const clubId = id || req.params.id;
+ const { clubId, name, location, description, contact, ownerEmail, status, femaleHandicap } = req.body;
const club = await Club.findByPk(clubId);
if (!club) {
@@ -226,6 +225,7 @@ exports.updateClub = async (req, res) => {
description: description !== undefined ? description : club.description,
contact: contact !== undefined ? contact : club.contact,
status: status || club.status,
+ femaleHandicap: femaleHandicap || club.femaleHandicap,
ownerId: newOwnerId
});
@@ -421,7 +421,7 @@ exports.addClubMember = async (req, res) => {
// 클럽 회원 정보 수정
exports.updateClubMember = async (req, res) => {
try {
- const { clubId, memberId, name, gender, memberType, email, phone, status } = req.body;
+ const { clubId, memberId, name, gender, memberType, email, phone, handicap, status } = req.body;
if (!clubId || !memberId) {
return res.status(400).json({ message: '잘못된 클럽 또는 회원 ID입니다.' });
@@ -461,6 +461,7 @@ exports.updateClubMember = async (req, res) => {
memberType: memberType || member.memberType,
email: email || member.email,
phone: phone || member.phone,
+ handicap: handicap || member.handicap,
status: status || member.status
});
diff --git a/backend/controllers/publicController.js b/backend/controllers/publicController.js
index b2844a9..e1c0e93 100644
--- a/backend/controllers/publicController.js
+++ b/backend/controllers/publicController.js
@@ -265,6 +265,10 @@ exports.addPublicGuest = async (req, res) => {
// 클럽의 회원 수와 구독 플랜의 최대 회원 수 확인
const memberCount = await Member.count({ where: { clubId: event.clubId } });
+ // 클럽 정보 가져오기 (여성 기본 핸디캡 확인을 위해)
+ const club = await Club.findByPk(event.clubId);
+ if (!club) return res.status(404).json({ message: '클럽 정보를 찾을 수 없습니다.' });
+
// 클럽의 구독 정보 가져오기 - 가장 최근 구독 정보
const clubSubscription = await sequelize.models.ClubSubscription.findOne({
where: { clubId: event.clubId },
@@ -288,6 +292,12 @@ exports.addPublicGuest = async (req, res) => {
}
}
+ // 여성 핸디캡 적용
+ let handicap = null;
+ if (gender === '여성' && club.femaleHandicap) {
+ handicap = club.femaleHandicap;
+ }
+
// publicAuth 미들웨어로 인증됨
const member = await Member.create({
name,
@@ -295,7 +305,8 @@ exports.addPublicGuest = async (req, res) => {
gender,
clubId: event.clubId,
memberType: '게스트',
- average: average || 0
+ average: average || 0,
+ handicap: handicap // 여성 핸디캡 적용
});
const participant = await EventParticipant.create({ eventId: event.id, memberId: member.id });
res.json({
diff --git a/backend/models/Club.js b/backend/models/Club.js
index b35bf9a..0df1cba 100644
--- a/backend/models/Club.js
+++ b/backend/models/Club.js
@@ -49,6 +49,12 @@ const Club = sequelize.define('Club', {
defaultValue: 0,
comment: '회원 수'
},
+ femaleHandicap: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: 15,
+ comment: '여성 기본 핸디캡'
+ },
createdAt: {
type: DataTypes.DATE,
allowNull: false,
diff --git a/frontend/src/App.vue b/frontend/src/App.vue
index 4e21c96..50abe00 100644
--- a/frontend/src/App.vue
+++ b/frontend/src/App.vue
@@ -12,7 +12,15 @@
@@ -121,6 +129,7 @@ const ownerName = ref('');
const isRouterReady = ref(false);
const userRole = computed(() => user.value?.role || '');
const isAdmin = computed(() => userRole.value === 'admin' || userRole.value === 'superadmin');
+const userClubRole = ref(localStorage.getItem('userClubRole') || '');
// 화면 크기 변경 감지
const handleResize = () => {
@@ -430,12 +439,29 @@ body {
margin-bottom: 10px;
}
+.club-title {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ margin-bottom: 5px;
+}
+
.club-header h3 {
margin: 0;
font-size: 1.2em;
font-weight: bold;
}
+.settings-icon {
+ color: #6c757d;
+ font-size: 1.1em;
+ transition: color 0.3s ease;
+}
+
+.settings-icon:hover {
+ color: #007bff;
+}
+
.club-location {
margin: 0;
font-size: 0.9em;
diff --git a/frontend/src/router/index.js b/frontend/src/router/index.js
index 604bfab..1ec33f7 100644
--- a/frontend/src/router/index.js
+++ b/frontend/src/router/index.js
@@ -19,6 +19,7 @@ const EventManagement = () => import('@/views/club/EventManagement.vue');
const EventCalendar = () => import('@/views/club/EventCalendar.vue');
const ScoreManagement = () => import('@/views/club/ScoreManagement.vue');
const UserClubCreate = () => import('@/views/club/ClubCreate.vue');
+const ClubSettings = () => import('@/views/club/ClubSettings.vue');
// 구독 관리 컴포넌트 import
const ClubSubscriptionManagement = () => import('@/views/club/subscription/SubscriptionManagement.vue');
@@ -133,6 +134,15 @@ const routes = [
requiresAuth: true,
requiredRoles: ['admin', '모임장', '운영진']
}
+ },
+ {
+ path: 'settings',
+ name: 'ClubSettings',
+ component: ClubSettings,
+ meta: {
+ requiresAuth: true,
+ requiredRoles: ['admin', '모임장', '운영진']
+ }
}
]
},
@@ -201,8 +211,9 @@ router.beforeEach(async (to, from, next) => {
return;
}
- // 클럽 구독 관리 페이지에 접근하려는 경우, 권한 확인
- if (to.name === 'ClubSubscription' && (userClubRole !== 'admin' && userClubRole !== '모임장' && userClubRole !== '운영진')) {
+ // 클럽 구독 관리 또는 설정 페이지에 접근하려는 경우, 권한 확인
+ if ((to.name === 'ClubSubscription' || to.name === 'ClubSettings') &&
+ (userClubRole !== 'admin' && userClubRole !== '모임장' && userClubRole !== '운영진')) {
next({ name: 'ClubDashboard' });
return;
}
diff --git a/frontend/src/views/club/ClubSettings.vue b/frontend/src/views/club/ClubSettings.vue
new file mode 100644
index 0000000..5fda256
--- /dev/null
+++ b/frontend/src/views/club/ClubSettings.vue
@@ -0,0 +1,606 @@
+
+
+
+
+
+
+
+
+
+
+
구독 정보
+
+
+
+
+
+ 시작일:
+ {{ formatDate(subscriptionInfo.startDate) }}
+
+
+ 만료일:
+ {{ formatDate(subscriptionInfo.endDate) }}
+
+
+ 회원 수:
+ {{ clubInfo.memberCount }}/{{ subscriptionInfo.maxMembers }}명
+
+
+ 월 구독료:
+ {{ subscriptionInfo.planPrice }}원
+
+
+
+
+ 구독 관리
+
+
+
+
현재 활성화된 구독이 없습니다.
+
구독 신청하기
+
+
+
+
+
+
기능 정보
+
+
+
+
+
+
+
{{ feature.name }}
+
{{ feature.description }}
+
+
+ {{ feature.active ? '활성화' : '비활성화' }}
+
+
+ 만료일: {{ formatDate(feature.expiryDate) }}
+
+
+ 플랜 포함
+
+
+ {{ feature.price }}원/월
+
+
+
+
+
+
+
+ 기능 추가 구매
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/views/club/EventManagement.vue b/frontend/src/views/club/EventManagement.vue
index d2a1ea0..d396f7f 100644
--- a/frontend/src/views/club/EventManagement.vue
+++ b/frontend/src/views/club/EventManagement.vue
@@ -21,6 +21,8 @@
stripedRows
filterDisplay="menu"
v-model:filters="filters"
+ sort-field="startDate"
+ :sort-order="-1"
class="mt-4"
>
diff --git a/frontend/src/views/club/MemberManagement.vue b/frontend/src/views/club/MemberManagement.vue
index 59935a1..963e901 100644
--- a/frontend/src/views/club/MemberManagement.vue
+++ b/frontend/src/views/club/MemberManagement.vue
@@ -22,6 +22,8 @@
@@ -62,29 +64,35 @@
:header="dialogMode === 'new' ? '새 회원 추가' : '회원 정보 수정'"
:modal="true" class="p-fluid">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -168,25 +176,27 @@