Add context menu to WeaponUnit
Also refactored and organized WeaponUnit and CharacterUnit
This commit is contained in:
parent
d4e598e36b
commit
2be23b5ea0
4 changed files with 480 additions and 282 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { MouseEvent, useEffect, useState } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import { Trans, useTranslation } from 'next-i18next'
|
import { Trans, useTranslation } from 'next-i18next'
|
||||||
import classnames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import Alert from '~components/Alert'
|
import Alert from '~components/Alert'
|
||||||
import Button from '~components/Button'
|
import Button from '~components/Button'
|
||||||
|
|
@ -30,52 +30,112 @@ interface Props {
|
||||||
gridCharacter?: GridCharacter
|
gridCharacter?: GridCharacter
|
||||||
position: number
|
position: number
|
||||||
editable: boolean
|
editable: boolean
|
||||||
|
removeCharacter: (id: string) => void
|
||||||
updateObject: (object: SearchableObject, position: number) => void
|
updateObject: (object: SearchableObject, position: number) => void
|
||||||
updateUncap: (id: string, position: number, uncap: 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 { t } = useTranslation('common')
|
||||||
|
|
||||||
const { party, grid } = useSnapshot(appState)
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const locale =
|
const locale =
|
||||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||||
|
|
||||||
const [imageUrl, setImageUrl] = useState('')
|
// State snapshot
|
||||||
|
const { party, grid } = useSnapshot(appState)
|
||||||
|
|
||||||
const classes = classnames({
|
// State: UI
|
||||||
CharacterUnit: true,
|
const [detailsModalOpen, setDetailsModalOpen] = useState(false)
|
||||||
editable: props.editable,
|
const [searchModalOpen, setSearchModalOpen] = useState(false)
|
||||||
filled: props.gridCharacter !== undefined,
|
const [contextMenuOpen, setContextMenuOpen] = useState(false)
|
||||||
})
|
|
||||||
|
|
||||||
const [modalOpen, setModalOpen] = useState(false)
|
|
||||||
const [alertOpen, setAlertOpen] = 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
|
const character = gridCharacter?.object
|
||||||
|
|
||||||
|
// Hooks
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateImageUrl()
|
generateImageUrl()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Methods: Open layer
|
||||||
|
function openCharacterModal(event: Event) {
|
||||||
|
setDetailsModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSearchModal(event: MouseEvent<HTMLDivElement>) {
|
||||||
|
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() {
|
function generateImageUrl() {
|
||||||
let imgSrc = ''
|
let imgSrc = ''
|
||||||
|
|
||||||
if (props.gridCharacter) {
|
if (gridCharacter) {
|
||||||
const character = props.gridCharacter.object!
|
const character = gridCharacter.object!
|
||||||
|
|
||||||
// Change the image based on the uncap level
|
// Change the image based on the uncap level
|
||||||
let suffix = '01'
|
let suffix = '01'
|
||||||
if (props.gridCharacter.uncap_level == 6) suffix = '04'
|
if (gridCharacter.uncap_level == 6) suffix = '04'
|
||||||
else if (props.gridCharacter.uncap_level == 5) suffix = '03'
|
else if (gridCharacter.uncap_level == 5) suffix = '03'
|
||||||
else if (props.gridCharacter.uncap_level > 2) suffix = '02'
|
else if (gridCharacter.uncap_level > 2) suffix = '02'
|
||||||
|
|
||||||
// Special casing for Lyria (and Young Cat eventually)
|
// Special casing for Lyria (and Young Cat eventually)
|
||||||
if (props.gridCharacter.object.granblue_id === '3030182000') {
|
if (gridCharacter.object.granblue_id === '3030182000') {
|
||||||
let element = 1
|
let element = 1
|
||||||
if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) {
|
if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) {
|
||||||
element = grid.weapons.mainWeapon.element
|
element = grid.weapons.mainWeapon.element
|
||||||
|
|
@ -92,49 +152,45 @@ const CharacterUnit = (props: Props) => {
|
||||||
setImageUrl(imgSrc)
|
setImageUrl(imgSrc)
|
||||||
}
|
}
|
||||||
|
|
||||||
function passUncapData(uncap: number) {
|
// Methods: Layer element rendering
|
||||||
if (props.gridCharacter)
|
const characterModal = () => {
|
||||||
props.updateUncap(props.gridCharacter.id, props.position, uncap)
|
if (gridCharacter) {
|
||||||
}
|
return (
|
||||||
|
<CharacterModal
|
||||||
const image = (
|
gridCharacter={gridCharacter}
|
||||||
<div className="CharacterImage">
|
open={detailsModalOpen}
|
||||||
<img alt={character?.name.en} className="grid_image" src={imageUrl} />
|
onOpenChange={handleCharacterModalOpenChange}
|
||||||
{props.editable ? (
|
/>
|
||||||
<span className="icon">
|
|
||||||
<PlusIcon />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const editableImage = (
|
const contextMenu = () => {
|
||||||
<SearchModal
|
if (editable && gridCharacter && gridCharacter.id) {
|
||||||
placeholderText={t('search.placeholders.character')}
|
return (
|
||||||
fromPosition={props.position}
|
<>
|
||||||
object="characters"
|
<ContextMenu onOpenChange={handleContextMenuOpenChange}>
|
||||||
send={props.updateObject}
|
<ContextMenuTrigger asChild>
|
||||||
>
|
<Button
|
||||||
{image}
|
accessoryIcon={<SettingsIcon />}
|
||||||
</SearchModal>
|
className={buttonClasses}
|
||||||
|
onClick={handleButtonClicked}
|
||||||
|
/>
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent align="start">
|
||||||
|
<ContextMenuItem onSelect={openCharacterModal}>
|
||||||
|
Modify character
|
||||||
|
</ContextMenuItem>
|
||||||
|
<ContextMenuItem onSelect={openRemoveCharacterAlert}>
|
||||||
|
Remove from grid
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
|
{characterModal()}
|
||||||
|
{removeAlert()}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
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 removeAlert = () => {
|
const removeAlert = () => {
|
||||||
|
|
@ -156,40 +212,40 @@ const CharacterUnit = (props: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextMenu = () => {
|
const searchModal = () => {
|
||||||
if (props.editable && gridCharacter && gridCharacter.id) {
|
if (editable) {
|
||||||
return (
|
return (
|
||||||
<>
|
<SearchModal
|
||||||
<ContextMenu>
|
placeholderText={t('search.placeholders.character')}
|
||||||
<ContextMenuTrigger asChild>
|
fromPosition={position}
|
||||||
<Button accessoryIcon={<SettingsIcon />} className="Options" />
|
object="characters"
|
||||||
</ContextMenuTrigger>
|
open={searchModalOpen}
|
||||||
<ContextMenuContent align="start">
|
onOpenChange={handleSearchModalOpenChange}
|
||||||
<ContextMenuItem onSelect={openCharacterModal}>
|
send={updateObject}
|
||||||
Modify character
|
|
||||||
</ContextMenuItem>
|
|
||||||
<ContextMenuItem onSelect={openRemoveCharacterAlert}>
|
|
||||||
Remove from grid
|
|
||||||
</ContextMenuItem>
|
|
||||||
</ContextMenuContent>
|
|
||||||
</ContextMenu>
|
|
||||||
<CharacterModal
|
|
||||||
gridCharacter={gridCharacter}
|
|
||||||
open={modalOpen}
|
|
||||||
onOpenChange={onCharacterModalOpenChange}
|
|
||||||
/>
|
/>
|
||||||
{removeAlert()}
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// Methods: Core element rendering
|
||||||
|
const image = (
|
||||||
|
<div className="CharacterImage" onClick={openSearchModal}>
|
||||||
|
<img alt={character?.name.en} className="grid_image" src={imageUrl} />
|
||||||
|
{editable ? (
|
||||||
|
<span className="icon">
|
||||||
|
<PlusIcon />
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const unitContent = (
|
const unitContent = (
|
||||||
|
<>
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{contextMenu()}
|
{contextMenu()}
|
||||||
{props.editable ? editableImage : image}
|
{image}
|
||||||
{gridCharacter && character ? (
|
{gridCharacter && character ? (
|
||||||
<UncapIndicator
|
<UncapIndicator
|
||||||
type="character"
|
type="character"
|
||||||
|
|
@ -204,15 +260,17 @@ const CharacterUnit = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
<h3 className="CharacterName">{character?.name[locale]}</h3>
|
<h3 className="CharacterName">{character?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
{searchModal()}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const withHovercard = (
|
const unitContentWithHovercard = (
|
||||||
<CharacterHovercard gridCharacter={gridCharacter!}>
|
<CharacterHovercard gridCharacter={gridCharacter!}>
|
||||||
{unitContent}
|
{unitContent}
|
||||||
</CharacterHovercard>
|
</CharacterHovercard>
|
||||||
)
|
)
|
||||||
|
|
||||||
return gridCharacter && !props.editable ? withHovercard : unitContent
|
return gridCharacter && !editable ? unitContentWithHovercard : unitContent
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CharacterUnit
|
export default CharacterUnit
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { PropsWithChildren, useEffect, useState } from 'react'
|
||||||
import { getCookie } from 'cookies-next'
|
import { getCookie } from 'cookies-next'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
@ -40,10 +40,16 @@ interface GridWeaponObject {
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
gridWeapon: GridWeapon
|
gridWeapon: GridWeapon
|
||||||
children: React.ReactNode
|
open: boolean
|
||||||
|
onOpenChange: (open: boolean) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponModal = ({ gridWeapon, children }: Props) => {
|
const WeaponModal = ({
|
||||||
|
gridWeapon,
|
||||||
|
open: modalOpen,
|
||||||
|
children,
|
||||||
|
onOpenChange,
|
||||||
|
}: PropsWithChildren<Props>) => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const locale =
|
const locale =
|
||||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||||
|
|
@ -87,6 +93,10 @@ const WeaponModal = ({ gridWeapon, children }: Props) => {
|
||||||
const [ax2Open, setAx2Open] = useState(false)
|
const [ax2Open, setAx2Open] = useState(false)
|
||||||
const [awakeningOpen, setAwakeningOpen] = useState(false)
|
const [awakeningOpen, setAwakeningOpen] = useState(false)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setOpen(modalOpen)
|
||||||
|
}, [modalOpen])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setElement(gridWeapon.element)
|
setElement(gridWeapon.element)
|
||||||
|
|
||||||
|
|
@ -308,13 +318,14 @@ const WeaponModal = ({ gridWeapon, children }: Props) => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function openChange(open: boolean) {
|
function handleOpenChange(open: boolean) {
|
||||||
if (gridWeapon.object.ax || gridWeapon.object.awakening) {
|
if (gridWeapon.object.ax || gridWeapon.object.awakening) {
|
||||||
setFormValid(false)
|
setFormValid(false)
|
||||||
} else {
|
} else {
|
||||||
setFormValid(true)
|
setFormValid(true)
|
||||||
}
|
}
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
|
onOpenChange(open)
|
||||||
}
|
}
|
||||||
|
|
||||||
const anySelectOpen =
|
const anySelectOpen =
|
||||||
|
|
@ -336,7 +347,7 @@ const WeaponModal = ({ gridWeapon, children }: Props) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
// TODO: Refactor into Dialog component
|
// TODO: Refactor into Dialog component
|
||||||
<Dialog open={open} onOpenChange={openChange}>
|
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||||
<DialogTrigger asChild>{children}</DialogTrigger>
|
<DialogTrigger asChild>{children}</DialogTrigger>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
className="Weapon"
|
className="Weapon"
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,16 @@
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover .Button {
|
.Button {
|
||||||
display: block;
|
pointer-events: none;
|
||||||
|
opacity: 0;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .Button,
|
||||||
|
.Button.Clicked {
|
||||||
|
pointer-events: initial;
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.editable .WeaponImage:hover {
|
&.editable .WeaponImage:hover {
|
||||||
|
|
@ -95,15 +103,6 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.Button {
|
|
||||||
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.14);
|
|
||||||
display: none;
|
|
||||||
position: absolute;
|
|
||||||
left: $unit;
|
|
||||||
top: $unit;
|
|
||||||
z-index: 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
color: var(--text-primary);
|
color: var(--text-primary);
|
||||||
font-size: $font-button;
|
font-size: $font-button;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,17 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState, MouseEvent } from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { Trans, useTranslation } from 'next-i18next'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
|
import Alert from '~components/Alert'
|
||||||
import SearchModal from '~components/SearchModal'
|
import SearchModal from '~components/SearchModal'
|
||||||
import WeaponModal from '~components/WeaponModal'
|
import WeaponModal from '~components/WeaponModal'
|
||||||
|
import {
|
||||||
|
ContextMenu,
|
||||||
|
ContextMenuTrigger,
|
||||||
|
ContextMenuContent,
|
||||||
|
} from '~components/ContextMenu'
|
||||||
|
import ContextMenuItem from '~components/ContextMenuItem'
|
||||||
import WeaponHovercard from '~components/WeaponHovercard'
|
import WeaponHovercard from '~components/WeaponHovercard'
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
import Button from '~components/Button'
|
import Button from '~components/Button'
|
||||||
|
|
@ -23,48 +30,147 @@ interface Props {
|
||||||
unitType: 0 | 1
|
unitType: 0 | 1
|
||||||
position: number
|
position: number
|
||||||
editable: boolean
|
editable: boolean
|
||||||
|
removeWeapon: (id: string) => void
|
||||||
updateObject: (object: SearchableObject, position: number) => void
|
updateObject: (object: SearchableObject, position: number) => void
|
||||||
updateUncap: (id: string, position: number, uncap: number) => void
|
updateUncap: (id: string, position: number, uncap: number) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponUnit = (props: Props) => {
|
const WeaponUnit = ({
|
||||||
|
gridWeapon,
|
||||||
|
unitType,
|
||||||
|
position,
|
||||||
|
editable,
|
||||||
|
removeWeapon: sendWeaponToRemove,
|
||||||
|
updateObject,
|
||||||
|
updateUncap,
|
||||||
|
}: Props) => {
|
||||||
|
// Translations and locale
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const [imageUrl, setImageUrl] = useState('')
|
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const locale =
|
const locale =
|
||||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||||
|
|
||||||
|
// State: UI
|
||||||
|
const [detailsModalOpen, setDetailsModalOpen] = useState(false)
|
||||||
|
const [searchModalOpen, setSearchModalOpen] = useState(false)
|
||||||
|
const [contextMenuOpen, setContextMenuOpen] = useState(false)
|
||||||
|
const [alertOpen, setAlertOpen] = useState(false)
|
||||||
|
|
||||||
|
// State: Other
|
||||||
|
const [imageUrl, setImageUrl] = useState('')
|
||||||
|
|
||||||
|
// Classes
|
||||||
const classes = classNames({
|
const classes = classNames({
|
||||||
WeaponUnit: true,
|
WeaponUnit: true,
|
||||||
mainhand: props.unitType == 0,
|
mainhand: unitType == 0,
|
||||||
grid: props.unitType == 1,
|
grid: unitType == 1,
|
||||||
editable: props.editable,
|
editable: editable,
|
||||||
filled: props.gridWeapon !== undefined,
|
filled: gridWeapon !== undefined,
|
||||||
empty: props.gridWeapon == undefined,
|
empty: gridWeapon == undefined,
|
||||||
})
|
})
|
||||||
|
|
||||||
const gridWeapon = props.gridWeapon
|
const buttonClasses = classNames({
|
||||||
|
Options: true,
|
||||||
|
Clicked: contextMenuOpen,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Other
|
||||||
const weapon = gridWeapon?.object
|
const weapon = gridWeapon?.object
|
||||||
|
|
||||||
|
// Hooks
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
generateImageUrl()
|
generateImageUrl()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Methods: Convenience
|
||||||
|
function canBeModified(gridWeapon: GridWeapon) {
|
||||||
|
const weapon = gridWeapon.object
|
||||||
|
|
||||||
|
return (
|
||||||
|
weapon.ax ||
|
||||||
|
weapon.awakening ||
|
||||||
|
(weapon.series && [2, 3, 17, 22, 24].includes(weapon.series))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Open layer
|
||||||
|
function openWeaponModal(event: Event) {
|
||||||
|
setDetailsModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openSearchModal(event: MouseEvent<HTMLDivElement>) {
|
||||||
|
if (editable) setSearchModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
function openRemoveWeaponAlert() {
|
||||||
|
setAlertOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Handle button clicked
|
||||||
|
function handleButtonClicked() {
|
||||||
|
setContextMenuOpen(!contextMenuOpen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Handle open change
|
||||||
|
function handleContextMenuOpenChange(open: boolean) {
|
||||||
|
if (!open) setContextMenuOpen(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleWeaponModalOpenChange(open: boolean) {
|
||||||
|
setDetailsModalOpen(open)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSearchModalOpenChange(open: boolean) {
|
||||||
|
setSearchModalOpen(open)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Mutate data
|
||||||
|
function passUncapData(index: number) {
|
||||||
|
if (gridWeapon) updateUncap(gridWeapon.id, position, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeWeapon() {
|
||||||
|
if (gridWeapon) sendWeaponToRemove(gridWeapon.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Data fetching and manipulation
|
||||||
|
function getCanonicalAxSkill(index: number) {
|
||||||
|
if (
|
||||||
|
gridWeapon &&
|
||||||
|
gridWeapon.object.ax &&
|
||||||
|
gridWeapon.object.ax_type > 0 &&
|
||||||
|
gridWeapon.ax
|
||||||
|
) {
|
||||||
|
const axOptions = ax[gridWeapon.object.ax_type - 1]
|
||||||
|
const weaponAxSkill: SimpleAxSkill = gridWeapon.ax[0]
|
||||||
|
|
||||||
|
let axSkill = axOptions.find((ax) => ax.id === weaponAxSkill.modifier)
|
||||||
|
|
||||||
|
if (index !== 0 && axSkill && axSkill.secondary) {
|
||||||
|
const weaponSubAxSkill: SimpleAxSkill = gridWeapon.ax[1]
|
||||||
|
axSkill = axSkill.secondary.find(
|
||||||
|
(ax) => ax.id === weaponSubAxSkill.modifier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return axSkill
|
||||||
|
} else return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Image string generation
|
||||||
function generateImageUrl() {
|
function generateImageUrl() {
|
||||||
let imgSrc = ''
|
let imgSrc = ''
|
||||||
if (props.gridWeapon) {
|
if (gridWeapon) {
|
||||||
const weapon = props.gridWeapon.object!
|
const weapon = gridWeapon.object!
|
||||||
|
|
||||||
if (props.unitType == 0) {
|
if (unitType == 0) {
|
||||||
if (props.gridWeapon.object.element == 0 && props.gridWeapon.element)
|
if (gridWeapon.object.element == 0 && gridWeapon.element)
|
||||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${props.gridWeapon.element}.jpg`
|
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||||
else
|
else
|
||||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg`
|
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}.jpg`
|
||||||
} else {
|
} else {
|
||||||
if (props.gridWeapon.object.element == 0 && props.gridWeapon.element)
|
if (gridWeapon.object.element == 0 && gridWeapon.element)
|
||||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${props.gridWeapon.element}.jpg`
|
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||||
else
|
else
|
||||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
|
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
|
||||||
}
|
}
|
||||||
|
|
@ -74,29 +180,30 @@ const WeaponUnit = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function placeholderImageUrl() {
|
function placeholderImageUrl() {
|
||||||
return props.unitType == 0
|
return unitType == 0
|
||||||
? '/images/placeholders/placeholder-weapon-main.png'
|
? '/images/placeholders/placeholder-weapon-main.png'
|
||||||
: '/images/placeholders/placeholder-weapon-grid.png'
|
: '/images/placeholders/placeholder-weapon-grid.png'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Methods: Image element rendering
|
||||||
function awakeningImage() {
|
function awakeningImage() {
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.awakening &&
|
gridWeapon.object.awakening &&
|
||||||
props.gridWeapon.awakening &&
|
gridWeapon.awakening &&
|
||||||
props.gridWeapon.awakening.type > 0 &&
|
gridWeapon.awakening.type > 0 &&
|
||||||
props.gridWeapon.awakening.type != null
|
gridWeapon.awakening.type != null
|
||||||
) {
|
) {
|
||||||
const awakening = weaponAwakening.find(
|
const awakening = weaponAwakening.find(
|
||||||
(awakening) => awakening.id === props.gridWeapon?.awakening?.type
|
(awakening) => awakening.id === gridWeapon?.awakening?.type
|
||||||
)
|
)
|
||||||
const name = awakening?.name[locale]
|
const name = awakening?.name[locale]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
alt={`${name} Lv${props.gridWeapon.awakening.level}`}
|
alt={`${name} Lv${gridWeapon.awakening.level}`}
|
||||||
className="Awakening"
|
className="Awakening"
|
||||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/awakening/weapon_${props.gridWeapon.awakening.type}.png`}
|
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/awakening/weapon_${gridWeapon.awakening.type}.png`}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -109,18 +216,18 @@ const WeaponUnit = (props: Props) => {
|
||||||
|
|
||||||
// If there is a grid weapon, it is a Draconic Weapon and it has keys
|
// If there is a grid weapon, it is a Draconic Weapon and it has keys
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 3 &&
|
gridWeapon.object.series === 3 &&
|
||||||
props.gridWeapon.weapon_keys
|
gridWeapon.weapon_keys
|
||||||
) {
|
) {
|
||||||
if (index === 0 && props.gridWeapon.weapon_keys[0]) {
|
if (index === 0 && gridWeapon.weapon_keys[0]) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[0].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[0].name[locale]}`
|
||||||
filename = `${props.gridWeapon.weapon_keys[0].slug}.png`
|
filename = `${gridWeapon.weapon_keys[0].slug}.png`
|
||||||
} else if (index === 1 && props.gridWeapon.weapon_keys[1]) {
|
} else if (index === 1 && gridWeapon.weapon_keys[1]) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[1].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[1].name[locale]}`
|
||||||
|
|
||||||
const element = props.gridWeapon.object.element
|
const element = gridWeapon.object.element
|
||||||
filename = `${props.gridWeapon.weapon_keys[1].slug}-${element}.png`
|
filename = `${gridWeapon.weapon_keys[1].slug}-${element}.png`
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -137,12 +244,12 @@ const WeaponUnit = (props: Props) => {
|
||||||
function telumaImages() {
|
function telumaImages() {
|
||||||
let images: JSX.Element[] = []
|
let images: JSX.Element[] = []
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 3 &&
|
gridWeapon.object.series === 3 &&
|
||||||
props.gridWeapon.weapon_keys &&
|
gridWeapon.weapon_keys &&
|
||||||
props.gridWeapon.weapon_keys.length > 0
|
gridWeapon.weapon_keys.length > 0
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < props.gridWeapon.weapon_keys.length; i++) {
|
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||||
const image = telumaImage(i)
|
const image = telumaImage(i)
|
||||||
if (image) images.push(image)
|
if (image) images.push(image)
|
||||||
}
|
}
|
||||||
|
|
@ -158,27 +265,27 @@ const WeaponUnit = (props: Props) => {
|
||||||
|
|
||||||
// If there is a grid weapon, it is a Dark Opus Weapon and it has keys
|
// If there is a grid weapon, it is a Dark Opus Weapon and it has keys
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 17 &&
|
gridWeapon.object.series === 17 &&
|
||||||
props.gridWeapon.weapon_keys
|
gridWeapon.weapon_keys
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
props.gridWeapon.weapon_keys[index] &&
|
gridWeapon.weapon_keys[index] &&
|
||||||
(props.gridWeapon.weapon_keys[index].slot === 1 ||
|
(gridWeapon.weapon_keys[index].slot === 1 ||
|
||||||
props.gridWeapon.weapon_keys[index].slot === 2)
|
gridWeapon.weapon_keys[index].slot === 2)
|
||||||
) {
|
) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[index].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||||
filename = `${props.gridWeapon.weapon_keys[index].slug}.png`
|
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||||
} else if (
|
} else if (
|
||||||
props.gridWeapon.weapon_keys[index] &&
|
gridWeapon.weapon_keys[index] &&
|
||||||
props.gridWeapon.weapon_keys[index].slot === 0
|
gridWeapon.weapon_keys[index].slot === 0
|
||||||
) {
|
) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[index].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||||
|
|
||||||
const weapon = props.gridWeapon.object.proficiency
|
const weapon = gridWeapon.object.proficiency
|
||||||
|
|
||||||
const suffix = `${weapon}`
|
const suffix = `${weapon}`
|
||||||
filename = `${props.gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
filename = `${gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -195,12 +302,12 @@ const WeaponUnit = (props: Props) => {
|
||||||
function ultimaImages() {
|
function ultimaImages() {
|
||||||
let images: JSX.Element[] = []
|
let images: JSX.Element[] = []
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 17 &&
|
gridWeapon.object.series === 17 &&
|
||||||
props.gridWeapon.weapon_keys &&
|
gridWeapon.weapon_keys &&
|
||||||
props.gridWeapon.weapon_keys.length > 0
|
gridWeapon.weapon_keys.length > 0
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < props.gridWeapon.weapon_keys.length; i++) {
|
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||||
const image = ultimaImage(i)
|
const image = ultimaImage(i)
|
||||||
if (image) images.push(image)
|
if (image) images.push(image)
|
||||||
}
|
}
|
||||||
|
|
@ -216,29 +323,29 @@ const WeaponUnit = (props: Props) => {
|
||||||
|
|
||||||
// If there is a grid weapon, it is a Dark Opus Weapon and it has keys
|
// If there is a grid weapon, it is a Dark Opus Weapon and it has keys
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 2 &&
|
gridWeapon.object.series === 2 &&
|
||||||
props.gridWeapon.weapon_keys
|
gridWeapon.weapon_keys
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
props.gridWeapon.weapon_keys[index] &&
|
gridWeapon.weapon_keys[index] &&
|
||||||
props.gridWeapon.weapon_keys[index].slot === 0
|
gridWeapon.weapon_keys[index].slot === 0
|
||||||
) {
|
) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[index].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||||
filename = `${props.gridWeapon.weapon_keys[index].slug}.png`
|
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||||
} else if (
|
} else if (
|
||||||
props.gridWeapon.weapon_keys[index] &&
|
gridWeapon.weapon_keys[index] &&
|
||||||
props.gridWeapon.weapon_keys[index].slot === 1
|
gridWeapon.weapon_keys[index].slot === 1
|
||||||
) {
|
) {
|
||||||
altText = `${props.gridWeapon.weapon_keys[index].name[locale]}`
|
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||||
|
|
||||||
const element = props.gridWeapon.object.element
|
const element = gridWeapon.object.element
|
||||||
const mod = props.gridWeapon.object.name.en.includes('Repudiation')
|
const mod = gridWeapon.object.name.en.includes('Repudiation')
|
||||||
? 'primal'
|
? 'primal'
|
||||||
: 'magna'
|
: 'magna'
|
||||||
|
|
||||||
const suffix = `${mod}-${element}`
|
const suffix = `${mod}-${element}`
|
||||||
const weaponKey = props.gridWeapon.weapon_keys[index]
|
const weaponKey = gridWeapon.weapon_keys[index]
|
||||||
|
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
|
|
@ -250,9 +357,9 @@ const WeaponUnit = (props: Props) => {
|
||||||
'chain-glorification',
|
'chain-glorification',
|
||||||
].includes(weaponKey.slug)
|
].includes(weaponKey.slug)
|
||||||
) {
|
) {
|
||||||
filename = `${props.gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
filename = `${gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
||||||
} else {
|
} else {
|
||||||
filename = `${props.gridWeapon.weapon_keys[index].slug}.png`
|
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,12 +377,12 @@ const WeaponUnit = (props: Props) => {
|
||||||
function opusImages() {
|
function opusImages() {
|
||||||
let images: JSX.Element[] = []
|
let images: JSX.Element[] = []
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.series === 2 &&
|
gridWeapon.object.series === 2 &&
|
||||||
props.gridWeapon.weapon_keys &&
|
gridWeapon.weapon_keys &&
|
||||||
props.gridWeapon.weapon_keys.length > 0
|
gridWeapon.weapon_keys.length > 0
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < props.gridWeapon.weapon_keys.length; i++) {
|
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||||
const image = opusImage(i)
|
const image = opusImage(i)
|
||||||
if (image) images.push(image)
|
if (image) images.push(image)
|
||||||
}
|
}
|
||||||
|
|
@ -288,13 +395,13 @@ const WeaponUnit = (props: Props) => {
|
||||||
const axSkill = getCanonicalAxSkill(index)
|
const axSkill = getCanonicalAxSkill(index)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.ax &&
|
gridWeapon.object.ax &&
|
||||||
props.gridWeapon.object.ax_type > 0 &&
|
gridWeapon.object.ax_type > 0 &&
|
||||||
props.gridWeapon.ax &&
|
gridWeapon.ax &&
|
||||||
axSkill
|
axSkill
|
||||||
) {
|
) {
|
||||||
const altText = `${axSkill.name[locale]} Lv${props.gridWeapon.ax[index].strength}`
|
const altText = `${axSkill.name[locale]} Lv${gridWeapon.ax[index].strength}`
|
||||||
return (
|
return (
|
||||||
<img
|
<img
|
||||||
alt={altText}
|
alt={altText}
|
||||||
|
|
@ -309,12 +416,12 @@ const WeaponUnit = (props: Props) => {
|
||||||
function axImages() {
|
function axImages() {
|
||||||
let images: JSX.Element[] = []
|
let images: JSX.Element[] = []
|
||||||
if (
|
if (
|
||||||
props.gridWeapon &&
|
gridWeapon &&
|
||||||
props.gridWeapon.object.ax &&
|
gridWeapon.object.ax &&
|
||||||
props.gridWeapon.ax &&
|
gridWeapon.ax &&
|
||||||
props.gridWeapon.ax.length > 0
|
gridWeapon.ax.length > 0
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < props.gridWeapon.ax.length; i++) {
|
for (let i = 0; i < gridWeapon.ax.length; i++) {
|
||||||
const image = axImage(i)
|
const image = axImage(i)
|
||||||
if (image) images.push(image)
|
if (image) images.push(image)
|
||||||
}
|
}
|
||||||
|
|
@ -323,46 +430,86 @@ const WeaponUnit = (props: Props) => {
|
||||||
return images
|
return images
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCanonicalAxSkill(index: number) {
|
// Methods: Layer element rendering
|
||||||
if (
|
const weaponModal = () => {
|
||||||
props.gridWeapon &&
|
if (gridWeapon) {
|
||||||
props.gridWeapon.object.ax &&
|
|
||||||
props.gridWeapon.object.ax_type > 0 &&
|
|
||||||
props.gridWeapon.ax
|
|
||||||
) {
|
|
||||||
const axOptions = ax[props.gridWeapon.object.ax_type - 1]
|
|
||||||
const weaponAxSkill: SimpleAxSkill = props.gridWeapon.ax[0]
|
|
||||||
|
|
||||||
let axSkill = axOptions.find((ax) => ax.id === weaponAxSkill.modifier)
|
|
||||||
|
|
||||||
if (index !== 0 && axSkill && axSkill.secondary) {
|
|
||||||
const weaponSubAxSkill: SimpleAxSkill = props.gridWeapon.ax[1]
|
|
||||||
axSkill = axSkill.secondary.find(
|
|
||||||
(ax) => ax.id === weaponSubAxSkill.modifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return axSkill
|
|
||||||
} else return
|
|
||||||
}
|
|
||||||
|
|
||||||
function passUncapData(index: number) {
|
|
||||||
if (props.gridWeapon)
|
|
||||||
props.updateUncap(props.gridWeapon.id, props.position, index)
|
|
||||||
}
|
|
||||||
|
|
||||||
function canBeModified(gridWeapon: GridWeapon) {
|
|
||||||
const weapon = gridWeapon.object
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
weapon.ax ||
|
<WeaponModal
|
||||||
weapon.awakening ||
|
gridWeapon={gridWeapon}
|
||||||
(weapon.series && [2, 3, 17, 22, 24].includes(weapon.series))
|
open={detailsModalOpen}
|
||||||
|
onOpenChange={handleWeaponModalOpenChange}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextMenu = () => {
|
||||||
|
if (editable && gridWeapon && gridWeapon.id) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ContextMenu onOpenChange={handleContextMenuOpenChange}>
|
||||||
|
<ContextMenuTrigger asChild>
|
||||||
|
<Button
|
||||||
|
accessoryIcon={<SettingsIcon />}
|
||||||
|
className={buttonClasses}
|
||||||
|
onClick={handleButtonClicked}
|
||||||
|
/>
|
||||||
|
</ContextMenuTrigger>
|
||||||
|
<ContextMenuContent align="start">
|
||||||
|
{canBeModified(gridWeapon) ? (
|
||||||
|
<ContextMenuItem onSelect={openWeaponModal}>
|
||||||
|
Modify weapon
|
||||||
|
</ContextMenuItem>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
<ContextMenuItem onSelect={openRemoveWeaponAlert}>
|
||||||
|
Remove from grid
|
||||||
|
</ContextMenuItem>
|
||||||
|
</ContextMenuContent>
|
||||||
|
</ContextMenu>
|
||||||
|
{weaponModal()}
|
||||||
|
{removeAlert()}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeAlert = () => {
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
open={alertOpen}
|
||||||
|
primaryAction={removeWeapon}
|
||||||
|
primaryActionText={t('modals.weapons.buttons.remove')}
|
||||||
|
cancelAction={() => setAlertOpen(false)}
|
||||||
|
cancelActionText={t('buttons.cancel')}
|
||||||
|
message={
|
||||||
|
<Trans i18nKey="modals.characters.messages.remove">
|
||||||
|
Are you sure you want to remove{' '}
|
||||||
|
<strong>{{ weapon: gridWeapon?.object.name[locale] }}</strong> from
|
||||||
|
your team?
|
||||||
|
</Trans>
|
||||||
|
}
|
||||||
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const searchModal = () => {
|
||||||
|
return (
|
||||||
|
<SearchModal
|
||||||
|
placeholderText={t('search.placeholders.weapon')}
|
||||||
|
fromPosition={position}
|
||||||
|
object="weapons"
|
||||||
|
open={searchModalOpen}
|
||||||
|
onOpenChange={handleSearchModalOpenChange}
|
||||||
|
send={updateObject}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Methods: Core element rendering
|
||||||
const image = (
|
const image = (
|
||||||
<div className="WeaponImage">
|
<div className="WeaponImage" onClick={openSearchModal}>
|
||||||
<div className="Modifiers">
|
<div className="Modifiers">
|
||||||
{awakeningImage()}
|
{awakeningImage()}
|
||||||
<div className="Skills">
|
<div className="Skills">
|
||||||
|
|
@ -380,7 +527,7 @@ const WeaponUnit = (props: Props) => {
|
||||||
})}
|
})}
|
||||||
src={imageUrl !== '' ? imageUrl : placeholderImageUrl()}
|
src={imageUrl !== '' ? imageUrl : placeholderImageUrl()}
|
||||||
/>
|
/>
|
||||||
{props.editable ? (
|
{editable ? (
|
||||||
<span className="icon">
|
<span className="icon">
|
||||||
<PlusIcon />
|
<PlusIcon />
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -390,31 +537,12 @@ const WeaponUnit = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
const editableImage = (
|
|
||||||
<SearchModal
|
|
||||||
placeholderText={t('search.placeholders.weapon')}
|
|
||||||
fromPosition={props.position}
|
|
||||||
object="weapons"
|
|
||||||
send={props.updateObject}
|
|
||||||
>
|
|
||||||
{image}
|
|
||||||
</SearchModal>
|
|
||||||
)
|
|
||||||
|
|
||||||
const unitContent = (
|
const unitContent = (
|
||||||
|
<>
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{props.editable &&
|
{contextMenu()}
|
||||||
gridWeapon &&
|
{image}
|
||||||
gridWeapon.id &&
|
{gridWeapon && weapon ? (
|
||||||
canBeModified(gridWeapon) ? (
|
|
||||||
<WeaponModal gridWeapon={gridWeapon}>
|
|
||||||
<Button accessoryIcon={<SettingsIcon />} />
|
|
||||||
</WeaponModal>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
{props.editable ? editableImage : image}
|
|
||||||
{gridWeapon ? (
|
|
||||||
<UncapIndicator
|
<UncapIndicator
|
||||||
type="weapon"
|
type="weapon"
|
||||||
ulb={gridWeapon.object.uncap.ulb || false}
|
ulb={gridWeapon.object.uncap.ulb || false}
|
||||||
|
|
@ -428,13 +556,15 @@ const WeaponUnit = (props: Props) => {
|
||||||
)}
|
)}
|
||||||
<h3 className="WeaponName">{weapon?.name[locale]}</h3>
|
<h3 className="WeaponName">{weapon?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
|
{searchModal()}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
|
|
||||||
const withHovercard = (
|
const unitContentWithHovercard = (
|
||||||
<WeaponHovercard gridWeapon={gridWeapon!}>{unitContent}</WeaponHovercard>
|
<WeaponHovercard gridWeapon={gridWeapon!}>{unitContent}</WeaponHovercard>
|
||||||
)
|
)
|
||||||
|
|
||||||
return gridWeapon && !props.editable ? withHovercard : unitContent
|
return gridWeapon && !editable ? unitContentWithHovercard : unitContent
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WeaponUnit
|
export default WeaponUnit
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue