270 lines
7.2 KiB
TypeScript
270 lines
7.2 KiB
TypeScript
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
|
import { useRouter } from "next/router";
|
|
import { useSnapshot } from "valtio";
|
|
import { getCookie } from "cookies-next";
|
|
import clonedeep from "lodash.clonedeep";
|
|
|
|
import PartySegmentedControl from "~components/PartySegmentedControl";
|
|
import PartyDetails from "~components/PartyDetails";
|
|
import WeaponGrid from "~components/WeaponGrid";
|
|
import SummonGrid from "~components/SummonGrid";
|
|
import CharacterGrid from "~components/CharacterGrid";
|
|
|
|
import api from "~utils/api";
|
|
import { appState, initialAppState } from "~utils/appState";
|
|
import { GridType, TeamElement } from "~utils/enums";
|
|
|
|
import "./index.scss";
|
|
|
|
// Props
|
|
interface Props {
|
|
new?: boolean;
|
|
team?: Party;
|
|
raids: Raid[][];
|
|
pushHistory?: (path: string) => void;
|
|
}
|
|
|
|
const Party = (props: Props) => {
|
|
// Cookies
|
|
const cookie = getCookie("account");
|
|
const accountData: AccountCookie = cookie
|
|
? JSON.parse(cookie as string)
|
|
: null;
|
|
|
|
const headers = useMemo(() => {
|
|
return accountData
|
|
? { headers: { Authorization: `Bearer ${accountData.token}` } }
|
|
: {};
|
|
}, [accountData]);
|
|
|
|
// Set up router
|
|
const router = useRouter();
|
|
|
|
// Set up states
|
|
const { party } = useSnapshot(appState);
|
|
const [currentTab, setCurrentTab] = useState<GridType>(GridType.Weapon);
|
|
|
|
// Reset state on first load
|
|
useEffect(() => {
|
|
const resetState = clonedeep(initialAppState);
|
|
appState.grid = resetState.grid;
|
|
if (props.team) storeParty(props.team);
|
|
}, []);
|
|
|
|
// Methods: Creating a new party
|
|
async function createParty(extra: boolean = false) {
|
|
let body = {
|
|
party: {
|
|
...(accountData && { user_id: accountData.userId }),
|
|
extra: extra,
|
|
},
|
|
};
|
|
|
|
return await api.endpoints.parties.create(body, headers);
|
|
}
|
|
|
|
// Methods: Updating the party's details
|
|
function checkboxChanged(event: React.ChangeEvent<HTMLInputElement>) {
|
|
appState.party.extra = event.target.checked;
|
|
|
|
if (party.id) {
|
|
api.endpoints.parties.update(
|
|
party.id,
|
|
{
|
|
party: { extra: event.target.checked },
|
|
},
|
|
headers
|
|
);
|
|
}
|
|
}
|
|
|
|
function updateDetails(name?: string, description?: string, raid?: Raid) {
|
|
if (
|
|
appState.party.name !== name ||
|
|
appState.party.description !== description ||
|
|
appState.party.raid?.id !== raid?.id
|
|
) {
|
|
if (appState.party.id)
|
|
api.endpoints.parties
|
|
.update(
|
|
appState.party.id,
|
|
{
|
|
party: {
|
|
name: name,
|
|
description: description,
|
|
raid_id: raid?.id,
|
|
},
|
|
},
|
|
headers
|
|
)
|
|
.then(() => {
|
|
appState.party.name = name;
|
|
appState.party.description = description;
|
|
appState.party.raid = raid;
|
|
appState.party.updated_at = party.updated_at;
|
|
});
|
|
}
|
|
}
|
|
|
|
// Deleting the party
|
|
function deleteTeam(event: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
|
|
if (appState.party.editable && appState.party.id) {
|
|
api.endpoints.parties
|
|
.destroy({ id: appState.party.id, params: headers })
|
|
.then(() => {
|
|
// Push to route
|
|
router.push("/");
|
|
|
|
// Clean state
|
|
const resetState = clonedeep(initialAppState);
|
|
Object.keys(resetState).forEach((key) => {
|
|
appState[key] = resetState[key];
|
|
});
|
|
|
|
// Set party to be editable
|
|
appState.party.editable = true;
|
|
})
|
|
.catch((error) => {
|
|
console.error(error);
|
|
});
|
|
}
|
|
}
|
|
|
|
// Methods: Storing party data
|
|
const storeParty = function (party: Party) {
|
|
// Store the important party and state-keeping values
|
|
appState.party.name = party.name;
|
|
appState.party.description = party.description;
|
|
appState.party.raid = party.raid;
|
|
appState.party.updated_at = party.updated_at;
|
|
appState.party.job = party.job;
|
|
appState.party.jobSkills = party.job_skills;
|
|
|
|
appState.party.id = party.id;
|
|
appState.party.extra = party.extra;
|
|
appState.party.user = party.user;
|
|
appState.party.favorited = party.favorited;
|
|
appState.party.created_at = party.created_at;
|
|
appState.party.updated_at = party.updated_at;
|
|
|
|
// Populate state
|
|
storeCharacters(party.characters);
|
|
storeWeapons(party.weapons);
|
|
storeSummons(party.summons);
|
|
};
|
|
|
|
const storeCharacters = (list: Array<GridCharacter>) => {
|
|
list.forEach((object: GridCharacter) => {
|
|
if (object.position != null)
|
|
appState.grid.characters[object.position] = object;
|
|
});
|
|
};
|
|
|
|
const storeWeapons = (list: Array<GridWeapon>) => {
|
|
list.forEach((gridObject: GridWeapon) => {
|
|
if (gridObject.mainhand) {
|
|
appState.grid.weapons.mainWeapon = gridObject;
|
|
appState.party.element = gridObject.object.element;
|
|
} else if (!gridObject.mainhand && gridObject.position != null) {
|
|
appState.grid.weapons.allWeapons[gridObject.position] = gridObject;
|
|
}
|
|
});
|
|
};
|
|
|
|
const storeSummons = (list: Array<GridSummon>) => {
|
|
list.forEach((gridObject: GridSummon) => {
|
|
if (gridObject.main) appState.grid.summons.mainSummon = gridObject;
|
|
else if (gridObject.friend)
|
|
appState.grid.summons.friendSummon = gridObject;
|
|
else if (
|
|
!gridObject.main &&
|
|
!gridObject.friend &&
|
|
gridObject.position != null
|
|
)
|
|
appState.grid.summons.allSummons[gridObject.position] = gridObject;
|
|
});
|
|
};
|
|
|
|
// Methods: Navigating with segmented control
|
|
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;
|
|
}
|
|
}
|
|
|
|
// Render: JSX components
|
|
const navigation = (
|
|
<PartySegmentedControl
|
|
selectedTab={currentTab}
|
|
onClick={segmentClicked}
|
|
onCheckboxChange={checkboxChanged}
|
|
/>
|
|
);
|
|
|
|
const weaponGrid = (
|
|
<WeaponGrid
|
|
new={props.new || false}
|
|
weapons={props.team?.weapons}
|
|
createParty={createParty}
|
|
pushHistory={props.pushHistory}
|
|
/>
|
|
);
|
|
|
|
const summonGrid = (
|
|
<SummonGrid
|
|
new={props.new || false}
|
|
summons={props.team?.summons}
|
|
createParty={createParty}
|
|
pushHistory={props.pushHistory}
|
|
/>
|
|
);
|
|
|
|
const characterGrid = (
|
|
<CharacterGrid
|
|
new={props.new || false}
|
|
characters={props.team?.characters}
|
|
createParty={createParty}
|
|
pushHistory={props.pushHistory}
|
|
/>
|
|
);
|
|
|
|
const currentGrid = () => {
|
|
switch (currentTab) {
|
|
case GridType.Character:
|
|
return characterGrid;
|
|
case GridType.Weapon:
|
|
return weaponGrid;
|
|
case GridType.Summon:
|
|
return summonGrid;
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
{navigation}
|
|
<section id="Party">{currentGrid()}</section>
|
|
{
|
|
<PartyDetails
|
|
editable={party.editable}
|
|
updateCallback={updateDetails}
|
|
deleteCallback={deleteTeam}
|
|
/>
|
|
}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default Party;
|