Skip to content

Commit

Permalink
Merge pull request #14 from coconut-thisABLE/refactor/detail/add-review
Browse files Browse the repository at this point in the history
Refactor/detail/add review
  • Loading branch information
seohyun319 authored Dec 23, 2022
2 parents 490cb7a + 40dfc7d commit af457d4
Show file tree
Hide file tree
Showing 8 changed files with 359 additions and 6 deletions.
60 changes: 60 additions & 0 deletions components/detail/ReviewContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import styled from '@emotion/styled'
import { useState } from 'react'
import { reviewAverageCount } from '../../data'
import { ReviewSortType } from '../../types/state'
import Text from '../common/Text'
import ReviewInput from './ReviewInput'
import ReviewList from './ReviewList'

// TODO: set location id
const ReviewContainer = () => {
const [sort, setSort] = useState<ReviewSortType>('recommended')

return (
<>
<ReviewContainerHeader>
<Text size={1.2} bold>
{reviewAverageCount.count} 개의 리뷰
</Text>
<ReviewSortContainer>
<SelectSort
sort={sort}
name={'recommended'}
onClick={() => setSort('recommended')}
>
추천순
</SelectSort>
<SelectSort
sort={sort}
name={'createdAt'}
onClick={() => setSort('createdAt')}
>
최신순
</SelectSort>
</ReviewSortContainer>
</ReviewContainerHeader>
<ReviewInput />
<ReviewList />
</>
)
}

const ReviewContainerHeader = styled.header`
display: flex;
justify-content: space-around;
align-items: flex-end;
flex-direction: row;
`
const SelectSort = styled.div<{ sort: string; name: string }>`
font-weight: ${({ sort, name }) => (sort === name ? 'bold' : 'normal')};
padding: 0 0.5rem;
cursor: pointer;
`
const ReviewSortContainer = styled.div`
display: flex;
${SelectSort}:first-of-type {
border-right: 1px solid black;
}
`

export default ReviewContainer
113 changes: 113 additions & 0 deletions components/detail/ReviewInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import styled from '@emotion/styled'
import React, { useState, useEffect } from 'react'
import Text, { StyledText } from '../common/Text'

import Radio from '@mui/material/Radio'
import RadioGroup from '@mui/material/RadioGroup'
import FormControlLabel from '@mui/material/FormControlLabel'
import FormControl from '@mui/material/FormControl'
import Rating from '@mui/material/Rating'
import { ReviewUserType } from '../../types/state'

const ReviewInput = () => {
const [userType, setUserType] = useState<ReviewUserType>('anonymous')
const [inputValue, setInputValue] = useState<string>('')
const [rate, setRate] = useState<number | null>(0)

return (
<ReviewInputContainer>
<ReviewInputHeader>
<UserInfo>
<Text>평점</Text>
<Rating
value={rate}
precision={0.5}
onChange={(_, newRate) => {
setRate(newRate)
}}
/>
</UserInfo>
<FormControl>
<RadioGroup
row
value={userType}
onChange={(e) => setUserType(e.target.value as ReviewUserType)}
>
<FormControlLabel
value="disabled"
control={<Radio size="small" />}
label="장애인"
/>
<FormControlLabel
value="able"
control={<Radio size="small" />}
label="비장애인"
/>
<FormControlLabel
value="anonymous"
control={<Radio size="small" />}
label="익명"
/>
</RadioGroup>
</FormControl>
</ReviewInputHeader>

<ReviewInputArea
onChange={(e) => setInputValue(e.target.value)}
placeholder="리뷰는 익명으로 등록됩니다."
value={inputValue}
/>
<ReviewInputButton
onClick={() => {
// postReview(userType, locationId, inputValue, rating)
setInputValue('')
setRate(0)
}}
>
등록
</ReviewInputButton>
</ReviewInputContainer>
)
}

const ReviewInputContainer = styled.section`
display: flex;
flex-direction: column;
margin-top: 1rem;
`
const ReviewInputHeader = styled.div`
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
`
const UserInfo = styled.div`
display: flex;
align-items: center;
justify-content: center;
${StyledText} {
margin-right: 0.2rem;
}
`
const ReviewInputArea = styled.textarea`
border: 2px solid #9d9d9d;
border-radius: 10px;
font-size: 1rem;
min-height: 5rem;
padding: 0.3rem;
margin-top: 0.4rem;
resize: none;
`
const ReviewInputButton = styled.button`
display: flex;
background-color: #e599b3;
color: white;
font-size: 0.9rem;
margin-top: 0.6rem;
padding: 0.4rem;
justify-content: center;
align-items: center;
border-radius: 5px;
`

export default ReviewInput
112 changes: 112 additions & 0 deletions components/detail/ReviewList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import styled from '@emotion/styled'
import Image from 'next/image'
import { reviews } from '../../data'
import Text, { StyledText } from '../common/Text'

import Rating from '@mui/material/Rating'

const ReviewList = () => {
return (
<ReviewListContainer>
{reviews?.data?.map((review) => (
<ReviewContainer key={review._id}>
<ReviewInfoWrapper>
<ReviewStarUserTypeWrapper>
<Rating
value={review.star}
precision={0.5}
size="small"
readOnly
/>
<Text color="#f0a044" size={0.9}>
{review.userType}
</Text>
</ReviewStarUserTypeWrapper>
<Text color="#9d9d9d" size={0.7}>
{review.createdAt.substring(0, 10)}
</Text>
</ReviewInfoWrapper>
<ReviewText>{review.detail}</ReviewText>
<HelpButtonWrapper>
<HelpButton
// onClick={() => {
// postReviewRecommend(review._id)
// }}
>
<Image
src={'/images/thumbs_up.svg'}
width={15}
height={15}
></Image>
<ButtonDescriptionText>도움이 돼요</ButtonDescriptionText>
<Text color="#cb3267" size={1} bold>
{review.good}
</Text>
</HelpButton>
<HelpButton
// onClick={() => postReviewDiscourage(review._id)}
>
<Image
src={'/images/thumbs_down.svg'}
width={15}
height={15}
></Image>
<ButtonDescriptionText>도움이 안 돼요</ButtonDescriptionText>
<Text color="#cb3267" size={1} bold>
{review.bad}
</Text>
</HelpButton>
</HelpButtonWrapper>
</ReviewContainer>
))}
</ReviewListContainer>
)
}

const ReviewListContainer = styled.section``
const ReviewContainer = styled.div`
margin-top: 1rem;
padding-bottom: 1rem;
border-bottom: #9d9d9d;
border-bottom-width: 0.08rem;
border-bottom-style: solid;
`
const ReviewInfoWrapper = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`
const ReviewStarUserTypeWrapper = styled.div`
display: flex;
align-items: center;
${StyledText} {
margin-left: 0.4rem;
}
`
const ReviewText = styled.p`
font-size: 1rem;
align-items: center;
margin-left: 0.5rem;
margin-top: 0.5rem;
`
const HelpButtonWrapper = styled.div`
display: flex;
justify-content: space-between;
`
const HelpButton = styled.button`
display: flex;
font-weight: bold;
font-size: 0.8rem;
height: 1.7rem;
align-items: center;
border: 1px solid #f0a044;
border-radius: 10px;
background-color: #ffffff;
padding-left: 1rem;
padding-right: 1rem;
`
const ButtonDescriptionText = styled.p`
margin: 0 0.5rem 0 0.2rem;
`

export default ReviewList
26 changes: 20 additions & 6 deletions components/detail/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import styled from '@emotion/styled'
import { Dispatch, SetStateAction } from 'react'
import { useRouter } from 'next/router'
import { placeDetail, reviewAverageCount } from '../../data'
import { PlaceInfoType } from '../../types'
import FacilitiesIcons from '../common/FacilitiesIcons'
import { NameTypeSection } from '../common/PlaceInfo'
import Text, { StyledText } from '../common/Text'
import ChargerInfoToggle from './ChargerInfoToggle'
import { Dispatch, SetStateAction } from 'react'
import { useRouter } from 'next/router'
import ReviewContainer from './ReviewContainer'

import Rating from '@mui/material/Rating'

type DetailPropsType = {
setIsDetailOpen?: Dispatch<SetStateAction<boolean>>
}

const Detail = ({ setIsDetailOpen }: DetailPropsType) => {
const place: PlaceInfoType = placeDetail.response
// TODO: 동적 id와 실데이터 연결
const router = useRouter()

return (
<DetailContainer>
<button onClick={() => (setIsDetailOpen ? setIsDetailOpen(false) : router.push('/'))}>
Expand All @@ -35,17 +40,22 @@ const Detail = ({ setIsDetailOpen }: DetailPropsType) => {
</AddressText>
{reviewAverageCount && (
<ReviewAverageCountSection>
{reviewAverageCount.average}
<Rating
value={reviewAverageCount.average}
precision={0.1}
size="small"
readOnly
/>
<Text size={0.8}>({reviewAverageCount.average})</Text>
<Text>
(리뷰 <b>{reviewAverageCount.count}</b>
개)
리뷰 <b>{reviewAverageCount.count}</b>
</Text>
</ReviewAverageCountSection>
)}
<FacilitiesIcons place={place} size={50} hasDescription />
</DetailInfoSection>
<ChargerInfoToggle />
{/* <ReviewPage locationId={id} /> */}
<ReviewContainer />
</DetailContainer>
)
}
Expand All @@ -65,6 +75,10 @@ const AddressText = styled(StyledText)`
const ReviewAverageCountSection = styled.section`
display: flex;
margin: 1rem 0;
align-items: center;
${StyledText}:last-of-type {
margin-left: 0.6rem;
}
`

export default Detail
31 changes: 31 additions & 0 deletions data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,34 @@ export const reviewAverageCount = {
count: 5,
average: 4.5,
}

// 리뷰 리스트
export const reviews = {
message: 'List Review of location number 1 Success',
data: [
{
_id: '62343510c3dd5a345c6431d4',
locationId: 1,
userId: null,
userType: 'anonymous',
good: 1,
bad: 2,
detail:
'매장이 넓고 경사로가 있어서 이용하기 편리했어요 카페 내부도 예뻐요! 입구는 하나라 경사로 찾기 쉬울 것 같아요',
star: 4.5,
createdAt: '2022-03-18T09:40:53.077Z',
},
{
_id: '62343510c3dd5a345c6431d5',
locationId: 2,
userId: null,
userType: 'anonymous',
good: 1,
bad: 3,
detail:
'매장이 넓고 경사로가 있어서 이용하기 편리했어요 카페 내부도 예뻐요!',
star: 4.2,
createdAt: '2022-03-19T09:40:53.077Z',
},
],
}
3 changes: 3 additions & 0 deletions next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
const nextConfig = {
reactStrictMode: true,
swcMinify: true,
compiler: {
emotion: true,
},
}

module.exports = nextConfig
Loading

0 comments on commit af457d4

Please sign in to comment.