Refactored WeaponKeySelect and updated styles

This commit is contained in:
Justin Edmund 2022-12-20 23:06:27 -08:00
parent 9a9a0397e9
commit 85fd5df516
9 changed files with 120 additions and 68 deletions

View file

@ -311,7 +311,7 @@ const AXSelect = (props: Props) => {
if (ax) {
const rangeString = `${ax.minValue}~${ax.maxValue}${ax.suffix || ''}`
element.className = 'Input Visible'
element.className = 'Input Contained Visible'
element.disabled = false
element.placeholder = rangeString
element.min = `${ax.minValue}`
@ -320,12 +320,12 @@ const AXSelect = (props: Props) => {
} else {
if (primaryAxValueInput.current && secondaryAxValueInput.current) {
if (primaryAxValueInput.current == element) {
primaryAxValueInput.current.className = 'Input'
primaryAxValueInput.current.className = 'Input Contained'
primaryAxValueInput.current.disabled = true
primaryAxValueInput.current.placeholder = ''
}
secondaryAxValueInput.current.className = 'Input'
secondaryAxValueInput.current.className = 'Input Contained'
secondaryAxValueInput.current.disabled = true
secondaryAxValueInput.current.placeholder = ''
}
@ -356,6 +356,7 @@ const AXSelect = (props: Props) => {
open={openAX1}
onChange={handleAX1SelectChange}
onClick={() => openSelect(primaryAxModifierSelect)}
triggerClass="modal"
ref={primaryAxModifierSelect}
>
{generateOptions(0)}
@ -383,6 +384,7 @@ const AXSelect = (props: Props) => {
open={openAX2}
onChange={handleAX2SelectChange}
onClick={() => openSelect(secondaryAxModifierSelect)}
triggerClass="modal"
ref={secondaryAxModifierSelect}
>
{generateOptions(1)}

View file

@ -7,6 +7,14 @@
display: block;
padding: $unit-2x;
width: 100%;
&.Contained {
background-color: var(--input-bound-bg);
&:hover {
background-color: var(--input-bound-bg-hover);
}
}
}
.InputError {

View file

@ -7,15 +7,26 @@ interface Props
React.InputHTMLAttributes<HTMLInputElement>,
HTMLInputElement
> {
contained?: boolean
error?: string
label?: string
}
const defaultProps = {
contained: false,
}
const Input = React.forwardRef<HTMLInputElement, Props>(function input(
props: Props,
{ contained, error, label, ...props },
forwardedRef
) {
const classes = classNames({ Input: true }, props.className)
const classes = classNames(
{
Input: true,
Contained: contained,
},
props.className
)
return (
<label className="Label" htmlFor={props.name}>
@ -27,12 +38,12 @@ const Input = React.forwardRef<HTMLInputElement, Props>(function input(
ref={forwardedRef}
formNoValidate
/>
{props.label}
{props.error && props.error.length > 0 && (
<p className="InputError">{props.error}</p>
)}
{label}
{error && error.length > 0 && <p className="InputError">{error}</p>}
</label>
)
})
Input.defaultProps = defaultProps
export default Input

View file

@ -6,9 +6,22 @@
display: flex;
padding: $unit-2x $unit-2x;
&.modal {
background-color: var(--select-modal-bg);
&:hover {
background-color: var(--select-modal-bg-hover);
}
}
&:hover {
background-color: var(--input-bg-hover);
color: var(--text-primary);
cursor: pointer;
&[data-placeholder] > span:not(.SelectIcon) {
color: var(--text-primary);
}
}
&[data-placeholder] > span:not(.SelectIcon) {

View file

@ -11,25 +11,27 @@ interface Props {
open: boolean
defaultValue?: string | number
placeholder?: string
trigger?: React.ReactNode
name?: string
children?: React.ReactNode
onClick?: () => void
onChange?: (value: string) => void
triggerClass?: string
}
const Select = React.forwardRef<HTMLSelectElement, Props>(function useFieldSet(
const Select = React.forwardRef<HTMLButtonElement, Props>(function useFieldSet(
props,
ref
) {
return (
<RadixSelect.Root
defaultValue={props.defaultValue as string}
name={props.name}
onValueChange={props.onChange}
>
<RadixSelect.Trigger
className={classNames('SelectTrigger', props.triggerClass)}
placeholder={props.placeholder}
ref={ref}
>
<RadixSelect.Value placeholder={props.placeholder} />
<RadixSelect.Icon className="SelectIcon">

View file

@ -1,7 +1,7 @@
.SelectItem {
border-radius: $item-corner;
border: 2px solid transparent;
color: var(--text-secondary);
color: var(--text-tertiary);
font-size: $font-regular;
padding: ($unit * 1.5) $unit-2x;

View file

@ -1,5 +1,8 @@
import React, { useEffect, useState } from 'react'
import Select from '~components/Select'
import SelectGroup from '~components/SelectGroup'
import SelectItem from '~components/SelectItem'
import api from '~utils/api'
import './index.scss'
@ -9,14 +12,13 @@ interface Props {
currentValue?: WeaponKey
series: number
slot: number
onChange?: (event: React.ChangeEvent<HTMLSelectElement>) => void
onBlur?: (event: React.ChangeEvent<HTMLSelectElement>) => void
onChange?: (value: string, slot: number) => void
}
const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
function useFieldSet(props, ref) {
const [open, setOpen] = useState(false)
const [keys, setKeys] = useState<WeaponKey[][]>([])
const [currentKey, setCurrentKey] = useState('')
const pendulumNames = [
{ en: 'Pendulum', jp: '' },
@ -31,10 +33,6 @@ const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
{ en: 'Gate of Omnipotence', jp: '' },
]
useEffect(() => {
if (props.currentValue) setCurrentKey(props.currentValue.id)
}, [props.currentValue])
useEffect(() => {
const filterParams = {
params: {
@ -66,6 +64,10 @@ const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
fetchWeaponKeys()
}, [props.series, props.slot])
function openSelect() {
setOpen(!open)
}
function weaponKeyGroup(index: number) {
;['α', 'β', 'γ', 'Δ'].sort((a, b) => a.localeCompare(b, 'el'))
@ -78,9 +80,9 @@ const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
keys[index].length > 0 &&
keys[index].sort(sortByOrder).map((item, i) => {
return (
<option key={i} value={item.id}>
<SelectItem key={i} value={item.id}>
{item.name.en}
</option>
</SelectItem>
)
})
@ -93,21 +95,20 @@ const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
else if (props.series == 22) name = emblemNames[index]
return (
<optgroup
<SelectGroup
key={index}
label={
props.series == 17 && props.slot == 2 ? name.en : `${name.en}s`
}
separator={false}
>
{options}
</optgroup>
</SelectGroup>
)
}
function handleChange(event: React.ChangeEvent<HTMLSelectElement>) {
if (props.onChange) props.onChange(event)
setCurrentKey(event.currentTarget.value)
function handleChange(value: string) {
if (props.onChange) props.onChange(value, props.slot)
}
const emptyOption = () => {
@ -121,22 +122,24 @@ const WeaponKeyDropdown = React.forwardRef<HTMLSelectElement, Props>(
}
return (
<select
<Select
key={`weapon-key-${props.slot}`}
value={currentKey}
onBlur={props.onBlur}
defaultValue={props.currentValue ? props.currentValue.id : 'no-key'}
open={open}
onChange={handleChange}
onClick={openSelect}
ref={ref}
triggerClass="modal"
>
<option key="-1" value="-1">
<SelectItem key="no-key" value="no-key">
{emptyOption()}
</option>
</SelectItem>
{Array.from(Array(keys?.length)).map((x, i) => {
return weaponKeyGroup(i)
})}
</select>
</Select>
)
}
)
export default WeaponKeyDropdown
export default WeaponKeySelect

View file

@ -1,4 +1,4 @@
import React, { useState } from 'react'
import React, { useEffect, useState } from 'react'
import { getCookie } from 'cookies-next'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
@ -8,7 +8,7 @@ import * as Dialog from '@radix-ui/react-dialog'
import AXSelect from '~components/AxSelect'
import ElementToggle from '~components/ElementToggle'
import WeaponKeyDropdown from '~components/WeaponKeyDropdown'
import WeaponKeySelect from '~components/WeaponKeySelect'
import Button from '~components/Button'
import api from '~utils/api'
@ -50,21 +50,38 @@ const WeaponModal = (props: Props) => {
? { Authorization: `Bearer ${accountData.token}` }
: {}
// Refs
const weaponKey1Select = React.createRef<HTMLSelectElement>()
const weaponKey2Select = React.createRef<HTMLSelectElement>()
const weaponKey3Select = React.createRef<HTMLSelectElement>()
// State
const [open, setOpen] = useState(false)
const [formValid, setFormValid] = useState(false)
const [element, setElement] = useState(-1)
const [primaryAxModifier, setPrimaryAxModifier] = useState(-1)
const [secondaryAxModifier, setSecondaryAxModifier] = useState(-1)
const [primaryAxValue, setPrimaryAxValue] = useState(0.0)
const [secondaryAxValue, setSecondaryAxValue] = useState(0.0)
const [weaponKey1, setWeaponKey1] = useState<WeaponKey | undefined>()
const [weaponKey2, setWeaponKey2] = useState<WeaponKey | undefined>()
const [weaponKey3, setWeaponKey3] = useState<WeaponKey | undefined>()
const [weaponKey1Id, setWeaponKey1Id] = useState('')
const [weaponKey2Id, setWeaponKey2Id] = useState('')
const [weaponKey3Id, setWeaponKey3Id] = useState('')
useEffect(() => {
setElement(props.gridWeapon.element)
if (props.gridWeapon.weapon_keys) {
if (props.gridWeapon.weapon_keys[0]) {
setWeaponKey1(props.gridWeapon.weapon_keys[0])
}
if (props.gridWeapon.weapon_keys[1])
setWeaponKey2(props.gridWeapon.weapon_keys[1])
if (props.gridWeapon.weapon_keys[2])
setWeaponKey3(props.gridWeapon.weapon_keys[2])
}
}, [props])
function receiveAxValues(
primaryAxModifier: number,
primaryAxValue: number,
@ -91,14 +108,15 @@ const WeaponModal = (props: Props) => {
if (props.gridWeapon.object.element == 0) object.weapon.element = element
if ([2, 3, 17, 24].includes(props.gridWeapon.object.series))
object.weapon.weapon_key1_id = weaponKey1Select.current?.value
if ([2, 3, 17, 24].includes(props.gridWeapon.object.series)) {
object.weapon.weapon_key1_id = weaponKey1Id
}
if ([2, 3, 17].includes(props.gridWeapon.object.series))
object.weapon.weapon_key2_id = weaponKey2Select.current?.value
object.weapon.weapon_key2_id = weaponKey2Id
if (props.gridWeapon.object.series == 17)
object.weapon.weapon_key3_id = weaponKey3Select.current?.value
object.weapon.weapon_key3_id = weaponKey3Id
if (props.gridWeapon.object.ax > 0) {
object.weapon.ax_modifier1 = primaryAxModifier
@ -131,12 +149,18 @@ const WeaponModal = (props: Props) => {
console.error(error)
}
function receiveWeaponKey(value: string, slot: number) {
if (slot === 0) setWeaponKey1Id(value)
if (slot === 1) setWeaponKey2Id(value)
if (slot === 2) setWeaponKey3Id(value)
}
const elementSelect = () => {
return (
<section>
<h3>{t('modals.weapon.subtitles.element')}</h3>
<ElementToggle
currentElement={props.gridWeapon.element}
currentElement={element}
sendValue={receiveElementValue}
/>
</section>
@ -148,45 +172,33 @@ const WeaponModal = (props: Props) => {
<section>
<h3>{t('modals.weapon.subtitles.weapon_keys')}</h3>
{[2, 3, 17, 22].includes(props.gridWeapon.object.series) ? (
<WeaponKeyDropdown
currentValue={
props.gridWeapon.weapon_keys
? props.gridWeapon.weapon_keys[0]
: undefined
}
<WeaponKeySelect
currentValue={weaponKey1 != null ? weaponKey1 : undefined}
series={props.gridWeapon.object.series}
slot={0}
ref={weaponKey1Select}
onChange={receiveWeaponKey}
/>
) : (
''
)}
{[2, 3, 17].includes(props.gridWeapon.object.series) ? (
<WeaponKeyDropdown
currentValue={
props.gridWeapon.weapon_keys
? props.gridWeapon.weapon_keys[1]
: undefined
}
<WeaponKeySelect
currentValue={weaponKey2 != null ? weaponKey2 : undefined}
series={props.gridWeapon.object.series}
slot={1}
ref={weaponKey2Select}
onChange={receiveWeaponKey}
/>
) : (
''
)}
{props.gridWeapon.object.series == 17 ? (
<WeaponKeyDropdown
currentValue={
props.gridWeapon.weapon_keys
? props.gridWeapon.weapon_keys[2]
: undefined
}
<WeaponKeySelect
currentValue={weaponKey3 != null ? weaponKey3 : undefined}
series={props.gridWeapon.object.series}
slot={2}
ref={weaponKey3Select}
onChange={receiveWeaponKey}
/>
) : (
''
@ -245,6 +257,7 @@ const WeaponModal = (props: Props) => {
: ''}
{props.gridWeapon.object.ax > 0 ? axSelect() : ''}
<Button
contained={true}
onClick={updateWeapon}
disabled={props.gridWeapon.object.ax > 0 && !formValid}
text={t('modals.weapon.buttons.confirm')}