2026-01-06 17:47:30 +09:00

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>
)
}