-
Notifications
You must be signed in to change notification settings - Fork 6
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
refactor: 모달 celuveat UI library 적용 #664
The head ref may contain hidden characters: "663-refactor-\uBAA8\uB2EC-celuveat-ui-library-\uC801\uC6A9"
Changes from all commits
ec17dca
18aaebe
e7fb99e
e429368
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
import { Modal } from 'celuveat-ui-library'; | ||
import React, { ReactNode } from 'react'; | ||
import styled from 'styled-components'; | ||
import Exit from '~/assets/icons/exit.svg'; | ||
import useCeluveatModal from '~/hooks/useCeluveatModal'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 요놈은 라이브러리 성격을 띄니까 라이브러리에서 선언을 해도 좋을 것 같아요~ |
||
|
||
interface Props { | ||
title?: string; | ||
children: ReactNode; | ||
} | ||
|
||
function Dialog({ title, children }: Props) { | ||
const { closeModal } = useCeluveatModal(); | ||
|
||
return ( | ||
<> | ||
<Modal.Overlay as={<StyledOverlay />} /> | ||
<StyledContent> | ||
<StyledTitle>{title}</StyledTitle> | ||
<StyledExitButton onClick={closeModal} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 컴파운드 컴포넌트로 모달을 구현을 해주셨는데 컴파운드 컴포넌트를 사용하는 이유는 무엇이라고 생각하나요?? 지금 구현하신 모달에서는 거의 모든 기능을 사용자에게 제어권을 위임하는 형태입니다. Modal 라이브러리 사용도 Overlay만 사용되는데 라이브러리까지 만들어서 사용을 한다는 건 너무 오버 엔지니어링 같습니다 ㅜㅜ 각 모달 컴포넌트(Overlay, Content, ExitButton 등)의 요구사항을 잘 파악하고 해당 라이브러리에 각 기능들을 구현, 사용처에서는 해당 기능을 잘 몰라도 사용할 수 있게끔 구현하는 것이 최종 목적이라고 생각이 듭니다. 마지막으로 무엇을 해결하기 위해 컴파운드 컴포넌트를 썼는지 라이브러리를 왜 썼는지 그 이유와 근거에 대해서 더 잘 이해하고 사용해보았으면 더 많은 공부가 될 것 같아요~
|
||
{children} | ||
</StyledContent> | ||
</> | ||
); | ||
} | ||
|
||
export default Dialog; | ||
|
||
const StyledOverlay = styled.div` | ||
position: absolute; | ||
top: 0; | ||
|
||
width: 100%; | ||
height: 100%; | ||
|
||
background-color: black; | ||
|
||
opacity: 0.2; | ||
`; | ||
|
||
const StyledContent = styled.div` | ||
position: fixed; | ||
top: 50%; | ||
left: 50vw; | ||
|
||
min-width: 540px; | ||
max-width: 66.6%; | ||
|
||
padding: 2.4rem; | ||
margin: 0 auto; | ||
|
||
border-radius: 12px; | ||
background-color: white; | ||
|
||
transform: translateX(-50%) translateY(-50%); | ||
`; | ||
|
||
const StyledTitle = styled.h4` | ||
text-align: center; | ||
|
||
margin-bottom: 2.4rem; | ||
`; | ||
|
||
const StyledExitButton = styled(Exit)` | ||
position: absolute; | ||
top: 12px; | ||
right: 12px; | ||
|
||
cursor: pointer; | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import Dialog from './Dialog'; | ||
|
||
export default Dialog; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { ChangeEvent, FormEvent, useState } from 'react'; | ||
import { useParams } from 'react-router-dom'; | ||
import styled from 'styled-components'; | ||
import { postRevisedInfo } from '~/api/restaurant'; | ||
import TextButton from '~/components/@common/Button'; | ||
import Dialog from '~/components/@common/Dialog'; | ||
import { BORDER_RADIUS, FONT_SIZE } from '~/styles/common'; | ||
|
||
const labels = [ | ||
'레스토랑이 폐점했어요.', | ||
'레스토랑 이름이 잘못되었어요.', | ||
'레스토랑 주소가 잘못되었어요.', | ||
'레스토랑 전화번호가 잘못되었어요', | ||
]; | ||
|
||
function SuggestionForm() { | ||
const { id } = useParams(); | ||
const [checkedItems, setCheckedItems] = useState<string[]>([]); | ||
const [textareaValue, setTextareaValue] = useState(''); | ||
|
||
const handleSubmit = (e: FormEvent) => { | ||
e.preventDefault(); | ||
|
||
const requestData = textareaValue ? [...checkedItems, textareaValue] : checkedItems; | ||
postRevisedInfo({ restaurantId: Number(id), data: { contents: requestData } }); | ||
window.location.reload(); | ||
}; | ||
|
||
const clickCheckBox = (e: ChangeEvent<HTMLInputElement>) => { | ||
const { checked, value } = e.target; | ||
|
||
setCheckedItems(prev => (checked ? [...prev, value] : prev.filter(item => item !== value))); | ||
}; | ||
|
||
const onChangeTextarea = (e: ChangeEvent<HTMLTextAreaElement>) => { | ||
setTextareaValue(e.target.value); | ||
}; | ||
|
||
return ( | ||
<Dialog title="정보 수정 제안"> | ||
<StyledForm onSubmit={handleSubmit}> | ||
<h5>수정 항목</h5> | ||
<p>잘못되었거나 수정이 필요한 정보들을 모두 선택해주세요.</p> | ||
<StyledUnorderedList> | ||
{labels.map(label => ( | ||
<StyledListItem> | ||
<CheckBox value={label} onChange={clickCheckBox} /> | ||
<span>{label}</span> | ||
</StyledListItem> | ||
))} | ||
<StyledTextarea placeholder="(선택) 내용을 입력해주세요." onChange={onChangeTextarea} /> | ||
</StyledUnorderedList> | ||
<TextButton | ||
type="submit" | ||
text="등록하기" | ||
onClick={handleSubmit} | ||
colorType="light" | ||
disabled={!checkedItems.length && !textareaValue} | ||
/> | ||
</StyledForm> | ||
</Dialog> | ||
); | ||
} | ||
|
||
export default SuggestionForm; | ||
|
||
const StyledForm = styled.form` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 2rem; | ||
|
||
font-size: ${FONT_SIZE.md}; | ||
|
||
p { | ||
color: var(--gray-3); | ||
} | ||
`; | ||
|
||
const StyledUnorderedList = styled.ul` | ||
display: flex; | ||
flex-direction: column; | ||
gap: 2rem; | ||
`; | ||
|
||
const StyledListItem = styled.li` | ||
display: flex; | ||
align-items: center; | ||
gap: 0.8rem; | ||
`; | ||
|
||
const StyledTextarea = styled.textarea` | ||
height: 128px; | ||
|
||
padding: 0.8rem; | ||
|
||
border: none; | ||
border-radius: ${BORDER_RADIUS.sm}; | ||
background-color: var(--gray-1); | ||
`; | ||
|
||
const CheckBox = styled.input.attrs({ type: 'checkbox' })` | ||
width: 24px; | ||
height: 24px; | ||
|
||
border: 1px solid #ddd; | ||
border-radius: 50%; | ||
background-image: url('~/assets/icons/unchecked-icon.svg'); | ||
background-size: cover; | ||
|
||
transition: all 0.2s ease; | ||
appearance: none; | ||
|
||
&:checked { | ||
border: 1px solid var(--primary-6); | ||
background-color: var(--primary-6); | ||
background-image: url('~/assets/icons/checked-icon.svg'); | ||
background-size: cover; | ||
} | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import SuggestionForm from './SuggestionForm'; | ||
|
||
export default SuggestionForm; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import Dialog from '../@common/Dialog'; | ||
import RestaurantReviewList from '../RestaurantReviewList/RestaurantReviewList'; | ||
import { ReviewDeleteForm, ReviewForm, ReviewReportForm } from '../ReviewForm'; | ||
|
||
const REVIEW_FORM_TITLE = { | ||
create: '리뷰 작성하기', | ||
update: '리뷰 수정하기', | ||
delete: '리뷰 삭제하기', | ||
report: '리뷰 신고하기', | ||
all: '리뷰 모두 보기', | ||
} as const; | ||
|
||
interface FormModalProps { | ||
type: keyof typeof REVIEW_FORM_TITLE; | ||
reviewId?: number; | ||
} | ||
|
||
function FormModal({ type, reviewId }: FormModalProps) { | ||
return ( | ||
<div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. && 를 고치는 방향을 위해서 라이브러리를 만들고 적용하는 것 아니였나용?? ( 그대로 남아있네용 ㅠㅠ ) |
||
{type === 'create' && ( | ||
<Dialog title={REVIEW_FORM_TITLE[type]}> | ||
<ReviewForm type="create" reviewId={reviewId} /> | ||
</Dialog> | ||
)} | ||
{type === 'update' && ( | ||
<Dialog title={REVIEW_FORM_TITLE[type]}> | ||
<ReviewForm type="update" reviewId={reviewId} /> | ||
</Dialog> | ||
)} | ||
{type === 'delete' && ( | ||
<Dialog title={REVIEW_FORM_TITLE[type]}> | ||
<ReviewDeleteForm reviewId={reviewId} /> | ||
</Dialog> | ||
)} | ||
{type === 'report' && ( | ||
<Dialog title={REVIEW_FORM_TITLE[type]}> | ||
<ReviewReportForm reviewId={reviewId} /> | ||
</Dialog> | ||
)} | ||
{type === 'all' && ( | ||
<Dialog title={REVIEW_FORM_TITLE[type]}> | ||
<RestaurantReviewList /> | ||
</Dialog> | ||
)} | ||
</div> | ||
); | ||
} | ||
|
||
export default FormModal; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import FormModal from '~/components/FormModal/FormModal'; | ||
|
||
export default FormModal; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
린트 설정을 사용자가 직접 수정하는 설정으로 하고 있는데 이렇게 바꾼 이유가??