Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f0a74e4
Update Dockerfile.prod
seong-jin-jo Nov 1, 2025
8cd0bb8
Merge pull request #218 from code-zero-to-one/main
seong-jin-jo Nov 1, 2025
5d71d02
배포!
seong-jin-jo Nov 1, 2025
2c693b9
refactor: 안쓰는 completeStudy 함수 제거
aken-you Nov 2, 2025
db19869
refactor: 그룹스터디 신청 상태에서 신청 안했을 경우를 나타내는 상태 추가
aken-you Nov 3, 2025
43230b9
fix: ApplyGroupStudyModal의 trigger에서 SSR 결과물과 CSR 결과물이 다른 문제 해결
aken-you Nov 3, 2025
892a4bf
Merge pull request #221 from code-zero-to-one/hotfix/apply-group-stud…
aken-you Nov 8, 2025
128f3eb
fix: 참여자가 모집 인원수보다 크거나 같을 경우, 신청하기 버튼 비활성화
aken-you Nov 9, 2025
82811ed
style: 콘솔 제거
aken-you Nov 9, 2025
0a40e72
Merge pull request #222 from code-zero-to-one/fix/study-apply
aken-you Nov 9, 2025
a2425b7
refactor: 헤더 탭 네이밍 변경
aken-you Nov 9, 2025
9bcdf51
fix: InterviewPost 타입 제거
aken-you Nov 9, 2025
dfe3476
Merge pull request #224 from code-zero-to-one/fix/study-apply
aken-you Nov 9, 2025
f3d1cb0
Merge pull request #223 from code-zero-to-one/refactor/header-tab
aken-you Nov 9, 2025
2e75c2f
feat: 참가자 항목의 이미지를 클릭하면, 유저 프로필 모달 표시
aken-you Nov 9, 2025
a0df2d0
feat: 스터디 신청자 페이지 수정 완료
yeun38 Nov 9, 2025
820c44e
Merge pull request #226 from code-zero-to-one/feat/QNRR-596-manage-ap…
yeun38 Nov 9, 2025
6d0b5e4
Merge pull request #225 from code-zero-to-one/refactor/group-study-me…
aken-you Nov 9, 2025
0de4f6e
Merge branch 'main' into develop
aken-you Nov 9, 2025
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
17 changes: 16 additions & 1 deletion src/features/my-page/ui/profile-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,22 @@ export default function ProfileCard(props: ProfileCardProps) {
</p>
</div>
</div>
<p className="font-designer-16r text-text-default">{applicant.answer}</p>
{applicant.interviewPost.map((q) => {
const matchedAnswer = applicant.answer.find((a) => a.id === q.id);

return (
<div key={q.id} className="mb-4">
<p className="font-designer-16b text-text-default">
{q.id}. {q.question}
</p>

<p className="font-designer-16r text-text-default">
{matchedAnswer?.answer ?? '—'}
</p>
</div>
);
})}

<div className="flex w-full justify-end gap-100">
<Button
size="medium"
Expand Down
14 changes: 7 additions & 7 deletions src/features/study/group/api/group-study-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,6 @@ export interface GroupStudyData {
simpleDetailInfo: SimpleDetailInfo;
}

export interface InterviewPost {
interviewPost: string[];
}

// 그룹 스터디 신청 Request 타입
export interface ApplyGroupStudyRequest {
groupStudyId: number;
Expand All @@ -146,8 +142,10 @@ export interface DetailInfoDetail extends DetailInfo, Timestamps {
thumbnailUploadUrl: string | null;
}

/** 상세 화면용 InterviewPost (기존 InterviewPost 확장) */
export interface InterviewPostDetail extends InterviewPost, Timestamps {}
/** 상세 화면용 InterviewPost */
export interface InterviewPostDetail extends Timestamps {
interviewPost: { question: string; id: number }[];
}

// 그룹 스터디 신청 Response 타입
export interface ApplyGroupStudyResponse {
Expand All @@ -161,7 +159,9 @@ export interface ApplyGroupStudyResponse {
export interface OpenGroupStudyRequest {
basicInfo: BasicInfo;
detailInfo: DetailInfo;
interviewPost: InterviewPost;
interviewPost: {
interviewPost: string[];
};
thumbnailExtension: ThumbnailExtension;
}

Expand Down
3 changes: 2 additions & 1 deletion src/features/study/group/application/api/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ export interface GroupStudyApply {
progressScore: number;
role: ApplyRole;
lastAccessed: string;
answer: string[];
answer: { id: number; answer: string }[];
status: ApplyStatus;
processedAt: string | null;
reason: string | null;
createdAt: string;
updatedAt: string;
interviewPost: { id: number; question: string }[];
}

export interface Applicant {
Expand Down
9 changes: 5 additions & 4 deletions src/features/study/group/ui/apply-group-study-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useController, useForm } from 'react-hook-form';
import Button from '@/shared/ui/button';
import Checkbox from '@/shared/ui/checkbox';
import { Modal } from '@/shared/ui/modal';
import { GroupStudyDetailResponse } from '../api/group-study-types';
import {
ApplyGroupStudyFormData,
ApplyGroupStudyFormSchema,
Expand All @@ -16,7 +17,7 @@ import { useApplyGroupStudyMutation } from '../model/use-apply-group-study';
interface ApplyGroupStudyModalProps {
groupStudyId: number;
title: string;
questions: string[];
questions: GroupStudyDetailResponse['interviewPost']['interviewPost'];
trigger: React.ReactNode;
}

Expand Down Expand Up @@ -64,7 +65,7 @@ function ApplyGroupStudyForm({
}: {
groupStudyId: number;
title: string;
questions: string[];
questions: { question: string; id: number }[];
onClose: () => void;
}) {
const {
Expand Down Expand Up @@ -118,8 +119,8 @@ function ApplyGroupStudyForm({
className="flex flex-col gap-300"
onSubmit={handleSubmit(onSubmit)}
>
{questions.map((question, index) => (
<div key={question} className="flex flex-col gap-150">
{questions.map(({ question, id }, index) => (
<div key={id} className="flex flex-col gap-150">
<label
htmlFor={`question-${index}`}
className="font-designer-15b text-text-default"
Expand Down
16 changes: 11 additions & 5 deletions src/features/study/group/ui/group-study-member-item.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client';

import { useState } from 'react';
import UserProfileModal from '@/entities/user/ui/user-profile-modal';
import {
formatHHMM,
formatKoreaRelativeTime,
Expand Down Expand Up @@ -53,11 +54,16 @@ export default function GroupStudyMemberItem({
>
{/* 사용자 프로필 */}
<div className="relative inline-block">
<UserAvatar
image={member.profileImageUrl}
alt={`${member.memberName} 프로필 이미지`}
size={100}
className="border-border-default bg-background-default rounded-full border object-cover"
<UserProfileModal
memberId={member.id}
trigger={
<UserAvatar
image={member.profileImageUrl}
alt={`${member.memberName} 프로필 이미지`}
size={100}
className="border-border-default bg-background-default rounded-full border object-cover"
/>
}
/>

{/* 랭크 아이콘 */}
Expand Down
2 changes: 2 additions & 0 deletions src/features/study/group/ui/study-info-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,8 @@ export default function StudyInfoSection({
memberId={memberId}
isLeader={isLeader}
groupStudyStatus={studyDetail.basicInfo.status}
approvedCount={studyDetail.basicInfo.approvedCount}
maxMembersCount={studyDetail.basicInfo.maxMembersCount}
data={summaryBasicInfoItems(studyDetail.basicInfo)}
title={studyDetail.detailInfo.title}
questions={studyDetail.interviewPost.interviewPost}
Expand Down
12 changes: 10 additions & 2 deletions src/features/study/group/ui/summary-study-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
import React from 'react';
import Button from '@/shared/ui/button';
import ApplyGroupStudyModal from './apply-group-study-modal';
import { GroupStudyStatus } from '../api/group-study-types';
import {
GroupStudyDetailResponse,
GroupStudyStatus,
} from '../api/group-study-types';
import { useGroupStudyMyStatusQuery } from '../model/use-group-study-my-status-query';

interface SummaryStudyInfoProps {
Expand All @@ -14,9 +17,11 @@ interface SummaryStudyInfoProps {
}[];
title: string;
groupStudyId: number;
questions: string[];
questions: GroupStudyDetailResponse['interviewPost']['interviewPost'];
isLeader: boolean;
groupStudyStatus: GroupStudyStatus;
approvedCount: GroupStudyDetailResponse['basicInfo']['approvedCount'];
maxMembersCount: GroupStudyDetailResponse['basicInfo']['maxMembersCount'];
memberId?: number;
}

Expand All @@ -27,6 +32,8 @@ export default function SummaryStudyInfo({
questions,
isLeader,
groupStudyStatus,
approvedCount,
maxMembersCount,
memberId,
}: SummaryStudyInfoProps) {
const { data: myApplicationStatus } = useGroupStudyMyStatusQuery({
Expand Down Expand Up @@ -74,6 +81,7 @@ export default function SummaryStudyInfo({
disabled={
myApplicationStatus?.status !== 'NONE' ||
groupStudyStatus === 'IN_PROGRESS' ||
approvedCount >= maxMembersCount ||
!isLoggedIn
}
>
Expand Down
4 changes: 2 additions & 2 deletions src/widgets/home/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ export default async function Header() {

{/* 1차 MVP에선 사용하지 않아 제외 */}
<nav className="font-designer-14m text-text-default flex flex-grow items-center gap-300 px-600">
<Link href={isLoggedIn ? '/home' : '/login'}>1:1 CS스터디</Link>
<Link href="/study">스터디 둘러보기</Link>
<Link href={isLoggedIn ? '/home' : '/login'}>1:1 스터디</Link>
<Link href="/study">그룹스터디</Link>
{/* <Link href="/">팀소개하기로 했었구나</Link> */}
</nav>

Expand Down