Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
161 commits
Select commit Hold shift + click to select a range
39e788f
refactor: profile-default.svg 관련 코드 삭제
aken-you Aug 30, 2025
68e8eb5
refactor: const 분리
Mimiminz Sep 4, 2025
dba7562
refactor: lib 분리
Mimiminz Sep 4, 2025
4b112dc
refactor: study api 파일 별 분리
Mimiminz Sep 4, 2025
19f5c22
refactor: study type 분리
Mimiminz Sep 4, 2025
f363891
fix: 스터디 시작 유무, 상세조회 이동
Mimiminz Sep 4, 2025
99faeae
refactor: 스터디 query 분리
Mimiminz Sep 4, 2025
17f2a87
refactor: 스키마 파일 이동
Mimiminz Sep 4, 2025
247a4ad
refactor: 인터뷰 관련 UI 파일 분리
Mimiminz Sep 4, 2025
8479243
refactor: 스케쥴 관련 UI 파일 분리
Mimiminz Sep 4, 2025
1bae87e
refactor: 스터디 참여 관련 UI 분리
Mimiminz Sep 4, 2025
bf21c39
fix: 변경된 파일 경로 수정
Mimiminz Sep 4, 2025
9a2f2d5
fix: 파일 경로 수정
Mimiminz Sep 5, 2025
4e4e673
Merge branch 'develop' of https://github.com/code-zero-to-one/study-p…
Mimiminz Sep 11, 2025
206653a
레이아웃, 로고, 파비콘 수정 완료
yeun38 Sep 13, 2025
f920fa9
refactor: review feature -> entities 분리
Mimiminz Sep 14, 2025
144b522
fix: 변경되지 않은 import 수정
Mimiminz Sep 14, 2025
17c3134
fix: warning 수정
Mimiminz Sep 14, 2025
e11cf19
Merge pull request #143 from code-zero-to-one/refactor/study-file-sep…
Mimiminz Sep 14, 2025
22af899
refator: 컨텐츠 1400px로 화면 레이아웃 고정
yeun38 Sep 19, 2025
978fd6d
Merge pull request #148 from code-zero-to-one/feat/QNRR-492-edit-layout
yeun38 Sep 21, 2025
4bcacd9
feat: 오늘의 스터디 새로운 디자인 적용
aken-you Aug 22, 2025
994dfc5
refactor: 오늘의 스터디 상세 부분 컴포넌트로 분리
aken-you Sep 10, 2025
c8e5fca
refactor: TodayStudyDetail 컴포넌트 내부에서 동시에 실행되지 않은 코드 분리
aken-you Sep 10, 2025
ac3b74a
refactor: 피드백 JSX를 반환하는 함수 생성
aken-you Sep 10, 2025
e46a997
refactor: 프로필 보기 클릭하면 상대방 프로필 모달 표시
aken-you Sep 10, 2025
bd9bacd
style: 피드백 없을 때 보여줄 안내 문구 수정
aken-you Sep 10, 2025
4874f73
refactor: renderFeedback에서 피드백 존재 여부로 조건부 렌더링 판단
aken-you Sep 10, 2025
a3eaa61
feat: 전화번호 모달 생성
aken-you Sep 11, 2025
c17bc30
feat: 스터디원의 전화번호 데이터 설정
aken-you Sep 22, 2025
5593616
refactor: 이미 다른 곳에 있는 type 제거
aken-you Sep 24, 2025
5b274cc
Merge pull request #147 from code-zero-to-one/refactor/today-study-se…
aken-you Sep 24, 2025
acc0651
Merge branch 'develop' into refactor/profile-default
aken-you Sep 27, 2025
2627d4e
chore: @radix-ui/react-radio-group 설치
aken-you Sep 27, 2025
3965a01
feat: input disable 상태 시 커스텀
Mimiminz Sep 27, 2025
71a4f5a
feat: 단일 선택 옵션 추가
Mimiminz Sep 27, 2025
33dc7c3
feat: 그룹 스터디 스키마 추가 (수정필요)
Mimiminz Sep 27, 2025
881e717
feat: 그룹 스터디 생성 const 값 추가
Mimiminz Sep 27, 2025
116fcf7
feat: 그룹 스터디 request 타입 추가 (수정 필요)
Mimiminz Sep 27, 2025
f10f9be
feat: Radio 컴포넌트 생성
aken-you Sep 27, 2025
f3d09fa
feat: Radio 컴포넌트 스토리북 생성
aken-you Sep 27, 2025
5ed3e60
fix: RadioGroupItem의 size 타입을 옵셔널로 수정
aken-you Sep 27, 2025
a87dff6
refactor: radio 스토리북 오타 수정
aken-you Sep 27, 2025
1e96443
feat: RadioGroup 스토리북 설명 추가
aken-you Sep 27, 2025
e878c28
refactor: 스토리북 RadioGroup의 onValueChange 사용
aken-you Sep 27, 2025
2093d75
fix: 경력 const 변경
Mimiminz Sep 27, 2025
5276026
feat: 스텝 1 추가
Mimiminz Sep 27, 2025
4e52907
feat: 스텝 2 추가
Mimiminz Sep 27, 2025
4315d08
fix: 경력 인풋/아웃풋 다르게 변경
Mimiminz Sep 27, 2025
6376a90
feat: 스텝 3 추가
Mimiminz Sep 27, 2025
c5b14f3
feat: 폰트 크기 타입 추가
Mimiminz Sep 27, 2025
c285185
fix: group 단일/복수 추가 및 다른 타입 확장 가능성 추가
Mimiminz Sep 27, 2025
181ad38
feat: 스텝 별 그룹 스터디 생성 모달 추가
Mimiminz Sep 27, 2025
396dfbc
style: 테스트를 위한 코드 추가
Mimiminz Sep 27, 2025
8d76b4d
refactor: RadioGroup의 grid 스타일 제거
aken-you Sep 28, 2025
b02a83e
Merge pull request #150 from code-zero-to-one/feature/radio-button
aken-you Sep 28, 2025
f354f60
Merge pull request #134 from code-zero-to-one/refactor/profile-default
aken-you Sep 28, 2025
59ffb53
feat: 스터디 목록 UI구현중 #1
yeun38 Sep 28, 2025
902f7ac
feat: 그룹 스터디 썸네일 input 생성
aken-you Sep 29, 2025
468e3f6
feat: 카메라 아이콘 추가
aken-you Sep 29, 2025
2ebdf88
feat: 그룹 스터디 썸네일 input storybook 작성
aken-you Sep 29, 2025
3d81e87
feat: logout 아이콘 추가
aken-you Sep 29, 2025
4abec73
style: 네이밍 변경
Mimiminz Oct 2, 2025
72fd2fc
Merge pull request #152 from code-zero-to-one/feat/group-study-thumbn…
Mimiminz Oct 2, 2025
83c4686
Merge branch 'develop' of https://github.com/code-zero-to-one/study-p…
Mimiminz Oct 2, 2025
ac6abe2
refactor: admin과 service 그룹화
aken-you Oct 2, 2025
dec9942
style: 네이밍 변경
Mimiminz Oct 2, 2025
da6e68d
feat: step1 UI 수정
Mimiminz Oct 2, 2025
f17bc71
feat: 스터디 개설 api에 맞게 업데이트
Mimiminz Oct 2, 2025
80b6477
fix: next 조건 수정
Mimiminz Oct 2, 2025
06d3ac4
style: 중간 업데이트용 커밋
Mimiminz Oct 2, 2025
12bb848
feat:승인반려 ui 적용
yeun38 Oct 3, 2025
5d4d446
feat: 어드민 페이지의 테이블 구현
aken-you Oct 3, 2025
aa1cb88
feat: 테이블의 날짜 데이터를 yyyy-mm-dd로 표시
aken-you Oct 3, 2025
550b162
Merge pull request #153 from code-zero-to-one/feat/admin-page-user-list
aken-you Oct 4, 2025
3d5de1c
refactor: AdminPage에서 멤버 테이블을 컴포넌트로 분리
aken-you Oct 5, 2025
1bb4614
feat: 온도 불러오기 타입 수정
yeun38 Oct 5, 2025
e096cf4
Merge branch 'feat/QNRR-225-study-list' into feat/QNRR-488-approve-deny
yeun38 Oct 5, 2025
e1a3da0
Merge branch 'develop' into feat/QNRR-488-approve-deny
yeun38 Oct 5, 2025
da8616f
fix: develop페이지와 싱크 맞춤
yeun38 Oct 5, 2025
276a878
feat: 사용자 목록 조회 API 설정
aken-you Oct 6, 2025
b834703
feat: 페이지네이션 컴포넌트 생성
aken-you Oct 6, 2025
470f8ec
feat: 권한, 계정상태 필터 추가
aken-you Oct 6, 2025
e30989a
refactor: 총 사용자 UI를 MemberListTable 컴포넌트로 이동
aken-you Oct 6, 2025
012ddbe
feat: 검색어 필터 추가
aken-you Oct 6, 2025
007a24b
feat: 검색어을 지우는 버튼 추가
aken-you Oct 6, 2025
e4cf316
style: 이름 검색어 input placeholder 수정
aken-you Oct 6, 2025
f10ae13
feat: 타입 제외한 api 연결 완료
yeun38 Oct 7, 2025
6a597ec
feat: 신청자 목록 조회 및 승인/거절 api 연결
yeun38 Oct 7, 2025
7f9759b
fix: 루트에 있는 not-found 페이지 삭제
aken-you Oct 8, 2025
a25c341
Merge pull request #155 from code-zero-to-one/fix/build-404-page
aken-you Oct 9, 2025
6890717
fix: 변경된 타입에 맞게 step1 수정
Mimiminz Oct 9, 2025
0e520f4
Merge pull request #154 from code-zero-to-one/feat/qnrr-556-user-list…
aken-you Oct 9, 2025
4753910
feat: 그룹스터디 신청 모달
aken-you Oct 9, 2025
4c5c243
feat: 관리자 페이지에서 사용자 정보 변경 UI 생성
aken-you Oct 9, 2025
8cb73cb
refactor: 권한과 상태를 const 폴더로 이동
aken-you Oct 9, 2025
dac20b0
style: MemberListFilter 컴포넌트의 최상위 요소로 div 추가
aken-you Oct 9, 2025
d7b5293
feat: 사용자 계정 상태 변경
aken-you Oct 9, 2025
1c9b290
feat: 사용자 권한 변경
aken-you Oct 9, 2025
aff7e96
refactor: 선택한 행 배경색 변경
aken-you Oct 9, 2025
71e2883
refactor: 권한과 상태 배열 상수로 관리
aken-you Oct 9, 2025
f451827
refactor: 멘토일 경우 옆에 check 아이콘으로 표시
aken-you Oct 9, 2025
af4764d
feat: step2 스키마 수정
Mimiminz Oct 9, 2025
100001a
refactor: 어드민 layout 수정
aken-you Oct 9, 2025
bf7c79c
feat: TabMenu 컴포넌트 생성
aken-you Oct 9, 2025
8127979
refactor: 어드민 사이드바 아이콘 수정
aken-you Oct 9, 2025
c2a7dc9
refactor: AdminPage에서 사용하지 않은 코드 삭제
aken-you Oct 9, 2025
140106f
feat: 어드민 사용자 상세 정보 페이지 layout 설정
aken-you Oct 9, 2025
8e0ca1d
feat: 사용자 상세 정보 계정 이력 페이지 구현
aken-you Oct 9, 2025
6600054
feat: 어드민 권한을 가지고 있은 사람이 어드민 페이지에 접속하면, 홈으로 리다이렉션
aken-you Oct 9, 2025
4f56de9
feat: 사용자 상세 정보 프로필 페이지 구현
aken-you Oct 9, 2025
479d43e
feat: 성실온도 페이지와 study 페이지 컴포넌트 추가
aken-you Oct 9, 2025
df23861
style: RecentLoginHistory 컴포넌트 주석 처리
aken-you Oct 9, 2025
bccf391
feat:스터디 목록 타입 추가 및 api 수정 사항 반영
yeun38 Oct 10, 2025
65a2408
feat: step3 스키마 수정
Mimiminz Oct 10, 2025
f06f47a
feat: 스터디 개설 api 추가
Mimiminz Oct 10, 2025
96f9f02
Merge branch 'develop' into feat/group-study-start-modal
Mimiminz Oct 10, 2025
2df707f
feat: 그룹스터디 신청 api
aken-you Oct 10, 2025
01a001d
refactor: 사용하지 않는 컴포넌트 제거
aken-you Oct 10, 2025
b4b3cc0
style: 콘솔 제거
aken-you Oct 10, 2025
3799f5a
fix: 타입 미변경으로 인한 빌드에러 수정
Mimiminz Oct 10, 2025
4edcf59
style: 주석 변경
Mimiminz Oct 10, 2025
7c1ef2d
feat: 신청 대기중인 목록조회 api 수정
yeun38 Oct 10, 2025
4c0f81f
Merge pull request #161 from code-zero-to-one/feat/QNRR-488-approve-deny
yeun38 Oct 10, 2025
d8509d0
Merge pull request #157 from code-zero-to-one/feat/qnrr-554-change-me…
aken-you Oct 10, 2025
0e867e8
feat: 어드민 사이드바 사용자 프로필 정보 api 연결
aken-you Oct 10, 2025
00cd6ed
Merge branch 'develop' into feat/qnrr-559-account-history
aken-you Oct 10, 2025
891a712
style: RecentLoginHistory 컴포넌트 주석 삭제
aken-you Oct 10, 2025
80f6646
Merge pull request #158 from code-zero-to-one/feat/qnrr-559-account-h…
aken-you Oct 10, 2025
afdc80e
feat: 썸네일 업로드 로직 추가
Mimiminz Oct 10, 2025
59fed83
fix: global.css 적용 안되던 문제 수정
Mimiminz Oct 10, 2025
3e41a21
feat: checkout 외의 영역을 클릭할 경우, 상세 정보로 이동
aken-you Oct 10, 2025
e5c44a9
feat: 성실온도 내역 페이지 생성
aken-you Oct 10, 2025
bd9216e
Merge branch 'develop' into feat/qnrr-500-apply-group-study
aken-you Oct 10, 2025
71008dc
feat: 성실온도 preset 적용
aken-you Oct 10, 2025
b577abd
fix: memberId 변환 제거
aken-you Oct 10, 2025
442e922
fix: 이미지 업로드 로직 수정
Mimiminz Oct 10, 2025
3a24bf5
Merge branch 'feat/group-study-start-modal' of https://github.com/cod…
Mimiminz Oct 10, 2025
f493086
Merge branch 'develop' into feat/group-study-start-modal
Mimiminz Oct 10, 2025
650193c
fix: 컨플릭트로 인한 네이밍 수정
Mimiminz Oct 10, 2025
7af6373
Merge pull request #162 from code-zero-to-one/feat/move-admin-detail
aken-you Oct 11, 2025
d0da49b
fix: global css 변경사항 주석
Mimiminz Oct 11, 2025
6e9bcce
Merge pull request #159 from code-zero-to-one/feat/group-study-start-…
Mimiminz Oct 11, 2025
112c0b3
fix: 주석 다시 처리
Mimiminz Oct 11, 2025
7eb297c
Merge pull request #164 from code-zero-to-one/feat/group-study-start-…
Mimiminz Oct 11, 2025
6f5e460
Merge pull request #163 from code-zero-to-one/feat/qnrr-561-sincerity…
aken-you Oct 11, 2025
00100d6
Merge branch 'develop' into feat/qnrr-500-apply-group-study
aken-you Oct 11, 2025
c2ed466
style: GroupStudyListRequest 주석 추가
aken-you Oct 11, 2025
80f3775
refactor: 테스트 코드 주석 제거
aken-you Oct 11, 2025
4861860
style: 불필요한 공백 제거
aken-you Oct 11, 2025
eaf2fa1
Merge pull request #160 from code-zero-to-one/feat/qnrr-500-apply-gro…
aken-you Oct 11, 2025
87261b2
feat: 어드민 페이지로 이동하는 드롭다운 옵션 추가
aken-you Oct 11, 2025
9d5bf42
Merge pull request #165 from code-zero-to-one/feat/go-to-admin-page
aken-you Oct 11, 2025
4144e7b
feat: 어드민 페이지에서 로그아웃 버튼이 메인 페이지로 이동하는 버튼으로 변경
aken-you Oct 11, 2025
1334c3e
Merge pull request #166 from code-zero-to-one/refactor/go-to-main-pag…
aken-you Oct 11, 2025
231af4a
style: 헤더의 스타일 둘러보기와 팀소개 주석처리
aken-you Oct 11, 2025
f4a0df1
Merge pull request #167 from code-zero-to-one/style/header
aken-you Oct 11, 2025
a0239ec
refactor: color가 gray인 Badge에서 border 삭제
aken-you Oct 11, 2025
a7b0d5d
Merge pull request #168 from code-zero-to-one/refactor/gray-badge
aken-you Oct 11, 2025
0d671dd
feat: loginMostRecentlyAt가 null이면 -로 표시
aken-you Oct 11, 2025
fc69856
Merge pull request #169 from code-zero-to-one/feat/loginMostRecentlyA…
aken-you Oct 11, 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
189 changes: 189 additions & 0 deletions app/(admin)/admin/detail/[id]/account-history/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import {
dehydrate,
HydrationBoundary,
QueryClient,
} from '@tanstack/react-query';
import { ArrowRightIcon } from 'lucide-react';
import { getAccountHistoriesInServer } from '@/features/admin/api/account-history.server';
import { GetAccountHistoriesResponse } from '@/features/admin/api/types';
import { formatHHMM, formatYYYYMMDD } from '@/shared/lib/time';
import Badge from '@/shared/ui/badge';

export default async function AccountHistoryPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const queryClient = new QueryClient();
const { id: memberId } = await params;

// 서버 side에서 첫 페이지 데이터 미리 가져오기
await queryClient.prefetchQuery({
queryKey: ['accountHistory', memberId],
queryFn: () => getAccountHistoriesInServer({ memberId: Number(memberId) }),
});

const data: GetAccountHistoriesResponse = await queryClient.getQueryData([
'accountHistory',
memberId,
]);

return (
<HydrationBoundary state={dehydrate(queryClient)}>
<div className="flex flex-col gap-300">
<div className="border-border-default rounded-100 flex w-full flex-col gap-200 border p-200">
<div className="flex items-center gap-150">
<span className="font-designer-16b text-text-default w-[73px]">
계정 생성일
</span>
<div className="font-designer-14r text-text-subtle">
{formatYYYYMMDD(data.joinedAt)}
</div>
</div>

<div className="flex items-center gap-150">
<span className="font-designer-16b text-text-default w-[73px]">
최근 로그인
</span>
<div className="font-designer-14r text-text-subtle">
{data.loginMostRecentlyAt
? formatYYYYMMDD(data.loginMostRecentlyAt)
: '기록 없음'}
</div>
</div>

<div className="flex items-center gap-150">
<span className="font-designer-16b text-text-default w-[73px]">
권한
</span>
<div className="font-designer-14r text-text-subtle">일반</div>
</div>

<div className="flex items-center gap-150">
<span className="font-designer-16b text-text-default w-[73px]">
계정 상태
</span>

<Badge color="green">활성</Badge>
</div>
</div>

<RecentLoginHistory loginHists={data.loginHists} />
<RecentRoleChangeHistory roleChangeHists={data.roleChangeHists} />
<RecentStatusChangeHistory
memberStatusChangeHists={data.memberStatusChangeHists}
/>
</div>
</HydrationBoundary>
);
}

function RecentLoginHistory({
loginHists,
}: Pick<GetAccountHistoriesResponse, 'loginHists'>) {
return (
<div className="border-border-default rounded-100 flex w-full flex-col gap-150 border p-200">
<h3 className="font-designer-16b text-text-default">최근 로그인 기록</h3>

<ul>
{loginHists.map((hist) => (
<li
key={hist}
className="font-designer-14r text-text-subtle border-b-border-subtle flex items-center gap-100 border-b py-100"
>
<span>{formatYYYYMMDD(hist)}</span>
<span>{formatHHMM(hist)}</span>
</li>
))}
</ul>
</div>
);
}

function RecentRoleChangeHistory({
roleChangeHists,
}: Pick<GetAccountHistoriesResponse, 'roleChangeHists'>) {
return (
<div className="border-border-default rounded-100 flex w-full flex-col gap-150 border p-200">
<h3 className="font-designer-16b text-text-default">권한 변경 이력</h3>

{roleChangeHists.length > 0 ? (
<ul>
{roleChangeHists.map((hist) => (
<li
key={hist.changedAt}
className="font-designer-14r text-text-subtle flex justify-between py-100"
>
<div className="flex items-center gap-100">
<span>{formatYYYYMMDD(hist.changedAt)}</span>
<span>{formatHHMM(hist.changedAt)}</span>
</div>

<div className="flex items-center gap-200">
<span>{hist.from}</span>

<ArrowRightIcon width={20} height={20} />

<span>{hist.to}</span>
</div>
</li>
))}
</ul>
) : (
<div className="font-designer-14r text-text-subtle flex justify-center">
변경 이력이 없습니다.
</div>
)}
</div>
);
}

function RecentStatusChangeHistory({
memberStatusChangeHists,
}: Pick<GetAccountHistoriesResponse, 'memberStatusChangeHists'>) {
return (
<div className="border-border-default rounded-100 flex w-full flex-col gap-150 border p-200">
<h3 className="font-designer-16b text-text-default">
계정 상태 변경 이력
</h3>

{memberStatusChangeHists.length > 0 ? (
<ul>
{memberStatusChangeHists.map((hist) => (
<li
key={hist.changedAt}
className="font-designer-14r text-text-subtle flex justify-between py-100"
>
<div className="flex items-center gap-100">
<span>{formatYYYYMMDD(hist.changedAt)}</span>
<span>{formatHHMM(hist.changedAt)}</span>
</div>

<div className="flex items-center gap-200">
<Badge
color={hist.from === '활성' ? 'green' : 'gray'}
shape="rectangle"
>
{hist.from}
</Badge>

<ArrowRightIcon width={20} height={20} />

<Badge
color={hist.to === '활성' ? 'green' : 'gray'}
shape="rectangle"
>
{hist.to}
</Badge>
</div>
</li>
))}
</ul>
) : (
<div className="font-designer-14r text-text-subtle flex justify-center">
변경 이력이 없습니다.
</div>
)}
</div>
);
}
30 changes: 30 additions & 0 deletions app/(admin)/admin/detail/[id]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { ArrowLeftIcon } from 'lucide-react';
import Link from 'next/link';
import AdminDetailSideBar from '@/widgets/admin/ui/admin-detail-side-bar';

export default async function AdminDetailLayout({
children,
params,
}: {
children: React.ReactNode;
params: Promise<{ id: string }>;
}) {
const { id: memberId } = await params;

return (
<div>
<header className="mb-300 flex items-center gap-200">
<Link href="/admin">
<ArrowLeftIcon />
</Link>
<h1 className="font-bold-h4">사용자 상세 정보</h1>
</header>

<div className="flex gap-200">
<AdminDetailSideBar memberId={memberId} />

<div className="flex-1">{children}</div>
</div>
</div>
);
}
5 changes: 5 additions & 0 deletions app/(admin)/admin/detail/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { notFound } from 'next/navigation';

export default function AdminDetailByIdPage() {
notFound(); // /admin/detail/[id] 경로 404 처리
}
140 changes: 140 additions & 0 deletions app/(admin)/admin/detail/[id]/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { QueryClient } from '@tanstack/react-query';
import { getUserProfileInServer } from '@/entities/user/api/get-user-profile.server';
import { GetUserProfileResponse } from '@/entities/user/api/types';
import ProfileInfoCard from '@/entities/user/ui/profile-info-card';
import CakeIcon from '@/features/my-page/ui/icon/cake.svg';
import GithubIcon from '@/features/my-page/ui/icon/github-logo.svg';
import GlobeIcon from '@/features/my-page/ui/icon/globe-simple.svg';
import PhoneIcon from '@/features/my-page/ui/icon/phone.svg';
import { getSincerityPresetByLevelName } from '@/shared/config/sincerity-temp-presets';
import UserAvatar from '@/shared/ui/avatar';
import Badge from '@/shared/ui/badge';

// todo: UserProfileModal과 거의 유사하여 나중에 리팩토링하기
export default async function ProfilePage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const queryClient = new QueryClient();
const { id: memberId } = await params;

// 서버 side에서 첫 페이지 데이터 미리 가져오기
await queryClient.prefetchQuery({
queryKey: ['userProfile', memberId],
queryFn: () => getUserProfileInServer(Number(memberId)),
});

const profile: GetUserProfileResponse = await queryClient.getQueryData([
'userProfile',
memberId,
]);

const temperPreset = getSincerityPresetByLevelName(
profile.sincerityTemp.levelName,
);

return (
<div className="border-border-default rounded-100 flex flex-col gap-400 border p-400">
<div className="flex flex-row gap-300 px-200">
<UserAvatar
image={
profile.memberProfile.profileImage?.resizedImages[0].resizedImageUrl
}
size={80}
/>

<div>
<div className="flex flex-wrap gap-75 pb-75">
{profile.memberProfile.mbti && (
<Badge color="orange">{profile.memberProfile.mbti}</Badge>
)}
{profile.memberProfile.interests.slice(0, 4).map((interest) => (
<Badge key={interest.id} color="purple">
{interest.name}
</Badge>
))}
</div>

<div className="flex items-center justify-start">
<div className="font-designer-28b pb-50">
{profile.memberProfile.memberName}
</div>

<span
className="bg-border-default mx-150 block h-[12px] w-[1px]"
aria-hidden="true"
/>

<div className="flex items-center">
<temperPreset.Icon className="h-400 w-400" />
<span
className={`${temperPreset.textClass} font-designer-14b pl-[2px]`}
>
{profile.sincerityTemp.temperature.toFixed(1)} ℃
</span>
</div>
</div>

<div className="font-designer-15m pb-300">
{profile.memberProfile.simpleIntroduction}
</div>

<div className="grid grid-cols-2 gap-x-250 gap-y-100">
<Field
icon={<CakeIcon />}
value={profile.memberProfile.birthDate}
/>
<Field
icon={<GithubIcon />}
value={profile.memberProfile.githubLink?.url}
/>
<Field icon={<PhoneIcon />} value={profile.memberProfile.tel} />
<Field
icon={<GlobeIcon />}
value={profile.memberProfile.blogOrSnsLink?.url}
/>
</div>
</div>
</div>

<div className="flex flex-col gap-200">
<ProfileInfoCard
title="선호하는 스터디 주제"
content={profile.memberInfo.preferredStudySubject?.name}
/>
<ProfileInfoCard
title="기술 스택"
content={profile.memberInfo.techStacks
.map((t) => t.techStackName)
.join(', ')}
/>
<ProfileInfoCard
title="가능 시간대"
content={profile.memberInfo.availableStudyTimes
.map((t) => t.label)
.join(', ')}
/>
<ProfileInfoCard
title="자기소개"
content={profile.memberInfo.selfIntroduction}
/>
<ProfileInfoCard
title="공부 주제 및 계획"
content={profile.memberInfo.studyPlan}
/>
</div>
</div>
);
}

function Field({ icon, value }: { icon: React.ReactNode; value?: string }) {
return (
<div className="flex items-center gap-100">
{icon}
<span className="font-designer-14r text-text-subtle leading-none">
{value ?? ''}
</span>
</div>
);
}
Loading