Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

리뷰 페이지 작성 #97

Merged
merged 10 commits into from
Jan 11, 2024
16 changes: 16 additions & 0 deletions src/app/review/[storeId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Header from '@components/common/Header';

interface ReviewLayoutProps {
children: React.ReactNode;
}

export default function layout({ children }: ReviewLayoutProps) {
return (
<div className="bg-gray-100">
<Header className="fixed top-0 bg-gray-100">
<p className="body-16-bold">로그 작성</p>
</Header>
<div className="px-[16px]">{children}</div>
</div>
);
}
55 changes: 55 additions & 0 deletions src/app/review/[storeId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use client';

import { useState, useCallback, ChangeEvent } from 'react';

import { usePostLog } from '@hooks/api/usePostLog';
import ImageUploader from '@components/review/ImageUploader';
import StarRating from '@components/review/StarRating';
import TextArea from '@components/review/TextArea';
import NavigationButton from '@components/terms/NavigationButton';

export default function Page({ params }: { params: { slug: string } }) {
const { mutate: postLog } = usePostLog();
const [rating, setRating] = useState(0);
const [description, setDescription] = useState('');

const storeId = params.slug;

const handleRating = useCallback(
(index: number) => () => {
setRating(index + 1);
},
[],
);

const handleChangeDescription = (e: ChangeEvent<HTMLTextAreaElement>) => {
setDescription(e.target.value);
};

const handleClickSubmitButton = () => {
// TODO: 이미지 기능 구현
postLog({ storeId, rating, storeImgUrl: '', description });
};

return (
<div className="h-[100dvh] pt-[56px] pb-[104px] overflow-y-scroll">
<h1 className="header-22 py-[16px]">
가게 이름에 <br />
<strong className="text-primary-500">NN번째</strong> 방문이에요!
</h1>
Copy link
Collaborator

@YelynnOh YelynnOh Jan 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기는 나중에 서버에서 보내주는 가게 이름 데이터랑 방문 수 데이터로 대체할 예정이신걸까용?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 서버랑 얘기해봐야해서... 아마 저희가 데이터 물고 페이지 넘어가야하지 않을까 싶어서 일단 뒀습니다...

<div className="flex flex-col py-[8px] gap-[16px]">
<StarRating rating={rating} onClick={handleRating} />
<ImageUploader />
<TextArea value={description} onChange={handleChangeDescription} />
</div>
<NavigationButton
className="bg-transparent fixed bottom-0 left-[50%] -translate-x-[50%]"
// TODO: 추후 storeImgUrl 조건 추가
disabled={!rating || !description}
onClick={handleClickSubmitButton}
>
작성완료
</NavigationButton>
</div>
);
}
20 changes: 0 additions & 20 deletions src/app/review/page.tsx

This file was deleted.

2 changes: 1 addition & 1 deletion src/app/search/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useSearchParams } from 'next/navigation';
import useDebounce from '@hooks/useDebounce';
import SearchTopBar from '@components/search/SearchTopBar';
import Header from '@components/common/Header';
import { useGetStoreList } from '@api/useGetStoreList';
import { useGetStoreList } from '@hooks/api/useGetStoreList';
import useInput from '@hooks/useInput';
import cn from '@utils/cn';
import NoSearchResult from '@components/common/NoSearchResult';
Expand Down
15 changes: 7 additions & 8 deletions src/components/common/Header/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
'use client';

import { useRouter } from 'next/navigation';
import { HTMLAttributes } from 'react';

import cn from '@utils/cn';
import LeftArrow from 'public/assets/icon24/left_arrow_24.svg';

interface HeaderProps {
children?: React.ReactNode;
className?: string;
}

export default function Header({ children, className }: HeaderProps) {
export default function Header({
className,
children,
}: HTMLAttributes<HTMLHeadElement>) {
const { back } = useRouter();

const handleClickBackButton = () => {
back();
};

return (
<div
<header
className={cn(
'flex items-center px-[16px] py-[8px] w-full h-[56px]',
className,
Expand All @@ -29,6 +28,6 @@ export default function Header({ children, className }: HeaderProps) {
</button>
{/* NOTE: 저희 서비스에서는 텍스트 혹은 search input이 들어갑니다. Header 컴포넌트 내부에 넣어주시면 됩니다. */}
{children}
</div>
</header>
);
}
2 changes: 1 addition & 1 deletion src/components/review/ImageUploader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default function ImageUploader() {

return (
<div
className="rounded-[24px] text-center w-full h-[160px] flex flex-col justify-center items-center gap-[8px]"
className="bg-white rounded-[24px] text-center w-full h-[160px] flex flex-col justify-center items-center gap-[8px]"
onClick={handleClickUploadButton}
>
<p className="body-16-bold">사진을 추가해주세요.</p>
Expand Down
6 changes: 3 additions & 3 deletions src/components/review/StarRating/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ interface StarRatingProps {

export default function StarRating({ rating, onClick }: StarRatingProps) {
return (
<div className="rounded-[24px] w-full h-[118px] flex flex-col justify-center items-center">
<div className="bg-white rounded-[24px] w-full h-[118px] flex flex-col justify-center items-center">
<div>
<p className="body-16-bold text-center">만족도를 평가해주세요.</p>
<div className="flex pt-[8px]">
{Array.from({ length: starNum }).map((_, index) =>
index < rating ? (
<FilledStarIcon key={index} onClick={onClick} />
<FilledStarIcon key={index} onClick={onClick(index)} />
) : (
<DefaultStarIcon key={index} onClick={onClick} />
<DefaultStarIcon key={index} onClick={onClick(index)} />
),
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { UseQueryResult, useQuery } from '@tanstack/react-query';
import { AxiosError } from 'axios';

import { axiosRequest } from './api-config';
import { axiosRequest } from '../../api/api-config';

interface Store {
// TODO: spec 확정 시 수정
Expand Down
32 changes: 32 additions & 0 deletions src/hooks/api/usePostLog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { UseMutationResult, useMutation } from '@tanstack/react-query';
import { AxiosError } from 'axios';
import { useRouter } from 'next/navigation';

import { axiosRequest } from '../../api/api-config';

// TODO: api spec 확정되면 변경
interface Log {
storeId: string;
rating: number;
storeImgUrl: string;
description: string;
}

const postLog = ({ ...props }: Log): Promise<void> => {
const body = {
...props,
};
return axiosRequest('post', `/endpoint`, body);
};

export const usePostLog = (): UseMutationResult<void, AxiosError, Log> => {
const { push } = useRouter();
return useMutation({
mutationKey: ['post-log'],
mutationFn: ({ ...props }) => postLog({ ...props }),
onSuccess: () => {
// TODO: 확정되면 변경
push('/');
},
});
};