Update Party component

* Moves tab state management to the parent to prevent flickering and re-rendering
* Fixes local ID saving so that unauth users can make parties again
* Fixes the saving and display of numeric values (button count, chain count, turn count)
This commit is contained in:
Justin Edmund 2023-07-02 02:32:35 -07:00
parent 7db02886fa
commit f14e90acfc

View file

@ -23,13 +23,12 @@ import { setEditKey, storeEditKey, unsetEditKey } from '~utils/userToken'
import type { DetailsObject } from '~types' import type { DetailsObject } from '~types'
import styles from './index.module.scss'
// Props // Props
interface Props { interface Props {
new?: boolean new?: boolean
team?: Party team?: Party
selectedTab: GridType selectedTab: GridType
handleTabChanged: (value: string) => void
pushHistory?: (path: string) => void pushHistory?: (path: string) => void
} }
@ -47,7 +46,6 @@ const Party = (props: Props) => {
// Set up states // Set up states
const { party } = useSnapshot(appState) const { party } = useSnapshot(appState)
const [editable, setEditable] = useState(false) const [editable, setEditable] = useState(false)
const [currentTab, setCurrentTab] = useState<GridType>(GridType.Weapon)
const [refresh, setRefresh] = useState(false) const [refresh, setRefresh] = useState(false)
const [errorMessage, setErrorMessage] = useState('') const [errorMessage, setErrorMessage] = useState('')
@ -104,18 +102,13 @@ const Party = (props: Props) => {
setEditable(editable) setEditable(editable)
}, [refresh]) }, [refresh])
// Set selected tab from props
useEffect(() => {
setCurrentTab(props.selectedTab)
}, [props.selectedTab])
// Methods: Creating a new party // Methods: Creating a new party
async function createParty(details?: DetailsObject) { async function createParty(details?: DetailsObject) {
let payload = {} let payload = {}
if (details) payload = formatDetailsObject(details) if (details) payload = formatDetailsObject(details)
return await api.endpoints.parties return await api.endpoints.parties
.create({ ...payload, ...getLocalId() }) .create(payload)
.then((response) => storeParty(response.data.party)) .then((response) => storeParty(response.data.party))
} }
@ -155,14 +148,17 @@ const Party = (props: Props) => {
if (details.autoSummon != undefined) if (details.autoSummon != undefined)
payload.auto_summon = details.autoSummon payload.auto_summon = details.autoSummon
if (details.clearTime) payload.clear_time = details.clearTime if (details.clearTime) payload.clear_time = details.clearTime
if (details.buttonCount) payload.button_count = details.buttonCount if (details.buttonCount !== undefined)
if (details.chainCount) payload.chain_count = details.chainCount payload.button_count = details.buttonCount
if (details.turnCount) payload.turn_count = details.turnCount if (details.chainCount !== undefined)
payload.chain_count = details.chainCount
if (details.turnCount !== undefined) payload.turn_count = details.turnCount
if (details.extra != undefined) payload.extra = details.extra if (details.extra != undefined) payload.extra = details.extra
if (details.job) payload.job_id = details.job.id if (details.job) payload.job_id = details.job.id
if (details.guidebook1_id) payload.guidebook1_id = details.guidebook1_id if (details.guidebook1_id) payload.guidebook1_id = details.guidebook1_id
if (details.guidebook2_id) payload.guidebook2_id = details.guidebook2_id if (details.guidebook2_id) payload.guidebook2_id = details.guidebook2_id
if (details.guidebook3_id) payload.guidebook3_id = details.guidebook3_id if (details.guidebook3_id) payload.guidebook3_id = details.guidebook3_id
if (getLocalId()) payload.local_id = getLocalId()
if (Object.keys(payload).length >= 1) return { party: payload } if (Object.keys(payload).length >= 1) return { party: payload }
else return {} else return {}
@ -208,7 +204,7 @@ const Party = (props: Props) => {
// setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title')) // setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title'))
if (props.team && props.team.shortcode) { if (props.team && props.team.shortcode) {
const body = getLocalId() const body = { local_id: getLocalId() }
api api
.remix({ shortcode: props.team.shortcode, body: body }) .remix({ shortcode: props.team.shortcode, body: body })
.then((response) => { .then((response) => {
@ -270,9 +266,12 @@ const Party = (props: Props) => {
appState.party.autoGuard = team.auto_guard appState.party.autoGuard = team.auto_guard
appState.party.autoSummon = team.auto_summon appState.party.autoSummon = team.auto_summon
appState.party.clearTime = team.clear_time appState.party.clearTime = team.clear_time
appState.party.buttonCount = team.button_count appState.party.buttonCount =
appState.party.chainCount = team.chain_count team.button_count !== null ? team.button_count : undefined
appState.party.turnCount = team.turn_count appState.party.chainCount =
team.chain_count !== null ? team.chain_count : undefined
appState.party.turnCount =
team.turn_count !== null ? team.turn_count : undefined
appState.party.id = team.id appState.party.id = team.id
appState.party.shortcode = team.shortcode appState.party.shortcode = team.shortcode
@ -301,9 +300,9 @@ const Party = (props: Props) => {
// Create a string to send the user back to the tab they're currently on // Create a string to send the user back to the tab they're currently on
let tab = '' let tab = ''
if (currentTab === GridType.Character) { if (props.selectedTab === GridType.Character) {
tab = 'characters' tab = 'characters'
} else if (currentTab === GridType.Summon) { } else if (props.selectedTab === GridType.Summon) {
tab = 'summons' tab = 'summons'
} }
@ -349,32 +348,7 @@ const Party = (props: Props) => {
// Methods: Navigating with segmented control // Methods: Navigating with segmented control
function segmentClicked(event: React.ChangeEvent<HTMLInputElement>) { function segmentClicked(event: React.ChangeEvent<HTMLInputElement>) {
const path = [ props.handleTabChanged(event.target.value)
// Enable when using Next.js Router
'p',
router.asPath.split('/').filter((el) => el != '')[1],
event.target.value,
].join('/')
switch (event.target.value) {
case 'characters':
setCurrentTab(GridType.Character)
break
case 'weapons':
setCurrentTab(GridType.Weapon)
break
case 'summons':
setCurrentTab(GridType.Summon)
break
default:
break
}
// Ideally, we would use the Next.js Router to replace the URL,
// but something about shallow routing isn't working so the page is refreshing.
// A consequence is that the browser push stack gets fucked
// router.replace(path, undefined, { shallow: true })
history.pushState({}, '', '/' + path)
} }
// Render: JSX components // Render: JSX components
@ -390,7 +364,10 @@ const Party = (props: Props) => {
} }
const navigation = ( const navigation = (
<PartySegmentedControl selectedTab={currentTab} onClick={segmentClicked} /> <PartySegmentedControl
selectedTab={props.selectedTab}
onClick={segmentClicked}
/>
) )
const weaponGrid = ( const weaponGrid = (
@ -427,7 +404,7 @@ const Party = (props: Props) => {
) )
const currentGrid = () => { const currentGrid = () => {
switch (currentTab) { switch (props.selectedTab) {
case GridType.Character: case GridType.Character:
return characterGrid return characterGrid
case GridType.Weapon: case GridType.Weapon:
@ -458,6 +435,7 @@ const Party = (props: Props) => {
party={props.team} party={props.team}
new={props.new || false} new={props.new || false}
editable={party.editable} editable={party.editable}
remixCallback={remixTeam}
updateCallback={updateDetails} updateCallback={updateDetails}
/> />
</React.Fragment> </React.Fragment>