Update PartyHeader and DropdownMenuItem
* Remove extraneous states and hooks from PartyHeader * Only show PartyDropdown if we are looking at an existing party * Add destructive prop for DropdownMenuItem * Remove extraneous classes from PartyDropdown * Localize dropdown contents
This commit is contained in:
parent
9a16574948
commit
0e10ac5a48
6 changed files with 69 additions and 114 deletions
|
|
@ -50,7 +50,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
& .destructive {
|
||||
&.destructive {
|
||||
color: $error;
|
||||
|
||||
&:hover {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,13 @@ import classNames from 'classnames'
|
|||
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
interface Props extends DropdownMenuPrimitive.DropdownMenuItemProps {}
|
||||
interface Props extends DropdownMenuPrimitive.DropdownMenuItemProps {
|
||||
destructive?: boolean
|
||||
}
|
||||
|
||||
const defaultProps = {
|
||||
destructive: false,
|
||||
}
|
||||
|
||||
export const DropdownMenuItem = React.forwardRef<HTMLDivElement, Props>(
|
||||
function dropdownMenuItem(
|
||||
|
|
@ -13,6 +19,7 @@ export const DropdownMenuItem = React.forwardRef<HTMLDivElement, Props>(
|
|||
const classes = classNames(props.className, {
|
||||
[styles.menuItem]: true,
|
||||
[styles.language]: props.className?.includes('language'),
|
||||
[styles.destructive]: props.destructive,
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
@ -27,4 +34,6 @@ export const DropdownMenuItem = React.forwardRef<HTMLDivElement, Props>(
|
|||
}
|
||||
)
|
||||
|
||||
DropdownMenuItem.defaultProps = defaultProps
|
||||
|
||||
export default DropdownMenuItem
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
// Libraries
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { subscribe, useSnapshot } from 'valtio'
|
||||
import { useSnapshot } from 'valtio'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import classNames from 'classnames'
|
||||
|
||||
// Dependencies: Common
|
||||
import Button from '~components/common/Button'
|
||||
|
|
@ -11,9 +10,9 @@ import {
|
|||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
} from '~components/common/DropdownMenuContent'
|
||||
import DropdownMenuGroup from '~components/common/DropdownMenuGroup'
|
||||
import DropdownMenuItem from '~components/common/DropdownMenuItem'
|
||||
|
||||
// Dependencies: Toasts
|
||||
import RemixedToast from '~components/toasts/RemixedToast'
|
||||
|
|
@ -24,12 +23,7 @@ import DeleteTeamAlert from '~components/dialogs/DeleteTeamAlert'
|
|||
import RemixTeamAlert from '~components/dialogs/RemixTeamAlert'
|
||||
|
||||
// Dependencies: Utils
|
||||
import api from '~utils/api'
|
||||
import { accountState } from '~utils/accountState'
|
||||
import { appState } from '~utils/appState'
|
||||
import { getLocalId } from '~utils/localId'
|
||||
import { retrieveLocaleCookies } from '~utils/retrieveCookies'
|
||||
import { setEditKey, storeEditKey } from '~utils/userToken'
|
||||
|
||||
// Dependencies: Icons
|
||||
import EllipsisIcon from '~public/icons/Ellipsis.svg'
|
||||
|
|
@ -51,9 +45,6 @@ const PartyDropdown = ({
|
|||
|
||||
// Router
|
||||
const router = useRouter()
|
||||
const locale =
|
||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||
const localeData = retrieveLocaleCookies()
|
||||
|
||||
const [open, setOpen] = useState(false)
|
||||
|
||||
|
|
@ -63,23 +54,9 @@ const PartyDropdown = ({
|
|||
const [copyToastOpen, setCopyToastOpen] = useState(false)
|
||||
const [remixToastOpen, setRemixToastOpen] = useState(false)
|
||||
|
||||
const [name, setName] = useState('')
|
||||
const [originalName, setOriginalName] = useState('')
|
||||
|
||||
// Snapshots
|
||||
const { account } = useSnapshot(accountState)
|
||||
const { party: partySnapshot } = useSnapshot(appState)
|
||||
|
||||
// Subscribe to app state to listen for party name and
|
||||
// unsubscribe when component is unmounted
|
||||
const unsubscribe = subscribe(appState, () => {
|
||||
const newName =
|
||||
appState.party && appState.party.name ? appState.party.name : ''
|
||||
setName(newName)
|
||||
})
|
||||
|
||||
useEffect(() => () => unsubscribe(), [])
|
||||
|
||||
// Methods: Event handlers (Buttons)
|
||||
function handleButtonClicked() {
|
||||
setOpen(!open)
|
||||
|
|
@ -145,39 +122,37 @@ const PartyDropdown = ({
|
|||
remixTeamCallback()
|
||||
}
|
||||
|
||||
const editableItems = () => {
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuGroup className="MenuGroup">
|
||||
<DropdownMenuItem className="MenuItem" onClick={copyToClipboard}>
|
||||
<span>Copy link to team</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem className="MenuItem" onClick={openRemixTeamAlert}>
|
||||
<span>Remix team</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuGroup className="MenuGroup">
|
||||
<DropdownMenuItem className="MenuItem" onClick={openDeleteTeamAlert}>
|
||||
<span className="destructive">Delete team</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</>
|
||||
)
|
||||
}
|
||||
const items = (
|
||||
<>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem onClick={copyToClipboard}>
|
||||
<span>{t('dropdown.party.copy')}</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={openRemixTeamAlert}>
|
||||
<span>{t('dropdown.party.remix')}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem destructive={true} onClick={openDeleteTeamAlert}>
|
||||
<span>{t('dropdown.party.delete')}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="DropdownWrapper">
|
||||
<div className="dropdownWrapper">
|
||||
<DropdownMenu open={open} onOpenChange={handleOpenChange}>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
leftAccessoryIcon={<EllipsisIcon />}
|
||||
className={classNames({ Active: open })}
|
||||
active={open}
|
||||
blended={true}
|
||||
leftAccessoryIcon={<EllipsisIcon />}
|
||||
onClick={handleButtonClicked}
|
||||
/>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent>{editableItems()}</DropdownMenuContent>
|
||||
<DropdownMenuContent>{items}</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ import { accountState } from '~utils/accountState'
|
|||
import { appState, initialAppState } from '~utils/appState'
|
||||
import { formatTimeAgo } from '~utils/timeAgo'
|
||||
|
||||
import RemixTeamAlert from '~components/dialogs/RemixTeamAlert'
|
||||
import RemixedToast from '~components/toasts/RemixedToast'
|
||||
|
||||
import EditIcon from '~public/icons/Edit.svg'
|
||||
import RemixIcon from '~public/icons/Remix.svg'
|
||||
import SaveIcon from '~public/icons/Save.svg'
|
||||
|
|
@ -24,9 +27,6 @@ import SaveIcon from '~public/icons/Save.svg'
|
|||
import type { DetailsObject } from 'types'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
import RemixTeamAlert from '~components/dialogs/RemixTeamAlert'
|
||||
import RemixedToast from '~components/toasts/RemixedToast'
|
||||
import { set } from 'local-storage'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
|
|
@ -45,23 +45,15 @@ const PartyHeader = (props: Props) => {
|
|||
const router = useRouter()
|
||||
const locale = router.locale || 'en'
|
||||
|
||||
const isNewParty =
|
||||
router.asPath === '/' || router.asPath.split('/')[1] === 'new'
|
||||
|
||||
const { party: partySnapshot } = useSnapshot(appState)
|
||||
|
||||
// State: Component
|
||||
const [remixAlertOpen, setRemixAlertOpen] = useState(false)
|
||||
const [remixToastOpen, setRemixToastOpen] = useState(false)
|
||||
|
||||
// State: Data
|
||||
const [name, setName] = useState('')
|
||||
const [chargeAttack, setChargeAttack] = useState(true)
|
||||
const [fullAuto, setFullAuto] = useState(false)
|
||||
const [autoGuard, setAutoGuard] = useState(false)
|
||||
const [autoSummon, setAutoSummon] = useState(false)
|
||||
const [buttonCount, setButtonCount] = useState<number | undefined>(undefined)
|
||||
const [chainCount, setChainCount] = useState<number | undefined>(undefined)
|
||||
const [turnCount, setTurnCount] = useState<number | undefined>(undefined)
|
||||
const [clearTime, setClearTime] = useState(0)
|
||||
|
||||
const userClass = classNames({
|
||||
[styles.user]: true,
|
||||
[styles.empty]: !party.user,
|
||||
|
|
@ -76,39 +68,6 @@ const PartyHeader = (props: Props) => {
|
|||
light: party && party.element == 6,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (props.party) {
|
||||
setName(props.party.name)
|
||||
setAutoGuard(props.party.auto_guard)
|
||||
setFullAuto(props.party.full_auto)
|
||||
setAutoSummon(props.party.auto_summon)
|
||||
setChargeAttack(props.party.charge_attack)
|
||||
setClearTime(props.party.clear_time)
|
||||
if (props.party.turn_count) setTurnCount(props.party.turn_count)
|
||||
if (props.party.button_count) setButtonCount(props.party.button_count)
|
||||
if (props.party.chain_count) setChainCount(props.party.chain_count)
|
||||
}
|
||||
}, [props.party])
|
||||
|
||||
// Subscribe to router changes and reset state
|
||||
// if the new route is a new team
|
||||
useEffect(() => {
|
||||
router.events.on('routeChangeStart', (url, { shallow }) => {
|
||||
if (url === '/new' || url === '/') {
|
||||
const party = initialAppState.party
|
||||
|
||||
setName(party.name ? party.name : '')
|
||||
setAutoGuard(party.autoGuard)
|
||||
setFullAuto(party.fullAuto)
|
||||
setChargeAttack(party.chargeAttack)
|
||||
setClearTime(party.clearTime)
|
||||
setTurnCount(party.turnCount)
|
||||
setButtonCount(party.buttonCount)
|
||||
setChainCount(party.chainCount)
|
||||
}
|
||||
})
|
||||
}, [])
|
||||
|
||||
// Actions: Favorites
|
||||
function toggleFavorite() {
|
||||
if (appState.party.favorited) unsaveFavorite()
|
||||
|
|
@ -255,7 +214,7 @@ const PartyHeader = (props: Props) => {
|
|||
)
|
||||
|
||||
const autoGuardToken = (
|
||||
<Token active className="autoGuard">
|
||||
<Token active={party.autoGuard} className="autoGuard">
|
||||
{`${t('party.details.labels.auto_guard')} ${
|
||||
party.autoGuard ? 'On' : 'Off'
|
||||
}`}
|
||||
|
|
@ -326,8 +285,8 @@ const PartyHeader = (props: Props) => {
|
|||
{fullAutoToken}
|
||||
{autoSummonToken}
|
||||
{autoGuardToken}
|
||||
{party.turnCount ? turnCountToken : ''}
|
||||
{party.clearTime > 0 ? clearTimeToken() : ''}
|
||||
{party.turnCount && turnCountToken}
|
||||
{party.clearTime > 0 && clearTimeToken()}
|
||||
{buttonChainToken()}
|
||||
</>
|
||||
)
|
||||
|
|
@ -374,7 +333,7 @@ const PartyHeader = (props: Props) => {
|
|||
<h1 className={party.name ? '' : 'empty'}>
|
||||
{party.name ? party.name : t('no_title')}
|
||||
</h1>
|
||||
{party.remix && party.sourceParty ? (
|
||||
{party.remix && party.sourceParty && (
|
||||
<Tooltip content={t('tooltips.source')}>
|
||||
<Button
|
||||
blended={true}
|
||||
|
|
@ -384,22 +343,18 @@ const PartyHeader = (props: Props) => {
|
|||
onClick={() => goTo(party.sourceParty?.shortcode)}
|
||||
/>
|
||||
</Tooltip>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.attribution}>
|
||||
{renderUserBlock()}
|
||||
{appState.party.raid ? linkedRaidBlock(appState.party.raid) : ''}
|
||||
{party.created_at != '' ? (
|
||||
{appState.party.raid && linkedRaidBlock(appState.party.raid)}
|
||||
{party.created_at != '' && (
|
||||
<time
|
||||
className={styles.lastUpdated}
|
||||
dateTime={new Date(party.created_at).toString()}
|
||||
>
|
||||
{formatTimeAgo(new Date(party.created_at), locale)}
|
||||
</time>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -414,11 +369,13 @@ const PartyHeader = (props: Props) => {
|
|||
text={t('buttons.show_info')}
|
||||
/>
|
||||
</EditPartyModal>
|
||||
<PartyDropdown
|
||||
editable={props.editable}
|
||||
deleteTeamCallback={props.deleteCallback}
|
||||
remixTeamCallback={props.remixCallback}
|
||||
/>
|
||||
{!isNewParty && (
|
||||
<PartyDropdown
|
||||
editable={props.editable}
|
||||
deleteTeamCallback={props.deleteCallback}
|
||||
remixTeamCallback={props.remixCallback}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className={styles.right}>
|
||||
|
|
|
|||
|
|
@ -58,6 +58,13 @@
|
|||
"remove": "Remove from grid",
|
||||
"remove_job_skill": "Remove class skill"
|
||||
},
|
||||
"dropdown": {
|
||||
"party": {
|
||||
"copy": "Copy link to team",
|
||||
"delete": "Delete team",
|
||||
"remix": "Remix team"
|
||||
}
|
||||
},
|
||||
"elements": {
|
||||
"null": "Null",
|
||||
"wind": "Wind",
|
||||
|
|
|
|||
|
|
@ -58,6 +58,13 @@
|
|||
"remove": "編成から削除",
|
||||
"remove_job_skill": "ジョブスキルを削除"
|
||||
},
|
||||
"dropdown": {
|
||||
"party": {
|
||||
"copy": "編成のリンクをコピー",
|
||||
"delete": "編成を削除",
|
||||
"remix": "編成をリミックス"
|
||||
}
|
||||
},
|
||||
"elements": {
|
||||
"null": "無",
|
||||
"wind": "風",
|
||||
|
|
|
|||
Loading…
Reference in a new issue