Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/components/pages/premium-study-detail-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ export default function PremiumStudyDetailPage({

const activeTab = (searchParams.get('tab') as StudyTabValue) || 'intro';

const { data: studyDetail, isLoading } =
useGroupStudyDetailQuery(groupStudyId);
const {
data: studyDetail,
isLoading,
refetch: refetchStudyDetail,
} = useGroupStudyDetailQuery(groupStudyId);

const leaderId = studyDetail?.basicInfo.leader.memberId;

Expand Down Expand Up @@ -120,6 +123,7 @@ export default function PremiumStudyDetailPage({
alert('스터디 삭제에 실패하였습니다.');
},
onSettled: () => {
refetchStudyDetail().catch(() => {});
router.push('/premium-study');
setShowModal(false);
},
Expand Down
6 changes: 3 additions & 3 deletions src/features/study/group/api/create-group-study.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { axiosInstance } from '@/api/client/axios';
import { GroupStudyFormRequest } from './group-study-types';
import { GroupStudyCreateRequest } from './group-study-types';

// CS 스터디 매칭 신청
export const createGroupStudy = async (payload: GroupStudyFormRequest) => {
// 그룹 스터디 개설
export const createGroupStudy = async (payload: GroupStudyCreateRequest) => {
try {
const res = await axiosInstance.post('/group-studies', payload);

Expand Down
61 changes: 60 additions & 1 deletion src/features/study/group/api/group-study-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,65 @@ export interface BasicInfo {
updatedAt: string;
}

// 요청용 BasicInfo (백엔드 request body에서 createdAt, updatedAt 제외됨)
// ============================================================
// Create/Update API 공통 타입
// ============================================================

/** Create/Update API에서 공통으로 사용되는 BasicInfo 필드 */
export interface BasicInfoCommon {
type: StudyType;
targetRoles: TargetRole[];
maxMembersCount: number;
experienceLevels: ExperienceLevel[];
method: StudyMethod;
regularMeeting: RegularMeeting;
location: string;
startDate: string;
endDate: string;
price: number;
studyLeaderParticipation: boolean;
}

/** Create/Update API에서 공통으로 사용되는 Request 구조 */
export interface GroupStudyRequestCommon {
detailInfo: DetailInfo;
interviewPost: {
interviewPost: string[];
};
thumbnailExtension: ThumbnailExtension;
}

// ============================================================
// Create API 전용 타입
// ============================================================

/** Create API용 BasicInfo (classification 필수) */
export interface BasicInfoCreateRequest extends BasicInfoCommon {
classification: 'GROUP_STUDY' | 'PREMIUM_STUDY';
}

/** Create API 전체 Request */
export interface GroupStudyCreateRequest extends GroupStudyRequestCommon {
basicInfo: BasicInfoCreateRequest;
}

// ============================================================
// Update API 전용 타입
// ============================================================

/** Update API용 BasicInfo (classification 없음 - 수정 불가) */
export type BasicInfoUpdateRequest = BasicInfoCommon;

/** Update API 전체 Request */
export interface GroupStudyUpdateRequest extends GroupStudyRequestCommon {
basicInfo: BasicInfoUpdateRequest;
}

// ============================================================
// 기존 타입 (하위 호환성 유지)
// ============================================================

/** @deprecated BasicInfoCreateRequest 사용 권장 */
export type BasicInfoRequest = Omit<BasicInfo, 'createdAt' | 'updatedAt'>;

export interface BasicInfoDetail extends BasicInfo {
Expand Down Expand Up @@ -162,6 +220,7 @@ export interface ApplyGroupStudyResponse {
createdAt: string;
}

/** @deprecated GroupStudyCreateRequest 또는 GroupStudyUpdateRequest 사용 권장 */
export interface GroupStudyFormRequest {
basicInfo: BasicInfoRequest;
detailInfo: DetailInfo;
Expand Down
4 changes: 2 additions & 2 deletions src/features/study/group/api/update-group-study.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { axiosInstance } from '@/api/client/axios';
import {
GroupStudyCreationResponse,
GroupStudyFormRequest,
GroupStudyUpdateRequest,
} from './group-study-types';

// 그룹 스터디 수정
export const updateGroupStudy = async (
groupStudyId: number,
payload: GroupStudyFormRequest,
payload: GroupStudyUpdateRequest,
): Promise<GroupStudyCreationResponse> => {
try {
const res = await axiosInstance.put<GroupStudyCreationResponse>(
Expand Down
9 changes: 6 additions & 3 deletions src/features/study/group/const/use-group-study-mutation.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { useMutation } from '@tanstack/react-query';
import { createGroupStudy } from '../api/create-group-study';
import { GroupStudyFormRequest } from '../api/group-study-types';
import {
GroupStudyCreateRequest,
GroupStudyUpdateRequest,
} from '../api/group-study-types';
import { updateGroupStudy } from '../api/update-group-study';

// 그룹 스터디 개설 mutation
export const useCreateGroupStudyMutation = () => {
return useMutation({
mutationFn: (payload: GroupStudyFormRequest) => createGroupStudy(payload),
mutationFn: (payload: GroupStudyCreateRequest) => createGroupStudy(payload),
});
};

// 그룹 스터디 수정 mutation
export const useUpdateGroupStudyMutation = (groupStudyId: number) => {
return useMutation({
mutationFn: (payload: GroupStudyFormRequest) =>
mutationFn: (payload: GroupStudyUpdateRequest) =>
updateGroupStudy(groupStudyId, payload),
});
};
87 changes: 69 additions & 18 deletions src/features/study/group/model/group-study-form.schema.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { z } from 'zod';
import { GroupStudyFormRequest } from '../api/group-study-types';
import {
BasicInfoCommon,
GroupStudyCreateRequest,
GroupStudyFormRequest,
GroupStudyRequestCommon,
GroupStudyUpdateRequest,
} from '../api/group-study-types';
import {
STUDY_TYPES,
TARGET_ROLE_OPTIONS,
Expand Down Expand Up @@ -127,28 +133,35 @@ export function buildOpenGroupDefaultValues(
};
}

export function toOpenGroupRequest(
v: GroupStudyFormValues,
): GroupStudyFormRequest {
// ============================================================
// 변환 함수 (내부 헬퍼)
// ============================================================

/** 공통 BasicInfo 필드 변환 */
function buildBasicInfoCommon(v: GroupStudyFormValues): BasicInfoCommon {
const isPremiumStudy = v.classification === 'PREMIUM_STUDY';

return {
studyLeaderParticipation: v.studyLeaderParticipation,
type: v.type,
targetRoles: v.targetRoles,
maxMembersCount: Number(v.maxMembersCount),
experienceLevels: v.experienceLevels ?? [],
method: v.method,
regularMeeting: v.regularMeeting,
location: v.location.trim(),
startDate: v.startDate.trim(),
endDate: v.endDate.trim(),
price: isPremiumStudy ? Number(v.price) || 0 : 0,
};
}

/** 공통 Request 구조 변환 */
function buildCommonRequest(v: GroupStudyFormValues): GroupStudyRequestCommon {
const thumbnailExt =
v.thumbnailExtension === 'DEFAULT' ? 'JPG' : v.thumbnailExtension;

return {
basicInfo: {
studyLeaderParticipation: v.studyLeaderParticipation,
classification: v.classification,
type: v.type,
targetRoles: v.targetRoles,
maxMembersCount: Number(v.maxMembersCount),
experienceLevels: v.experienceLevels ?? [],
method: v.method,
regularMeeting: v.regularMeeting,
location: v.location.trim(),
startDate: v.startDate.trim(),
endDate: v.endDate.trim(),
price: isPremiumStudy ? Number(v.price) || 0 : 0,
},
detailInfo: {
thumbnailExtension: thumbnailExt,
title: v.title,
Expand All @@ -161,3 +174,41 @@ export function toOpenGroupRequest(
thumbnailExtension: thumbnailExt,
};
}

// ============================================================
// Create/Update 전용 변환 함수
// ============================================================

/** Create API용 Request 변환 */
export function toCreateRequest(
v: GroupStudyFormValues,
): GroupStudyCreateRequest {
return {
...buildCommonRequest(v),
basicInfo: {
...buildBasicInfoCommon(v),
classification: v.classification,
},
};
}

/** Update API용 Request 변환 */
export function toUpdateRequest(
v: GroupStudyFormValues,
): GroupStudyUpdateRequest {
return {
...buildCommonRequest(v),
basicInfo: buildBasicInfoCommon(v),
};
}

// ============================================================
// 기존 함수 (하위 호환성 유지)
// ============================================================

/** @deprecated toCreateRequest 또는 toUpdateRequest 사용 권장 */
export function toOpenGroupRequest(
v: GroupStudyFormValues,
): GroupStudyFormRequest {
return toCreateRequest(v);
}
7 changes: 4 additions & 3 deletions src/features/study/group/ui/group-study-form-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
buildOpenGroupDefaultValues,
GroupStudyFormValues,
StudyClassification,
toOpenGroupRequest,
toCreateRequest,
toUpdateRequest,
} from '../model/group-study-form.schema';
import { useGroupStudyDetailQuery } from '../model/use-study-query';

Expand Down Expand Up @@ -140,7 +141,7 @@ export default function GroupStudyFormModal({

const handleCreate = async (values: GroupStudyFormValues) => {
try {
const body = toOpenGroupRequest(values);
const body = toCreateRequest(values);
const created = await createGroupStudy(body);

if (values.thumbnailFile) {
Expand All @@ -166,7 +167,7 @@ export default function GroupStudyFormModal({

const handleEdit = async (values: GroupStudyFormValues) => {
try {
const body = toOpenGroupRequest(values);
const body = toUpdateRequest(values);
const updated = await updateGroupStudy(body);

if (values.thumbnailFile) {
Expand Down
Loading