Implement SelectWithSelect
A table item with a select on the left and a select on the right
This commit is contained in:
parent
bbccf8427b
commit
0860e7d694
2 changed files with 179 additions and 0 deletions
16
components/SelectWithSelect/index.scss
Normal file
16
components/SelectWithSelect/index.scss
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
.SelectSet {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit;
|
||||
width: 100%;
|
||||
|
||||
.SelectTrigger.Left {
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.SelectTrigger.Right {
|
||||
flex-grow: 0;
|
||||
min-width: 10rem;
|
||||
}
|
||||
}
|
||||
163
components/SelectWithSelect/index.tsx
Normal file
163
components/SelectWithSelect/index.tsx
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// Core dependencies
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import classNames from 'classnames'
|
||||
|
||||
// UI Dependencies
|
||||
import Select from '~components/Select'
|
||||
import SelectItem from '~components/SelectItem'
|
||||
|
||||
// Styles and icons
|
||||
import './index.scss'
|
||||
|
||||
// Types
|
||||
interface Props {
|
||||
name: string
|
||||
object: 'ring'
|
||||
dataSet: ItemSkill[]
|
||||
leftSelectValue: number
|
||||
leftSelectDisabled: boolean
|
||||
rightSelectValue: number
|
||||
onOpenChange: (index: 'left' | 'right', open: boolean) => void
|
||||
sendValues: (left: number, right: number) => void
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
selectDisabled: false,
|
||||
}
|
||||
|
||||
const SelectWithInput = ({
|
||||
name,
|
||||
object,
|
||||
dataSet,
|
||||
leftSelectDisabled,
|
||||
leftSelectValue,
|
||||
rightSelectValue,
|
||||
onOpenChange,
|
||||
sendValues,
|
||||
}: Props) => {
|
||||
const router = useRouter()
|
||||
const locale =
|
||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||
const { t } = useTranslation('common')
|
||||
|
||||
// UI state
|
||||
const [leftSelectOpen, setLeftSelectOpen] = useState(false)
|
||||
const [rightSelectOpen, setRightSelectOpen] = useState(false)
|
||||
|
||||
// Field properties
|
||||
// prettier-ignore
|
||||
const [currentItemSkill, setCurrentItemSkill] = useState<ItemSkill | undefined>(undefined)
|
||||
const [currentItemValue, setCurrentItemValue] = useState(rightSelectValue)
|
||||
|
||||
// Hooks
|
||||
|
||||
// Set default values from props
|
||||
useEffect(() => {
|
||||
setCurrentItemSkill(dataSet.find((sk) => sk.id === leftSelectValue))
|
||||
setCurrentItemValue(rightSelectValue)
|
||||
}, [leftSelectValue, rightSelectValue])
|
||||
|
||||
// Methods: UI state management
|
||||
function changeOpen(side: 'left' | 'right') {
|
||||
if (side === 'left' && !leftSelectDisabled) {
|
||||
setLeftSelectOpen(!leftSelectOpen)
|
||||
onOpenChange('left', !open)
|
||||
} else if (side === 'right') {
|
||||
setRightSelectOpen(!rightSelectOpen)
|
||||
onOpenChange('right', !open)
|
||||
}
|
||||
}
|
||||
|
||||
function onClose() {
|
||||
onOpenChange('left', false)
|
||||
onOpenChange('right', false)
|
||||
}
|
||||
|
||||
// Methods: Rendering
|
||||
function generateLeftOptions() {
|
||||
let options: React.ReactNode[] = dataSet.map((skill, i) => {
|
||||
return (
|
||||
<SelectItem key={`${name}-key-${i}`} value={skill.id}>
|
||||
{skill.name[locale]}
|
||||
</SelectItem>
|
||||
)
|
||||
})
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function generateRightOptions() {
|
||||
if (currentItemSkill && currentItemSkill.values) {
|
||||
let options = currentItemSkill.values.map((value, i) => {
|
||||
return (
|
||||
<SelectItem key={`${name}-values-${i + 1}`} value={value}>
|
||||
{value}
|
||||
{currentItemSkill.suffix ? currentItemSkill.suffix : ''}
|
||||
</SelectItem>
|
||||
)
|
||||
})
|
||||
|
||||
options.unshift(
|
||||
<SelectItem key={`${name}-values-0`} value="no-value">
|
||||
{t('no_value')}
|
||||
</SelectItem>
|
||||
)
|
||||
|
||||
return options
|
||||
}
|
||||
}
|
||||
|
||||
// Methods: User input detection
|
||||
function handleLeftSelectChange(rawValue: string) {
|
||||
const value = parseInt(rawValue)
|
||||
const skill = dataSet.find((sk) => sk.id === value)
|
||||
setCurrentItemSkill(skill)
|
||||
setCurrentItemValue(0)
|
||||
sendValues(leftSelectValue, rightSelectValue)
|
||||
}
|
||||
|
||||
function handleRightSelectChange(rawValue: string) {
|
||||
const value = parseFloat(rawValue)
|
||||
setCurrentItemValue(value)
|
||||
sendValues(leftSelectValue, rightSelectValue)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="SelectSet">
|
||||
<Select
|
||||
key={`${name}_type`}
|
||||
value={`${currentItemSkill ? currentItemSkill.id : 0}`}
|
||||
open={leftSelectOpen}
|
||||
disabled={leftSelectDisabled}
|
||||
onValueChange={handleLeftSelectChange}
|
||||
onOpenChange={() => changeOpen('left')}
|
||||
onClose={onClose}
|
||||
triggerClass="Left modal"
|
||||
>
|
||||
{generateLeftOptions()}
|
||||
</Select>
|
||||
|
||||
<Select
|
||||
key={`${name}_value`}
|
||||
value={`${currentItemValue > 0 ? currentItemValue : 'no-value'}`}
|
||||
open={rightSelectOpen}
|
||||
onValueChange={handleRightSelectChange}
|
||||
onOpenChange={() => changeOpen('right')}
|
||||
onClose={onClose}
|
||||
triggerClass={classNames({
|
||||
Right: true,
|
||||
modal: true,
|
||||
hidden: currentItemSkill?.id === 0,
|
||||
})}
|
||||
>
|
||||
{generateRightOptions()}
|
||||
</Select>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
SelectWithInput.defaultProps = defaultProps
|
||||
|
||||
export default SelectWithInput
|
||||
Loading…
Reference in a new issue