-
Notifications
You must be signed in to change notification settings - Fork 4
refactor: 밸런스 게임 서브 태그 모달 ui 및 로직 수정 #310
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
Changes from all commits
746277b
931a611
f0a47f9
e56d7c6
74d441a
bc60acf
ed6c8d8
ffa5a8f
722cb1a
9987479
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 | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,19 +1,21 @@ | ||||||||||||||||||||||||||||||||||||||
| import React from 'react'; | ||||||||||||||||||||||||||||||||||||||
| import React, { useEffect, useRef, useState } from 'react'; | ||||||||||||||||||||||||||||||||||||||
| import { BalanceGame } from '@/types/game'; | ||||||||||||||||||||||||||||||||||||||
| import { MobileCheckIcon } from '@/assets'; | ||||||||||||||||||||||||||||||||||||||
| import { TAG_OPTIONS } from '@/constants/game'; | ||||||||||||||||||||||||||||||||||||||
| import Modal from '@/components/mobile/atoms/Modal/Modal'; | ||||||||||||||||||||||||||||||||||||||
| import Button from '@/components/mobile/atoms/Button/Button'; | ||||||||||||||||||||||||||||||||||||||
| import Divider from '@/components/atoms/Divider/Divider'; | ||||||||||||||||||||||||||||||||||||||
| import { validateGameTag } from '@/hooks/game/validateBalanceGameForm'; | ||||||||||||||||||||||||||||||||||||||
| import { createArrayFromCommaString } from '@/utils/array'; | ||||||||||||||||||||||||||||||||||||||
| import useOutsideClick from '@/hooks/common/useOutsideClick'; | ||||||||||||||||||||||||||||||||||||||
| import * as S from './GameTagModal.style'; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| interface GameTagModalProps { | ||||||||||||||||||||||||||||||||||||||
| form: BalanceGame; | ||||||||||||||||||||||||||||||||||||||
| isOpen?: boolean; | ||||||||||||||||||||||||||||||||||||||
| onClose?: () => void; | ||||||||||||||||||||||||||||||||||||||
| setMainTagValue: (name: string, tag: string) => void; | ||||||||||||||||||||||||||||||||||||||
| setSubTagValue: (e: React.ChangeEvent<HTMLInputElement>) => void; | ||||||||||||||||||||||||||||||||||||||
| setSubTagValue: (name: string, tag: string) => void; | ||||||||||||||||||||||||||||||||||||||
| submitGame: () => void; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -25,12 +27,62 @@ const GameTagModal = ({ | |||||||||||||||||||||||||||||||||||||
| setSubTagValue, | ||||||||||||||||||||||||||||||||||||||
| submitGame, | ||||||||||||||||||||||||||||||||||||||
| }: GameTagModalProps) => { | ||||||||||||||||||||||||||||||||||||||
| const inputRef = useRef<HTMLInputElement>(null); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const currentMainTag: string = form.mainTag; | ||||||||||||||||||||||||||||||||||||||
| const [subTagArray] = useState(() => createArrayFromCommaString(form.subTag)); | ||||||||||||||||||||||||||||||||||||||
| const [currentSubTag, setCurrentSubTag] = useState<string[]>(subTagArray); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const [inputValue, setInputValue] = useState<string>(''); | ||||||||||||||||||||||||||||||||||||||
| const [inputError, setInputError] = useState<boolean>(false); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||
| const subTagList = inputValue | ||||||||||||||||||||||||||||||||||||||
| ? [...currentSubTag, inputValue] | ||||||||||||||||||||||||||||||||||||||
| : currentSubTag; | ||||||||||||||||||||||||||||||||||||||
| setSubTagValue('subTag', subTagList.join(',')); | ||||||||||||||||||||||||||||||||||||||
| }, [currentSubTag, inputValue, setSubTagValue]); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => { | ||||||||||||||||||||||||||||||||||||||
| const { value } = e.target; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (value.length > 10) return; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| setInputValue(value); | ||||||||||||||||||||||||||||||||||||||
| setInputError(false); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleSpaceAction = () => { | ||||||||||||||||||||||||||||||||||||||
| if (!inputValue.trim()) return; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| setCurrentSubTag((prev) => [...prev, inputValue.trim()]); | ||||||||||||||||||||||||||||||||||||||
| setInputValue(''); | ||||||||||||||||||||||||||||||||||||||
| setInputError(false); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
| useOutsideClick(inputRef, handleSpaceAction); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+63
Contributor
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. 🛠️ Refactor suggestion
사용자가 이미 3개의 태그를 만든 뒤 입력을 유지한 상태에서 밖을 클릭하면 if (!inputValue.trim()) return;
+ if (currentSubTag.length >= 3) return;📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||||
| const handleKeyUp = (e: React.KeyboardEvent<HTMLInputElement>) => { | ||||||||||||||||||||||||||||||||||||||
| if (!inputValue) { | ||||||||||||||||||||||||||||||||||||||
| setInputError(false); | ||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if (e.code === 'Space') { | ||||||||||||||||||||||||||||||||||||||
| e.preventDefault(); | ||||||||||||||||||||||||||||||||||||||
| handleSpaceAction(); | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| setInputError(inputValue.length >= 10); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleMainTag = (tag: string) => { | ||||||||||||||||||||||||||||||||||||||
| setMainTagValue('mainTag', tag); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleDeleteSubTag = (idx: number) => { | ||||||||||||||||||||||||||||||||||||||
| setCurrentSubTag((prev) => prev.filter((_, i) => i !== idx)); | ||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| const handleTagSubmit = () => { | ||||||||||||||||||||||||||||||||||||||
| if (!currentMainTag) return; | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
|
|
@@ -66,28 +118,54 @@ const GameTagModal = ({ | |||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| <div css={S.tagWrapper}> | ||||||||||||||||||||||||||||||||||||||
| <div css={S.tagBottomWrapper}> | ||||||||||||||||||||||||||||||||||||||
| <div css={S.textBox}> | ||||||||||||||||||||||||||||||||||||||
| <span css={S.tagTextStyling}>서브태그</span> | ||||||||||||||||||||||||||||||||||||||
| <span css={S.subTagTextStyling}>(최대 3개)</span> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| <div css={S.subTagWrapper(currentSubTag.length === 3)}> | ||||||||||||||||||||||||||||||||||||||
| {currentSubTag.map((tag, idx) => ( | ||||||||||||||||||||||||||||||||||||||
| <div css={S.subTagChipStyling} key={tag}> | ||||||||||||||||||||||||||||||||||||||
|
Contributor
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. 🛠️ Refactor suggestion
현재 |
||||||||||||||||||||||||||||||||||||||
| <span>#{tag}</span> | ||||||||||||||||||||||||||||||||||||||
| <button | ||||||||||||||||||||||||||||||||||||||
| type="button" | ||||||||||||||||||||||||||||||||||||||
| css={S.subTagButtonStyling} | ||||||||||||||||||||||||||||||||||||||
| onClick={() => handleDeleteSubTag(idx)} | ||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||
| ⨉ | ||||||||||||||||||||||||||||||||||||||
| </button> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| ))} | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||
| name="subTag" | ||||||||||||||||||||||||||||||||||||||
| css={S.inputStyling} | ||||||||||||||||||||||||||||||||||||||
| placeholder="ex. 너무어려운밸런스게임, 선택장애, 이상형" | ||||||||||||||||||||||||||||||||||||||
| value={form.subTag} | ||||||||||||||||||||||||||||||||||||||
| onChange={setSubTagValue} | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| {currentSubTag.length !== 3 && ( | ||||||||||||||||||||||||||||||||||||||
| <div css={S.inputWrapper}> | ||||||||||||||||||||||||||||||||||||||
| <input | ||||||||||||||||||||||||||||||||||||||
| type="text" | ||||||||||||||||||||||||||||||||||||||
| ref={inputRef} | ||||||||||||||||||||||||||||||||||||||
| css={S.inputStyling} | ||||||||||||||||||||||||||||||||||||||
| value={inputValue} | ||||||||||||||||||||||||||||||||||||||
| placeholder="ex. 연애, 데이트, 데이트취향" | ||||||||||||||||||||||||||||||||||||||
| onChange={handleInputChange} | ||||||||||||||||||||||||||||||||||||||
| onKeyUp={handleKeyUp} | ||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||
| {inputError && ( | ||||||||||||||||||||||||||||||||||||||
| <span css={S.errorMessageStyling}> | ||||||||||||||||||||||||||||||||||||||
| 서브태그 1개 당 최대 10자까지 입력 가능 | ||||||||||||||||||||||||||||||||||||||
| </span> | ||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| )} | ||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||
| size="large" | ||||||||||||||||||||||||||||||||||||||
| variant="roundPrimary" | ||||||||||||||||||||||||||||||||||||||
| onClick={handleTagSubmit} | ||||||||||||||||||||||||||||||||||||||
| disabled={!currentMainTag} | ||||||||||||||||||||||||||||||||||||||
| active={!!currentMainTag} | ||||||||||||||||||||||||||||||||||||||
| css={S.customButtonStyle(!currentMainTag)} | ||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||
| 등록하기 | ||||||||||||||||||||||||||||||||||||||
| </Button> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| <Button | ||||||||||||||||||||||||||||||||||||||
| size="large" | ||||||||||||||||||||||||||||||||||||||
| variant="roundPrimary" | ||||||||||||||||||||||||||||||||||||||
| onClick={handleTagSubmit} | ||||||||||||||||||||||||||||||||||||||
| disabled={!currentMainTag} | ||||||||||||||||||||||||||||||||||||||
| active={!!currentMainTag} | ||||||||||||||||||||||||||||||||||||||
| css={S.customButtonStyle(!currentMainTag)} | ||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||
| 등록하기 | ||||||||||||||||||||||||||||||||||||||
| </Button> | ||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||
| </Modal> | ||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| const color = { | ||
| MAIN: '#7782FF', | ||
| SECONDARY: '#9DB7FF', | ||
| BK: '#181818', | ||
| GY: { | ||
| 1: '#8C8C8C', | ||
|
|
||
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.
의 ref를 훅과 적절하게 연결되어 있는거 같네요~