hensei-web/components/mastery/RingSelect/index.tsx
Justin Edmund a02a6c70aa
Jedmund/image embeds 2 (#424)
## Component Refactors:
- Updated `CharacterHovercard` to improve over mastery and awakening
section logic.
- Refactored `CharacterModal` to streamline state management (rings,
awakening, perpetuity) and object preparation.
- Adjusted `CharacterUnit` for consistent over mastery handling.
- Simplified `AwakeningSelectWithInput` to use awakening slug values and
improve error handling.
- Updated `RingSelect` to refine ring value syncing and index logic.
- Modified `Party` and `PartyHead` to ensure consistent over mastery
processing and proper preview URL construction.
- Updated `WeaponModal` to align awakening value handling with the new
slug-based approach.

## Styling and Configuration:
- Improved grid layout and styling in the `WeaponRep` SCSS module.
- Updated `next.config.js` rewrite rules to support new preview and
character routes.
- Added a new API endpoint (`pages/api/preview/[shortcode].tsx`) for
fetching party preview images.

## Type Definitions:
- Refined types in `types/GridCharacter.d.ts` and `types/index.d.ts` to
reflect updated structures for rings, over mastery, and awakening.
2025-02-09 22:54:15 -08:00

157 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Core dependencies
import React, { useEffect, useState } from 'react'
// UI dependencies
import ExtendedMasterySelect from '~components/mastery/ExtendedMasterySelect'
// Data
import { overMastery } from '~data/overMastery'
// Styles and icons
import styles from './index.module.scss'
// Types
import { CharacterOverMastery, ExtendedMastery } from '~types'
const emptyRing: ExtendedMastery = {
modifier: 0,
strength: 0,
}
interface Props {
gridCharacter: GridCharacter
sendValues: (overMastery: CharacterOverMastery) => void
}
const RingSelect = ({ gridCharacter, sendValues }: Props) => {
// Ring value states
const [rings, setRings] = useState<CharacterOverMastery>([
{ ...emptyRing, modifier: 1 },
{ ...emptyRing, modifier: 2 },
emptyRing,
emptyRing,
])
useEffect(() => {
if (gridCharacter.over_mastery) {
setRings([
gridCharacter.over_mastery[0],
gridCharacter.over_mastery[1],
gridCharacter.over_mastery[2],
gridCharacter.over_mastery[3],
])
}
}, [gridCharacter])
useEffect(() => {
sendValues(rings)
}, [rings])
function dataSet(index: number) {
const noValue = {
name: {
en: 'No over mastery bonus',
ja: 'EXリミットボーナスなし',
},
id: 0,
granblue_id: '',
slug: 'no-bonus',
minValue: 0,
maxValue: 0,
suffix: '',
fractional: false,
secondary: [],
}
switch (index) {
case 0:
return overMastery.a ? [overMastery.a[0]] : []
case 1:
return overMastery.a ? [overMastery.a[1]] : []
case 2:
return overMastery.b ? [noValue, ...overMastery.b] : []
case 3:
return overMastery.c ? [noValue, ...overMastery.c] : []
default:
return []
}
}
function receiveRingValues(index: number, left: number, right: number) {
if (index === 0 || index === 1) {
// For rings 1 and 2 (indices 0 and 1), update using the synced function.
setSyncedRingValues(index as 0 | 1, right)
} else if (index === 2 && left === 0) {
// If ring 3 (index 2) is being unset (left is 0), then also unset ring 4.
setRings((prev) => {
const newRings = [...prev]
newRings[2] = { modifier: 0, strength: 0 }
newRings[3] = { modifier: 0, strength: 0 }
return newRings
})
} else {
// For any other case (including ring 4 being unset), update only that ring.
setRings((prev) => {
const newRings = [...prev]
newRings[index] = { modifier: left, strength: right }
return newRings
})
}
}
function setSyncedRingValues(changedIndex: 0 | 1, newStrength: number) {
// Assume dataSet(0) holds the attack-related data and dataSet(1) holds the HP-related data.
// (Adjust these calls if your datasets are in different positions.)
const attackItem = dataSet(0)[0] as ItemSkill
const hpItem = dataSet(1)[0] as ItemSkill
const attackValues: number[] = attackItem.values ?? []
const hpValues: number[] = hpItem.values ?? []
// Determine the index based on which ring changed:
const selectedIndex =
changedIndex === 0
? attackValues.indexOf(newStrength)
: hpValues.indexOf(newStrength)
// If the new strength value isnt found, do nothing.
if (selectedIndex === -1) {
return
}
// Get the corresponding values for both rings.
const newAttackValue = attackValues[selectedIndex] ?? 0
const newHpValue = hpValues[selectedIndex] ?? 0
// Update both ring values simultaneously.
setRings((prev) => {
const newRings = [...prev]
newRings[0] = { modifier: 1, strength: newAttackValue }
newRings[1] = { modifier: 2, strength: newHpValue }
return newRings
})
}
return (
<div className={styles.rings}>
{rings.map((ringStat, i) => {
return (
<ExtendedMasterySelect
name={`ring-${i}`}
object="ring"
key={`ring-${i}`}
dataSet={dataSet(i)}
leftSelectDisabled={i === 0 || i === 1}
leftSelectValue={ringStat?.modifier ?? 0}
rightSelectValue={ringStat?.strength ?? 0}
sendValues={(left: number, right: number) => {
receiveRingValues(i, left, right)
}}
/>
)
})}
</div>
)
}
export default RingSelect