Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
2bec5a9
πŸ“ docs: 이전 λ‚΄μš© μ‚­μ œ
HaeJungg Nov 4, 2024
c9cb33a
✨ feat: 리뷰 점수 및 κ·Έλž˜ν”„ μΆ”κ°€
HaeJungg Nov 4, 2024
877d112
Merge branch 'develop' into Feat/CR-74/DetailPage
HaeJungg Nov 4, 2024
760da18
✨ feat: env μ„€μ • μΆ”κ°€
HaeJungg Nov 4, 2024
32b980e
πŸ› fix: νƒ€μž… μˆ˜μ •
HaeJungg Nov 4, 2024
ae5b2e3
πŸ› fix: 데이터 이름 μˆ˜μ •
HaeJungg Nov 4, 2024
d68a3ca
✨ feat: λͺ© api μΆ”κ°€
HaeJungg Nov 4, 2024
b856831
πŸ”₯ chore: μ‚¬μš©ν•˜μ§€μ•ŠλŠ” λ ˆμ΄μ•„μ›ƒ μ‚­μ œ
HaeJungg Nov 4, 2024
2a7b9c5
πŸ› fix: 데이터에 맞게 μˆ˜μ •, λΆ„κΈ°μ²˜λ¦¬
HaeJungg Nov 4, 2024
c8f946a
✨ feat: μΊλŸ¬μ…€ μ§μ ‘κ΅¬ν˜„
HaeJungg Nov 5, 2024
2c441a1
πŸ› fix: eslint error
HaeJungg Nov 5, 2024
32d0ba6
✨ feat: λ””ν…ŒμΌ νŽ˜μ΄μ§€ 쑰립
HaeJungg Nov 5, 2024
df9a682
πŸ› fix: λ²„νŠΌ type μˆ˜μ •
HaeJungg Nov 5, 2024
9c75c5f
✨ feat: cn ν›… μΆ”κ°€
HaeJungg Nov 5, 2024
9c42273
πŸ’„ design: ui μˆ˜μ •
HaeJungg Nov 5, 2024
2878e03
✨ feat: 약속 λ””ν…ŒμΌ λͺ¨λ‹¬ μ—°κ²°
HaeJungg Nov 5, 2024
c9976ef
πŸ’„ design: ν”„λ‘œν•„ μ»΄ν¬λ„ŒνŠΈλ‘œ ꡐ체
HaeJungg Nov 5, 2024
01257f3
✨ feat: 크루 리뷰뢀뢄 쑰립
HaeJungg Nov 5, 2024
396277b
Merge branch 'develop' into Feat/CR-74/DetailPage
HaeJungg Nov 5, 2024
6c55ee4
πŸ› fix: λ ˆμ΄μ•„μ›ƒ md λ°˜μ‘ν˜• μ•ˆλ˜λŠ” 문제 μˆ˜μ •
HaeJungg Nov 5, 2024
2328329
🚚 chore: 파일 μœ„μΉ˜ λ³€κ²½
HaeJungg Nov 5, 2024
631a9a1
πŸ’„ design: λ ˆμ΄μ•„μ›ƒμ— 따라 μˆ˜μ •
HaeJungg Nov 5, 2024
c2b84ef
πŸ’„ design: λ ˆμ΄μ•„μ›ƒμ— 따라 μˆ˜μ •
HaeJungg Nov 5, 2024
2b49953
πŸ’„ design: 헀더 λ°˜μ‘ν˜• λ””μžμΈ μˆ˜μ •
HaeJungg Nov 5, 2024
242b79f
πŸ’„ design: my 간격 μΆ”κ°€
HaeJungg Nov 5, 2024
72ec8d1
πŸ’„ design: mx 간격 μΆ”κ°€
HaeJungg Nov 5, 2024
49834ee
πŸ› fix: response값에 λ”°λ₯Έ νƒ€μž…, κ°’λ³€κ²½
HaeJungg Nov 5, 2024
bfd1939
πŸ› fix: response값에 λ”°λ₯Έ νƒ€μž…, κ°’λ³€κ²½
HaeJungg Nov 5, 2024
d482519
πŸ› fix: νƒ€μž…μ—λŸ¬ μˆ˜μ •
HaeJungg Nov 5, 2024
4a0d17c
✨ feat: notification μΆ”κ°€
HaeJungg Nov 5, 2024
c700910
✨ feat: 확인 μ‚­μ œ λͺ¨λ‹¬ μΆ”κ°€
HaeJungg Nov 5, 2024
50bf5d4
Merge branch 'develop' into Feat/CR-74/DetailPage
HaeJungg Nov 5, 2024
ee9d9db
πŸ’„ design: max 1200으둜 μˆ˜μ •, container μ‚­μ œ
HaeJungg Nov 5, 2024
a343c0f
🎨 style: eslint changed
HaeJungg Nov 5, 2024
5e97bc0
Merge branch 'develop' into Feat/CR-74/DetailPage
HaeJungg Nov 5, 2024
9657c0a
πŸ› fix: eslint changed
HaeJungg Nov 5, 2024
5330725
Merge branch 'develop' into Feat/CR-74/DetailPage
HaeJungg Nov 5, 2024
4123bdc
πŸ”₯ fix: μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” ν…ŒμŠ€νŠΈ μ£Όμ„μ²˜λ¦¬
HaeJungg Nov 6, 2024
9ecb083
✏️ fix: νŽ˜μ΄μ§€λ„€μ΄μ…˜μœΌλ‘œ λ³€κ²½ν•˜λ©΄μ„œ νƒ€μž… λ³€κ²½
HaeJungg Nov 6, 2024
8576d6a
πŸ“ docs: λͺ©λ°μ΄ν„° rate λ³€κ²½
HaeJungg Nov 6, 2024
26df4ab
πŸ’„ design: νŽ˜μ΄μ§€λ„€μ΄μ…˜ λ””μžμΈ λ³€κ²½
HaeJungg Nov 6, 2024
5f6785d
🎨 style: eslint changed
HaeJungg Nov 6, 2024
3af40d7
πŸ› fix: ν”„λ‘œν•„μ— 이미지 μ „λ‹¬μ•ˆλ˜λŠ” 문제 μˆ˜μ • μ•ˆμ“°λŠ” import 제거
HaeJungg Nov 6, 2024
8daeebd
✨ feat: rate λ³€κ²½
HaeJungg Nov 6, 2024
dcbc5b7
πŸ› fix: ν¬λ£¨μΉ΄λ“œ κ²½λ‘œμˆ˜μ •
HaeJungg Nov 6, 2024
b6b436d
✨ feat: 크루 리뷰 데이터 λͺ© api νŽ˜μ΄μ§€λ„€μ΄μ…˜
HaeJungg Nov 6, 2024
5ad31af
✨ feat: 리뷰리슀트 νŽ˜μ΄μ§€λ„€μ΄μ…˜
HaeJungg Nov 6, 2024
91f4f42
πŸ§ͺ test: μŠ€ν† λ¦¬λΆ μΆ”κ°€
HaeJungg Nov 6, 2024
dc083a9
πŸ› fix: 파일 μœ„μΉ˜ λ³€κ²½, 넀이밍 λ³€κ²½
HaeJungg Nov 6, 2024
f15e233
πŸ“ docs: 데이터 일뢀 λ³€κ²½
HaeJungg Nov 6, 2024
5a45fd2
πŸ“ docs: 주석 μΆ”κ°€
HaeJungg Nov 6, 2024
9d8d75d
πŸ› fix: import λ³€κ²½
HaeJungg Nov 6, 2024
6a55030
✨ feat: λͺ© 데이터 가곡
HaeJungg Nov 6, 2024
53381de
πŸ’„ design: μŠ€νƒ€μΌ λ³€κ²½
HaeJungg Nov 6, 2024
20f4d78
✨ feat: 크루 리뷰 쑰립
HaeJungg Nov 6, 2024
b1eceba
πŸ› fix: ν”„λ‘œν•„λͺ¨μŒ 변경에 λ”°λ₯Έ νƒ€μž…, μ½”λ“œ μˆ˜μ •
HaeJungg Nov 6, 2024
ac65f03
πŸ› fix: lint μ—λŸ¬, λΉŒλ“œ μ—λŸ¬ μˆ˜μ •
HaeJungg Nov 6, 2024
c33e66a
πŸ› fix: lint μ—λŸ¬, λΉŒλ“œ μ—λŸ¬ μˆ˜μ •
HaeJungg Nov 6, 2024
0f1d615
πŸ› fix: lint μ—λŸ¬, λΉŒλ“œ μ—λŸ¬ μˆ˜μ •
HaeJungg Nov 6, 2024
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
33 changes: 33 additions & 0 deletions src/_apis/detail/get-crew-detail.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { fetchApi } from '@/src/utils/api';

type CrewMember = {
id: number;
nickname: string;
profileImageUrl?: string;
};

type CrewDetail = {
id: number;
title: string;
mainLocation: string;
subLocation: string;
participantCount: number;
totalCount: number;
isConfirmed: boolean;
imageUrl: string;
totalGatheringCount: number;
CrewMembers: CrewMember[];
isCaptain: boolean;
isCrew: boolean;
};

export async function getCrewDetail(): Promise<CrewDetail> {
const response = await fetchApi<CrewDetail>('/api/mock-api/detail?type=crewDetail', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

return response;
}
29 changes: 29 additions & 0 deletions src/_apis/detail/get-gathering-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { fetchApi } from '@/src/utils/api';

type GatheringList = {
id: number;
title: string;
dateTime: string;
location: string;
currentCount: number;
totalCount: number;
imageUrl: string;
isLiked: boolean;
};

export async function getGatheringList(): Promise<GatheringList[]> {
const response = await fetchApi<GatheringList[]>('/api/mock-api/detail?type=gatherings', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});

return response.map((item) => ({
...item,
dateTime: item.dateTime,
currentCount: item.currentCount,
totalCount: item.totalCount,
isLiked: item.isLiked ?? false,
}));
}
62 changes: 62 additions & 0 deletions src/_apis/detail/get-review-list.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { CrewReview } from '@/src/types/review';

export interface ReviewRateInfo {
totalRate: number;
averageRate: number;
ratingsData: Array<{ score: number; count: number }>;
}

export interface ReviewListData {
info: ReviewRateInfo;
data: CrewReview[];
totalItems: number;
totalPages: number;
currentPage: number;
}

export async function getReviewList(page: number, limit: number): Promise<ReviewListData> {
const response = await fetch(`/api/mock-api/detail?type=reviews`);
const reviewData: CrewReview[] = await response.json(); // 리뷰 데이터λ₯Ό λ°°μ—΄λ‘œ λ°”λ‘œ λ°›μŒ

// 데이터가 λΉ„μ–΄ μžˆλŠ” 경우 κΈ°λ³Έκ°’ λ°˜ν™˜
if (!reviewData || reviewData.length === 0) {
return {
info: {
totalRate: 0,
averageRate: 0,
ratingsData: [5, 4, 3, 2, 1].map((score) => ({ score, count: 0 })),
},
data: [],
totalItems: 0,
totalPages: 0,
currentPage: page,
};
}

// νŽ˜μ΄μ§€λ„€μ΄μ…˜ 적용
const startIndex = (page - 1) * limit;
const paginatedData = reviewData.slice(startIndex, startIndex + limit);

// 톡계 정보 생성
const totalRate = reviewData.reduce((sum, review) => sum + review.rate, 0);
const averageRate = reviewData.length ? totalRate / reviewData.length : 0;

const ratingsData = [5, 4, 3, 2, 1].map((score) => ({
score,
count: reviewData.filter((review) => review.rate === score).length,
}));

const info: ReviewRateInfo = {
totalRate,
averageRate,
ratingsData,
};

return {
info,
data: paginatedData,
totalItems: reviewData.length,
totalPages: Math.ceil(reviewData.length / limit),
currentPage: page,
};
}
2 changes: 1 addition & 1 deletion src/app/(crew)/api-test/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useQuery } from '@tanstack/react-query';
import { getUsersQuery } from '@/src/_queries/useGetUserQuery';
import { ApiError } from '@/src/utils/api';

// react-query μ˜ˆμ‹œ
// FIX: react-query둜 μž„μ‹œλ‘œ μž‘μ„±λœ μ½”λ“œμž…λ‹ˆλ‹€. μΆ”ν›„ μ‚­μ œ

export default function TestPage() {
const { data: users, error, isLoading, isError } = useQuery(getUsersQuery());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React, { useState } from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import ClientProvider from '@/src/components/client-provider';
import { CrewReview } from '@/src/types/review';
import { CrewReviewData } from '@/src/mock/review-data';
import CrewReviewList from './crew-review-list';

const meta: Meta<typeof CrewReviewList> = {
title: 'components/CrewReviewList',
component: CrewReviewList,
parameters: {
layout: 'fulled',
nextjs: {
appDirectory: true,
},
},
tags: ['autodocs'],
decorators: [
(Story) => (
<ClientProvider>
<Story />
</ClientProvider>
),
],
} satisfies Meta<typeof CrewReviewList>;

export default meta;
type Story = StoryObj<typeof CrewReviewList>;

function RenderReviewPagination() {
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 6;

// νŽ˜μ΄μ§€μ— λ§žλŠ” 리뷰 데이터 κ°€μ Έμ˜€κΈ°
const totalItems = CrewReviewData.data.length;
const totalPages = Math.ceil(totalItems / itemsPerPage);

const currentReviews = CrewReviewData.data.slice(
(currentPage - 1) * itemsPerPage,
currentPage * itemsPerPage,
);

return (
<CrewReviewList
reviews={currentReviews as CrewReview[]}
totalPages={totalPages}
currentPage={currentPage}
onPageChange={setCurrentPage}
/>
);
}

export const Default: Story = {
render: () => <RenderReviewPagination />,
};
64 changes: 64 additions & 0 deletions src/app/(crew)/crew/detail/[id]/_components/crew-review-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use client';

import React from 'react';
import { Pagination } from '@mantine/core';
import ReviewCard from '@/src/components/common/review-list/review-card';
import { CrewReview } from '@/src/types/review';

interface CrewReviewListProps {
reviews: CrewReview[];
totalPages: number;
currentPage: number;
onPageChange: (page: number) => void;
}

export default function CrewReviewList({
reviews,
totalPages,
currentPage,
onPageChange,
}: CrewReviewListProps) {
return (
<div className="flex flex-col justify-between p-6">
<div className="mb-6 grid flex-grow gap-4">
{reviews.map((review) => (
<ReviewCard
key={review.id}
rate={review.rate}
comment={review.comment}
createdAt={review.createdAt}
crewId={review.crewId}
reviewer={review.reviewer}
/>
))}
</div>
<div className="mt-6 flex justify-center">
<Pagination
total={totalPages}
value={currentPage}
onChange={onPageChange}
styles={{
control: {
border: 'none',
backgroundColor: 'transparent',
'&[data-active]': {
backgroundColor: 'transparent',
fontWeight: 'var(--pagination-active-font-weight)',
color: 'var(--pagination-active-color)',
boxShadow: 'none',
},
'&:hover': {
backgroundColor: 'transparent',
},
},
root: {
'--pagination-active-color': '#3388FF',
'--pagination-active-font-weight': 'bold',
},
}}
size="sm"
/>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import { Meta, StoryFn } from '@storybook/react';
import RatingDisplay, { ReviewRateInfo } from './rating-display';

export default {
title: 'Components/RatingDisplay',
component: RatingDisplay,
tags: ['autodocs'],
argTypes: {
totalRate: { control: 'number', description: '총 평가 개수' },
averageRate: { control: 'number', description: '평균 평점' },
ratingsData: { control: 'object', description: '각 μ μˆ˜λ³„ 평가 개수' },
},
} as Meta<typeof RatingDisplay>;

interface RatingDisplayStoryProps {
totalRate: number;
averageRate: number;
ratingsData: { score: number; count: number }[];
}

// Template을 ν•¨μˆ˜ μ„ μ–ΈμœΌλ‘œ λ³€κ²½ν•˜κ³  StoryFn νƒ€μž…μ„ μ‚¬μš©
const Template: StoryFn<RatingDisplayStoryProps> = function Template(args) {
const { totalRate, averageRate, ratingsData } = args;
const reviewRateInfo: ReviewRateInfo = { totalRate, averageRate, ratingsData };
return <RatingDisplay reviewRateInfo={reviewRateInfo} />;
};

// μŠ€ν† λ¦¬ μ •μ˜
export const Default = Template.bind({});
Default.args = {
totalRate: 24,
averageRate: 3.5,
ratingsData: [
{ score: 5, count: 6 },
{ score: 4, count: 9 },
{ score: 3, count: 4 },
{ score: 2, count: 3 },
{ score: 1, count: 2 },
],
};

export const HighRating = Template.bind({});
HighRating.args = {
totalRate: 15,
averageRate: 4.7,
ratingsData: [
{ score: 5, count: 10 },
{ score: 4, count: 3 },
{ score: 3, count: 1 },
{ score: 2, count: 1 },
{ score: 1, count: 0 },
],
};

export const LowRating = Template.bind({});
LowRating.args = {
totalRate: 20,
averageRate: 1.8,
ratingsData: [
{ score: 5, count: 1 },
{ score: 4, count: 1 },
{ score: 3, count: 2 },
{ score: 2, count: 5 },
{ score: 1, count: 11 },
],
};
Loading