From 2be23b5ea09e23dce0107a55c5e4839f4a782d90 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Fri, 20 Jan 2023 20:38:44 -0800 Subject: [PATCH] Add context menu to WeaponUnit Also refactored and organized WeaponUnit and CharacterUnit --- components/CharacterUnit/index.tsx | 266 ++++++++++------- components/WeaponModal/index.tsx | 21 +- components/WeaponUnit/index.scss | 21 +- components/WeaponUnit/index.tsx | 454 +++++++++++++++++++---------- 4 files changed, 480 insertions(+), 282 deletions(-) diff --git a/components/CharacterUnit/index.tsx b/components/CharacterUnit/index.tsx index f286cbf1..317e46f6 100644 --- a/components/CharacterUnit/index.tsx +++ b/components/CharacterUnit/index.tsx @@ -1,8 +1,8 @@ -import React, { useEffect, useState } from 'react' +import React, { MouseEvent, useEffect, useState } from 'react' import { useRouter } from 'next/router' import { useSnapshot } from 'valtio' import { Trans, useTranslation } from 'next-i18next' -import classnames from 'classnames' +import classNames from 'classnames' import Alert from '~components/Alert' import Button from '~components/Button' @@ -30,52 +30,112 @@ interface Props { gridCharacter?: GridCharacter position: number editable: boolean + removeCharacter: (id: string) => void updateObject: (object: SearchableObject, position: number) => void updateUncap: (id: string, position: number, uncap: number) => void - removeCharacter: (id: string) => void } -const CharacterUnit = (props: Props) => { +const CharacterUnit = ({ + gridCharacter, + position, + editable, + removeCharacter: sendCharacterToRemove, + updateObject, + updateUncap, +}: Props) => { + // Translations and locale const { t } = useTranslation('common') - - const { party, grid } = useSnapshot(appState) - const router = useRouter() const locale = router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en' - const [imageUrl, setImageUrl] = useState('') + // State snapshot + const { party, grid } = useSnapshot(appState) - const classes = classnames({ - CharacterUnit: true, - editable: props.editable, - filled: props.gridCharacter !== undefined, - }) - - const [modalOpen, setModalOpen] = useState(false) + // State: UI + const [detailsModalOpen, setDetailsModalOpen] = useState(false) + const [searchModalOpen, setSearchModalOpen] = useState(false) + const [contextMenuOpen, setContextMenuOpen] = useState(false) const [alertOpen, setAlertOpen] = useState(false) - const gridCharacter = props.gridCharacter + // State: Other + const [imageUrl, setImageUrl] = useState('') + + // Classes + const classes = classNames({ + CharacterUnit: true, + editable: editable, + filled: gridCharacter !== undefined, + }) + + const buttonClasses = classNames({ + Options: true, + Clicked: contextMenuOpen, + }) + + // Other const character = gridCharacter?.object + // Hooks useEffect(() => { generateImageUrl() }) + // Methods: Open layer + function openCharacterModal(event: Event) { + setDetailsModalOpen(true) + } + + function openSearchModal(event: MouseEvent) { + if (editable) setSearchModalOpen(true) + } + + function openRemoveCharacterAlert() { + setAlertOpen(true) + } + + // Methods: Handle button clicked + function handleButtonClicked() { + setContextMenuOpen(!contextMenuOpen) + } + + // Methods: Handle open change + function handleCharacterModalOpenChange(open: boolean) { + setDetailsModalOpen(open) + } + + function handleSearchModalOpenChange(open: boolean) { + setSearchModalOpen(open) + } + + function handleContextMenuOpenChange(open: boolean) { + if (!open) setContextMenuOpen(false) + } + + // Methods: Mutate data + function passUncapData(uncap: number) { + if (gridCharacter) updateUncap(gridCharacter.id, position, uncap) + } + + function removeCharacter() { + if (gridCharacter) sendCharacterToRemove(gridCharacter.id) + } + + // Methods: Image string generation function generateImageUrl() { let imgSrc = '' - if (props.gridCharacter) { - const character = props.gridCharacter.object! + if (gridCharacter) { + const character = gridCharacter.object! // Change the image based on the uncap level let suffix = '01' - if (props.gridCharacter.uncap_level == 6) suffix = '04' - else if (props.gridCharacter.uncap_level == 5) suffix = '03' - else if (props.gridCharacter.uncap_level > 2) suffix = '02' + if (gridCharacter.uncap_level == 6) suffix = '04' + else if (gridCharacter.uncap_level == 5) suffix = '03' + else if (gridCharacter.uncap_level > 2) suffix = '02' // Special casing for Lyria (and Young Cat eventually) - if (props.gridCharacter.object.granblue_id === '3030182000') { + if (gridCharacter.object.granblue_id === '3030182000') { let element = 1 if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) { element = grid.weapons.mainWeapon.element @@ -92,49 +152,45 @@ const CharacterUnit = (props: Props) => { setImageUrl(imgSrc) } - function passUncapData(uncap: number) { - if (props.gridCharacter) - props.updateUncap(props.gridCharacter.id, props.position, uncap) + // Methods: Layer element rendering + const characterModal = () => { + if (gridCharacter) { + return ( + + ) + } } - const image = ( -
- {character?.name.en} - {props.editable ? ( - - - - ) : ( - '' - )} -
- ) - - const editableImage = ( - - {image} - - ) - - function openCharacterModal(event: Event) { - setModalOpen(true) - } - - function onCharacterModalOpenChange(open: boolean) { - setModalOpen(open) - } - - function openRemoveCharacterAlert() { - setAlertOpen(true) - } - - function removeCharacter() { - if (gridCharacter) props.removeCharacter(gridCharacter.id) + const contextMenu = () => { + if (editable && gridCharacter && gridCharacter.id) { + return ( + <> + + +