Update handling for over mastery and awakening
- Rings are now arrays, not objects - Awakenings lookup based on slug, not id - Use 0-index for rings, not 1-index - Add appropriate optional operators - Add temporary lookup table for character awakenings
This commit is contained in:
parent
a188143422
commit
75a3e26cce
6 changed files with 107 additions and 105 deletions
|
|
@ -65,7 +65,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const overMasterySection = () => {
|
||||
if (props.gridCharacter && props.gridCharacter.over_mastery) {
|
||||
if (props.gridCharacter && props.gridCharacter.over_mastery.length > 0) {
|
||||
return (
|
||||
<section className={styles.mastery}>
|
||||
<h5 className={tintElement}>
|
||||
|
|
@ -73,14 +73,13 @@ const CharacterHovercard = (props: Props) => {
|
|||
</h5>
|
||||
<ul>
|
||||
{[...Array(4)].map((e, i) => {
|
||||
const ringIndex = i + 1
|
||||
const ringStat: ExtendedMastery =
|
||||
props.gridCharacter.over_mastery[ringIndex]
|
||||
props.gridCharacter.over_mastery[i]
|
||||
|
||||
if (ringStat && ringStat.modifier && ringStat.modifier > 0) {
|
||||
if (ringIndex === 1 || ringIndex === 2) {
|
||||
if (i === 0 || i === 1) {
|
||||
return masteryElement(overMastery.a, ringStat)
|
||||
} else if (ringIndex === 3) {
|
||||
} else if (i === 2) {
|
||||
return masteryElement(overMastery.b, ringStat)
|
||||
} else {
|
||||
return masteryElement(overMastery.c, ringStat)
|
||||
|
|
@ -96,8 +95,9 @@ const CharacterHovercard = (props: Props) => {
|
|||
const aetherialMasterySection = () => {
|
||||
if (
|
||||
props.gridCharacter &&
|
||||
props.gridCharacter.over_mastery &&
|
||||
props.gridCharacter.aetherial_mastery &&
|
||||
props.gridCharacter.aetherial_mastery.modifier > 0
|
||||
props.gridCharacter.aetherial_mastery?.modifier > 0
|
||||
) {
|
||||
return (
|
||||
<section className={styles.mastery}>
|
||||
|
|
@ -136,9 +136,8 @@ const CharacterHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const awakeningSection = () => {
|
||||
const gridAwakening = props.gridCharacter.awakening
|
||||
|
||||
if (gridAwakening) {
|
||||
if (props.gridCharacter.awakening) {
|
||||
const gridAwakening = props.gridCharacter.awakening
|
||||
return (
|
||||
<section className={styles.awakening}>
|
||||
<h5 className={tintElement}>
|
||||
|
|
|
|||
|
|
@ -44,6 +44,13 @@ interface Props {
|
|||
updateCharacter: (object: GridCharacterObject) => Promise<any>
|
||||
}
|
||||
|
||||
const AWAKENING_MAP: { [key: string]: string } = {
|
||||
'character-balanced': 'b1847c82-ece0-4d7a-8af1-c7868d90f34a',
|
||||
'character-atk': '6e233877-8cda-4c8f-a091-3db6f68749e2',
|
||||
'character-def': 'c95441de-f949-4a62-b02b-101aa2e0a638',
|
||||
'character-multi': 'e36b0573-79c3-4dd2-9524-c95def4bbb1a',
|
||||
}
|
||||
|
||||
const CharacterModal = ({
|
||||
gridCharacter,
|
||||
children,
|
||||
|
|
@ -64,12 +71,7 @@ const CharacterModal = ({
|
|||
|
||||
// State: Data
|
||||
const [perpetuity, setPerpetuity] = useState(false)
|
||||
const [rings, setRings] = useState<CharacterOverMastery>({
|
||||
1: { ...emptyExtendedMastery, modifier: 1 },
|
||||
2: { ...emptyExtendedMastery, modifier: 2 },
|
||||
3: emptyExtendedMastery,
|
||||
4: emptyExtendedMastery,
|
||||
})
|
||||
const [rings, setRings] = useState<CharacterOverMastery>([])
|
||||
const [earring, setEarring] = useState<ExtendedMastery>(emptyExtendedMastery)
|
||||
const [awakening, setAwakening] = useState<Awakening>()
|
||||
const [awakeningLevel, setAwakeningLevel] = useState(1)
|
||||
|
|
@ -94,46 +96,36 @@ const CharacterModal = ({
|
|||
})
|
||||
}
|
||||
|
||||
setAwakening(gridCharacter.awakening.type)
|
||||
setAwakeningLevel(gridCharacter.awakening.level)
|
||||
if (gridCharacter.awakening) {
|
||||
setAwakening(gridCharacter.awakening.type)
|
||||
setAwakeningLevel(gridCharacter.awakening.level)
|
||||
}
|
||||
setPerpetuity(gridCharacter.perpetuity)
|
||||
}, [gridCharacter])
|
||||
|
||||
// Prepare the GridWeaponObject to send to the server
|
||||
function prepareObject() {
|
||||
let object: GridCharacterObject = {
|
||||
function prepareObject(): GridCharacterObject {
|
||||
return {
|
||||
character: {
|
||||
ring1: {
|
||||
modifier: rings[1].modifier,
|
||||
strength: rings[1].strength,
|
||||
},
|
||||
ring2: {
|
||||
modifier: rings[2].modifier,
|
||||
strength: rings[2].strength,
|
||||
},
|
||||
ring3: {
|
||||
modifier: rings[3].modifier,
|
||||
strength: rings[3].strength,
|
||||
},
|
||||
ring4: {
|
||||
modifier: rings[4].modifier,
|
||||
strength: rings[4].strength,
|
||||
},
|
||||
rings: rings, // your local rings array
|
||||
earring: {
|
||||
modifier: earring.modifier,
|
||||
strength: earring.strength,
|
||||
strength:
|
||||
earring.modifier && earring.modifier > 0 ? earring.strength : 0,
|
||||
},
|
||||
// Only include awakening if one is set.
|
||||
...(awakening
|
||||
? {
|
||||
awakening: {
|
||||
id: awakening.id,
|
||||
level: awakeningLevel,
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
transcendence_step: transcendenceStep,
|
||||
perpetuity: perpetuity,
|
||||
},
|
||||
}
|
||||
|
||||
if (awakening) {
|
||||
object.character.awakening_id = awakening.id
|
||||
object.character.awakening_level = awakeningLevel
|
||||
}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
// Methods: Modification checking
|
||||
|
|
@ -152,12 +144,12 @@ const CharacterModal = ({
|
|||
|
||||
function ringsChanged() {
|
||||
// Create an empty ExtendedMastery object
|
||||
const emptyRingset: CharacterOverMastery = {
|
||||
1: { ...emptyExtendedMastery, modifier: 1 },
|
||||
2: { ...emptyExtendedMastery, modifier: 2 },
|
||||
3: emptyExtendedMastery,
|
||||
4: emptyExtendedMastery,
|
||||
}
|
||||
const emptyRingset: CharacterOverMastery = [
|
||||
{ ...emptyExtendedMastery, modifier: 1 },
|
||||
{ ...emptyExtendedMastery, modifier: 2 },
|
||||
emptyExtendedMastery,
|
||||
emptyExtendedMastery,
|
||||
]
|
||||
|
||||
// Check if the current ringset is empty on the current GridCharacter and our local state
|
||||
const isEmptyRingset =
|
||||
|
|
@ -195,8 +187,8 @@ const CharacterModal = ({
|
|||
function awakeningChanged() {
|
||||
// Check if the awakening in local state is different from the one on the current GridCharacter
|
||||
const awakeningChanged =
|
||||
!isEqual(gridCharacter.awakening.type, awakening) ||
|
||||
gridCharacter.awakening.level !== awakeningLevel
|
||||
!isEqual(gridCharacter.awakening?.type, awakening) ||
|
||||
gridCharacter.awakening?.level !== awakeningLevel
|
||||
|
||||
// Return true if the awakening has been modified and is not empty
|
||||
return awakeningChanged
|
||||
|
|
@ -227,8 +219,26 @@ const CharacterModal = ({
|
|||
})
|
||||
}
|
||||
|
||||
function receiveAwakeningValues(id: string, level: number) {
|
||||
setAwakening(gridCharacter.object.awakenings.find((a) => a.id === id))
|
||||
function receiveAwakeningValues(slug: string, level: number) {
|
||||
const mappedId = AWAKENING_MAP[slug] || null
|
||||
const existingAwakening = gridCharacter.object.awakenings.find(
|
||||
(a) => a.slug === slug
|
||||
)
|
||||
|
||||
if (existingAwakening && mappedId) {
|
||||
setAwakening({
|
||||
...existingAwakening,
|
||||
id: mappedId,
|
||||
})
|
||||
} else {
|
||||
setAwakening({
|
||||
id: mappedId || '',
|
||||
slug,
|
||||
name: { en: '', jp: '' },
|
||||
order: 0,
|
||||
})
|
||||
}
|
||||
|
||||
setAwakeningLevel(level)
|
||||
}
|
||||
|
||||
|
|
@ -307,13 +317,13 @@ const CharacterModal = ({
|
|||
object="earring"
|
||||
dataSet={elementalizeAetherialMastery(gridCharacter)}
|
||||
selectValue={
|
||||
gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.modifier
|
||||
gridCharacter.over_mastery && gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery?.modifier
|
||||
: 0
|
||||
}
|
||||
inputValue={
|
||||
gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.strength
|
||||
gridCharacter.over_mastery && gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery?.strength
|
||||
: 0
|
||||
}
|
||||
sendValidity={receiveValidity}
|
||||
|
|
|
|||
|
|
@ -148,12 +148,12 @@ const CharacterUnit = ({
|
|||
let character = cloneDeep(gridCharacter)
|
||||
|
||||
if (character.over_mastery) {
|
||||
const overMastery: CharacterOverMastery = {
|
||||
1: gridCharacter.over_mastery[0],
|
||||
2: gridCharacter.over_mastery[1],
|
||||
3: gridCharacter.over_mastery[2],
|
||||
4: gridCharacter.over_mastery[3],
|
||||
}
|
||||
const overMastery: CharacterOverMastery = [
|
||||
gridCharacter.over_mastery[0],
|
||||
gridCharacter.over_mastery[1],
|
||||
gridCharacter.over_mastery[2],
|
||||
gridCharacter.over_mastery[3],
|
||||
]
|
||||
|
||||
character.over_mastery = overMastery
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// Core dependencies
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
|
@ -73,7 +72,8 @@ const AwakeningSelectWithInput = ({
|
|||
setCurrentAwakening(awakening)
|
||||
setCurrentLevel(level ? level : 1)
|
||||
|
||||
if (awakening) sendValidity(true)
|
||||
// If there is an awakening (even if it's the default) we consider the field valid.
|
||||
if (awakening || defaultAwakening) sendValidity(true)
|
||||
}, [])
|
||||
|
||||
// Methods: UI state management
|
||||
|
|
@ -90,35 +90,32 @@ const AwakeningSelectWithInput = ({
|
|||
|
||||
// Methods: Rendering
|
||||
function generateOptions() {
|
||||
const sortedDataSet = [...dataSet].sort((a, b) => {
|
||||
return a.order - b.order
|
||||
})
|
||||
|
||||
let options: React.ReactNode[] = sortedDataSet.map((awakening, i) => {
|
||||
return generateItem(awakening)
|
||||
})
|
||||
|
||||
const sortedDataSet = [...dataSet].sort((a, b) => a.order - b.order)
|
||||
let options: React.ReactNode[] = sortedDataSet.map((awakening) =>
|
||||
generateItem(awakening)
|
||||
)
|
||||
if (!dataSet.includes(defaultAwakening))
|
||||
options.unshift(generateItem(defaultAwakening))
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
function generateItem(awakening: Awakening) {
|
||||
return (
|
||||
<SelectItem key={awakening.slug} value={awakening.id}>
|
||||
<SelectItem key={awakening.slug} value={awakening.slug}>
|
||||
{awakening.name[locale]}
|
||||
</SelectItem>
|
||||
)
|
||||
}
|
||||
|
||||
// Methods: User input detection
|
||||
function handleSelectChange(id: string) {
|
||||
function handleSelectChange(value: string) {
|
||||
// Here, value is the awakening slug.
|
||||
const input = inputRef.current
|
||||
if (input && !handleInputError(parseFloat(input.value))) return
|
||||
|
||||
setCurrentAwakening(dataSet.find((awakening) => awakening.id === id))
|
||||
sendValues(id, currentLevel)
|
||||
const selectedAwakening = dataSet.find((a) => a.slug === value)
|
||||
setCurrentAwakening(selectedAwakening)
|
||||
sendValues(value, currentLevel)
|
||||
}
|
||||
|
||||
function handleInputChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
|
|
@ -127,7 +124,10 @@ const AwakeningSelectWithInput = ({
|
|||
|
||||
const newLevel = parseInt(event.target.value)
|
||||
setCurrentLevel(newLevel)
|
||||
sendValues(currentAwakening ? currentAwakening.id : '0', newLevel)
|
||||
sendValues(
|
||||
currentAwakening ? currentAwakening.slug : defaultAwakening.slug,
|
||||
newLevel
|
||||
)
|
||||
}
|
||||
|
||||
// Methods: Handle error
|
||||
|
|
@ -135,16 +135,12 @@ const AwakeningSelectWithInput = ({
|
|||
let error = ''
|
||||
|
||||
if (currentAwakening) {
|
||||
if (value && value % 1 != 0) {
|
||||
if (value && value % 1 !== 0) {
|
||||
error = t(`awakening.errors.value_not_whole`)
|
||||
} else if (value < 1) {
|
||||
error = t(`awakening.errors.value_too_low`, {
|
||||
minValue: 1,
|
||||
})
|
||||
error = t(`awakening.errors.value_too_low`, { minValue: 1 })
|
||||
} else if (value > maxLevel) {
|
||||
error = t(`awakening.errors.value_too_high`, {
|
||||
maxValue: maxLevel,
|
||||
})
|
||||
error = t(`awakening.errors.value_too_high`, { maxValue: maxLevel })
|
||||
} else if (!value || value <= 0) {
|
||||
error = t(`awakening.errors.value_empty`)
|
||||
} else {
|
||||
|
|
@ -165,13 +161,9 @@ const AwakeningSelectWithInput = ({
|
|||
|
||||
const rangeString = () => {
|
||||
let placeholder = ''
|
||||
|
||||
if (awakening) {
|
||||
const minValue = 1
|
||||
const maxValue = maxLevel
|
||||
placeholder = `${minValue}~${maxValue}`
|
||||
if (currentAwakening) {
|
||||
placeholder = `1~${maxLevel}`
|
||||
}
|
||||
|
||||
return placeholder
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +172,8 @@ const AwakeningSelectWithInput = ({
|
|||
<div className={styles.set}>
|
||||
<Select
|
||||
key="awakening-type"
|
||||
value={`${awakening ? awakening.id : defaultAwakening.id}`}
|
||||
// Use the slug as the value
|
||||
value={`${awakening ? awakening.slug : defaultAwakening.slug}`}
|
||||
open={open}
|
||||
disabled={selectDisabled}
|
||||
onValueChange={handleSelectChange}
|
||||
|
|
@ -200,7 +193,8 @@ const AwakeningSelectWithInput = ({
|
|||
className={inputClasses}
|
||||
fieldsetClassName={classNames({
|
||||
hidden:
|
||||
currentAwakening === undefined || currentAwakening.id === '0',
|
||||
currentAwakening === undefined ||
|
||||
currentAwakening.slug === defaultAwakening.slug,
|
||||
})}
|
||||
wrapperClassName="fullHeight"
|
||||
bound={true}
|
||||
|
|
|
|||
|
|
@ -324,13 +324,13 @@ const Party = (props: Props) => {
|
|||
list.forEach((object: GridCharacter) => {
|
||||
let character = clonedeep(object)
|
||||
|
||||
if (character.over_mastery) {
|
||||
const overMastery: CharacterOverMastery = {
|
||||
1: object.over_mastery[0],
|
||||
2: object.over_mastery[1],
|
||||
3: object.over_mastery[2],
|
||||
4: object.over_mastery[3],
|
||||
}
|
||||
if (character.over_mastery && character.over_mastery) {
|
||||
const overMastery: CharacterOverMastery = [
|
||||
object.over_mastery[0],
|
||||
object.over_mastery[1],
|
||||
object.over_mastery[2],
|
||||
object.over_mastery[3],
|
||||
]
|
||||
|
||||
character.over_mastery = overMastery
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,13 +136,12 @@ const WeaponModal = ({
|
|||
}
|
||||
|
||||
// Receive values from AwakeningSelectWithInput
|
||||
function receiveAwakeningValues(id: string, level: number) {
|
||||
setAwakening(gridWeapon.object.awakenings.find((a) => a.id === id))
|
||||
console.log(level)
|
||||
function receiveAwakeningValues(slug: string, level: number) {
|
||||
// Look up the awakening by its slug, since the select sends a slug.
|
||||
setAwakening(gridWeapon.object.awakenings.find((a) => a.slug === slug))
|
||||
setAwakeningLevel(level)
|
||||
setFormValid(true)
|
||||
}
|
||||
|
||||
// Receive values from WeaponKeySelect
|
||||
function receiveWeaponKey(value: WeaponKey, slot: number) {
|
||||
if (slot === 0) setWeaponKey1(value)
|
||||
|
|
|
|||
Loading…
Reference in a new issue