Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
746b462
feat review page 메뉴바
inji0212 Nov 4, 2024
599b829
feat review 메뉴바 ui 완성
inji0212 Nov 4, 2024
14521d5
feat 리뷰페이지 리뷰카드 제작
inji0212 Nov 5, 2024
7a33ea1
feat 임시 페이지네이션 및 디자인 (디자인 변경으로 인한)
inji0212 Nov 6, 2024
b65d599
Merge branch 'dev' into feat/reviewpage
inji0212 Nov 6, 2024
913330c
feat 1차 api연동( 페이지네이션 , sort x)
inji0212 Nov 6, 2024
12164c1
Merge branch 'dev' of https://github.com/Manchui/Frontend into feat/r…
inji0212 Nov 6, 2024
8666932
feat api 필터 제외 연동
inji0212 Nov 6, 2024
f47668d
feat 리뷰 필터 기능 완료, 카드 링크 이동 완료
inji0212 Nov 6, 2024
38d7f3a
fix 불필요한 파일 및 코드 정리
inji0212 Nov 6, 2024
74f958e
Delete pagination에러
inji0212 Nov 6, 2024
e2d7a87
Merge branch 'dev' of https://github.com/Manchui/Frontend into feat/r…
inji0212 Nov 7, 2024
033349e
fix 리뷰페이지 정렬 필터 기능 추가, 리뷰 카드 디자인 수정및 해당 상세 페이지 이동 버튼 추가
inji0212 Nov 7, 2024
4286af1
fix gnb 필요없는 메뉴
inji0212 Nov 8, 2024
52790a3
Merge branch 'dev' of https://github.com/Manchui/Frontend into fix/gnb
inji0212 Nov 10, 2024
342b059
fix gnb drawer 링크 이동시 닫히게, toggle 호버로 수정
inji0212 Nov 10, 2024
7276d1c
fix gnb 버튼 호버 스타일 수정
inji0212 Nov 10, 2024
ee9d585
fix toggle 이미지변경및 스타일 알맞게 수정
inji0212 Nov 10, 2024
050a5ae
fix drawer 스타일 수정
inji0212 Nov 10, 2024
ea45f1f
design header 수정 및 생성페이지 날짜 토스트추가와 이미지 사이즈 수정
inji0212 Nov 10, 2024
9fd5bbf
fix review page bookmark page와 동일한 레이아웃으로 수정
inji0212 Nov 10, 2024
d74ed56
fix 리뷰 프로필 수정 및 버튼 애니메이션 추가
inji0212 Nov 11, 2024
47c12bd
feat drawer 메뉴버튼 애니메이션 추가
inji0212 Nov 11, 2024
5edf792
chore 코드리뷰 반영
inji0212 Nov 11, 2024
d8aa80c
design gnb 메뉴, 프로필 호버, drawer호버 수정, 프로필드랍다운 디자인 수정
inji0212 Nov 13, 2024
71e8cc7
fix 화면 크기 변경시에도 모달메뉴 닫히게
inji0212 Nov 13, 2024
c5b88af
Merge branch 'dev' into fix/gnb
inji0212 Nov 13, 2024
e8207d7
chore 프로필 드랍다운 컬러 수정
inji0212 Nov 13, 2024
47510ab
Merge branch into fix/reviewandcreatepage
inji0212 Nov 13, 2024
d16c777
design 정원, 캘린더 디자인수정
inji0212 Nov 13, 2024
edc67f3
Merge branch 'dev' into fix/reviewandcreatepage
inji0212 Nov 15, 2024
b6f1723
fix 엔터 수정중
inji0212 Nov 15, 2024
b4b0cf5
Merge branch 'dev' into fix/reviewandcreatepage
inji0212 Nov 18, 2024
37f7106
Merge branch 'dev' into fix/reviewandcreatepage
inji0212 Nov 18, 2024
bd826cd
fix 리뷰 페이지 북마크 페이지에 스타일 맞춤
inji0212 Nov 18, 2024
812ff33
fix review rating 수정중
inji0212 Nov 19, 2024
7e02993
fix score 값을 api로 get
inji0212 Nov 19, 2024
3c605da
fix score별로 rating부분 변화
inji0212 Nov 19, 2024
5ed0292
fix toast추가 및 불필요한 코드 삭제
inji0212 Nov 22, 2024
031dbbd
Merge branch 'dev' into fix/reviewandcreatepage
inji0212 Nov 22, 2024
4e838f7
feat : 생성했던 모임들중 마감된 모임이 있을 경우 dropdown으로 나타나게 수정
inji0212 Nov 24, 2024
a4f7b08
refactor : 별점 필터링에 맞는 총리뷰수및 프로그레스바 수정
inji0212 Nov 24, 2024
d481f2a
Merge branch 'dev' of https://github.com/Manchui/Frontend into fix/re…
inji0212 Nov 24, 2024
641c5a4
fix: 이전 모임 가져와서 보여주는 기능 추가중(미완)
inji0212 Nov 24, 2024
32c011f
fix 발표를 위해 기본 기능으로 수정해둠
inji0212 Nov 24, 2024
c2ce0e2
chore 백엔드 변경에 따라 이름 수정
inji0212 Nov 24, 2024
bf0a924
Merge branch 'dev' into fix/reviewandcreatepage
inji0212 Nov 25, 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
6 changes: 3 additions & 3 deletions public/icons/x-white.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions public/icons/x.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/apis/getCloseGatheringData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { instance } from '@/apis/api';
import type { GetCloseGatheringResponse } from '@manchui-api';

export async function getCloseGatheringData(): Promise<GetCloseGatheringResponse> {
try {
const res = await instance.get<GetCloseGatheringResponse>('/api/gatherings');

return res.data;
} catch (e) {
console.log('GetCloseGatheringResponse 함수에서 오류 발생', e);
throw new Error('닫힌 모임 데이터를 불러오는데 실패했습니다.');
}
}
13 changes: 13 additions & 0 deletions src/apis/getCloseGatheringIdData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { instance } from '@/apis/api';
import type { GetCloseGatheringIdResponse } from '@manchui-api';

export async function getCloseGatheringIdData(gatheringsId: number): Promise<GetCloseGatheringIdResponse> {
try {
const res = await instance.get<GetCloseGatheringIdResponse>(`/api/gatherings/${gatheringsId}`);

return res.data;
} catch (e) {
console.log('getCloseGatheringIdData 함수에서 오류 발생', e);
throw new Error('닫힌 모임 데이터를 불러오는데 실패했습니다.');
}
}
8 changes: 5 additions & 3 deletions src/apis/getReviewData.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { instanceWithoutAccess } from '@/apis/api';
import type { GetReviewResponse } from '@manchui-api';

type GetReviewProps= {
type GetReviewProps = {
category?: string;
endDate?: string;
location?: string;
page?: number;
query?: string;
score?: number;
size?: number;
sort?: string;
startDate?: string;
}
};

export async function getReviewData({
page = 0,
Expand All @@ -21,19 +22,20 @@ export async function getReviewData({
endDate,
query,
sort,
score,
}: GetReviewProps): Promise<GetReviewResponse> {
const params = new URLSearchParams({
page: page.toString(),
size: size.toString(),
...(sort && { sort }),
...(score && { score: score?.toString() }),
...(query && { query }),
...(category && { category }),
...(location && { location }),
...(startDate && { startDate }),
...(endDate && { endDate }),
});


try {
const res = await instanceWithoutAccess.get<GetReviewResponse>('/api/reviews?', {
params,
Expand Down
49 changes: 49 additions & 0 deletions src/apis/getReviewScoreZeroData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { instanceWithoutAccess } from '@/apis/api';
import type { GetReviewResponse } from '@manchui-api';

type GetReviewProps = {
category?: string;
endDate?: string;
location?: string;
page?: number;
query?: string;
score?: number;
size?: number;
sort?: string;
startDate?: string;
};

export async function getReviewScoreZeroData({
page = 0,
size = 10,
category,
location,
startDate,
endDate,
query,
sort,
score = 0,
}: GetReviewProps): Promise<GetReviewResponse> {
const params = new URLSearchParams({
page: page.toString(),
size: size.toString(),
...(score && { score: score?.toString() }),
...(sort && { sort }),
...(query && { query }),
...(category && { category }),
...(location && { location }),
...(startDate && { startDate }),
...(endDate && { endDate }),
});

try {
const res = await instanceWithoutAccess.get<GetReviewResponse>('/api/reviews?', {
params,
});

return res.data;
} catch (e) {
console.error('getReviewScoreZeroData 함수에서 오류 발생:', e);
throw new Error('리뷰 데이터를 불러오는데 실패했습니다.');
}
}
6 changes: 3 additions & 3 deletions src/components/Create/CapacityDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export function CapacityDropdown({ errorMin, errorMax, selectedMinNum, selectedM
return (
<div>
<h2 className="mb-3 text-base font-semibold text-gray-900"> 모집 정원 </h2>
<div className="flex w-full flex-col justify-center gap-2 mobile:flex-row mobile:justify-between tablet:gap-10">
<div className="flex flex-1 items-center">
<div className="flex w-full flex-col justify-center gap-2 phablet:flex-row phablet:justify-between phablet:gap-10">
<div className="flex flex-1 items-center gap-2">
<p className="mr-2 whitespace-nowrap text-sm font-medium">최소 인원 </p>
<div className="flex-1">
<LongDropdown
Expand All @@ -33,7 +33,7 @@ export function CapacityDropdown({ errorMin, errorMax, selectedMinNum, selectedM
</div>
</div>

<div className="flex flex-1 items-center">
<div className="flex flex-1 items-center gap-2">
<p className="mr-2 whitespace-nowrap text-sm font-medium">최대 인원 </p>
<div className="flex-1">
<LongDropdown
Expand Down
22 changes: 17 additions & 5 deletions src/components/Create/CategoryDropdown/index.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
import { useEffect, useState } from 'react';
import LongDropdown from '@/components/shared/Dropdown/LongDropdown';
import { FILTER_OPTIONS } from '@/constants/filter';
import type { GetCloseGatheringIdResponse } from '@manchui-api';

type CategoryDropdownProps = {
closeGatheringIdData?: GetCloseGatheringIdResponse['data'];
error: string;
setSelectedCategory: (category: string) => void;
};

export function CategoryDropdown({ setSelectedCategory ,error}: CategoryDropdownProps) {
const categoryList = FILTER_OPTIONS.slice(1).map(option => option.label);
export function CategoryDropdown({ closeGatheringIdData, setSelectedCategory, error }: CategoryDropdownProps) {
const categoryList = FILTER_OPTIONS.slice(1).map((option) => option.label);
const [placeholder, setPlaceholder] = useState<string>('서비스 카테고리를 정해주세요.');
useEffect(() => {
if (closeGatheringIdData) {
setSelectedCategory(closeGatheringIdData.category);
setPlaceholder(closeGatheringIdData.category);
}
}, [closeGatheringIdData, setSelectedCategory]);

const isCategorySelected = Boolean(closeGatheringIdData?.category);

// console.log('Selected placeholder:', placeholder);

return (
<div>
<h2 className="mb-3 text-base font-semibold text-gray-900"> 카테고리 </h2>
<LongDropdown listDropdown={categoryList} placeholder="서비스 카테고리를 정해주세요." onListChange={setSelectedCategory} />
{error && <p className="mt-1 -mb-5 text-red-500 text-sm font-medium ">{error}를 선택하세요.</p>}
<LongDropdown listDropdown={categoryList} placeholder={placeholder} onListChange={setSelectedCategory} disabled={isCategorySelected} />
{error && <p className="-mb-5 mt-1 text-sm font-medium text-red-500">{error}를 선택하세요.</p>}
</div>
);
}

2 changes: 1 addition & 1 deletion src/components/Create/DescriptionInput/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function DescriptionInput({ description, setDescription, error }: Descrip
<textarea
value={description || ''}
placeholder="모임에 대한 설명을 작성해주세요."
className="min-h-40 w-full resize-none rounded-xl border border-blue-100 bg-blue-50 pl-2 pt-3 text-sm font-medium"
className="resize-none min-h-40 w-full rounded-xl border border-blue-100 bg-blue-50 pl-2 pt-3 text-sm font-medium"
onChange={handleChange}
/>
{error && <p className="-mb-5 mt-1 text-sm font-medium text-red-500">{errorMessage}</p>}
Expand Down
78 changes: 65 additions & 13 deletions src/components/Create/GroupNameInput/index.tsx
Original file line number Diff line number Diff line change
@@ -1,29 +1,81 @@
/* eslint-disable no-unused-vars */
/* eslint-disable @typescript-eslint/no-unused-vars */
import { getCloseGatheringData } from '@/apis/getCloseGatheringData';
import LongDropdown from '@/components/shared/Dropdown/LongDropdown';
import useGetCloseGatheringData from '@/hooks/useGetCloseGatheringData';
import { dehydrate, QueryClient } from '@tanstack/react-query';

type CloseGatheringData = {
gatheringId: number;
groupName: string;
}[];

type GroupNameInputProps = {
error: string;
name: string | null;
setGatheringId: (id: number) => void;
setName: (name: string) => void;
};

export function GroupNameInput({ name, setName, error }: GroupNameInputProps) {

const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
setName(inputValue);
};
export function GroupNameInput({ name, setName, setGatheringId, error }: GroupNameInputProps) {
const { data: closeGatheringData } = useGetCloseGatheringData();

// const gatheringList: CloseGatheringData = (closeGatheringData?.data?.closedGatheringList as unknown as CloseGatheringData) || [];

const errorMessage = error==='모임 이름' ? `${error}을 입력하세요.` : error;
const errorMessage = error === '모임 이름' ? `${error}을 입력하세요.` : error;
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
e.preventDefault(); // Enter 키에 의한 폼 제출을 막음
}
};
return (
<div>
<h2 className="text-base font-semibold text-gray-900"> 모임 이름 </h2>
<h2 className="text-base font-semibold text-gray-900">모임 이름</h2>
{/* {gatheringList.length > 0 ? (
<LongDropdown
isCloseGathering
listDropdown={gatheringList}
placeholder="모임 이름을 작성해주세요"
onListChange={(selectedGroupName) => {
setName(selectedGroupName);
const selectedGroup = gatheringList.find((item) => item.groupName === selectedGroupName);
if (selectedGroup) {
setGatheringId(selectedGroup.gatheringId);
}
}}
/>
) : ( */}
<input
value={name || ''}
placeholder="모임 이름을 작성해주세요"
className='mt-3 h-11 w-full rounded-xl border border-blue-100 bg-blue-50 pl-2 text-sm font-medium '
onChange={handleChange}
placeholder="모임 이름을 작성해 주세요"
className="mt-3 h-11 w-full rounded-xl border border-blue-100 bg-blue-50 pl-2 text-sm font-medium"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = e.target.value;
setName(inputValue);
// const selectedGroup = gatheringList.find((item) => item.groupName === inputValue);
// if (selectedGroup) {
// setGatheringId(selectedGroup.gatheringId);
// }
}}
onKeyPress={handleKeyPress}
/>
{error && <p className="mt-1 text-red-500 text-sm font-medium -mb-5">{errorMessage}</p>}
{/* )} */}
{error && <p className="-mb-5 mt-1 text-sm font-medium text-red-500">{errorMessage}</p>}
</div>

);
}

export const getServerSideProps = async () => {
const queryClient = new QueryClient();

await queryClient.prefetchQuery({
queryKey: ['getClosegatherings'],
queryFn: () => getCloseGatheringData(),
});

return {
props: {
dehydratedState: dehydrate(queryClient),
},
};
};
4 changes: 2 additions & 2 deletions src/components/Create/ImageUploader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default function ImageUploader({ error, setSelectedImage }: ImageUploader
<div className="scrollbar-hide -mt-3 flex items-center space-x-3 overflow-x-auto">
<button
type="button"
className="mt-3 flex size-[100px] shrink-0 flex-col items-center justify-center rounded-lg border border-blue-200 text-sm font-medium text-blue-800 mobile:size-[150px]"
className="mt-3 flex aspect-[280/156] h-[100px] shrink-0 flex-col items-center justify-center rounded-lg border border-blue-200 text-sm font-medium text-blue-800 tablet:h-[150px]"
onClick={handleButtonClick}
>
<Image src="/icons/+.svg" alt="+" width={18} height={18} className="mb-2" />
Expand All @@ -47,7 +47,7 @@ export default function ImageUploader({ error, setSelectedImage }: ImageUploader
<input type="file" accept="image/*" ref={fileInputRef} onChange={handleFileChange} style={{ display: 'none' }} />

{previewImage && (
<div className="relative mt-3 size-[100px] shrink-0 rounded-lg border border-blue-200 mobile:size-[150px]">
<div className="relative mt-3 aspect-[280/156] h-[100px] shrink-0 rounded-lg border border-blue-200 tablet:h-[150px]">
<Image src={previewImage} alt="예시 이미지" layout="fill" objectFit="cover" className="rounded-lg" />
<button
type="button"
Expand Down
25 changes: 25 additions & 0 deletions src/components/review/FilterSection/ScoreFilter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Image from 'next/image';
import { Toast } from '@/components/shared/Toast';
import { useScore, useSetScore } from '@/store/useFilterStore';

export default function ScoreFilter() {
const score = useScore();
const setScore = useSetScore();

const handleScoreRemove = () => {
setScore(0);
Toast('info', '별점 필터가 초기화되었습니다.');
};
return (
<div>
{score ? (
<div className="relative flex items-center justify-center gap-2 rounded-lg border border-gray-100 bg-blue-800 p-3 text-13-16-response font-semibold text-white ease-out">
<span className="leading-none">{score}점</span>
<button type="button" onClick={handleScoreRemove} className="flex size-3 items-center justify-center">
<Image src="icons/x-white.svg" alt="x" width={12} height={12} />
</button>
</div>
) : null}
</div>
);
}
13 changes: 6 additions & 7 deletions src/components/review/FilterSection/SortToggle/index.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
import type { Dispatch, SetStateAction } from 'react';
import { useState } from 'react';
import Dropdown from '@/components/main/Dropdown';
import { Toast } from '@/components/shared/Toast';
import { useSetSort, useSort } from '@/store/useFilterStore';

const sortData = [
{ api: 'ratingDesc', name: '별점 높은순' },
{ api: 'ratingAsc', name: '별점 낮은순' },
];

interface RegionDropdownProps {
setSort: Dispatch<SetStateAction<string | undefined>>;
sort?: string;
}

export default function SortToggle({ sort, setSort }: RegionDropdownProps) {

export default function SortToggle() {
const [sortDropOpen, setSortDropOpen] = useState(false);
const sort=useSort();
const setSort=useSetSort();

const handleInitClick = () => {
setSort(undefined);
setSortDropOpen(false);

Toast('success', '순서가 초기화되었습니다.');
Toast('info', '순서가 초기화되었습니다.');
};

const handleSortSelect = (value: { api: string; name: string }) => {
Expand Down
Loading