Read-only TranscendenceStar and optimistic updates
This commit is contained in:
parent
ae09f2434d
commit
c9ae4cd90b
7 changed files with 91 additions and 23 deletions
|
|
@ -307,6 +307,10 @@ const CharacterGrid = (props: Props) => {
|
||||||
|
|
||||||
// Optimistically update UI
|
// Optimistically update UI
|
||||||
updateUncapLevel(position, uncapLevel)
|
updateUncapLevel(position, uncapLevel)
|
||||||
|
|
||||||
|
if (uncapLevel < 6) {
|
||||||
|
updateTranscendenceStage(position, 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -355,11 +359,17 @@ const CharacterGrid = (props: Props) => {
|
||||||
) {
|
) {
|
||||||
storePreviousTranscendenceStage(position)
|
storePreviousTranscendenceStage(position)
|
||||||
|
|
||||||
|
const payload = {
|
||||||
|
character: {
|
||||||
|
uncap_level: stage > 0 ? 6 : 5,
|
||||||
|
transcendence_step: stage,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (stage != previousTranscendenceStages[position])
|
if (stage != previousTranscendenceStages[position])
|
||||||
// TODO: We can use the update character API
|
|
||||||
await api.endpoints.grid_characters
|
await api.endpoints.grid_characters
|
||||||
.update(id, { character: { transcendence_step: stage } })
|
.update(id, payload)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
storeGridCharacter(response.data)
|
storeGridCharacter(response.data)
|
||||||
})
|
})
|
||||||
|
|
@ -379,17 +389,21 @@ const CharacterGrid = (props: Props) => {
|
||||||
function initiateTranscendenceUpdate(
|
function initiateTranscendenceUpdate(
|
||||||
id: string,
|
id: string,
|
||||||
position: number,
|
position: number,
|
||||||
uncapLevel: number
|
stage: number
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
party.user &&
|
party.user &&
|
||||||
accountState.account.user &&
|
accountState.account.user &&
|
||||||
party.user.id === accountState.account.user.id
|
party.user.id === accountState.account.user.id
|
||||||
) {
|
) {
|
||||||
memoizeTranscendenceAction(id, position, uncapLevel)
|
memoizeTranscendenceAction(id, position, stage)
|
||||||
|
|
||||||
// Optimistically update UI
|
// Optimistically update UI
|
||||||
updateTranscendenceStage(position, uncapLevel)
|
updateTranscendenceStage(position, stage)
|
||||||
|
|
||||||
|
if (stage > 0) {
|
||||||
|
updateUncapLevel(position, 6)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,11 +424,11 @@ const CharacterGrid = (props: Props) => {
|
||||||
|
|
||||||
const updateTranscendenceStage = (
|
const updateTranscendenceStage = (
|
||||||
position: number,
|
position: number,
|
||||||
uncapLevel: number | undefined
|
stage: number | undefined
|
||||||
) => {
|
) => {
|
||||||
const character = appState.grid.characters[position]
|
const character = appState.grid.characters[position]
|
||||||
if (character && uncapLevel) {
|
if (character && stage !== undefined) {
|
||||||
character.uncap_level = uncapLevel
|
character.transcendence_step = stage
|
||||||
appState.grid.characters[position] = character
|
appState.grid.characters[position] = character
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,7 +314,8 @@ const CharacterUnit = ({
|
||||||
flb={character.uncap.flb || false}
|
flb={character.uncap.flb || false}
|
||||||
ulb={character.uncap.ulb || false}
|
ulb={character.uncap.ulb || false}
|
||||||
uncapLevel={gridCharacter.uncap_level}
|
uncapLevel={gridCharacter.uncap_level}
|
||||||
transcendenceStep={gridCharacter.transcendence_step}
|
editable={editable}
|
||||||
|
transcendenceStage={gridCharacter.transcendence_step}
|
||||||
updateUncap={passUncapData}
|
updateUncap={passUncapData}
|
||||||
updateTranscendence={passTranscendenceData}
|
updateTranscendence={passTranscendenceData}
|
||||||
special={character.special}
|
special={character.special}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
border-radius: $card-corner;
|
border-radius: $card-corner;
|
||||||
border: 0.5px solid rgba(0, 0, 0, 0.18);
|
border: 0.5px solid rgba(0, 0, 0, 0.18);
|
||||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
|
||||||
display: flex;
|
display: none;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: $unit-half;
|
gap: $unit-half;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
&.open {
|
&.open {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
h4 {
|
h4 {
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ const TranscendencePopover = ({
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
Transcendence: true,
|
Transcendence: true,
|
||||||
Popover: true,
|
Popover: true,
|
||||||
open: true, // This is hardcoded for now
|
open: open,
|
||||||
})
|
})
|
||||||
|
|
||||||
const levelClasses = classNames({
|
const levelClasses = classNames({
|
||||||
|
|
@ -39,6 +39,7 @@ const TranscendencePopover = ({
|
||||||
}, [stage])
|
}, [stage])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(`Setting popover state to ${popoverOpen}`)
|
||||||
setOpen(popoverOpen)
|
setOpen(popoverOpen)
|
||||||
}, [popoverOpen])
|
}, [popoverOpen])
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,39 @@
|
||||||
.TranscendenceStar {
|
.TranscendenceStar {
|
||||||
|
$size: 18px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: scale(1.2);
|
||||||
|
}
|
||||||
|
|
||||||
&.Immutable {
|
&.Immutable {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.Empty {
|
||||||
|
@include hidpiImage('/icons/transcendence/0/stage-0', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Stage1 {
|
||||||
|
@include hidpiImage('/icons/transcendence/1/stage-1', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Stage2 {
|
||||||
|
@include hidpiImage('/icons/transcendence/2/stage-2', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Stage3 {
|
||||||
|
@include hidpiImage('/icons/transcendence/3/stage-3', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Stage4 {
|
||||||
|
@include hidpiImage('/icons/transcendence/4/stage-4', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.Stage5 {
|
||||||
|
@include hidpiImage('/icons/transcendence/5/stage-5', png, $size, $size);
|
||||||
|
}
|
||||||
|
|
||||||
.Figure {
|
.Figure {
|
||||||
$size: 18px;
|
$size: 18px;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
import './index.scss'
|
|
||||||
import TranscendenceFragment from '~components/TranscendenceFragment'
|
import TranscendenceFragment from '~components/TranscendenceFragment'
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
className?: string
|
className?: string
|
||||||
|
|
@ -27,11 +27,18 @@ const TranscendenceStar = ({
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [visibleStage, setVisibleStage] = useState(0)
|
const [visibleStage, setVisibleStage] = useState(0)
|
||||||
const [currentStage, setCurrentStage] = useState(0)
|
const [currentStage, setCurrentStage] = useState(0)
|
||||||
|
const [immutable, setImmutable] = useState(false)
|
||||||
|
|
||||||
// Classes
|
// Classes
|
||||||
const starClasses = classnames({
|
const starClasses = classnames({
|
||||||
TranscendenceStar: true,
|
TranscendenceStar: true,
|
||||||
Immutable: !editable,
|
Immutable: immutable,
|
||||||
|
Empty: stage === 0,
|
||||||
|
Stage1: stage === 1,
|
||||||
|
Stage2: stage === 2,
|
||||||
|
Stage3: stage === 3,
|
||||||
|
Stage4: stage === 4,
|
||||||
|
Stage5: stage === 5,
|
||||||
})
|
})
|
||||||
|
|
||||||
const baseImageClasses = classnames(className, {
|
const baseImageClasses = classnames(className, {
|
||||||
|
|
@ -39,6 +46,7 @@ const TranscendenceStar = ({
|
||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
console.log(`Setting visible stage to ${stage}`)
|
||||||
setVisibleStage(stage)
|
setVisibleStage(stage)
|
||||||
setCurrentStage(stage)
|
setCurrentStage(stage)
|
||||||
}, [stage])
|
}, [stage])
|
||||||
|
|
@ -71,21 +79,23 @@ const TranscendenceStar = ({
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className={starClasses}
|
className={starClasses}
|
||||||
onClick={interactive ? handleClick : () => {}}
|
onClick={editable ? handleClick : () => {}}
|
||||||
onMouseLeave={interactive ? handleMouseLeave : () => {}}
|
onMouseLeave={interactive ? handleMouseLeave : () => {}}
|
||||||
>
|
>
|
||||||
<div className="Fragments">
|
<div className="Fragments">
|
||||||
{[...Array(NUM_FRAGMENTS)].map((e, i) => {
|
{[...Array(NUM_FRAGMENTS)].map((e, i) => {
|
||||||
const loopStage = i + 1
|
const loopStage = i + 1
|
||||||
return (
|
return interactive ? (
|
||||||
<TranscendenceFragment
|
<TranscendenceFragment
|
||||||
key={`fragment_${loopStage}`}
|
key={`fragment_${loopStage}`}
|
||||||
stage={loopStage}
|
stage={loopStage}
|
||||||
visible={loopStage <= visibleStage}
|
visible={loopStage <= visibleStage}
|
||||||
interactive={interactive}
|
interactive={interactive}
|
||||||
onClick={interactive ? handleFragmentClick : () => {}}
|
onClick={handleFragmentClick}
|
||||||
onHover={interactive ? handleFragmentHover : () => {}}
|
onHover={handleFragmentHover}
|
||||||
/>
|
/>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,8 @@ interface Props {
|
||||||
type: 'character' | 'weapon' | 'summon'
|
type: 'character' | 'weapon' | 'summon'
|
||||||
rarity?: number
|
rarity?: number
|
||||||
uncapLevel?: number
|
uncapLevel?: number
|
||||||
transcendenceStep?: number
|
transcendenceStage?: number
|
||||||
|
editable: boolean
|
||||||
flb: boolean
|
flb: boolean
|
||||||
ulb: boolean
|
ulb: boolean
|
||||||
xlb?: boolean
|
xlb?: boolean
|
||||||
|
|
@ -64,16 +65,23 @@ const UncapIndicator = (props: Props) => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openPopover() {
|
function togglePopover(open: boolean) {
|
||||||
setPopoverOpen(true)
|
setPopoverOpen(open)
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendTranscendenceStage(stage: number) {
|
||||||
|
if (props.updateTranscendence) props.updateTranscendence(stage)
|
||||||
|
togglePopover(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const transcendence = (i: number) => {
|
const transcendence = (i: number) => {
|
||||||
return (
|
return (
|
||||||
<TranscendenceStar
|
<TranscendenceStar
|
||||||
key={`star_${i}`}
|
key={`star_${i}`}
|
||||||
|
stage={props.transcendenceStage}
|
||||||
|
editable={props.editable}
|
||||||
interactive={false}
|
interactive={false}
|
||||||
onClick={openPopover}
|
onClick={() => togglePopover(true)}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -120,8 +128,8 @@ const UncapIndicator = (props: Props) => {
|
||||||
return props.type === 'character' || props.type === 'summon' ? (
|
return props.type === 'character' || props.type === 'summon' ? (
|
||||||
<TranscendencePopover
|
<TranscendencePopover
|
||||||
open={popoverOpen}
|
open={popoverOpen}
|
||||||
stage={props.transcendenceStep ? props.transcendenceStep : 0}
|
stage={props.transcendenceStage ? props.transcendenceStage : 0}
|
||||||
sendValue={props.updateTranscendence}
|
sendValue={sendTranscendenceStage}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
|
|
@ -151,4 +159,8 @@ const UncapIndicator = (props: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UncapIndicator.defaultProps = {
|
||||||
|
editable: false,
|
||||||
|
}
|
||||||
|
|
||||||
export default UncapIndicator
|
export default UncapIndicator
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue