110 lines
3.6 KiB
JavaScript
110 lines
3.6 KiB
JavaScript
'use client'
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import { useOnClickOutside } from 'usehooks-ts'
|
|
import { useMessage } from '@/hooks/useMessage'
|
|
|
|
/**
|
|
*
|
|
* @param {string} title - 선택 제목 (선택이 없을때 보여질 값)
|
|
* @param {array} options - 선택 옵션 객체 {}
|
|
* @param {function} onChange - 선택 변경 함수
|
|
* @param {object} value - 선택 값 객체 {}
|
|
* @param {boolean} disabled - 선택 비활성화 여부
|
|
* @param {string} sourceKey - options에 있는 키
|
|
* @param {string} targetKey - value에 있는 키
|
|
* @param {string} showKey - options 있는 키중 보여줄 키
|
|
* @param {object} params - 추가 파라미터
|
|
* @param {boolean} showFirstOptionWhenEmpty - value가 빈값일 때 첫 번째 옵션을 보여줄지 여부
|
|
* @returns
|
|
*/
|
|
export default function QSelectBox({
|
|
title = '',
|
|
options = [],
|
|
onChange,
|
|
value,
|
|
disabled = false,
|
|
sourceKey = '',
|
|
targetKey = '',
|
|
showKey = '',
|
|
params = {},
|
|
tagTitle = '',
|
|
showFirstOptionWhenEmpty = false,
|
|
}) {
|
|
const { getMessage } = useMessage()
|
|
|
|
/**
|
|
* 초기 상태 처리
|
|
* useState 초기 값으로 사용해야 해서 useState 보다 위에 작성
|
|
* @returns {string} 초기 상태
|
|
*/
|
|
const handleInitState = () => {
|
|
if (options.length === 0) return title !== '' ? title : getMessage('selectbox.title')
|
|
if (showKey !== '' && !value) {
|
|
//value가 없으면 showKey가 있으면 우선 보여준다
|
|
if (showFirstOptionWhenEmpty && options.length > 0) {
|
|
return options[0][showKey]
|
|
}
|
|
return title !== '' ? title : getMessage('selectbox.title')
|
|
} else if (showKey !== '' && value) {
|
|
//value가 있으면 sourceKey와 targetKey를 비교하여 보여준다
|
|
|
|
const option = options.find((option) => {
|
|
return option[sourceKey] === value[targetKey]
|
|
})
|
|
if (!option) {
|
|
if (showFirstOptionWhenEmpty && options.length > 0) {
|
|
return options[0][showKey]
|
|
}
|
|
return title !== '' ? title : getMessage('selectbox.title')
|
|
} else {
|
|
return option[showKey]
|
|
}
|
|
} else {
|
|
//일치하는 조건이 없으면 기본값을 보여준다.
|
|
if (showFirstOptionWhenEmpty && options.length > 0) {
|
|
return showKey !== '' ? options[0][showKey] : options[0].name
|
|
}
|
|
return title !== '' ? title : getMessage('selectbox.title')
|
|
}
|
|
}
|
|
|
|
const [openSelect, setOpenSelect] = useState(false)
|
|
const [selected, setSelected] = useState(handleInitState())
|
|
const ref = useRef(null)
|
|
|
|
const handleClickSelectOption = (option) => {
|
|
setSelected(showKey !== '' ? option[showKey] : option.name)
|
|
onChange?.(option, params)
|
|
}
|
|
|
|
const handleClose = () => {
|
|
setOpenSelect(false)
|
|
}
|
|
|
|
useEffect(() => {
|
|
// value && handleClickSelectOption(value)
|
|
setSelected(handleInitState())
|
|
}, [options, value, sourceKey, targetKey, showKey, showFirstOptionWhenEmpty])
|
|
|
|
useOnClickOutside(ref, handleClose)
|
|
|
|
return (
|
|
<div
|
|
className={`sort-select ${openSelect ? 'active' : ''} ${disabled ? 'disabled' : ''}`}
|
|
ref={ref}
|
|
onClick={disabled ? () => {} : () => setOpenSelect(!openSelect)}
|
|
title={tagTitle}
|
|
>
|
|
<p>{selected}</p>
|
|
<ul className="select-item-wrap" style={{ maxHeight: '200px' }}>
|
|
{options?.length > 0 &&
|
|
options?.map((option, index) => (
|
|
<li key={option.id + '_' + index} className="select-item" onClick={() => handleClickSelectOption(option)}>
|
|
<button key={option.id + 'btn'}>{showKey !== '' ? option[showKey] : option.name}</button>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
)
|
|
}
|