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
4 changes: 2 additions & 2 deletions app/(service)/(my)/my-study/entry-list/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import EntryList from '@/features/my-page/ui/entry-list';
import Image from 'next/image';
import ApplicantList from '@/features/my-page/ui/applicant-list';

export default function EntryPage() {
return (
Expand All @@ -14,7 +14,7 @@ export default function EntryPage() {
<div className="flex-1 text-center">새로운 신청자 확인하기</div>
</div>

<EntryList />
<ApplicantList />
</div>
);
}
25 changes: 23 additions & 2 deletions app/(service)/(nav)/study/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
export default function StudyPage() {
return <div>Study Page</div>;
import {
HydrationBoundary,
dehydrate,
QueryClient,
} from '@tanstack/react-query';

import { prefetchGroupStudyDetail } from '@/features/study/group/model/use-study-query';

import StudyDetailPage from '@/features/study/group/ui/group-study-detail-page';

export default async function Page({ params }: { params: { id: string } }) {
const id = Number(params.id);

const qc = new QueryClient();

// 서버에서 미리 패치 (API 호출이 서버에서 실행됨)
await prefetchGroupStudyDetail(qc, id);

return (
<HydrationBoundary state={dehydrate(qc)}>
<StudyDetailPage id={id} />
</HydrationBoundary>
);
}
2 changes: 1 addition & 1 deletion app/(service)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function ServiceLayout({
{/** 1400 + 48*2 패딩 양옆 48로 임의적용 */}
<div className="m-auto flex w-[1496px] flex-1 flex-col items-center">
<Header />
<main className="w-full p-600">{children}</main>
<main className="w-full px-600">{children}</main>
</div>
</div>
</MainProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { axiosInstance } from '@/shared/tanstack-query/axios';
import { EntryListRequest, GroupStudyApplyListResponse } from './types';
import {
getApplicantsByStatusRequest,
getApplicantsByStatusResponse,
} from './type';

// 그룹 스터디 리스트 조회
export const getEntryList = async (
params: EntryListRequest,
): Promise<GroupStudyApplyListResponse> => {
// 상태별 스터디 신청자 조회
export const getApplicantsByStatus = async (
params: getApplicantsByStatusRequest,
): Promise<getApplicantsByStatusResponse> => {
const { page, size, status, groupStudyId } = params;

const { data } = await axiosInstance.get(
Expand Down
78 changes: 78 additions & 0 deletions src/features/application/api/type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
export type ApplyStatus = 'PENDING' | 'APPROVED' | 'REJECTED';

export type ApplyRole = 'LEADER' | 'PARTICIPANT';

export interface GroupStudyApply {
applyId: number;
applicantInfo: Applicant;
groupStudy: GroupStudy;
progressScore: number;
role: ApplyRole;
lastAccessed: string;
answer: string[];
status: ApplyStatus;
processedAt: string | null;
reason: string | null;
createdAt: string;
updatedAt: string;
}

export interface Applicant {
memberId: number;
memberName: string;
profileImage: ProfileImage;
sincerityTemp: SincerityTemp;
}

export interface ProfileImage {
imageId: number;
resizedImages: ResizedImage[];
}

export interface SincerityTemp {
temperature: number;
levelId: number;
levelName: '1단계' | '2단계' | '3단계' | '4단계'; // 추후 서버 기준에 맞게 확장 가능
}

export interface GroupStudy {
groupStudyId: number;
title: string;
description: string;
}

export interface ResizedImage {
resizedImageId: number;
resizedImageUrl: string;
imageSizeType: ImageSizeType;
}

export interface ImageSizeType {
imageTypeName: 'ORIGINAL' | 'SMALL' | 'MEDIUM' | 'LARGE';
width: number | null;
height: number | null;
}

// api DTO
export interface getApplicantsByStatusRequest {
groupStudyId: number;
page: number;
size: number;
status: ApplyStatus;
}

export interface getApplicantsByStatusResponse {
content: GroupStudyApply[];
page: number;
size: number;
totalElements: number;
totalPages: number;
hasNext: boolean;
hasPrevious: boolean;
}

export interface updateApplicantByStatusRequest {
applyId: number;
groupStudyId: number;
status?: ApplyStatus;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { axiosInstance } from '@/shared/tanstack-query/axios';
import { EntryStatusRequest } from './types';
import { updateApplicantByStatusRequest } from './type';

// 그룹 스터디 리스트 조회
export const updateEntryStatus = async (params: EntryStatusRequest) => {
// 스터디 신청자 상태 변경
export const updateApplicantByStatus = async (
params: updateApplicantByStatusRequest,
) => {
const { status, groupStudyId, applyId } = params;

const { data } = await axiosInstance.patch(
Expand Down
27 changes: 27 additions & 0 deletions src/features/application/model/use-applicant-qeury.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { getApplicantsByStatus } from '../api/get-applicants-by-status';
import { ApplyStatus } from '../api/type';

export const useApplicantsByStatusQuery = ({
groupStudyId,
status,
}: {
groupStudyId: number;
status: ApplyStatus;
}) => {
return useInfiniteQuery({
queryKey: ['entryList', groupStudyId, status],
queryFn: ({ pageParam = 0 }) =>
getApplicantsByStatus({
groupStudyId,
page: pageParam,
size: 20,
status,
}),
initialPageParam: 1,
getNextPageParam: (lastPage) =>
lastPage.hasNext ? lastPage.page + 1 : undefined,
maxPages: 3,
enabled: !!groupStudyId,
});
};
77 changes: 0 additions & 77 deletions src/features/my-page/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,80 +80,3 @@ export interface StudyDashboardResponse {
studyActivity: StudyActivity;
growthMetric: GrowthMetric;
}

export interface EntryListRequest {
groupStudyId: number;
page: number;
size: number;
status?: 'PENDING';
}

export interface EntryStatusRequest {
groupStudyId: number;
applyId: number;
status: 'APPROVED' | 'REJECTED';
}

export interface ImageSizeType {
imageTypeName: 'ORIGINAL' | 'SMALL' | 'MEDIUM' | 'LARGE';
width: number | null;
height: number | null;
}

export interface ResizedImage {
resizedImageId: number;
resizedImageUrl: string;
imageSizeType: ImageSizeType;
}

export interface ProfileImage {
imageId: number;
resizedImages: ResizedImage[];
}

export interface SincerityTemp {
temperature: number;
levelId: number;
levelName: '1단계' | '2단계' | '3단계' | '4단계'; // 추후 서버 기준에 맞게 확장 가능
}

export interface Applicant {
memberId: number;
memberName: string;
profileImage: ProfileImage;
sincerityTemp: SincerityTemp;
}

export interface GroupStudy {
groupStudyId: number;
title: string;
description: string;
}

export type ApplyRole = 'LEADER' | 'PARTICIPANT';
export type ApplyStatus = 'PENDING' | 'APPROVED' | 'REJECTED';

export interface GroupStudyApply {
applyId: number;
applicantInfo: Applicant;
groupStudy: GroupStudy;
progressScore: number;
role: ApplyRole;
lastAccessed: string;
answer: string[];
status: ApplyStatus;
processedAt: string | null;
reason: string | null;
createdAt: string;
updatedAt: string;
}

export interface GroupStudyApplyListResponse {
content: GroupStudyApply[];
page: number;
size: number;
totalElements: number;
totalPages: number;
hasNext: boolean;
hasPrevious: boolean;
}
24 changes: 24 additions & 0 deletions src/features/my-page/ui/applicant-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client';
import React from 'react';

import { useApplicantsByStatusQuery } from '@/features/application/model/use-applicant-qeury';
import ProfileCard from './profile-card';

export default function ApplicantList() {
const { data } = useApplicantsByStatusQuery({
groupStudyId: 1,
status: 'PENDING',
});

return (
<div className="flex w-full flex-col gap-500">
{data?.pages.map((page, pageIndex) => (
<React.Fragment key={pageIndex}>
{page.content.map((applicant) => (
<ProfileCard key={applicant.applyId} data={applicant} />
))}
</React.Fragment>
))}
</div>
);
}
44 changes: 0 additions & 44 deletions src/features/my-page/ui/entry-list.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import React from 'react';
import { getSincerityPresetByLevelName } from '@/shared/config/sincerity-temp-presets';
import { cn } from '@/shared/shadcn/lib/utils';
import Button from '@/shared/ui/button';
import { GroupStudyApply } from '../api/types';
import { GroupStudyApply } from '@/features/application/api/type';

export default function EntryCard(props: { data: GroupStudyApply }) {
export default function ProfileCard(props: { data: GroupStudyApply }) {
const { data: applicant } = props;
const temperPreset = getSincerityPresetByLevelName(
applicant.applicantInfo.sincerityTemp.levelName as string,
Expand All @@ -33,8 +33,6 @@ export default function EntryCard(props: { data: GroupStudyApply }) {
return `${diffWeek}주 전`;
};

const ApplicantStatus = () => {};

return (
<div className="rounded-100 flex w-full cursor-pointer flex-col gap-150 border border-[#E9EAEB] p-300">
<div className="flex gap-150">
Expand Down
2 changes: 1 addition & 1 deletion src/features/my-page/ui/profile-edit-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import MultiItemSelector from '@/shared/ui/form/multi-item-selector';
import { BaseInput, TextAreaInput } from '@/shared/ui/input';
import { Modal } from '@/shared/ui/modal';

import { DEFAULT_OPTIONS, MBTI_OPTIONS } from '../consts/my-page-const';
import { DEFAULT_OPTIONS, MBTI_OPTIONS } from '../const/my-page-const';
import {
ProfileFormSchema,
type ProfileFormInput,
Expand Down
26 changes: 26 additions & 0 deletions src/features/study/group/api/get-gruoup-study-detail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { axiosInstance } from '@/shared/tanstack-query/axios';
import {
GroupStudyDetailRequest,
GroupStudyDetailResponse,
} from './group-study-types';

// 그룹 스터디 리스트 조회
export const getGroupStudyDetail = async (
params: GroupStudyDetailRequest,
): Promise<GroupStudyDetailResponse> => {
const { groupStudyId } = params;

console.log('groupStudyId', groupStudyId);

try {
const { data } = await axiosInstance.get(`/group-studies/${groupStudyId}`);

if (data.statusCode !== 200) {
throw new Error('Failed to fetch group study list');
}

console.log('data', data);

return data.content;
} catch (err) {}
};
Loading
Loading