Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f487578
chore: QA서버, 운영 서버 이미지 전체 허용
Mimiminz Aug 25, 2025
ab26082
feat: 키워드 모달 추가
aken-you Aug 25, 2025
24aefc3
feat: 자신이 이번주에 스터디 후기를 남겼는지 여부에 관한 데이터 요청 커스텀 훅 생성
aken-you Aug 26, 2025
47d4d63
fix: TextAreaInput onChange 타입 에러
aken-you Aug 26, 2025
20ade3b
feat: 후기를 작성안하면, 주말에 30분 주기로 후기 모달 렌더링
aken-you Aug 26, 2025
c853f08
Merge branch 'develop' of https://github.com/code-zero-to-one/study-p…
Mimiminz Aug 27, 2025
bc053d8
fix: 첫 렌더링 시에 스터디 후기 모달이 뜨지 않는 문제 해결
aken-you Aug 27, 2025
e111a82
fix: 리뷰 상태 쿼리에 isFetching 추가로 모달 렌더링 조건 개선
aken-you Aug 27, 2025
7c6ca7e
feat: 스터디 후기 작성 여부 useQuery의 enabled 속성 추가
aken-you Aug 27, 2025
57880c2
chore: progress bar package 추가
Mimiminz Aug 28, 2025
339f5c1
refactor: 자신이 이번 주 스터디 후기 작성 대상자인지 여부 조회하는 함수 네이밍 변경
aken-you Aug 28, 2025
8191964
feat: 성실온도 타입 추가
Mimiminz Aug 29, 2025
973d84c
refactor: MoreKeywordReviewModal 안의 더보기 버튼 조건부 렌더링 설정
aken-you Aug 29, 2025
0692843
fix: THIRTY_MIN 값 오타 수정
aken-you Aug 29, 2025
440e91e
fix: 스터디 모달의 후기 스타일 적용 안된 부분 적용
aken-you Aug 29, 2025
01197cd
fix: 스터디 주제 없으면 후기에 표시 x
aken-you Aug 29, 2025
8bcf716
Merge pull request #127 from code-zero-to-one/feat/study-review
aken-you Aug 29, 2025
20fa577
fix: 스터디 후기에서 content는 필수 x
aken-you Aug 29, 2025
53418c4
refactor: 후기에 유저 이미지 적용
aken-you Aug 29, 2025
ad51487
fix: 후기 내용의 줄 수에 따라 '더보기' 버튼 표시
aken-you Aug 29, 2025
9ff42b2
refactor: 스터디 리뷰 content가 빈 문자열이면 서버에게 Null로 전송
aken-you Aug 29, 2025
71088e6
refactor: 스터디 리뷰 content가 빈 문자열이면 서버에게 undefined로 전송
aken-you Aug 29, 2025
03d0d36
Merge pull request #130 from code-zero-to-one/feat/study-review
aken-you Aug 29, 2025
e3cf059
feat: 온도별 컬러, 아이콘 프리셋 설정
Mimiminz Aug 29, 2025
5a94851
feat: 마이 프로필 카드에 온도 추가
Mimiminz Aug 29, 2025
ab9eb3e
style: 네이밍 변경
Mimiminz Aug 29, 2025
c8ef034
Merge branch 'develop' of https://github.com/code-zero-to-one/study-p…
Mimiminz Aug 29, 2025
3c86056
fix: 머지 컨플릭트 수정 -> div 위치 변경
Mimiminz Aug 29, 2025
4973b91
feat: 유저 프로필 모달에 성실온도 추가
Mimiminz Aug 29, 2025
c825f1d
style: 사용하지 않는 가로 세로값 삭제
Mimiminz Aug 29, 2025
9357e8d
fix: indicator 색상 background 적용 변경
Mimiminz Aug 29, 2025
60d7326
feat: 성실온도 설명 이미지 추가
Mimiminz Aug 29, 2025
d2b9b5e
feat: progress 컴포넌트 추가
Mimiminz Aug 29, 2025
fc6c98f
feat: 프로필 성실온도 추가
Mimiminz Aug 29, 2025
3c944a8
style: 정렬 수정
Mimiminz Aug 29, 2025
fc9b656
Merge pull request #131 from code-zero-to-one/QNRR-466-조민주-성실-온도-ui-및…
Mimiminz Aug 30, 2025
2a8fff7
fix: 스터디 신청 버튼 수정
aken-you Aug 30, 2025
e04e1ee
Merge pull request #132 from code-zero-to-one/fix/apply-study-button
aken-you Aug 30, 2025
5b55bfd
fix: levelId -> levelName 기준으로 매핑 수정
Mimiminz Aug 30, 2025
c576556
Merge branch 'develop' of https://github.com/code-zero-to-one/study-p…
Mimiminz Aug 30, 2025
8f5cc1a
Merge pull request #133 from code-zero-to-one/QNRR-466-조민주-성실-온도-ui-및…
Mimiminz Aug 30, 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
6 changes: 5 additions & 1 deletion app/(my)/my-page/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ export default async function MyPage() {

return (
<div className="flex flex-col gap-[26.67px]">
<Profile memberId={memberId} memberProfile={userProfile.memberProfile} />
<Profile
memberId={memberId}
memberProfile={userProfile.memberProfile}
sincerityTemp={userProfile.sincerityTemp}
/>
<ProfileInfo memberId={memberId} memberInfo={userProfile.memberInfo} />
</div>
);
Expand Down
84 changes: 59 additions & 25 deletions app/(my)/my-study-review/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
'use client';

import Image from 'next/image';
import { useState } from 'react';
import { useEffect, useRef, useState } from 'react';
import KeywordReview from '@/entities/user/ui/keyword-review';
import MoreKeywordReviewModal from '@/entities/user/ui/more-keyword-review-modal';
import { MyReviewItem } from '@/features/study/api/types';
import {
useMyNegativeKeywordsQuery,
useMyReviewsInfinityQuery,
useUserPositiveKeywordsQuery,
} from '@/features/study/model/use-review-query';
import { formatKoreaRelativeTime } from '@/shared/lib/time';
import UserAvatar from '@/shared/ui/avatar';

export default function MyStudyReview() {
const { data: positiveKeywordsData } = useUserPositiveKeywordsQuery({
pageSize: 5,
});

const { data: negativeKeywordsData } = useMyNegativeKeywordsQuery({
pageSize: 5,
});
Expand Down Expand Up @@ -55,11 +58,7 @@ export default function MyStudyReview() {
<div className="mb-200 flex justify-between">
<h3 className="font-designer-16b text-text-default">좋았던 점</h3>

{positiveKeywords.length > 5 && (
<button className="font-designer-12m text-text-subtlest cursor-pointer">
더보기
</button>
)}
<MorePositiveKeywordsModal />
</div>

<ul className="flex flex-col gap-50">
Expand All @@ -85,11 +84,7 @@ export default function MyStudyReview() {
개선이 필요한 점
</h3>

{negativeKeywords.length > 5 && (
<button className="font-designer-12m text-text-subtlest cursor-pointer">
더보기
</button>
)}
<MoreNegativeKeywordsModal />
</div>

<ul className="flex flex-col gap-50">
Expand Down Expand Up @@ -153,18 +148,52 @@ export default function MyStudyReview() {
);
}

function MorePositiveKeywordsModal() {
const { data: allPositiveKeywordsData } = useUserPositiveKeywordsQuery({});

const allPositiveKeywords = allPositiveKeywordsData?.keywords || [];

return (
<MoreKeywordReviewModal title="좋았던 점" keywords={allPositiveKeywords} />
);
}

function MoreNegativeKeywordsModal() {
const { data: allNegativeKeywordsData } = useMyNegativeKeywordsQuery({});

const allNegativeKeywords = allNegativeKeywordsData?.keywords || [];

return (
<MoreKeywordReviewModal
title="개선이 필요한 점"
keywords={allNegativeKeywords}
/>
);
}

function Review({ data }: { data: MyReviewItem }) {
const [expanded, setExpanded] = useState(false);
const [showButton, setShowButton] = useState(false);
const contentRef = useRef<HTMLParagraphElement>(null);

useEffect(() => {
if (contentRef.current) {
const lineHeight = parseInt(
window.getComputedStyle(contentRef.current).lineHeight,
10,
);
const maxHeight = lineHeight * 3; // 3줄 기준
setShowButton(contentRef.current.scrollHeight > maxHeight);
}
}, [data.content]);

return (
<li className="border-b-border-subtle flex flex-col gap-150 border-b py-250">
<div className="flex items-center gap-150">
<Image
src={data.writer.profileImageUrl || '/profile-default.svg'}
width={32}
height={32}
<UserAvatar
size={32}
image={data.writer.profileImageUrl}
alt={`${data.writer.memberName} 프로필 이미지`}
className="rounded-full"
/>

<div>
Expand All @@ -180,18 +209,23 @@ function Review({ data }: { data: MyReviewItem }) {

<div>
<p
className={`text-text-default font-designer-15r ${expanded ? 'line-clamp-none' : 'line-clamp-3'}`}
ref={contentRef}
className={`text-text-default font-designer-15r ${
expanded ? 'line-clamp-none' : 'line-clamp-3'
}`}
>
{data.content}
</p>
<button
className="font-designer-14r text-text-subtlest cursor-pointer"
onClick={() => setExpanded(!expanded)}
>
{expanded ? '접기' : '더보기'}
</button>
</div>

{showButton && (
<button
className="font-designer-14r text-text-subtlest cursor-pointer"
onClick={() => setExpanded(!expanded)}
>
{expanded ? '접기' : '더보기'}
</button>
)}
</div>
<div>
<div className="text-text-subtle">
<span className="font-designer-14b mr-100">스터디 기간</span>
Expand All @@ -203,7 +237,7 @@ function Review({ data }: { data: MyReviewItem }) {
<div className="text-text-subtle">
<span className="font-designer-14b mr-100">스터디 주제</span>
<span className="font-designer-13r">
{data.studySubjects.join(', ')}
{data.studySubjects.filter((subject) => subject).join(', ')}
</span>
</div>
</div>
Expand Down
12 changes: 6 additions & 6 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,18 @@ const nextConfig: NextConfig = {
},
{
protocol: 'https',
hostname: 'test-api.zeroone.it.kr',
pathname: '/profile-image/**',
hostname: 'lh3.googleusercontent.com',
pathname: '/**', // 구글 이미지 전체 허용
},
{
protocol: 'https',
hostname: 'api.zeroone.it.kr',
pathname: '/profile-image/**',
hostname: 'test-api.zeroone.it.kr',
pathname: '/**',
},
{
protocol: 'https',
hostname: 'lh3.googleusercontent.com',
pathname: '/**', // 구글 이미지 전체 허용
hostname: 'www.zeroone.it.kr',
pathname: '/**',
},
],
},
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@radix-ui/react-avatar": "^1.1.9",
"@radix-ui/react-dialog": "^1.1.10",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-slot": "^1.2.2",
"@radix-ui/react-switch": "^1.2.4",
"@radix-ui/react-toggle": "^1.1.9",
Expand Down
Binary file added public/images/help_outline.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 8 additions & 1 deletion src/entities/user/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,19 +65,26 @@ export interface MemberProfile {
simpleIntroduction: string;
mbti: string;
interests: Interest[];
hobbies: Hobby[];
hobbies?: Hobby[];
birthDate: string;
githubLink: SocialLink | undefined;
blogOrSnsLink: SocialLink | undefined;
tel: string;
}

export interface SincerityTemp {
temperature: number;
levelId: number;
levelName: string;
}

export interface GetUserProfileResponse {
memberId: number;
autoMatching: boolean;
studyApplied: boolean;
memberInfo: MemberInfo;
memberProfile: MemberProfile;
sincerityTemp: SincerityTemp;
}

export interface PatchAutoMatchingParams {
Expand Down
44 changes: 44 additions & 0 deletions src/entities/user/ui/more-keyword-review-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { XIcon } from 'lucide-react';
import { Modal } from '@/shared/ui/modal';
import KeywordReview from './keyword-review';

export default function MoreKeywordReviewModal({
title,
keywords,
}: {
title: string;
keywords: { id: number; content: string; count: number }[];
}) {
return (
<Modal.Root>
<Modal.Trigger asChild>
{keywords.length > 5 && (
<button className="font-designer-12m text-text-subtlest cursor-pointer">
더보기
</button>
)}
</Modal.Trigger>
<Modal.Portal>
<Modal.Overlay />
<Modal.Content size="large" className="w-full">
<Modal.Header className="border-border-default flex justify-between border-b">
<Modal.Title className="font-designer-20b text-text-strong">
{title}
</Modal.Title>
<Modal.Close>
<XIcon />
</Modal.Close>
</Modal.Header>

<Modal.Body className="flex flex-col gap-400 p-400">
<ul className="flex flex-col gap-50">
{keywords.map((keyword) => (
<KeywordReview key={keyword.id} {...keyword} />
))}
</ul>
</Modal.Body>
</Modal.Content>
</Modal.Portal>
</Modal.Root>
);
}
Loading