hensei-web/components/Party/index.tsx
2022-01-31 23:34:38 -08:00

293 lines
No EOL
8.7 KiB
TypeScript

import React, { ChangeEvent, useEffect, useState } from 'react'
import { useCookies } from 'react-cookie'
import api from '~utils/api'
// UI Elements
import PartySegmentedControl from '~components/PartySegmentedControl'
// Grids
import WeaponGrid from '~components/WeaponGrid'
import SummonGrid from '~components/SummonGrid'
import CharacterGrid from '~components/CharacterGrid'
// GridType
enum GridType {
Class,
Character,
Weapon,
Summon
}
export { GridType }
import './index.scss'
interface Props {
partyId?: string
mainWeapon?: Weapon
mainSummon?: Summon
friendSummon?: Summon
characters?: GridArray<Character>
weapons?: GridArray<Weapon>
summons?: GridArray<Summon>
extra: boolean
editable: boolean
exists: boolean
pushHistory?: (path: string) => void
}
const Party = (props: Props) => {
const [cookies, _] = useCookies(['user'])
const headers = (cookies.user != null) ? {
headers: {
'Authorization': `Bearer ${cookies.user.access_token}`
}
} : {}
// Grid data
const [characters, setCharacters] = useState<GridArray<Character>>({})
const [weapons, setWeapons] = useState<GridArray<Weapon>>({})
const [summons, setSummons] = useState<GridArray<Summon>>({})
const [mainWeapon, setMainWeapon] = useState<Weapon>()
const [mainSummon, setMainSummon] = useState<Summon>()
const [friendSummon, setFriendSummon] = useState<Summon>()
const [extra, setExtra] = useState<boolean>(false)
useEffect(() => {
setPartyId(props.partyId || '')
setMainWeapon(props.mainWeapon)
setMainSummon(props.mainSummon)
setFriendSummon(props.friendSummon)
setCharacters(props.characters || {})
setWeapons(props.weapons || {})
setSummons(props.summons || {})
setExtra(props.extra || false)
}, [props.partyId, props.mainWeapon, props.mainSummon, props.friendSummon, props.characters, props.weapons, props.summons, props.extra])
const weaponGrid = (
<WeaponGrid
userId={cookies.user ? cookies.user.userId : ''}
mainhand={mainWeapon}
grid={weapons}
editable={props.editable}
exists={props.exists}
extra={extra}
onSelect={itemSelected}
/>
)
const summonGrid = (
<SummonGrid
userId={cookies.user ? cookies.user.userId : ''}
main={mainSummon}
friend={friendSummon}
grid={summons}
editable={props.editable}
exists={props.exists}
onSelect={itemSelected}
/>
)
const characterGrid = (
<CharacterGrid
userId={cookies.user ? cookies.user.userId : ''}
grid={characters}
editable={props.editable}
exists={props.exists}
onSelect={itemSelected}
/>
)
const [currentTab, setCurrentTab] = useState<GridType>(GridType.Weapon)
const [partyId, setPartyId] = useState('')
function checkboxChanged(event: React.ChangeEvent<HTMLInputElement>) {
setExtra(event.target.checked)
}
function segmentClicked(event: React.ChangeEvent<HTMLInputElement>) {
switch(event.target.value) {
case 'class':
setCurrentTab(GridType.Class)
break
case 'characters':
setCurrentTab(GridType.Character)
break
case 'weapons':
setCurrentTab(GridType.Weapon)
break
case 'summons':
setCurrentTab(GridType.Summon)
break
default:
break
}
}
function itemSelected(type: GridType, item: Character | Weapon | Summon, position: number) {
if (!partyId) {
createParty()
.then(response => {
return response.data.party
})
.then(party => {
if (props.pushHistory) {
props.pushHistory(`/p/${party.shortcode}`)
}
return party.id
})
.then(partyId => {
setPartyId(partyId)
saveItem(partyId, type, item, position)
})
} else {
saveItem(partyId, type, item, position)
}
}
async function createParty() {
const body = (!cookies.user) ? {
party: {
is_extra: extra
}
} : {
party: {
user_id: cookies.user.userId,
is_extra: extra
}
}
return await api.endpoints.parties.create(body, headers)
}
function saveItem(partyId: string, type: GridType, item: Character | Weapon | Summon, position: number) {
switch(type) {
case GridType.Class:
saveClass()
break
case GridType.Character:
const character = item as Character
saveCharacter(character, position, partyId)
.then(() => {
storeCharacter(character, position)
})
break
case GridType.Weapon:
const weapon = item as Weapon
saveWeapon(weapon, position, partyId)
.then(() => {
storeWeapon(weapon, position)
})
break
case GridType.Summon:
const summon = item as Summon
saveSummon(summon, position, partyId)
.then(() => {
storeSummon(summon, position)
})
break
}
}
// Weapons
function storeWeapon(weapon: Weapon, position: number) {
if (position == -1) {
setMainWeapon(weapon)
} else {
// Store the grid unit weapon at the correct position
let newWeapons = Object.assign({}, weapons)
newWeapons[position] = weapon
setWeapons(newWeapons)
}
}
async function saveWeapon(weapon: Weapon, position: number, party: string) {
await api.endpoints.weapons.create({
'weapon': {
'party_id': party,
'weapon_id': weapon.id,
'position': position,
'mainhand': (position == -1)
}
}, headers)
}
// Summons
function storeSummon(summon: Summon, position: number) {
if (position == -1) {
setMainSummon(summon)
} else if (position == 6) {
setFriendSummon(summon)
} else {
// Store the grid unit summon at the correct position
let newSummons = Object.assign({}, summons)
newSummons[position] = summon
setSummons(newSummons)
}
}
async function saveSummon(summon: Summon, position: number, party: string) {
await api.endpoints.summons.create({
'summon': {
'party_id': party,
'summon_id': summon.id,
'position': position,
'main': (position == -1),
'friend': (position == 6)
}
}, headers)
}
// Character
function storeCharacter(character: Character, position: number) {
// Store the grid unit character at the correct position
let newCharacters = Object.assign({}, characters)
newCharacters[position] = character
setCharacters(newCharacters)
}
async function saveCharacter(character: Character, position: number, party: string) {
await api.endpoints.characters.create({
'character': {
'party_id': party,
'character_id': character.id,
'position': position
}
}, headers)
}
// Class
function saveClass() {
// TODO: Implement this
}
return (
<div>
<PartySegmentedControl
extra={extra}
editable={props.editable}
selectedTab={currentTab}
onClick={segmentClicked}
onCheckboxChange={checkboxChanged}
/>
{
(() => {
switch(currentTab) {
case GridType.Character:
return characterGrid
case GridType.Weapon:
return weaponGrid
case GridType.Summon:
return summonGrid
}
})()
}
</div>
)
}
export default Party