-
Notifications
You must be signed in to change notification settings - Fork 2
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
상품검색 페이지 #105
상품검색 페이지 #105
Changes from 4 commits
f427f5b
4d714a7
20285bd
29b00a6
1f0e732
a41e2d3
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,73 @@ | ||
import React, { useRef, forwardRef, useImperativeHandle } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
|
||
import { Grid } from '@material-ui/core'; | ||
import { makeStyles } from '@material-ui/core/styles'; | ||
|
||
import ClearIcon from '@material-ui/icons/HighlightOff'; | ||
|
||
const useStyles = makeStyles({ | ||
root: { | ||
backgroundColor: 'rgb(244,244,244)', | ||
padding: '0.2rem', | ||
borderRadius: '0.5rem', | ||
}, | ||
input: { | ||
backgroundColor: 'rgb(244,244,244)', | ||
border: 0, | ||
flex: 1, | ||
padding: 0, | ||
height: '1.5rem', | ||
}, | ||
icon: { | ||
color: '#bebebe' | ||
} | ||
}); | ||
|
||
const Search = ({ onChange, onKeyDown }, ref) => { | ||
const inputRef = useRef(null); | ||
const classes = useStyles({}); | ||
|
||
useImperativeHandle(ref, () => ({ | ||
set: (input) => { | ||
inputRef.current.value = input; | ||
}, | ||
get: () => { | ||
return inputRef.current.value; | ||
}, | ||
})); | ||
|
||
const onClearInput = () => { | ||
inputRef.current.value = ''; | ||
}; | ||
|
||
return ( | ||
<Grid | ||
container | ||
justify='space-around' | ||
alignItems='center' | ||
className={classes.root} | ||
> | ||
<input | ||
ref={inputRef} | ||
placeholder='검색어를 입력하세요.' | ||
className={classes.input} | ||
onChange={onChange} | ||
onKeyDown={onKeyDown} | ||
/> | ||
<ClearIcon onClick={onClearInput} className={classes.icon} /> | ||
</Grid> | ||
); | ||
}; | ||
|
||
Search.propTypes = { | ||
onChange: PropTypes.func, | ||
onKeyDown: PropTypes.func, | ||
}; | ||
|
||
Search.defaultProps = { | ||
onChange: () => { }, | ||
onKeyDown: () => { }, | ||
} | ||
|
||
export default forwardRef(Search); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import axios from 'axios'; | ||
import Inko from 'inko'; | ||
import React, { useRef, useState, useEffect, useContext } from 'react'; | ||
|
||
import { useHistory } from 'react-router-dom'; | ||
|
||
import { List, ListItem } from '@material-ui/core'; | ||
import { makeStyles } from '@material-ui/core/styles'; | ||
|
||
import Input from '../components/search'; | ||
import ToolBar from '../components/tool-bar'; | ||
|
||
import { filterContext } from '../contexts/filters'; | ||
|
||
const useStyles = makeStyles({ | ||
'root': { | ||
width: '100%', | ||
'& h6': { | ||
width: '100%', | ||
}, | ||
} | ||
}); | ||
|
||
const getKeywordList = async (keyword) => { | ||
const response = await axios.get('http://localhost:5000/info/keyword', { | ||
params: { keyword } | ||
}) | ||
return response.data; | ||
} | ||
|
||
const isEnglishOnly = (keyword) => !(/[가-힣]/.test(keyword)); | ||
const isKoreanOnly = (keyword) => !(/[a-zA-Z]/.test(keyword)); | ||
|
||
export default () => { | ||
const SEARCH_DELAY = 500; | ||
const classes = useStyles({}); | ||
const inputRef = useRef({ current: '' }); | ||
const { filter: { keyword }, dispatch, TYPE } = useContext(filterContext); | ||
const [list, setList] = useState([]); | ||
const [recommend, setRecommned] = useState(''); | ||
const timer = { current: '' }; | ||
const histroy = useHistory(); | ||
|
||
useEffect(() => { | ||
if (keyword.length) { | ||
inputRef.current.set(keyword); | ||
} | ||
}, []); | ||
|
||
const inputKeyword = () => { | ||
const keyword = inputRef.current.get(); | ||
if (timer.current) { | ||
clearTimeout(timer.current); | ||
} | ||
timer.current = setTimeout(async () => { | ||
const data = await getKeywordList(keyword); | ||
const list = data.map(({ _source: { word } }) => word); | ||
setList(list); | ||
}, SEARCH_DELAY); | ||
} | ||
|
||
useEffect(() => { | ||
const keyword = inputRef.current.get(); | ||
let recommendKeyword = ''; | ||
if (list.length >= 1 || keyword.length <= 1) { | ||
setRecommned(''); | ||
return; | ||
} | ||
if (isEnglishOnly(keyword)) { | ||
recommendKeyword = new Inko().en2ko(keyword); | ||
} | ||
if (isKoreanOnly(keyword)) { | ||
recommendKeyword = new Inko().ko2en(keyword); | ||
} | ||
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. 이 부분에 대해서는 추가적으로 개선작업이 반드시 필요할 것으로 생각됩니다. 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. 혼동을 피하는 메소드로 변경하겠습니다. 영어 섞이는 경우는 다른 방법으로 고려해보겠습니다. |
||
if (recommendKeyword.length > 1) { | ||
setRecommned(recommendKeyword); | ||
}; | ||
}, [list]); | ||
|
||
const onTransferKeyword = () => { | ||
inputRef.current.set(recommend); | ||
inputKeyword(); | ||
}; | ||
|
||
const updateKeyword = (event) => { | ||
const name = event.target.innerText; | ||
dispatch({ type: TYPE.KEYWORD, payload: name }); | ||
histroy.goBack(); | ||
}; | ||
|
||
const enterEvent = (event) => { | ||
if (event.key !== 'Enter') { | ||
return; | ||
} | ||
const name = inputRef.current.get(); | ||
dispatch({ type: TYPE.KEYWORD, payload: name }); | ||
histroy.goBack(); | ||
} | ||
|
||
return ( | ||
<> | ||
<div className={classes.root}> | ||
<ToolBar title={<Input ref={inputRef} onChange={inputKeyword} onKeyDown={enterEvent} />} /> | ||
</div> | ||
<List className={classes.root}> | ||
{recommend.length > 0 && | ||
(<ListItem onClick={onTransferKeyword}>{recommend}를 입력하려 하셨나요?</ListItem>) | ||
} | ||
{list.map((name) => ( | ||
<ListItem onClick={updateKeyword} divider button key={name}>{name}</ListItem> | ||
))} | ||
</List> | ||
</> | ||
); | ||
}; |
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.
api 호출은 custom Hooks 등의 방법으로 외부로 분리하여야 할 것 같네요. uri는 또 별도의 파일로 관리가 필요하겠고요.