Compare commits
41 commits
main
...
transforme
| Author | SHA1 | Date | |
|---|---|---|---|
| 31b590a542 | |||
| 973e7f34da | |||
| d0535d6031 | |||
| b2f64f1d78 | |||
| d42927623e | |||
| 500b7ffbbf | |||
| f73787c23d | |||
| fe32a49bc4 | |||
| 8ef2bf76e3 | |||
| 7cd87bd4a7 | |||
| 511d7ee0ec | |||
| 2838622335 | |||
| 587153a9e2 | |||
| 7224ae8585 | |||
| 43ccb464b1 | |||
| 686d0d0642 | |||
| af9064a356 | |||
| 2049ad4cf7 | |||
| 14994bfbbd | |||
| 8dbc6c1c6c | |||
| 11577a6b61 | |||
| abd98d27c9 | |||
| 17113e2ad9 | |||
| 5e0bda987d | |||
| da1acb1463 | |||
| 93e4fd74fd | |||
| bed7d0d408 | |||
| a70c09b373 | |||
| 5b42ca862e | |||
| 78ae6f2fd1 | |||
| 8ea2f97aac | |||
| 8f7670c07b | |||
| 83bebdb0c2 | |||
| 7c814610b9 | |||
| 881ed31dd1 | |||
| f5ee806f8b | |||
| 6ab2c2488d | |||
| cb4fd491ac | |||
| 9adcd50519 | |||
| 955cd14762 | |||
| 15a32d56bb |
137 changed files with 2326 additions and 1461 deletions
|
|
@ -3,12 +3,13 @@ import { useRouter } from 'next/router'
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import * as ElementTransformer from '~transformers/ElementTransformer'
|
||||
import * as ToggleGroup from '@radix-ui/react-toggle-group'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
interface Props {
|
||||
currentElement: number
|
||||
sendValue: (value: number) => void
|
||||
currentElement: GranblueElement
|
||||
sendValue: (value: GranblueElement) => void
|
||||
}
|
||||
|
||||
const ElementToggle = ({ currentElement, sendValue, ...props }: Props) => {
|
||||
|
|
@ -24,7 +25,7 @@ const ElementToggle = ({ currentElement, sendValue, ...props }: Props) => {
|
|||
|
||||
// Methods: Handlers
|
||||
const handleElementChange = (value: string) => {
|
||||
const newElement = parseInt(value)
|
||||
const newElement = ElementTransformer.toObject(parseInt(value))
|
||||
setElement(newElement)
|
||||
sendValue(newElement)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import 'fix-date'
|
|||
|
||||
import { accountState } from '~utils/accountState'
|
||||
import { formatTimeAgo } from '~utils/timeAgo'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
import { mapToGridArray } from '~utils/mapToGridArray'
|
||||
|
||||
import Button from '~components/common/Button'
|
||||
|
||||
|
|
@ -19,9 +21,12 @@ interface Props {
|
|||
shortcode: string
|
||||
id: string
|
||||
name: string
|
||||
raid: Raid
|
||||
grid: GridWeapon[]
|
||||
user?: User
|
||||
raid: Raid | null
|
||||
weapons: {
|
||||
mainWeapon: GridWeapon | null
|
||||
allWeapons: GridArray<GridWeapon> | null
|
||||
} | null
|
||||
user: User | null
|
||||
fullAuto: boolean
|
||||
autoGuard: boolean
|
||||
favorited: boolean
|
||||
|
|
@ -69,27 +74,19 @@ const GridRep = (props: Props) => {
|
|||
})
|
||||
|
||||
useEffect(() => {
|
||||
const newWeapons = Array(numWeapons)
|
||||
const gridWeapons = Array(numWeapons)
|
||||
|
||||
let foundMainhand = false
|
||||
for (const [key, value] of Object.entries(props.grid)) {
|
||||
if (value.position == -1) {
|
||||
setMainhand(value.object)
|
||||
foundMainhand = true
|
||||
} else if (!value.mainhand && value.position != null) {
|
||||
newWeapons[value.position] = value.object
|
||||
gridWeapons[value.position] = value
|
||||
}
|
||||
if (props.weapons && props.weapons.mainWeapon) {
|
||||
setMainhand(props.weapons.mainWeapon?.object)
|
||||
}
|
||||
|
||||
if (!foundMainhand) {
|
||||
setMainhand(undefined)
|
||||
if (props.weapons && props.weapons.allWeapons) {
|
||||
setWeapons(
|
||||
mapToGridArray(
|
||||
Object.values(props.weapons.allWeapons).map((w) => w?.object)
|
||||
)
|
||||
)
|
||||
setGrid(props.weapons.allWeapons)
|
||||
}
|
||||
|
||||
setWeapons(newWeapons)
|
||||
setGrid(gridWeapons)
|
||||
}, [props.grid])
|
||||
}, [props.weapons])
|
||||
|
||||
function navigate() {
|
||||
props.onClick(props.shortcode)
|
||||
|
|
@ -99,22 +96,16 @@ const GridRep = (props: Props) => {
|
|||
let url = ''
|
||||
|
||||
if (mainhand) {
|
||||
const weapon = Object.values(props.grid).find(
|
||||
(w) => w && w.object.id === mainhand.id
|
||||
)
|
||||
const weapon = props.weapons?.mainWeapon
|
||||
|
||||
if (mainhand.element == 0 && weapon && weapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.granblue_id}_${weapon.element}.jpg`
|
||||
if (mainhand.element === ElementMap.null && weapon && weapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.granblueId}_${weapon.element}.jpg`
|
||||
} else {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.granblue_id}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.granblueId}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
return mainhand && props.grid[0] ? (
|
||||
<img alt={mainhand.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
)
|
||||
return mainhand && <img alt={mainhand.name[locale]} src={url} />
|
||||
}
|
||||
|
||||
function generateGridImage(position: number) {
|
||||
|
|
@ -124,17 +115,17 @@ const GridRep = (props: Props) => {
|
|||
const gridWeapon = grid[position]
|
||||
|
||||
if (weapon && gridWeapon) {
|
||||
if (weapon.element == 0 && gridWeapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||
if (weapon.element === ElementMap.null && gridWeapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}_${gridWeapon.element}.jpg`
|
||||
} else {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
return weapons[position] ? (
|
||||
<img alt={weapons[position]?.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
weapons[position] && (
|
||||
<img alt={weapons[position]?.name[locale]} src={url} />
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -209,30 +200,28 @@ const GridRep = (props: Props) => {
|
|||
{` · ${t('party.details.labels.full_auto')}`}
|
||||
</span>
|
||||
)}
|
||||
{props.raid && props.raid.group.extra && (
|
||||
{props.raid && props.raid.group?.extra && (
|
||||
<span className={styles.extra}>{` · EX`}</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{account.authorized &&
|
||||
((props.user && account.user && account.user.id !== props.user.id) ||
|
||||
!props.user) ? (
|
||||
<Link href="#">
|
||||
<Button
|
||||
className={classNames({
|
||||
save: true,
|
||||
saved: props.favorited,
|
||||
})}
|
||||
leftAccessoryIcon={<SaveIcon className="stroke" />}
|
||||
active={props.favorited}
|
||||
bound={true}
|
||||
size="small"
|
||||
onClick={sendSaveData}
|
||||
/>
|
||||
</Link>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
((props.user && account.user && account.user.id !== props.user.id) ||
|
||||
!props.user) && (
|
||||
<Link href="#">
|
||||
<Button
|
||||
className={classNames({
|
||||
save: true,
|
||||
saved: props.favorited,
|
||||
})}
|
||||
leftAccessoryIcon={<SaveIcon className="stroke" />}
|
||||
active={props.favorited}
|
||||
bound={true}
|
||||
size="small"
|
||||
onClick={sendSaveData}
|
||||
/>
|
||||
</Link>
|
||||
)}
|
||||
</div>
|
||||
<div className={styles.attributed}>
|
||||
{attribution()}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { useRouter } from 'next/router'
|
|||
|
||||
import UncapIndicator from '~components/uncap/UncapIndicator'
|
||||
import WeaponLabelIcon from '~components/weapon/WeaponLabelIcon'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
|
|
@ -34,10 +35,11 @@ const HovercardHeader = ({ gridObject, object, type, ...props }: Props) => {
|
|||
const overlay = () => {
|
||||
if (type === 'character') {
|
||||
const gridCharacter = gridObject as GridCharacter
|
||||
if (gridCharacter.perpetuity) return <i className={styles.perpetuity} />
|
||||
if (gridCharacter.mastery.perpetuity)
|
||||
return <i className={styles.perpetuity} />
|
||||
} else if (type === 'summon') {
|
||||
const gridSummon = gridObject as GridSummon
|
||||
if (gridSummon.quick_summon) return <i className={styles.quickSummon} />
|
||||
if (gridSummon.quickSummon) return <i className={styles.quickSummon} />
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,11 +49,11 @@ const HovercardHeader = ({ gridObject, object, type, ...props }: Props) => {
|
|||
|
||||
// Change the image based on the uncap level
|
||||
let suffix = '01'
|
||||
if (gridCharacter.uncap_level == 6) suffix = '04'
|
||||
else if (gridCharacter.uncap_level == 5) suffix = '03'
|
||||
else if (gridCharacter.uncap_level > 2) suffix = '02'
|
||||
if (gridCharacter.uncapLevel == 6) suffix = '04'
|
||||
else if (gridCharacter.uncapLevel == 5) suffix = '03'
|
||||
else if (gridCharacter.uncapLevel > 2) suffix = '02'
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblue_id}_${suffix}.jpg`
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblueId}_${suffix}.jpg`
|
||||
}
|
||||
|
||||
const summonImage = () => {
|
||||
|
|
@ -71,29 +73,29 @@ const HovercardHeader = ({ gridObject, object, type, ...props }: Props) => {
|
|||
|
||||
let suffix = ''
|
||||
if (
|
||||
upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 &&
|
||||
gridSummon.uncap_level == 5
|
||||
upgradedSummons.indexOf(summon.granblueId.toString()) != -1 &&
|
||||
gridSummon.uncapLevel == 5
|
||||
) {
|
||||
suffix = '_02'
|
||||
} else if (
|
||||
gridSummon.object.uncap.xlb &&
|
||||
gridSummon.transcendence_step > 0
|
||||
gridSummon.transcendenceStep > 0
|
||||
) {
|
||||
suffix = '_03'
|
||||
}
|
||||
|
||||
// Generate the correct source for the summon
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg`
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblueId}${suffix}.jpg`
|
||||
}
|
||||
|
||||
const weaponImage = () => {
|
||||
const gridWeapon = gridObject as GridWeapon
|
||||
const weapon = object as Weapon
|
||||
|
||||
if (gridWeapon.object.element == 0 && gridWeapon.element)
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||
if (gridWeapon.object.element === ElementMap.null && gridWeapon.element)
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}_${gridWeapon.element}.jpg`
|
||||
else
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}.jpg`
|
||||
}
|
||||
|
||||
const image = () => {
|
||||
|
|
@ -118,7 +120,7 @@ const HovercardHeader = ({ gridObject, object, type, ...props }: Props) => {
|
|||
</div>
|
||||
<div className={styles.subInfo}>
|
||||
<div className={styles.icons}>
|
||||
<WeaponLabelIcon labelType={Element[object.element]} />
|
||||
<WeaponLabelIcon labelType={object.element.slug} />
|
||||
{'proficiency' in object && Array.isArray(object.proficiency) && (
|
||||
<WeaponLabelIcon labelType={Proficiency[object.proficiency[0]]} />
|
||||
)}
|
||||
|
|
@ -136,9 +138,7 @@ const HovercardHeader = ({ gridObject, object, type, ...props }: Props) => {
|
|||
ulb={object.uncap.ulb || false}
|
||||
flb={object.uncap.flb || false}
|
||||
transcendenceStage={
|
||||
'transcendence_step' in gridObject
|
||||
? gridObject.transcendence_step
|
||||
: 0
|
||||
'transcendenceStep' in gridObject ? gridObject.transcendenceStep : 0
|
||||
}
|
||||
special={'special' in object ? object.special : false}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const Layout = ({ children }: PropsWithChildren<Props>) => {
|
|||
|
||||
return (
|
||||
<>
|
||||
{appState.version ? ServerAvailable() : ''}
|
||||
{appState.version && ServerAvailable()}
|
||||
<main>{children}</main>
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export type MentionRef = {
|
|||
}
|
||||
|
||||
export type MentionSuggestion = {
|
||||
granblue_id: string
|
||||
granblueId: string
|
||||
name: {
|
||||
[key: string]: string
|
||||
en: string
|
||||
|
|
@ -101,10 +101,10 @@ export const MentionList = forwardRef<MentionRef, Props>(
|
|||
alt={item.name[locale]}
|
||||
src={
|
||||
item.type === 'character'
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/${item.type}-square/${item.granblue_id}_01.jpg`
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/${item.type}-square/${item.granblueId}_01.jpg`
|
||||
: item.type === 'job'
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${item.granblue_id}.png`
|
||||
: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/${item.type}-square/${item.granblue_id}.jpg`
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${item.granblueId}.png`
|
||||
: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/${item.type}-square/${item.granblueId}.jpg`
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ const AboutHead = ({ page }: Props) => {
|
|||
name="description"
|
||||
content={t(`page.descriptions.${currentPage}`)}
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
{/* OpenGraph */}
|
||||
|
|
|
|||
|
|
@ -83,8 +83,8 @@ const ChangelogUnit = ({ id, type, image }: Props) => {
|
|||
|
||||
return (
|
||||
<div className={styles.unit} key={id}>
|
||||
<img alt={item ? item.name[locale] : ''} src={imageUrl()} />
|
||||
<h4>{item ? item.name[locale] : ''}</h4>
|
||||
<img alt={item && item.name[locale]} src={imageUrl()} />
|
||||
<h4>{item && item.name[locale]}</h4>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import Button from '~components/common/Button'
|
|||
import Overlay from '~components/common/Overlay'
|
||||
|
||||
import { appState } from '~utils/appState'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
|
|
@ -46,21 +47,22 @@ const CharacterConflictModal = (props: Props) => {
|
|||
else if (uncap > 2) suffix = '02'
|
||||
|
||||
// Special casing for Lyria (and Young Cat eventually)
|
||||
if (character?.granblue_id === '3030182000') {
|
||||
let element = 1
|
||||
if (character?.granblueId === '3030182000') {
|
||||
let element: GranblueElement | undefined
|
||||
|
||||
if (
|
||||
appState.grid.weapons.mainWeapon &&
|
||||
appState.grid.weapons.mainWeapon.element
|
||||
) {
|
||||
element = appState.grid.weapons.mainWeapon.element
|
||||
} else if (appState.party.element != 0) {
|
||||
element = appState.party.element
|
||||
} else {
|
||||
element = ElementMap.wind
|
||||
}
|
||||
|
||||
suffix = `${suffix}_0${element}`
|
||||
suffix = `${suffix}_0${element?.id}`
|
||||
}
|
||||
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-square/${character?.granblue_id}_${suffix}.jpg`
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-square/${character?.granblueId}_${suffix}.jpg`
|
||||
}
|
||||
|
||||
function openChange(open: boolean) {
|
||||
|
|
@ -91,7 +93,7 @@ const CharacterConflictModal = (props: Props) => {
|
|||
<li className={styles.character} key={`conflict-${i}`}>
|
||||
<img
|
||||
alt={character.object.name[locale]}
|
||||
src={imageUrl(character.object, character.uncap_level)}
|
||||
src={imageUrl(character.object, character.uncapLevel)}
|
||||
/>
|
||||
<span>{character.object.name[locale]}</span>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -16,14 +16,17 @@ import type { DetailsObject, JobSkillObject, SearchableObject } from '~types'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import * as CharacterTransformer from '~transformers/CharacterTransformer'
|
||||
import * as GridCharacterTransformer from '~transformers/GridCharacterTransformer'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
import { use } from 'i18next'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
new: boolean
|
||||
editable: boolean
|
||||
characters?: GridCharacter[]
|
||||
characters?: GridArray<GridCharacter>
|
||||
createParty: (details?: DetailsObject) => Promise<Party>
|
||||
pushHistory?: (path: string) => void
|
||||
}
|
||||
|
|
@ -46,7 +49,7 @@ const CharacterGrid = (props: Props) => {
|
|||
const [errorAlertOpen, setErrorAlertOpen] = useState(false)
|
||||
|
||||
// Set up state for view management
|
||||
const { party, grid } = useSnapshot(appState)
|
||||
const { party } = useSnapshot(appState)
|
||||
const [modalOpen, setModalOpen] = useState(false)
|
||||
|
||||
// Set up state for conflict management
|
||||
|
|
@ -76,19 +79,39 @@ const CharacterGrid = (props: Props) => {
|
|||
}>({})
|
||||
|
||||
useEffect(() => {
|
||||
setJob(appState.party.job)
|
||||
setJobSkills(appState.party.jobSkills)
|
||||
setJobAccessory(appState.party.accessory)
|
||||
}, [appState])
|
||||
console.log('loading chara grid')
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
setJob(appState.party.protagonist.job)
|
||||
setJobSkills(
|
||||
appState.party.protagonist.skills
|
||||
? appState.party.protagonist.skills
|
||||
: {
|
||||
0: undefined,
|
||||
1: undefined,
|
||||
2: undefined,
|
||||
3: undefined,
|
||||
}
|
||||
)
|
||||
setJobAccessory(
|
||||
appState.party.protagonist.accessory
|
||||
? appState.party.protagonist.accessory
|
||||
: undefined
|
||||
)
|
||||
}, [])
|
||||
|
||||
// Initialize an array of current uncap values for each characters
|
||||
useEffect(() => {
|
||||
let initialPreviousUncapValues: { [key: number]: number } = {}
|
||||
Object.values(appState.grid.characters).map((o) => {
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncap_level) : 0
|
||||
const values = appState.party.grid.characters
|
||||
? appState.party.grid.characters
|
||||
: {}
|
||||
Object.values(values).map((o) => {
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncapLevel) : 0
|
||||
})
|
||||
setPreviousUncapValues(initialPreviousUncapValues)
|
||||
}, [appState.grid.characters])
|
||||
}, [appState.party.grid.characters])
|
||||
|
||||
// Methods: Adding an object from search
|
||||
function receiveCharacterFromSearch(
|
||||
|
|
@ -121,8 +144,10 @@ const CharacterGrid = (props: Props) => {
|
|||
|
||||
async function handleCharacterResponse(data: any) {
|
||||
if (data.hasOwnProperty('conflicts')) {
|
||||
setIncoming(data.incoming)
|
||||
setConflicts(data.conflicts)
|
||||
setIncoming(CharacterTransformer.toObject(data.incoming))
|
||||
setConflicts(
|
||||
data.conflicts.map((c: any) => GridCharacterTransformer.toObject(c))
|
||||
)
|
||||
setPosition(data.position)
|
||||
setModalOpen(true)
|
||||
} else {
|
||||
|
|
@ -140,13 +165,18 @@ const CharacterGrid = (props: Props) => {
|
|||
party_id: partyId,
|
||||
character_id: character.id,
|
||||
position: position,
|
||||
uncap_level: characterUncapLevel(character),
|
||||
uncapLevel: characterUncapLevel(character),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function storeGridCharacter(gridCharacter: GridCharacter) {
|
||||
appState.grid.characters[gridCharacter.position] = gridCharacter
|
||||
function storeGridCharacter(data: any) {
|
||||
const gridCharacter = GridCharacterTransformer.toObject(data)
|
||||
|
||||
appState.party.grid.characters = {
|
||||
...appState.party.grid.characters,
|
||||
[gridCharacter.position]: gridCharacter,
|
||||
}
|
||||
}
|
||||
|
||||
async function resolveConflict() {
|
||||
|
|
@ -164,7 +194,11 @@ const CharacterGrid = (props: Props) => {
|
|||
|
||||
// Remove conflicting characters from state
|
||||
conflicts.forEach(
|
||||
(c) => (appState.grid.characters[c.position] = undefined)
|
||||
(c) =>
|
||||
(appState.party.grid.characters = {
|
||||
...appState.party.grid.characters,
|
||||
[c.position]: null,
|
||||
})
|
||||
)
|
||||
|
||||
// Reset conflict
|
||||
|
|
@ -186,7 +220,10 @@ const CharacterGrid = (props: Props) => {
|
|||
async function removeCharacter(id: string) {
|
||||
try {
|
||||
const response = await api.endpoints.grid_characters.destroy({ id: id })
|
||||
appState.grid.characters[response.data.position] = undefined
|
||||
appState.party.grid.characters = {
|
||||
...appState.party.grid.characters,
|
||||
[response.data.position]: null,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
|
|
@ -214,10 +251,10 @@ const CharacterGrid = (props: Props) => {
|
|||
const team = response.data
|
||||
|
||||
setJob(team.job)
|
||||
appState.party.job = team.job
|
||||
appState.party.protagonist.job = team.job
|
||||
|
||||
setJobSkills(team.job_skills)
|
||||
appState.party.jobSkills = team.job_skills
|
||||
appState.party.protagonist.skills = team.job_skills
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -244,7 +281,7 @@ const CharacterGrid = (props: Props) => {
|
|||
// Update the current skills
|
||||
const newSkills = response.data.job_skills
|
||||
setJobSkills(newSkills)
|
||||
appState.party.jobSkills = newSkills
|
||||
appState.party.protagonist.skills = newSkills
|
||||
})
|
||||
.catch((error) => {
|
||||
const data = error.response.data
|
||||
|
|
@ -268,7 +305,7 @@ const CharacterGrid = (props: Props) => {
|
|||
// Update the current skills
|
||||
const newSkills = response.data.job_skills
|
||||
setJobSkills(newSkills)
|
||||
appState.party.jobSkills = newSkills
|
||||
appState.party.protagonist.skills = newSkills
|
||||
})
|
||||
.catch((error) => {
|
||||
const data = error.response.data
|
||||
|
|
@ -291,7 +328,7 @@ const CharacterGrid = (props: Props) => {
|
|||
)
|
||||
const team = response.data.party
|
||||
setJobAccessory(team.accessory)
|
||||
appState.party.accessory = team.accessory
|
||||
appState.party.protagonist.accessory = team.accessory
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -378,10 +415,13 @@ const CharacterGrid = (props: Props) => {
|
|||
position: number,
|
||||
uncapLevel: number | undefined
|
||||
) => {
|
||||
const character = appState.grid.characters[position]
|
||||
const character = appState.party.grid.characters?.[position]
|
||||
if (character && uncapLevel) {
|
||||
character.uncap_level = uncapLevel
|
||||
appState.grid.characters[position] = character
|
||||
character.uncapLevel = uncapLevel
|
||||
appState.party.grid.characters = {
|
||||
...appState.party.grid.characters,
|
||||
[position]: character,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -389,8 +429,8 @@ const CharacterGrid = (props: Props) => {
|
|||
// Save the current value in case of an unexpected result
|
||||
let newPreviousValues = { ...previousUncapValues }
|
||||
|
||||
if (grid.characters[position]) {
|
||||
newPreviousValues[position] = grid.characters[position]?.uncap_level
|
||||
if (party.grid.characters && party.grid.characters[position]) {
|
||||
newPreviousValues[position] = party.grid.characters[position]?.uncapLevel
|
||||
setPreviousUncapValues(newPreviousValues)
|
||||
}
|
||||
}
|
||||
|
|
@ -407,7 +447,7 @@ const CharacterGrid = (props: Props) => {
|
|||
|
||||
const payload = {
|
||||
character: {
|
||||
uncap_level: stage > 0 ? 6 : 5,
|
||||
uncapLevel: stage > 0 ? 6 : 5,
|
||||
transcendence_step: stage,
|
||||
},
|
||||
}
|
||||
|
|
@ -474,10 +514,13 @@ const CharacterGrid = (props: Props) => {
|
|||
position: number,
|
||||
stage: number | undefined
|
||||
) => {
|
||||
const character = appState.grid.characters[position]
|
||||
const character = appState.party.grid.characters?.[position]
|
||||
if (character && stage !== undefined) {
|
||||
character.transcendence_step = stage
|
||||
appState.grid.characters[position] = character
|
||||
character.transcendenceStep = stage
|
||||
appState.party.grid.characters = {
|
||||
...appState.party.grid.characters,
|
||||
[position]: character,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -485,8 +528,8 @@ const CharacterGrid = (props: Props) => {
|
|||
// Save the current value in case of an unexpected result
|
||||
let newPreviousValues = { ...previousUncapValues }
|
||||
|
||||
if (grid.characters[position]) {
|
||||
newPreviousValues[position] = grid.characters[position]?.uncap_level
|
||||
if (party.grid.characters && party.grid.characters[position]) {
|
||||
newPreviousValues[position] = party.grid.characters[position]?.uncapLevel
|
||||
setPreviousTranscendenceStages(newPreviousValues)
|
||||
}
|
||||
}
|
||||
|
|
@ -540,7 +583,9 @@ const CharacterGrid = (props: Props) => {
|
|||
return (
|
||||
<li key={`grid_unit_${i}`}>
|
||||
<CharacterUnit
|
||||
gridCharacter={grid.characters[i]}
|
||||
gridCharacter={
|
||||
party.grid.characters ? party.grid.characters[i] : null
|
||||
}
|
||||
editable={props.editable}
|
||||
position={i}
|
||||
updateObject={receiveCharacterFromSearch}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,13 @@ import React from 'react'
|
|||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import Button from '~components/common/Button'
|
||||
import {
|
||||
Hovercard,
|
||||
HovercardContent,
|
||||
HovercardTrigger,
|
||||
} from '~components/common/Hovercard'
|
||||
import Button from '~components/common/Button'
|
||||
import WeaponLabelIcon from '~components/weapon/WeaponLabelIcon'
|
||||
import UncapIndicator from '~components/uncap/UncapIndicator'
|
||||
import HovercardHeader from '~components/HovercardHeader'
|
||||
|
||||
import {
|
||||
overMastery,
|
||||
|
|
@ -19,7 +18,6 @@ import {
|
|||
import { ExtendedMastery } from '~types'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
import HovercardHeader from '~components/HovercardHeader'
|
||||
|
||||
interface Props {
|
||||
gridCharacter: GridCharacter
|
||||
|
|
@ -33,8 +31,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
const locale =
|
||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||
|
||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||
const tintElement = Element[props.gridCharacter.object.element]
|
||||
const tintElement = props.gridCharacter.object.element.slug
|
||||
|
||||
function goTo() {
|
||||
const urlSafeName = props.gridCharacter.object.name.en.replaceAll(' ', '_')
|
||||
|
|
@ -65,7 +62,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const overMasterySection = () => {
|
||||
if (props.gridCharacter && props.gridCharacter.over_mastery) {
|
||||
if (props.gridCharacter && props.gridCharacter.mastery.overMastery) {
|
||||
return (
|
||||
<section className={styles.mastery}>
|
||||
<h5 className={tintElement}>
|
||||
|
|
@ -75,7 +72,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
{[...Array(4)].map((e, i) => {
|
||||
const ringIndex = i + 1
|
||||
const ringStat: ExtendedMastery =
|
||||
props.gridCharacter.over_mastery[i]
|
||||
props.gridCharacter.mastery.overMastery[i]
|
||||
if (ringStat && ringStat.modifier && ringStat.modifier > 0) {
|
||||
if (ringIndex === 1 || ringIndex === 2) {
|
||||
return masteryElement(overMastery.a, ringStat)
|
||||
|
|
@ -95,8 +92,8 @@ const CharacterHovercard = (props: Props) => {
|
|||
const aetherialMasterySection = () => {
|
||||
if (
|
||||
props.gridCharacter &&
|
||||
props.gridCharacter.aetherial_mastery &&
|
||||
props.gridCharacter.aetherial_mastery.modifier > 0
|
||||
props.gridCharacter.mastery.aetherialMastery &&
|
||||
props.gridCharacter.mastery.aetherialMastery.modifier > 0
|
||||
) {
|
||||
return (
|
||||
<section className={styles.mastery}>
|
||||
|
|
@ -106,7 +103,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
<ul>
|
||||
{masteryElement(
|
||||
aetherialMastery,
|
||||
props.gridCharacter.aetherial_mastery
|
||||
props.gridCharacter.mastery.aetherialMastery
|
||||
)}
|
||||
</ul>
|
||||
</section>
|
||||
|
|
@ -115,7 +112,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const permanentMasterySection = () => {
|
||||
if (props.gridCharacter && props.gridCharacter.perpetuity) {
|
||||
if (props.gridCharacter && props.gridCharacter.mastery.perpetuity) {
|
||||
return (
|
||||
<section className={styles.mastery}>
|
||||
<h5 className={tintElement}>
|
||||
|
|
@ -135,7 +132,7 @@ const CharacterHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const awakeningSection = () => {
|
||||
const gridAwakening = props.gridCharacter.awakening
|
||||
const gridAwakening = props.gridCharacter.mastery.awakening
|
||||
|
||||
if (gridAwakening) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -22,6 +22,13 @@ const emptyExtendedMastery: ExtendedMastery = {
|
|||
strength: 0,
|
||||
}
|
||||
|
||||
const emptyRingset: CharacterOverMastery = {
|
||||
1: { ...emptyExtendedMastery, modifier: 1 },
|
||||
2: { ...emptyExtendedMastery, modifier: 2 },
|
||||
3: emptyExtendedMastery,
|
||||
4: emptyExtendedMastery,
|
||||
}
|
||||
|
||||
const MAX_AWAKENING_LEVEL = 9
|
||||
|
||||
// Styles and icons
|
||||
|
|
@ -85,16 +92,29 @@ const CharacterModal = ({
|
|||
}, [modalOpen])
|
||||
|
||||
useEffect(() => {
|
||||
if (gridCharacter.aetherial_mastery) {
|
||||
console.log('Setting up grid character')
|
||||
console.log(gridCharacter)
|
||||
|
||||
if (gridCharacter.mastery.overMastery) {
|
||||
setRings(gridCharacter.mastery.overMastery)
|
||||
} else {
|
||||
setRings(emptyRingset)
|
||||
}
|
||||
|
||||
if (gridCharacter.mastery.aetherialMastery) {
|
||||
setEarring({
|
||||
modifier: gridCharacter.aetherial_mastery.modifier,
|
||||
strength: gridCharacter.aetherial_mastery.strength,
|
||||
modifier: gridCharacter.mastery.aetherialMastery.modifier,
|
||||
strength: gridCharacter.mastery.aetherialMastery.strength,
|
||||
})
|
||||
}
|
||||
|
||||
setAwakening(gridCharacter.awakening.type)
|
||||
setAwakeningLevel(gridCharacter.awakening.level)
|
||||
setPerpetuity(gridCharacter.perpetuity)
|
||||
setAwakening(gridCharacter.mastery.awakening.type)
|
||||
setAwakeningLevel(
|
||||
gridCharacter.mastery.awakening.level
|
||||
? gridCharacter.mastery.awakening.level
|
||||
: 1
|
||||
)
|
||||
setPerpetuity(gridCharacter.mastery.perpetuity)
|
||||
}, [gridCharacter])
|
||||
|
||||
// Prepare the GridWeaponObject to send to the server
|
||||
|
|
@ -144,25 +164,18 @@ const CharacterModal = ({
|
|||
rings ||
|
||||
aetherialMastery ||
|
||||
awakening ||
|
||||
gridCharacter.perpetuity !== perpetuity
|
||||
gridCharacter.mastery.perpetuity !== perpetuity
|
||||
)
|
||||
}
|
||||
|
||||
function ringsChanged() {
|
||||
// Create an empty ExtendedMastery object
|
||||
const emptyRingset: CharacterOverMastery = {
|
||||
1: { ...emptyExtendedMastery, modifier: 1 },
|
||||
2: { ...emptyExtendedMastery, modifier: 2 },
|
||||
3: emptyExtendedMastery,
|
||||
4: emptyExtendedMastery,
|
||||
}
|
||||
|
||||
// Check if the current ringset is empty on the current GridCharacter and our local state
|
||||
const isEmptyRingset =
|
||||
gridCharacter.over_mastery === undefined && isEqual(emptyRingset, rings)
|
||||
gridCharacter.mastery.overMastery === undefined &&
|
||||
isEqual(emptyRingset, rings)
|
||||
|
||||
// Check if the ringset in local state is different from the one on the current GridCharacter
|
||||
const ringsChanged = !isEqual(gridCharacter.over_mastery, rings)
|
||||
const ringsChanged = !isEqual(gridCharacter.mastery.overMastery, rings)
|
||||
|
||||
// Return true if the ringset has been modified and is not empty
|
||||
return ringsChanged && !isEmptyRingset
|
||||
|
|
@ -177,12 +190,12 @@ const CharacterModal = ({
|
|||
|
||||
// Check if the current earring is empty on the current GridCharacter and our local state
|
||||
const isEmptyRingset =
|
||||
gridCharacter.aetherial_mastery === undefined &&
|
||||
gridCharacter.mastery.aetherialMastery === undefined &&
|
||||
isEqual(emptyAetherialMastery, earring)
|
||||
|
||||
// Check if the earring in local state is different from the one on the current GridCharacter
|
||||
const aetherialMasteryChanged = !isEqual(
|
||||
gridCharacter.aetherial_mastery,
|
||||
gridCharacter.mastery.aetherialMastery,
|
||||
earring
|
||||
)
|
||||
|
||||
|
|
@ -193,8 +206,8 @@ const CharacterModal = ({
|
|||
function awakeningChanged() {
|
||||
// Check if the awakening in local state is different from the one on the current GridCharacter
|
||||
const awakeningChanged =
|
||||
!isEqual(gridCharacter.awakening.type, awakening) ||
|
||||
gridCharacter.awakening.level !== awakeningLevel
|
||||
!isEqual(gridCharacter.mastery.awakening.type, awakening) ||
|
||||
gridCharacter.mastery.awakening.level !== awakeningLevel
|
||||
|
||||
// Return true if the awakening has been modified and is not empty
|
||||
return awakeningChanged
|
||||
|
|
@ -248,17 +261,21 @@ const CharacterModal = ({
|
|||
|
||||
function close() {
|
||||
setEarring({
|
||||
modifier: gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.modifier
|
||||
modifier: gridCharacter.mastery.aetherialMastery
|
||||
? gridCharacter.mastery.aetherialMastery.modifier
|
||||
: 0,
|
||||
strength: gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.strength
|
||||
strength: gridCharacter.mastery.aetherialMastery
|
||||
? gridCharacter.mastery.aetherialMastery.strength
|
||||
: 0,
|
||||
})
|
||||
|
||||
setRings(gridCharacter.over_mastery || emptyExtendedMastery)
|
||||
setAwakening(gridCharacter.awakening.type)
|
||||
setAwakeningLevel(gridCharacter.awakening.level)
|
||||
setRings(gridCharacter.mastery.overMastery || emptyExtendedMastery)
|
||||
setAwakening(gridCharacter.mastery.awakening.type)
|
||||
setAwakeningLevel(
|
||||
gridCharacter.mastery.awakening.level
|
||||
? gridCharacter.mastery.awakening.level
|
||||
: 1
|
||||
)
|
||||
|
||||
setAlertOpen(false)
|
||||
setOpen(false)
|
||||
|
|
@ -305,13 +322,13 @@ const CharacterModal = ({
|
|||
object="earring"
|
||||
dataSet={elementalizeAetherialMastery(gridCharacter)}
|
||||
selectValue={
|
||||
gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.modifier
|
||||
gridCharacter.mastery.aetherialMastery
|
||||
? gridCharacter.mastery.aetherialMastery.modifier
|
||||
: 0
|
||||
}
|
||||
inputValue={
|
||||
gridCharacter.aetherial_mastery
|
||||
? gridCharacter.aetherial_mastery.strength
|
||||
gridCharacter.mastery.aetherialMastery
|
||||
? gridCharacter.mastery.aetherialMastery.strength
|
||||
: 0
|
||||
}
|
||||
sendValidity={receiveValidity}
|
||||
|
|
@ -325,8 +342,8 @@ const CharacterModal = ({
|
|||
<h3>{t('modals.characters.subtitles.awakening')}</h3>
|
||||
<AwakeningSelectWithInput
|
||||
dataSet={gridCharacter.object.awakenings}
|
||||
awakening={gridCharacter.awakening.type}
|
||||
level={gridCharacter.awakening.level}
|
||||
awakening={gridCharacter.mastery.awakening.type}
|
||||
level={gridCharacter.mastery.awakening.level}
|
||||
defaultAwakening={
|
||||
gridCharacter.object.awakenings.find(
|
||||
(a) => a.slug === 'character-balanced'
|
||||
|
|
@ -364,7 +381,7 @@ const CharacterModal = ({
|
|||
title={gridCharacter.object.name[locale]}
|
||||
subtitle={t('modals.characters.title')}
|
||||
image={{
|
||||
src: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-square/${gridCharacter.object.granblue_id}_01.jpg`,
|
||||
src: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-square/${gridCharacter.object.granblueId}_01.jpg`,
|
||||
alt: gridCharacter.object.name[locale],
|
||||
}}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@ const CharacterResult = (props: Props) => {
|
|||
const character = props.data
|
||||
|
||||
const characterUrl = () => {
|
||||
let url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblue_id}_01.jpg`
|
||||
let url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblueId}_01.jpg`
|
||||
|
||||
if (character.granblue_id === '3030182000') {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblue_id}_01_01.jpg`
|
||||
if (character.granblueId === '3030182000') {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-grid/${character.granblueId}_01_01.jpg`
|
||||
}
|
||||
|
||||
return url
|
||||
|
|
@ -40,9 +40,10 @@ const CharacterResult = (props: Props) => {
|
|||
flb={character.uncap.flb}
|
||||
ulb={character.uncap.ulb}
|
||||
special={character.special}
|
||||
transcendenceStage={character.uncap.ulb ? 5 : 0}
|
||||
/>
|
||||
<div className={styles.tags}>
|
||||
<WeaponLabelIcon labelType={Element[character.element]} />
|
||||
<WeaponLabelIcon labelType={character.element.slug} />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import UncapIndicator from '~components/uncap/UncapIndicator'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
import * as GridCharacterTransformer from '~transformers/GridCharacterTransformer'
|
||||
|
||||
import PlusIcon from '~public/icons/Add.svg'
|
||||
import SettingsIcon from '~public/icons/Settings.svg'
|
||||
|
|
@ -36,7 +38,7 @@ import type {
|
|||
import styles from './index.module.scss'
|
||||
|
||||
interface Props {
|
||||
gridCharacter?: GridCharacter
|
||||
gridCharacter: GridCharacter | null
|
||||
position: number
|
||||
editable: boolean
|
||||
removeCharacter: (id: string) => void
|
||||
|
|
@ -109,7 +111,7 @@ const CharacterUnit = ({
|
|||
function handlePerpetuityClick() {
|
||||
if (gridCharacter) {
|
||||
let object: PerpetuityObject = {
|
||||
character: { perpetuity: !gridCharacter.perpetuity },
|
||||
character: { perpetuity: !gridCharacter.mastery.perpetuity },
|
||||
}
|
||||
|
||||
updateCharacter(object)
|
||||
|
|
@ -144,21 +146,23 @@ const CharacterUnit = ({
|
|||
|
||||
// Save the server's response to state
|
||||
function processResult(response: AxiosResponse) {
|
||||
const gridCharacter: GridCharacter = response.data
|
||||
const gridCharacter: GridCharacter = GridCharacterTransformer.toObject(
|
||||
response.data
|
||||
)
|
||||
let character = cloneDeep(gridCharacter)
|
||||
|
||||
if (character.over_mastery) {
|
||||
if (character.mastery.overMastery) {
|
||||
const overMastery: CharacterOverMastery = {
|
||||
1: gridCharacter.over_mastery[0],
|
||||
2: gridCharacter.over_mastery[1],
|
||||
3: gridCharacter.over_mastery[2],
|
||||
4: gridCharacter.over_mastery[3],
|
||||
1: gridCharacter.mastery.overMastery[0],
|
||||
2: gridCharacter.mastery.overMastery[1],
|
||||
3: gridCharacter.mastery.overMastery[2],
|
||||
4: gridCharacter.mastery.overMastery[3],
|
||||
}
|
||||
|
||||
character.over_mastery = overMastery
|
||||
character.mastery.overMastery = overMastery
|
||||
}
|
||||
|
||||
appState.grid.characters[gridCharacter.position] = character
|
||||
appState.party.grid.characters[gridCharacter.position] = character
|
||||
}
|
||||
|
||||
function processError(error: any) {
|
||||
|
|
@ -187,23 +191,28 @@ const CharacterUnit = ({
|
|||
|
||||
// Change the image based on the uncap level
|
||||
let suffix = '01'
|
||||
if (gridCharacter.transcendence_step > 0) suffix = '04'
|
||||
else if (gridCharacter.uncap_level >= 5) suffix = '03'
|
||||
else if (gridCharacter.uncap_level > 2) suffix = '02'
|
||||
if (
|
||||
gridCharacter.transcendenceStep &&
|
||||
gridCharacter.transcendenceStep > 0
|
||||
)
|
||||
suffix = '04'
|
||||
else if (gridCharacter.uncapLevel >= 5) suffix = '03'
|
||||
else if (gridCharacter.uncapLevel > 2) suffix = '02'
|
||||
|
||||
// Special casing for Lyria (and Young Cat eventually)
|
||||
if (gridCharacter.object.granblue_id === '3030182000') {
|
||||
let element = 1
|
||||
if (gridCharacter.object.granblueId === '3030182000') {
|
||||
let element: GranblueElement | undefined
|
||||
|
||||
if (grid.weapons.mainWeapon && grid.weapons.mainWeapon.element) {
|
||||
element = grid.weapons.mainWeapon.element
|
||||
} else if (party.element != 0) {
|
||||
element = party.element
|
||||
} else {
|
||||
element = ElementMap.wind
|
||||
}
|
||||
|
||||
suffix = `${suffix}_0${element}`
|
||||
}
|
||||
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblue_id}_${suffix}.jpg`
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblueId}_${suffix}.jpg`
|
||||
}
|
||||
|
||||
setImageUrl(imgSrc)
|
||||
|
|
@ -292,7 +301,7 @@ const CharacterUnit = ({
|
|||
if (gridCharacter) {
|
||||
const classes = classNames({
|
||||
[styles.perpetuity]: true,
|
||||
[styles.empty]: !gridCharacter.perpetuity,
|
||||
[styles.empty]: !gridCharacter.mastery.perpetuity,
|
||||
})
|
||||
|
||||
return <i className={classes} onClick={handlePerpetuityClick} />
|
||||
|
|
@ -348,8 +357,8 @@ const CharacterUnit = ({
|
|||
type="character"
|
||||
flb={character.uncap.flb || false}
|
||||
ulb={character.uncap.ulb || false}
|
||||
uncapLevel={gridCharacter.uncap_level}
|
||||
transcendenceStage={gridCharacter.transcendence_step}
|
||||
uncapLevel={gridCharacter.uncapLevel}
|
||||
transcendenceStage={gridCharacter.transcendenceStep}
|
||||
position={gridCharacter.position}
|
||||
editable={editable}
|
||||
updateUncap={passUncapData}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@
|
|||
color: inherit;
|
||||
z-index: 10;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
place-items: flex-end;
|
||||
overflow-y: hidden;
|
||||
|
||||
&.filter {
|
||||
}
|
||||
}
|
||||
|
||||
.dialogContent {
|
||||
$multiplier: 4;
|
||||
|
||||
|
|
@ -51,11 +59,11 @@
|
|||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
min-width: inherit;
|
||||
min-height: 90vh;
|
||||
min-height: inherit;
|
||||
transform: initial;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 5vh;
|
||||
top: $unit-10x;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -101,110 +109,6 @@
|
|||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.Conflict {
|
||||
$weapon-diameter: 14rem;
|
||||
|
||||
.Content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-4x;
|
||||
padding: $unit-4x $unit-4x $unit-2x $unit-4x;
|
||||
|
||||
& > p {
|
||||
font-size: $font-regular;
|
||||
line-height: 1.4;
|
||||
|
||||
strong {
|
||||
font-weight: $bold;
|
||||
}
|
||||
|
||||
&:lang(ja) {
|
||||
line-height: 1.4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.weapon,
|
||||
.character {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit;
|
||||
text-align: center;
|
||||
width: $weapon-diameter;
|
||||
font-weight: $medium;
|
||||
|
||||
img {
|
||||
border-radius: 1rem;
|
||||
width: $weapon-diameter;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
span {
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
|
||||
.Diagram {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto 1fr;
|
||||
align-items: flex-start;
|
||||
|
||||
&.CharacterDiagram {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-2x;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arrow {
|
||||
align-items: center;
|
||||
color: $grey-55;
|
||||
display: flex;
|
||||
font-size: 4rem;
|
||||
text-align: center;
|
||||
height: $weapon-diameter;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit;
|
||||
|
||||
.Button {
|
||||
font-size: $font-regular;
|
||||
padding: ($unit * 1.5) ($unit * 2);
|
||||
width: 100%;
|
||||
|
||||
&.btn-disabled {
|
||||
background: $grey-90;
|
||||
color: $grey-70;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:not(.btn-disabled) {
|
||||
background: $grey-90;
|
||||
color: $grey-50;
|
||||
|
||||
&:hover {
|
||||
background: $grey-80;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes openModalDesktop {
|
||||
|
|
@ -221,11 +125,20 @@
|
|||
|
||||
@keyframes slideUp {
|
||||
0% {
|
||||
transform: translate(0%, 100%);
|
||||
transform: translateY(400px);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
60% {
|
||||
transform: translateY(-30px);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
80% {
|
||||
transform: translateY(10px);
|
||||
animation-timing-function: ease-out;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate(0, 0%);
|
||||
transform: translateY(0px);
|
||||
animation-timing-function: ease-in;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ interface Props
|
|||
React.DialogHTMLAttributes<HTMLDivElement>,
|
||||
HTMLDivElement
|
||||
> {
|
||||
wrapperClassName?: string
|
||||
headerref?: React.RefObject<HTMLDivElement>
|
||||
footerref?: React.RefObject<HTMLDivElement>
|
||||
scrollable?: boolean
|
||||
|
|
@ -127,7 +128,16 @@ const DialogContent = React.forwardRef<HTMLDivElement, Props>(function Dialog(
|
|||
|
||||
return (
|
||||
<DialogPrimitive.Portal>
|
||||
<dialog className={styles.dialog}>
|
||||
<dialog
|
||||
className={classNames(
|
||||
{
|
||||
[styles.dialog]: true,
|
||||
},
|
||||
props.wrapperClassName
|
||||
?.split(' ')
|
||||
.map((className) => styles[className])
|
||||
)}
|
||||
>
|
||||
<DialogPrimitive.Content
|
||||
{...props}
|
||||
className={classes}
|
||||
|
|
|
|||
|
|
@ -16,4 +16,11 @@
|
|||
display: flex;
|
||||
gap: $unit;
|
||||
}
|
||||
|
||||
@include breakpoint(phone) {
|
||||
position: fixed;
|
||||
bottom: $unit-14x;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@
|
|||
outline: none;
|
||||
}
|
||||
|
||||
p.empty:first-child::before {
|
||||
color: var(--text-tertiary);
|
||||
content: attr(data-placeholder);
|
||||
float: left;
|
||||
height: 0;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&.bound {
|
||||
background-color: var(--input-bound-bg);
|
||||
|
||||
|
|
@ -74,21 +82,21 @@
|
|||
h1 {
|
||||
font-size: $font-xlarge;
|
||||
font-weight: $medium;
|
||||
margin: $unit 0;
|
||||
margin: $unit-2x 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: $font-large;
|
||||
font-weight: $medium;
|
||||
margin: $unit 0;
|
||||
margin: $unit-2x 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $font-regular;
|
||||
font-weight: $medium;
|
||||
margin: $unit 0;
|
||||
margin: $unit-2x 0;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
|
|
@ -96,6 +104,7 @@
|
|||
border-radius: $item-corner-small;
|
||||
background: var(--highlight-bg);
|
||||
color: var(--highlight-text);
|
||||
font-weight: $normal;
|
||||
padding: 1px $unit-fourth;
|
||||
}
|
||||
|
||||
|
|
@ -116,15 +125,18 @@
|
|||
.mention {
|
||||
border-radius: $item-corner-small;
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px rgba(0, 0, 0, 0.25);
|
||||
background: var(--card-bg);
|
||||
0 1px 0px var(--null-shadow);
|
||||
background: var(--null-bg);
|
||||
color: var(--text-primary);
|
||||
font-weight: $medium;
|
||||
font-size: 15px;
|
||||
padding: 1px $unit-half;
|
||||
transition: all 0.1s ease-out;
|
||||
|
||||
&:hover {
|
||||
background: var(--card-bg-hover);
|
||||
background: var(--null-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--null-shadow-hover);
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -136,6 +148,7 @@
|
|||
color: var(--fire-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--fire-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--fire-shadow-hover);
|
||||
color: var(--fire-text-hover);
|
||||
|
|
@ -149,6 +162,7 @@
|
|||
color: var(--water-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--water-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--water-shadow-hover);
|
||||
color: var(--water-text-hover);
|
||||
|
|
@ -162,6 +176,7 @@
|
|||
color: var(--earth-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--earth-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--earth-shadow-hover);
|
||||
color: var(--earth-text-hover);
|
||||
|
|
@ -188,6 +203,7 @@
|
|||
color: var(--dark-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--dark-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--dark-shadow-hover);
|
||||
color: var(--dark-text-hover);
|
||||
|
|
@ -201,6 +217,7 @@
|
|||
color: var(--light-text);
|
||||
|
||||
&:hover {
|
||||
background: var(--light-bg-hover);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25),
|
||||
0 1px 0px var(--light-shadow-hover);
|
||||
color: var(--light-text-hover);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
import { ComponentProps, useCallback, useEffect } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useEditor, EditorContent } from '@tiptap/react'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
|
||||
import StarterKit from '@tiptap/starter-kit'
|
||||
import Link from '@tiptap/extension-link'
|
||||
import Highlight from '@tiptap/extension-highlight'
|
||||
import Placeholder from '@tiptap/extension-placeholder'
|
||||
import Typography from '@tiptap/extension-typography'
|
||||
import Youtube from '@tiptap/extension-youtube'
|
||||
import CustomMention from '~extensions/CustomMention'
|
||||
|
|
@ -18,7 +21,7 @@ import ItalicIcon from 'remixicon-react/ItalicIcon'
|
|||
import StrikethroughIcon from 'remixicon-react/StrikethroughIcon'
|
||||
import UnorderedListIcon from 'remixicon-react/ListUnorderedIcon'
|
||||
import OrderedListIcon from '~public/icons/remix/list-ordered-2.svg'
|
||||
import PaintbrushIcon from 'remixicon-react/PaintbrushLineIcon'
|
||||
import PaintbrushIcon from 'remixicon-react/PaintBrushLineIcon'
|
||||
import H1Icon from 'remixicon-react/H1Icon'
|
||||
import H2Icon from 'remixicon-react/H2Icon'
|
||||
import H3Icon from 'remixicon-react/H3Icon'
|
||||
|
|
@ -45,6 +48,8 @@ const Editor = ({
|
|||
const router = useRouter()
|
||||
const locale = router.locale || 'en'
|
||||
|
||||
const { t } = useTranslation('common')
|
||||
|
||||
useEffect(() => {
|
||||
editor?.commands.setContent(formatContent(content))
|
||||
}, [content])
|
||||
|
|
@ -72,6 +77,10 @@ const Editor = ({
|
|||
}),
|
||||
Link,
|
||||
Highlight,
|
||||
Placeholder.configure({
|
||||
emptyEditorClass: styles.empty,
|
||||
placeholder: t('modals.edit_team.placeholders.description'),
|
||||
}),
|
||||
Typography,
|
||||
CustomMention.configure({
|
||||
renderLabel({ options, node }) {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,6 @@
|
|||
&.flush {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.Arrow {
|
||||
fill: var(--dialog-bg);
|
||||
filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18));
|
||||
margin-top: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.trigger {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
.arrow {
|
||||
fill: var(--dialog-bg);
|
||||
filter: drop-shadow(0px 1px 1px rgb(0 0 0 / 0.18));
|
||||
margin-top: -1px;
|
||||
}
|
||||
|
|
@ -63,6 +63,10 @@
|
|||
|
||||
&.table {
|
||||
min-width: $unit * 30;
|
||||
|
||||
@include breakpoint(phone) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.hidden {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@
|
|||
border-radius: 9999px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
&.table {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.range {
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ const SliderTableField = (props: Props) => {
|
|||
max={props.max}
|
||||
step={props.step}
|
||||
value={[props.value ? props.value : 0]}
|
||||
className="table"
|
||||
onValueChange={handleValueChange}
|
||||
onValueCommit={handleValueCommit}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -36,6 +36,14 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.switch {
|
||||
@include breakpoint(phone) {
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
|
|
|
|||
|
|
@ -23,25 +23,26 @@ const TableField = (props: Props) => {
|
|||
)
|
||||
|
||||
const image = () => {
|
||||
return props.image && props.image.src.length > 0 ? (
|
||||
<div
|
||||
className={classNames(
|
||||
{
|
||||
[styles.preview]: true,
|
||||
},
|
||||
props.image.className
|
||||
?.split(' ')
|
||||
.map((className) => styles[className])
|
||||
)}
|
||||
>
|
||||
<img
|
||||
alt={props.image.alt}
|
||||
srcSet={props.image.src.join(', ')}
|
||||
src={props.image.src[0]}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
props.image &&
|
||||
props.image.src.length > 0 && (
|
||||
<div
|
||||
className={classNames(
|
||||
{
|
||||
[styles.preview]: true,
|
||||
},
|
||||
props.image.className
|
||||
?.split(' ')
|
||||
.map((className) => styles[className])
|
||||
)}
|
||||
>
|
||||
<img
|
||||
alt={props.image.alt}
|
||||
srcSet={props.image.src.join(', ')}
|
||||
src={props.image.src[0]}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,13 @@ const ToolbarIcon = ({ editor, action, level, icon, onClick }: Props) => {
|
|||
})
|
||||
|
||||
return (
|
||||
<Tooltip content={t(`toolbar.tooltips.${action}`)}>
|
||||
<Tooltip
|
||||
content={
|
||||
level
|
||||
? t(`toolbar.tooltips.${action}`, { level: level })
|
||||
: t(`toolbar.tooltips.${action}`)
|
||||
}
|
||||
>
|
||||
<button onClick={onClick} className={classes}>
|
||||
{icon}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ const GuidebookResult = (props: Props) => {
|
|||
<li className={styles.result} onClick={props.onClick}>
|
||||
<img
|
||||
alt={guidebook.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblue_id}.png`}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblueId}.png`}
|
||||
/>
|
||||
<div className={styles.info}>
|
||||
<h5>{guidebook.name[locale]}</h5>
|
||||
|
|
|
|||
|
|
@ -99,7 +99,7 @@ const GuidebookUnit = ({
|
|||
// Methods: Image string generation
|
||||
function generateImageUrl() {
|
||||
let imgSrc = guidebook
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblue_id}.png`
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/guidebooks/book_${guidebook.granblueId}.png`
|
||||
: ''
|
||||
|
||||
setImageUrl(imgSrc)
|
||||
|
|
|
|||
|
|
@ -39,5 +39,6 @@
|
|||
|
||||
@include breakpoint(phone) {
|
||||
gap: $unit-4x;
|
||||
margin-bottom: $unit * 24;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,7 +402,8 @@ const FilterModal = (props: Props) => {
|
|||
<Dialog open={open} onOpenChange={openChange}>
|
||||
<DialogTrigger asChild>{props.children}</DialogTrigger>
|
||||
<DialogContent
|
||||
className="Filter"
|
||||
className="filter"
|
||||
wrapperClassName="filter"
|
||||
headerref={headerRef}
|
||||
footerref={footerRef}
|
||||
onEscapeKeyDown={onEscapeKeyDown}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ const NewHead = () => {
|
|||
{/* HTML */}
|
||||
<title>{t('page.titles.new')}</title>
|
||||
<meta name="description" content={t('page.descriptions.new')} />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
{/* OpenGraph */}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ const ProfileHead = ({ user }: Props) => {
|
|||
username: user.username,
|
||||
})}
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
{/* OpenGraph */}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ const SavedHead = () => {
|
|||
return (
|
||||
<Head>
|
||||
<title>{t('page.titles.saved')}</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
<meta property="og:title" content={t('page.titles.saved')} />
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ const TeamsHead = () => {
|
|||
{/* HTML */}
|
||||
<title>{t('page.titles.discover')}</title>
|
||||
<meta name="description" content={t('page.descriptions.discover')} />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
{/* OpenGraph */}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.JobAccessoryItem {
|
||||
.item {
|
||||
background: none;
|
||||
border-radius: $input-corner;
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -18,13 +18,13 @@ const JobAccessoryItem = ({ accessory, selected }: Props) => {
|
|||
|
||||
return (
|
||||
<RadioGroup.Item
|
||||
className="JobAccessoryItem"
|
||||
className={styles.item}
|
||||
data-state={selected ? 'checked' : 'unchecked'}
|
||||
value={accessory.id}
|
||||
>
|
||||
<img
|
||||
alt={accessory.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/accessory-grid/${accessory.granblue_id}.jpg`}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/accessory-grid/${accessory.granblueId}.jpg`}
|
||||
/>
|
||||
<h4>{accessory.name[locale]}</h4>
|
||||
</RadioGroup.Item>
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
margin: 0 0 $unit $unit;
|
||||
}
|
||||
|
||||
&.ReadOnly {
|
||||
&.readOnly {
|
||||
min-width: inherit;
|
||||
max-width: inherit;
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@
|
|||
max-width: initial;
|
||||
}
|
||||
|
||||
.Accessories {
|
||||
.accessories {
|
||||
display: grid;
|
||||
gap: $unit;
|
||||
grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
|
||||
|
|
@ -38,7 +38,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.EquippedAccessory {
|
||||
.equipped {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-2x;
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.Accessory {
|
||||
.accessory {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit;
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import classNames from 'classnames'
|
|||
import capitalizeFirstLetter from '~utils/capitalizeFirstLetter'
|
||||
|
||||
import * as RadioGroup from '@radix-ui/react-radio-group'
|
||||
import Button from '~components/common/Button'
|
||||
import {
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
|
|
@ -91,7 +90,7 @@ const JobAccessoryPopover = ({
|
|||
)}
|
||||
</h3>
|
||||
<RadioGroup.Root
|
||||
className="Accessories"
|
||||
className={styles.accessories}
|
||||
onValueChange={handleAccessorySelected}
|
||||
>
|
||||
{accessories.map((accessory) => (
|
||||
|
|
@ -110,17 +109,17 @@ const JobAccessoryPopover = ({
|
|||
)
|
||||
|
||||
const readOnly = currentAccessory ? (
|
||||
<div className="EquippedAccessory">
|
||||
<div className={styles.equipped}>
|
||||
<h3>
|
||||
{t('equipped')}{' '}
|
||||
{job.accessory_type === 1
|
||||
? `${t('accessories.paladin')}s`
|
||||
: t('accessories.manadiver')}
|
||||
</h3>
|
||||
<div className="Accessory">
|
||||
<div className={styles.accessory}>
|
||||
<img
|
||||
alt={currentAccessory.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/accessory-grid/${currentAccessory.granblue_id}.jpg`}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/accessory-grid/${currentAccessory.granblueId}.jpg`}
|
||||
/>
|
||||
<h4>{currentAccessory.name[locale]}</h4>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -39,8 +39,8 @@ const JobDropdown = React.forwardRef<HTMLSelectElement, Props>(
|
|||
|
||||
// Set current job from state on mount
|
||||
useEffect(() => {
|
||||
if (party.job?.id !== '-1') {
|
||||
setCurrentJob(party.job)
|
||||
if (party.protagonist.job?.id !== '-1') {
|
||||
setCurrentJob(party.protagonist.job)
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
|
@ -95,7 +95,7 @@ const JobDropdown = React.forwardRef<HTMLSelectElement, Props>(
|
|||
icon={{
|
||||
alt: item.name[locale],
|
||||
src: [
|
||||
`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${item.granblue_id}.png`,
|
||||
`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${item.granblueId}.png`,
|
||||
],
|
||||
}}
|
||||
>
|
||||
|
|
@ -119,7 +119,7 @@ const JobDropdown = React.forwardRef<HTMLSelectElement, Props>(
|
|||
icon={{
|
||||
alt: currentJob ? currentJob.name[locale] : '',
|
||||
src: currentJob
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${currentJob.granblue_id}.png`
|
||||
? `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${currentJob.granblueId}.png`
|
||||
: '',
|
||||
}}
|
||||
open={open}
|
||||
|
|
|
|||
|
|
@ -85,27 +85,28 @@ const JobImage = ({
|
|||
}
|
||||
|
||||
const accessoryPopover = () => {
|
||||
return job && accessories ? (
|
||||
<JobAccessoryPopover
|
||||
buttonref={buttonRef}
|
||||
currentAccessory={currentAccessory}
|
||||
accessories={accessories}
|
||||
editable={editable}
|
||||
open={open}
|
||||
job={job}
|
||||
onAccessorySelected={onAccessorySelected}
|
||||
onOpenChange={handlePopoverOpenChanged}
|
||||
>
|
||||
{accessoryButton()}
|
||||
</JobAccessoryPopover>
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
job &&
|
||||
accessories && (
|
||||
<JobAccessoryPopover
|
||||
buttonref={buttonRef}
|
||||
currentAccessory={currentAccessory}
|
||||
accessories={accessories}
|
||||
editable={editable}
|
||||
open={open}
|
||||
job={job}
|
||||
onAccessorySelected={onAccessorySelected}
|
||||
onOpenChange={handlePopoverOpenChanged}
|
||||
>
|
||||
{accessoryButton()}
|
||||
</JobAccessoryPopover>
|
||||
)
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className={styles.image}>
|
||||
{hasAccessory ? accessoryPopover() : ''}
|
||||
{job && job.id !== '-1' ? image : ''}
|
||||
{hasAccessory && accessoryPopover()}
|
||||
{job && job.id !== '-1' && image}
|
||||
<div className={styles.overlay} />
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import SearchModal from '~components/search/SearchModal'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import type { JobSkillObject, SearchableObject } from '~types'
|
||||
import type { SearchableObject } from '~types'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
job?: Job
|
||||
jobSkills: JobSkillObject
|
||||
jobSkills: JobSkillList
|
||||
jobAccessory?: JobAccessory
|
||||
editable: boolean
|
||||
saveJob: (job?: Job) => void
|
||||
|
|
@ -76,8 +76,11 @@ const JobSection = (props: Props) => {
|
|||
|
||||
useEffect(() => {
|
||||
if (job) {
|
||||
if ((party.job && job.id != party.job.id) || !party.job)
|
||||
appState.party.job = job
|
||||
if (
|
||||
(party.protagonist.job && job.id != party.protagonist.job.id) ||
|
||||
!party.protagonist.job
|
||||
)
|
||||
appState.party.protagonist.job = job
|
||||
if (job.row === '1') setNumSkills(3)
|
||||
else setNumSkills(4)
|
||||
fetchJobAccessories()
|
||||
|
|
@ -178,7 +181,7 @@ const JobSection = (props: Props) => {
|
|||
<div className={styles.name}>
|
||||
<img
|
||||
alt={job?.name[locale]}
|
||||
src={`/images/job-icons/${job?.granblue_id}.png`}
|
||||
src={`/images/job-icons/${job?.granblueId}.png`}
|
||||
/>
|
||||
<h3>{job?.name[locale]}</h3>
|
||||
</div>
|
||||
|
|
@ -188,7 +191,7 @@ const JobSection = (props: Props) => {
|
|||
return (
|
||||
<section className={styles.job}>
|
||||
<JobImage
|
||||
job={party.job}
|
||||
job={party.protagonist.job}
|
||||
currentAccessory={currentAccessory}
|
||||
accessories={accessories}
|
||||
editable={props.editable}
|
||||
|
|
@ -198,21 +201,23 @@ const JobSection = (props: Props) => {
|
|||
<div className={styles.details}>
|
||||
{props.editable ? (
|
||||
<JobDropdown
|
||||
currentJob={party.job?.id}
|
||||
currentJob={party.protagonist.job?.id}
|
||||
onChange={receiveJob}
|
||||
ref={selectRef}
|
||||
/>
|
||||
) : (
|
||||
<div className={styles.name}>
|
||||
{party.job ? (
|
||||
{party.protagonist.job && (
|
||||
<img
|
||||
alt={party.job.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${party.job.granblue_id}.png`}
|
||||
alt={party.protagonist.job.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/job-icons/${party.protagonist.job.granblueId}.png`}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
<h3>{party.job ? party.job.name[locale] : t('no_job')}</h3>
|
||||
<h3>
|
||||
{party.protagonist.job
|
||||
? party.protagonist.job.name[locale]
|
||||
: t('no_job')}
|
||||
</h3>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ const JobSkillItem = React.forwardRef<HTMLDivElement, Props>(
|
|||
} else {
|
||||
jsx = (
|
||||
<div className={imageClasses}>
|
||||
{editable && hasJob ? <PlusIcon /> : ''}
|
||||
{editable && hasJob && <PlusIcon />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ const AXSelect = (props: Props) => {
|
|||
if (modifierSet == 0) {
|
||||
axOptionElements = axOptions.map((ax, i) => {
|
||||
return (
|
||||
<SelectItem key={i} value={ax.id} data-granblue-id={ax.granblue_id}>
|
||||
<SelectItem key={i} value={ax.id} data-granblue-id={ax.granblueId}>
|
||||
{ax.name[locale]}
|
||||
</SelectItem>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -19,11 +19,11 @@ const emptyRing: ExtendedMastery = {
|
|||
}
|
||||
|
||||
interface Props {
|
||||
gridCharacter: GridCharacter
|
||||
rings: CharacterOverMastery
|
||||
sendValues: (overMastery: CharacterOverMastery) => void
|
||||
}
|
||||
|
||||
const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
||||
const RingSelect = ({ rings: overMastery, sendValues }: Props) => {
|
||||
// Ring value states
|
||||
const [rings, setRings] = useState<CharacterOverMastery>({
|
||||
1: { ...emptyRing, modifier: 1 },
|
||||
|
|
@ -33,15 +33,13 @@ const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
|||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (gridCharacter.over_mastery) {
|
||||
setRings({
|
||||
1: gridCharacter.over_mastery[1],
|
||||
2: gridCharacter.over_mastery[2],
|
||||
3: gridCharacter.over_mastery[3],
|
||||
4: gridCharacter.over_mastery[4],
|
||||
})
|
||||
}
|
||||
}, [gridCharacter])
|
||||
setRings({
|
||||
1: overMastery[1],
|
||||
2: overMastery[2],
|
||||
3: overMastery[3],
|
||||
4: overMastery[4],
|
||||
})
|
||||
}, [overMastery])
|
||||
|
||||
useEffect(() => {
|
||||
sendValues(rings)
|
||||
|
|
@ -54,7 +52,7 @@ const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
|||
ja: 'EXリミットボーナスなし',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'no-bonus',
|
||||
minValue: 0,
|
||||
maxValue: 0,
|
||||
|
|
@ -80,6 +78,7 @@ const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
|||
function receiveRingValues(index: number, left: number, right: number) {
|
||||
// console.log(`Receiving values from ${index}: ${left} ${right}`)
|
||||
if (index == 1 || index == 2) {
|
||||
console.log('1 or 2')
|
||||
setSyncedRingValues(index, right)
|
||||
} else if (index == 3 && left == 0) {
|
||||
setRings({
|
||||
|
|
@ -132,6 +131,7 @@ const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
|||
{[...Array(4)].map((e, i) => {
|
||||
const index = i + 1
|
||||
const ringStat = rings[index]
|
||||
console.log(ringStat)
|
||||
|
||||
return (
|
||||
<ExtendedMasterySelect
|
||||
|
|
@ -140,8 +140,8 @@ const RingSelect = ({ gridCharacter, sendValues }: Props) => {
|
|||
key={`ring-${index}`}
|
||||
dataSet={dataSet(index)}
|
||||
leftSelectDisabled={index === 1 || index === 2}
|
||||
leftSelectValue={ringStat.modifier ? ringStat.modifier : 0}
|
||||
rightSelectValue={ringStat.strength ? ringStat.strength : 0}
|
||||
leftSelectValue={ringStat?.modifier ? ringStat?.modifier : 0}
|
||||
rightSelectValue={ringStat?.strength ? ringStat?.strength : 0}
|
||||
sendValues={(left: number, right: number) => {
|
||||
receiveRingValues(index, left, right)
|
||||
}}
|
||||
|
|
|
|||
|
|
@ -297,20 +297,21 @@ const EditPartyModal = ({
|
|||
// Methods: Modification checking
|
||||
function hasBeenModified() {
|
||||
const nameChanged =
|
||||
name !== party.name && !(name === '' && party.name === undefined)
|
||||
name !== party.name &&
|
||||
!(name === '' && (party.name === undefined || party.name === null))
|
||||
const descriptionChanged =
|
||||
description !== party.description &&
|
||||
!(description === '' && party.description === undefined)
|
||||
|
||||
const raidChanged = raid !== party.raid
|
||||
const chargeAttackChanged = chargeAttack !== party.chargeAttack
|
||||
const fullAutoChanged = fullAuto !== party.fullAuto
|
||||
const autoGuardChanged = autoGuard !== party.autoGuard
|
||||
const autoSummonChanged = autoSummon !== party.autoSummon
|
||||
const clearTimeChanged = clearTime !== party.clearTime
|
||||
const turnCountChanged = turnCount !== party.turnCount
|
||||
const buttonCountChanged = buttonCount !== party.buttonCount
|
||||
const chainCountChanged = chainCount !== party.chainCount
|
||||
const chargeAttackChanged = chargeAttack !== party.details.chargeAttack
|
||||
const fullAutoChanged = fullAuto !== party.details.fullAuto
|
||||
const autoGuardChanged = autoGuard !== party.details.autoGuard
|
||||
const autoSummonChanged = autoSummon !== party.details.autoSummon
|
||||
const clearTimeChanged = clearTime !== party.details.clearTime
|
||||
const turnCountChanged = turnCount !== party.details.turnCount
|
||||
const buttonCountChanged = buttonCount !== party.details.buttonCount
|
||||
const chainCountChanged = chainCount !== party.details.chainCount
|
||||
|
||||
// Debugging for if you need to check if a value is being changed
|
||||
// console.log(`
|
||||
|
|
@ -348,14 +349,17 @@ const EditPartyModal = ({
|
|||
setName(party.name ? party.name : '')
|
||||
setDescription(party.description ? party.description : '')
|
||||
setRaid(party.raid)
|
||||
setAutoGuard(party.autoGuard)
|
||||
setAutoSummon(party.autoSummon)
|
||||
setFullAuto(party.fullAuto)
|
||||
setChargeAttack(party.chargeAttack)
|
||||
setClearTime(party.clearTime)
|
||||
if (party.turnCount !== undefined) setTurnCount(party.turnCount)
|
||||
if (party.buttonCount !== undefined) setButtonCount(party.buttonCount)
|
||||
if (party.chainCount !== undefined) setChainCount(party.chainCount)
|
||||
setAutoGuard(party.details.autoGuard)
|
||||
setAutoSummon(party.details.autoSummon)
|
||||
setFullAuto(party.details.fullAuto)
|
||||
setChargeAttack(party.details.chargeAttack)
|
||||
setClearTime(party.details.clearTime)
|
||||
if (party.details.turnCount !== undefined)
|
||||
setTurnCount(party.details.turnCount)
|
||||
if (party.details.buttonCount !== undefined)
|
||||
setButtonCount(party.details.buttonCount)
|
||||
if (party.details.chainCount !== undefined)
|
||||
setChainCount(party.details.chainCount)
|
||||
}
|
||||
|
||||
async function updateDetails(event: React.MouseEvent) {
|
||||
|
|
@ -433,7 +437,7 @@ const EditPartyModal = ({
|
|||
const nameField = (
|
||||
<Input
|
||||
name="name"
|
||||
placeholder="Name your team"
|
||||
placeholder={t('modals.edit_team.placeholders.name')}
|
||||
autoFocus={true}
|
||||
value={name}
|
||||
maxLength={50}
|
||||
|
|
@ -476,15 +480,6 @@ const EditPartyModal = ({
|
|||
/>
|
||||
)
|
||||
|
||||
const editorField = (
|
||||
<Editor
|
||||
bound={true}
|
||||
content={description}
|
||||
editable={true}
|
||||
onUpdate={handleEditorUpdate}
|
||||
/>
|
||||
)
|
||||
|
||||
const chargeAttackField = (
|
||||
<SwitchTableField
|
||||
name="charge_attack"
|
||||
|
|
|
|||
|
|
@ -18,15 +18,17 @@ import { accountState } from '~utils/accountState'
|
|||
import { appState, initialAppState } from '~utils/appState'
|
||||
import { getLocalId } from '~utils/localId'
|
||||
import { GridType } from '~utils/enums'
|
||||
import * as PartyTransformer from '~transformers/PartyTransformer'
|
||||
import { retrieveCookies } from '~utils/retrieveCookies'
|
||||
import { setEditKey, storeEditKey, unsetEditKey } from '~utils/userToken'
|
||||
|
||||
import type { CharacterOverMastery, DetailsObject } from '~types'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
new?: boolean
|
||||
team?: Party
|
||||
party?: Party
|
||||
selectedTab: GridType
|
||||
raidGroups: RaidGroup[]
|
||||
handleTabChanged: (value: string) => void
|
||||
|
|
@ -57,10 +59,10 @@ const Party = (props: Props) => {
|
|||
// Reset state on first load
|
||||
useEffect(() => {
|
||||
const resetState = clonedeep(initialAppState)
|
||||
appState.grid = resetState.grid
|
||||
if (props.team) {
|
||||
storeParty(props.team)
|
||||
setUpdatedParty(props.team)
|
||||
appState.party.grid = resetState.party.grid
|
||||
if (props.party) {
|
||||
storeParty(props.party)
|
||||
setUpdatedParty(props.party)
|
||||
}
|
||||
}, [])
|
||||
|
||||
|
|
@ -85,20 +87,20 @@ const Party = (props: Props) => {
|
|||
|
||||
if (props.new) editable = true
|
||||
|
||||
if (accountData && props.team && !props.new) {
|
||||
if (accountData && props.party && !props.new) {
|
||||
if (accountData.token) {
|
||||
// Authenticated
|
||||
if (props.team.user && accountData.userId === props.team.user.id) {
|
||||
if (props.party.user && accountData.userId === props.party.user.id) {
|
||||
editable = true
|
||||
}
|
||||
} else {
|
||||
// Not authenticated
|
||||
if (!props.team.user && accountData.userId === props.team.local_id) {
|
||||
if (!props.party.user && accountData.userId === props.party.localId) {
|
||||
// Set editable
|
||||
editable = true
|
||||
|
||||
// Also set edit key header
|
||||
setEditKey(props.team.id, props.team.user)
|
||||
setEditKey(props.party.id, props.party.user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -122,9 +124,9 @@ const Party = (props: Props) => {
|
|||
async function updateParty(details: DetailsObject) {
|
||||
const payload = formatDetailsObject(details)
|
||||
|
||||
if (props.team && props.team.id) {
|
||||
if (props.party && props.party.id) {
|
||||
return await api.endpoints.parties
|
||||
.update(props.team.id, payload)
|
||||
.update(props.party.id, payload)
|
||||
.then((response) => {
|
||||
storeParty(response.data.party)
|
||||
setUpdatedParty(response.data.party)
|
||||
|
|
@ -142,7 +144,7 @@ const Party = (props: Props) => {
|
|||
|
||||
// Methods: Updating the party's details
|
||||
async function updateDetails(details: DetailsObject) {
|
||||
if (!props.team) return await createParty(details)
|
||||
if (!props.party) return await createParty(details)
|
||||
else return await updateParty(details)
|
||||
}
|
||||
|
||||
|
|
@ -180,11 +182,11 @@ const Party = (props: Props) => {
|
|||
}
|
||||
|
||||
function checkboxChanged(enabled: boolean) {
|
||||
appState.party.extra = enabled
|
||||
appState.party.details.extra = enabled
|
||||
|
||||
// Only save if this is a saved party
|
||||
if (props.team && props.team.id) {
|
||||
api.endpoints.parties.update(props.team.id, {
|
||||
if (props.party && props.party.id) {
|
||||
api.endpoints.parties.update(props.party.id, {
|
||||
party: { extra: enabled },
|
||||
})
|
||||
}
|
||||
|
|
@ -203,7 +205,7 @@ const Party = (props: Props) => {
|
|||
guidebook3_id: position === 3 ? id : undefined,
|
||||
}
|
||||
|
||||
if (props.team && props.team.id) {
|
||||
if (props.party && props.party.id) {
|
||||
updateParty(details)
|
||||
} else {
|
||||
createParty(details)
|
||||
|
|
@ -214,16 +216,16 @@ const Party = (props: Props) => {
|
|||
function remixTeam() {
|
||||
// setOriginalName(partySnapshot.name ? partySnapshot.name : t('no_title'))
|
||||
|
||||
if (props.team && props.team.shortcode) {
|
||||
if (props.party && props.party.shortcode) {
|
||||
const body = { local_id: getLocalId() }
|
||||
api
|
||||
.remix({ shortcode: props.team.shortcode, body: body })
|
||||
.remix({ shortcode: props.party.shortcode, body: body })
|
||||
.then((response) => {
|
||||
const remix = response.data.party
|
||||
const remix = PartyTransformer.toObject(response.data.party)
|
||||
|
||||
// Store the edit key in local storage
|
||||
if (remix.edit_key) {
|
||||
storeEditKey(remix.id, remix.edit_key)
|
||||
if (remix.editKey) {
|
||||
storeEditKey(remix.id, remix.editKey)
|
||||
setEditKey(remix.id, remix.user)
|
||||
}
|
||||
|
||||
|
|
@ -235,9 +237,9 @@ const Party = (props: Props) => {
|
|||
|
||||
// Deleting the party
|
||||
function deleteTeam() {
|
||||
if (props.team && editable) {
|
||||
if (props.party && editable) {
|
||||
api.endpoints.parties
|
||||
.destroy({ id: props.team.id })
|
||||
.destroy({ id: props.party.id })
|
||||
.then(() => {
|
||||
// Push to route
|
||||
if (cookies && cookies.account.username) {
|
||||
|
|
@ -267,36 +269,38 @@ const Party = (props: Props) => {
|
|||
appState.party.name = team.name
|
||||
appState.party.description = team.description ? team.description : ''
|
||||
appState.party.raid = team.raid
|
||||
appState.party.updated_at = team.updated_at
|
||||
appState.party.job = team.job
|
||||
appState.party.jobSkills = team.job_skills
|
||||
appState.party.accessory = team.accessory
|
||||
|
||||
appState.party.chargeAttack = team.charge_attack
|
||||
appState.party.fullAuto = team.full_auto
|
||||
appState.party.autoGuard = team.auto_guard
|
||||
appState.party.autoSummon = team.auto_summon
|
||||
appState.party.clearTime = team.clear_time
|
||||
appState.party.buttonCount =
|
||||
team.button_count !== null ? team.button_count : undefined
|
||||
appState.party.chainCount =
|
||||
team.chain_count !== null ? team.chain_count : undefined
|
||||
appState.party.turnCount =
|
||||
team.turn_count !== null ? team.turn_count : undefined
|
||||
appState.party.protagonist.job = team.protagonist.job
|
||||
appState.party.protagonist.skills = team.protagonist.skills
|
||||
appState.party.protagonist.accessory = team.protagonist.accessory
|
||||
appState.party.protagonist.masterLevel = team.protagonist.master_level
|
||||
appState.party.protagonist.ultimateMastery =
|
||||
team.protagonist.ultimate_mastery
|
||||
appState.party.details.chargeAttack = team.charge_attack
|
||||
appState.party.details.fullAuto = team.details.full_auto
|
||||
appState.party.details.autoGuard = team.details.auto_guard
|
||||
appState.party.details.autoSummon = team.details.auto_summon
|
||||
appState.party.details.clearTime = team.details.clear_time
|
||||
appState.party.details.buttonCount =
|
||||
team.details.button_count !== null ? team.details.button_count : undefined
|
||||
appState.party.details.chainCount =
|
||||
team.details.chain_count !== null ? team.details.chain_count : undefined
|
||||
appState.party.details.turnCount =
|
||||
team.details.turn_count !== null ? team.details.turn_count : undefined
|
||||
|
||||
appState.party.id = team.id
|
||||
appState.party.shortcode = team.shortcode
|
||||
appState.party.extra = team.extra
|
||||
appState.party.details.extra = team.details.extra
|
||||
appState.party.guidebooks = team.guidebooks
|
||||
appState.party.user = team.user
|
||||
appState.party.favorited = team.favorited
|
||||
appState.party.remix = team.remix
|
||||
appState.party.remixes = team.remixes
|
||||
appState.party.sourceParty = team.source_party
|
||||
appState.party.created_at = team.created_at
|
||||
appState.party.updated_at = team.updated_at
|
||||
appState.party.social.favorited = team.social.favorited
|
||||
appState.party.social.remix = team.social.remix
|
||||
appState.party.social.remixes = team.social.remixes
|
||||
appState.party.social.sourceParty = team.social.sourceParty
|
||||
appState.party.timestamps.createdAt = team.created_at
|
||||
appState.party.timestamps.updatedAt = team.updated_at
|
||||
|
||||
appState.party.detailsVisible = false
|
||||
appState.party.grid = team.grid
|
||||
console.log(team.grid)
|
||||
|
||||
// Store the edit key in local storage
|
||||
if (team.edit_key) {
|
||||
|
|
@ -304,11 +308,6 @@ const Party = (props: Props) => {
|
|||
setEditKey(team.id, team.user)
|
||||
}
|
||||
|
||||
// Populate state
|
||||
storeCharacters(team.characters)
|
||||
storeWeapons(team.weapons)
|
||||
storeSummons(team.summons)
|
||||
|
||||
// Create a string to send the user back to the tab they're currently on
|
||||
let tab = ''
|
||||
if (props.selectedTab === GridType.Character) {
|
||||
|
|
@ -326,53 +325,56 @@ const Party = (props: Props) => {
|
|||
}
|
||||
|
||||
const storeCharacters = (list: Array<GridCharacter>) => {
|
||||
list.forEach((object: GridCharacter) => {
|
||||
let character = clonedeep(object)
|
||||
|
||||
if (character.over_mastery) {
|
||||
const overMastery: CharacterOverMastery = {
|
||||
1: object.over_mastery[0],
|
||||
2: object.over_mastery[1],
|
||||
3: object.over_mastery[2],
|
||||
4: object.over_mastery[3],
|
||||
}
|
||||
|
||||
character.over_mastery = overMastery
|
||||
}
|
||||
|
||||
if (character.position != null) {
|
||||
appState.grid.characters[object.position] = character
|
||||
}
|
||||
})
|
||||
// list.forEach((object: GridCharacter) => {
|
||||
// let character = clonedeep(object)
|
||||
// if (character.mastery.overMastery) {
|
||||
// const overMastery: CharacterOverMastery = {
|
||||
// 1: object.mastery.overMastery[0],
|
||||
// 2: object.mastery.overMastery[1],
|
||||
// 3: object.mastery.overMastery[2],
|
||||
// 4: object.mastery.overMastery[3],
|
||||
// }
|
||||
// character.mastery.overMastery = overMastery
|
||||
// }
|
||||
// if (character.position != null) {
|
||||
// appState.grid.characters[object.position] = character
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
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) {
|
||||
let weapon = clonedeep(gridObject)
|
||||
if (weapon.object.element === 0 && weapon.element < 1)
|
||||
weapon.element = gridObject.object.element
|
||||
|
||||
appState.grid.weapons.allWeapons[gridObject.position] = weapon
|
||||
}
|
||||
})
|
||||
const storeWeapons = (
|
||||
allWeapons: Array<GridWeapon>,
|
||||
mainWeapon?: GridWeapon
|
||||
) => {
|
||||
// appState.grid.weapons.mainWeapon = mainWeapon
|
||||
// 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) {
|
||||
// let weapon = clonedeep(gridObject)
|
||||
// if (
|
||||
// weapon.object.element === ElementMap.null &&
|
||||
// weapon.element === ElementMap.null
|
||||
// )
|
||||
// weapon.element = gridObject.object.element
|
||||
// appState.grid.weapons.allWeapons[gridObject.position] = weapon
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
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
|
||||
})
|
||||
// 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
|
||||
|
|
@ -403,8 +405,8 @@ const Party = (props: Props) => {
|
|||
<WeaponGrid
|
||||
new={props.new || false}
|
||||
editable={editable}
|
||||
weapons={props.team?.weapons}
|
||||
guidebooks={props.team?.guidebooks}
|
||||
weapons={props.party?.grid.weapons}
|
||||
guidebooks={props.party?.guidebooks}
|
||||
createParty={createParty}
|
||||
pushHistory={props.pushHistory}
|
||||
updateExtra={checkboxChanged}
|
||||
|
|
@ -416,7 +418,7 @@ const Party = (props: Props) => {
|
|||
<SummonGrid
|
||||
new={props.new || false}
|
||||
editable={editable}
|
||||
summons={props.team?.summons}
|
||||
summons={props.party?.grid.summons}
|
||||
createParty={createParty}
|
||||
pushHistory={props.pushHistory}
|
||||
/>
|
||||
|
|
@ -426,7 +428,7 @@ const Party = (props: Props) => {
|
|||
<CharacterGrid
|
||||
new={props.new || false}
|
||||
editable={editable}
|
||||
characters={props.team?.characters}
|
||||
characters={props.party?.grid.characters}
|
||||
createParty={createParty}
|
||||
pushHistory={props.pushHistory}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import EditPartyModal from '../EditPartyModal'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import { youtube } from '~utils/youtube'
|
||||
|
||||
import type { DetailsObject } from 'types'
|
||||
|
||||
|
|
@ -39,10 +38,7 @@ const PartyFooter = (props: Props) => {
|
|||
const { t } = useTranslation('common')
|
||||
const router = useRouter()
|
||||
|
||||
const { party: partySnapshot } = useSnapshot(appState)
|
||||
|
||||
const youtubeUrlRegex =
|
||||
/(?:https:\/\/www\.youtube\.com\/watch\?v=|https:\/\/youtu\.be\/)([\w-]+)/g
|
||||
const { party } = useSnapshot(appState)
|
||||
|
||||
// State: Component
|
||||
const [currentSegment, setCurrentSegment] = useState(0)
|
||||
|
|
@ -55,69 +51,19 @@ const PartyFooter = (props: Props) => {
|
|||
const [sanitizedDescription, setSanitizedDescription] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (partySnapshot.description) {
|
||||
const purified = DOMPurify.sanitize(partySnapshot.description)
|
||||
if (party.description) {
|
||||
const purified = DOMPurify.sanitize(party.description)
|
||||
setSanitizedDescription(purified)
|
||||
} else {
|
||||
setSanitizedDescription('')
|
||||
}
|
||||
}, [partySnapshot.description])
|
||||
|
||||
// Extract the video IDs from the description
|
||||
// const videoIds = extractYoutubeVideoIds(partySnapshot.description)
|
||||
// Fetch the video titles for each ID
|
||||
// const fetchPromises = videoIds.map(({ id }) => fetchYoutubeData(id))
|
||||
// // Wait for all the video titles to be fetched
|
||||
// Promise.all(fetchPromises).then((videoTitles) => {
|
||||
// // Replace the video URLs in the description with LiteYoutubeEmbed elements
|
||||
// const newDescription = reactStringReplace(
|
||||
// partySnapshot.description,
|
||||
// youtubeUrlRegex,
|
||||
// (match, i) => (
|
||||
// <LiteYouTubeEmbed
|
||||
// key={`${match}-${i}`}
|
||||
// id={match}
|
||||
// title={videoTitles[i]}
|
||||
// wrapperClass={styles.youtube}
|
||||
// playerClass={styles.playerButton}
|
||||
// />
|
||||
// )
|
||||
// )
|
||||
// Update the state with the new description
|
||||
|
||||
async function fetchYoutubeData(videoId: string) {
|
||||
return await youtube
|
||||
.getVideoById(videoId, { maxResults: 1 })
|
||||
.then((data) => data.items[0].snippet.localized.title)
|
||||
}
|
||||
}, [party.description])
|
||||
|
||||
// Methods: Navigation
|
||||
function goTo(shortcode?: string) {
|
||||
if (shortcode) router.push(`/p/${shortcode}`)
|
||||
}
|
||||
|
||||
function extractYoutubeVideoIds(text: string) {
|
||||
// Initialize an array to store the video IDs
|
||||
const videoIds = []
|
||||
|
||||
// Use the regular expression to find all the Youtube URLs in the text
|
||||
let match
|
||||
while ((match = youtubeUrlRegex.exec(text)) !== null) {
|
||||
// Extract the video ID from the URL
|
||||
const videoId = match[1]
|
||||
|
||||
// Add the video ID to the array, along with the character position of the URL
|
||||
videoIds.push({
|
||||
id: videoId,
|
||||
url: match[0],
|
||||
position: match.index,
|
||||
})
|
||||
}
|
||||
|
||||
// Return the array of video IDs
|
||||
return videoIds
|
||||
}
|
||||
|
||||
// Methods: Favorites
|
||||
function toggleFavorite(teamId: string, favorited: boolean) {
|
||||
if (favorited) unsaveFavorite(teamId)
|
||||
|
|
@ -130,7 +76,7 @@ const PartyFooter = (props: Props) => {
|
|||
const index = remixes.findIndex((p) => p.id === teamId)
|
||||
const party = remixes[index]
|
||||
|
||||
party.favorited = true
|
||||
party.social.favorited = true
|
||||
|
||||
let clonedParties = clonedeep(remixes)
|
||||
clonedParties[index] = party
|
||||
|
|
@ -146,7 +92,7 @@ const PartyFooter = (props: Props) => {
|
|||
const index = remixes.findIndex((p) => p.id === teamId)
|
||||
const party = remixes[index]
|
||||
|
||||
party.favorited = false
|
||||
party.social.favorited = false
|
||||
|
||||
let clonedParties = clonedeep(remixes)
|
||||
clonedParties[index] = party
|
||||
|
|
@ -201,7 +147,9 @@ const PartyFooter = (props: Props) => {
|
|||
selected={currentSegment === 1}
|
||||
onClick={() => setCurrentSegment(1)}
|
||||
>
|
||||
{t('footer.remixes.label', { count: partySnapshot?.remixes?.length })}
|
||||
{t('footer.remixes.label', {
|
||||
count: party?.social.remixes?.length ?? 0,
|
||||
})}
|
||||
</Segment>
|
||||
</SegmentedControl>
|
||||
)
|
||||
|
|
@ -216,7 +164,7 @@ const PartyFooter = (props: Props) => {
|
|||
key={props.party?.shortcode}
|
||||
/>
|
||||
)}
|
||||
{(!partySnapshot || !partySnapshot.description) && (
|
||||
{(!party || !party.description) && (
|
||||
<section className={styles.noDescription}>
|
||||
<h3>{t('footer.description.empty')}</h3>
|
||||
{props.editable && (
|
||||
|
|
@ -240,10 +188,10 @@ const PartyFooter = (props: Props) => {
|
|||
|
||||
const remixesSection = (
|
||||
<section className={styles.remixes}>
|
||||
{partySnapshot?.remixes?.length > 0 && (
|
||||
{party?.social.remixes?.length > 0 && (
|
||||
<GridRepCollection>{renderRemixes()}</GridRepCollection>
|
||||
)}
|
||||
{partySnapshot?.remixes?.length === 0 && (
|
||||
{party?.social.remixes?.length === 0 && (
|
||||
<div className={styles.noRemixes}>
|
||||
<h3>{t('footer.remixes.empty')}</h3>
|
||||
<Button
|
||||
|
|
@ -257,19 +205,19 @@ const PartyFooter = (props: Props) => {
|
|||
)
|
||||
|
||||
function renderRemixes() {
|
||||
return partySnapshot?.remixes.map((party, i) => {
|
||||
return party?.social.remixes.map((party, i) => {
|
||||
return (
|
||||
<GridRep
|
||||
id={party.id}
|
||||
shortcode={party.shortcode}
|
||||
name={party.name}
|
||||
createdAt={new Date(party.created_at)}
|
||||
createdAt={new Date(party.timestamps.createdAt)}
|
||||
raid={party.raid}
|
||||
grid={party.weapons}
|
||||
weapons={party.grid.weapons}
|
||||
user={party.user}
|
||||
favorited={party.favorited}
|
||||
fullAuto={party.full_auto}
|
||||
autoGuard={party.auto_guard}
|
||||
favorited={party.social.favorited}
|
||||
fullAuto={party.details.fullAuto}
|
||||
autoGuard={party.details.autoGuard}
|
||||
key={`party-${i}`}
|
||||
onClick={goTo}
|
||||
onSave={toggleFavorite}
|
||||
|
|
@ -288,7 +236,7 @@ const PartyFooter = (props: Props) => {
|
|||
|
||||
<RemixTeamAlert
|
||||
creator={props.editable}
|
||||
name={partySnapshot.name ? partySnapshot.name : t('no_title')}
|
||||
name={party.name ? party.name : t('no_title')}
|
||||
open={remixAlertOpen}
|
||||
onOpenChange={handleRemixTeamAlertChange}
|
||||
remixCallback={remixTeamCallback}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ const PartyHead = ({ party, meta }: Props) => {
|
|||
raidName: party.raid ? party.raid.name[locale] : '',
|
||||
})}
|
||||
/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/images/favicon.png" />
|
||||
|
||||
{/* OpenGraph */}
|
||||
|
|
|
|||
|
|
@ -59,24 +59,24 @@ const PartyHeader = (props: Props) => {
|
|||
})
|
||||
|
||||
const linkClass = classNames({
|
||||
wind: party && party.element == 1,
|
||||
fire: party && party.element == 2,
|
||||
water: party && party.element == 3,
|
||||
earth: party && party.element == 4,
|
||||
dark: party && party.element == 5,
|
||||
light: party && party.element == 6,
|
||||
wind: party.element && party.element.slug === 'wind',
|
||||
fire: party.element && party.element.slug === 'fire',
|
||||
water: party.element && party.element.slug === 'water',
|
||||
earth: party.element && party.element.slug === 'earth',
|
||||
dark: party.element && party.element.slug === 'dark',
|
||||
light: party.element && party.element.slug === 'light',
|
||||
})
|
||||
|
||||
// Actions: Favorites
|
||||
function toggleFavorite() {
|
||||
if (appState.party.favorited) unsaveFavorite()
|
||||
if (appState.party.social.favorited) unsaveFavorite()
|
||||
else saveFavorite()
|
||||
}
|
||||
|
||||
function saveFavorite() {
|
||||
if (appState.party.id)
|
||||
api.saveTeam({ id: appState.party.id }).then((response) => {
|
||||
if (response.status == 201) appState.party.favorited = true
|
||||
if (response.status == 201) appState.party.social.favorited = true
|
||||
})
|
||||
else console.error('Failed to save team: No party ID')
|
||||
}
|
||||
|
|
@ -84,7 +84,7 @@ const PartyHeader = (props: Props) => {
|
|||
function unsaveFavorite() {
|
||||
if (appState.party.id)
|
||||
api.unsaveTeam({ id: appState.party.id }).then((response) => {
|
||||
if (response.status == 200) appState.party.favorited = false
|
||||
if (response.status == 200) appState.party.social.favorited = false
|
||||
})
|
||||
else console.error('Failed to unsave team: No party ID')
|
||||
}
|
||||
|
|
@ -202,33 +202,33 @@ const PartyHeader = (props: Props) => {
|
|||
|
||||
// Render: Tokens
|
||||
const chargeAttackToken = (
|
||||
<Token active={party.chargeAttack} className="chargeAttack">
|
||||
<Token active={party.details.chargeAttack} className="chargeAttack">
|
||||
{`${t('party.details.labels.charge_attack')} ${
|
||||
party.chargeAttack ? 'On' : 'Off'
|
||||
party.details.chargeAttack ? 'On' : 'Off'
|
||||
}`}
|
||||
</Token>
|
||||
)
|
||||
|
||||
const fullAutoToken = (
|
||||
<Token active={party.fullAuto} className="fullAuto">
|
||||
<Token active={party.details.fullAuto} className="fullAuto">
|
||||
{`${t('party.details.labels.full_auto')} ${
|
||||
party.fullAuto ? 'On' : 'Off'
|
||||
party.details.fullAuto ? 'On' : 'Off'
|
||||
}`}
|
||||
</Token>
|
||||
)
|
||||
|
||||
const autoGuardToken = (
|
||||
<Token active={party.autoGuard} className="autoGuard">
|
||||
<Token active={party.details.autoGuard} className="autoGuard">
|
||||
{`${t('party.details.labels.auto_guard')} ${
|
||||
party.autoGuard ? 'On' : 'Off'
|
||||
party.details.autoGuard ? 'On' : 'Off'
|
||||
}`}
|
||||
</Token>
|
||||
)
|
||||
|
||||
const autoSummonToken = (
|
||||
<Token active={party.autoSummon} className="autoSummon">
|
||||
<Token active={party.details.autoSummon} className="autoSummon">
|
||||
{`${t('party.details.labels.auto_summon')} ${
|
||||
party.autoSummon ? 'On' : 'Off'
|
||||
party.details.autoSummon ? 'On' : 'Off'
|
||||
}`}
|
||||
</Token>
|
||||
)
|
||||
|
|
@ -236,31 +236,39 @@ const PartyHeader = (props: Props) => {
|
|||
const turnCountToken = (
|
||||
<Token>
|
||||
{t('party.details.turns.with_count', {
|
||||
count: party.turnCount,
|
||||
count: party.details.turnCount,
|
||||
})}
|
||||
</Token>
|
||||
)
|
||||
|
||||
const buttonChainToken = () => {
|
||||
if (party.buttonCount !== undefined || party.chainCount !== undefined) {
|
||||
if (
|
||||
party.details.buttonCount !== undefined ||
|
||||
party.details.chainCount !== undefined
|
||||
) {
|
||||
let string = ''
|
||||
|
||||
if (party.buttonCount !== undefined) {
|
||||
string += `${party.buttonCount}b`
|
||||
if (party.details.buttonCount !== undefined) {
|
||||
string += `${party.details.buttonCount}b`
|
||||
}
|
||||
|
||||
if (party.buttonCount === undefined && party.chainCount !== undefined) {
|
||||
string += `0${t('party.details.suffix.buttons')}${party.chainCount}${t(
|
||||
if (
|
||||
party.details.buttonCount === undefined &&
|
||||
party.details.chainCount !== undefined
|
||||
) {
|
||||
string += `0${t('party.details.suffix.buttons')}${
|
||||
party.details.chainCount
|
||||
}${t('party.details.suffix.chains')}`
|
||||
} else if (
|
||||
party.details.buttonCount !== undefined &&
|
||||
party.details.chainCount !== undefined
|
||||
) {
|
||||
string += `${party.details.chainCount}${t(
|
||||
'party.details.suffix.chains'
|
||||
)}`
|
||||
} else if (
|
||||
party.buttonCount !== undefined &&
|
||||
party.chainCount !== undefined
|
||||
) {
|
||||
string += `${party.chainCount}${t('party.details.suffix.chains')}`
|
||||
} else if (
|
||||
party.buttonCount !== undefined &&
|
||||
party.chainCount === undefined
|
||||
party.details.buttonCount !== undefined &&
|
||||
party.details.chainCount === undefined
|
||||
) {
|
||||
string += `0${t('party.details.suffix.chains')}`
|
||||
}
|
||||
|
|
@ -270,8 +278,8 @@ const PartyHeader = (props: Props) => {
|
|||
}
|
||||
|
||||
const clearTimeToken = () => {
|
||||
const minutes = Math.floor(party.clearTime / 60)
|
||||
const seconds = party.clearTime - minutes * 60
|
||||
const minutes = Math.floor(party.details.clearTime / 60)
|
||||
const seconds = party.details.clearTime - minutes * 60
|
||||
|
||||
let string = ''
|
||||
if (minutes > 0)
|
||||
|
|
@ -291,8 +299,8 @@ const PartyHeader = (props: Props) => {
|
|||
{fullAutoToken}
|
||||
{autoSummonToken}
|
||||
{autoGuardToken}
|
||||
{party.turnCount !== undefined && turnCountToken}
|
||||
{party.clearTime > 0 && clearTimeToken()}
|
||||
{party.details.turnCount !== undefined && turnCountToken}
|
||||
{party.details.clearTime > 0 && clearTimeToken()}
|
||||
{buttonChainToken()}
|
||||
</>
|
||||
)
|
||||
|
|
@ -307,10 +315,12 @@ const PartyHeader = (props: Props) => {
|
|||
className={classNames({
|
||||
save: true,
|
||||
grow: true,
|
||||
saved: partySnapshot.favorited,
|
||||
saved: partySnapshot.social.favorited,
|
||||
})}
|
||||
text={
|
||||
appState.party.favorited ? t('buttons.saved') : t('buttons.save')
|
||||
appState.party.social.favorited
|
||||
? t('buttons.saved')
|
||||
: t('buttons.save')
|
||||
}
|
||||
onClick={toggleFavorite}
|
||||
/>
|
||||
|
|
@ -333,12 +343,13 @@ const PartyHeader = (props: Props) => {
|
|||
|
||||
const remixedButton = () => {
|
||||
const tooltipString =
|
||||
party.remix && party.sourceParty
|
||||
party.social.remix && party.social.sourceParty
|
||||
? t('tooltips.remix.source')
|
||||
: t('tooltips.remix.deleted')
|
||||
|
||||
const buttonAction =
|
||||
party.sourceParty && (() => goTo(party.sourceParty?.shortcode))
|
||||
party.social.sourceParty &&
|
||||
(() => goTo(party.social.sourceParty?.shortcode))
|
||||
|
||||
return (
|
||||
<Tooltip content={tooltipString}>
|
||||
|
|
@ -348,7 +359,7 @@ const PartyHeader = (props: Props) => {
|
|||
leftAccessoryIcon={<RemixIcon />}
|
||||
text={t('tokens.remix')}
|
||||
size="small"
|
||||
disabled={!party.sourceParty}
|
||||
disabled={!party.social.sourceParty}
|
||||
onClick={buttonAction}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
|
@ -364,17 +375,17 @@ const PartyHeader = (props: Props) => {
|
|||
<h1 className={party.name ? '' : styles.empty}>
|
||||
{party.name ? party.name : t('no_title')}
|
||||
</h1>
|
||||
{party.remix && remixedButton()}
|
||||
{party.social.remix && remixedButton()}
|
||||
</div>
|
||||
<div className={styles.attribution}>
|
||||
{renderUserBlock()}
|
||||
{appState.party.raid && linkedRaidBlock(appState.party.raid)}
|
||||
{party.created_at != '' && (
|
||||
{party.timestamps.createdAt != '' && (
|
||||
<time
|
||||
className={styles.lastUpdated}
|
||||
dateTime={new Date(party.created_at).toString()}
|
||||
dateTime={new Date(party.timestamps.createdAt).toString()}
|
||||
>
|
||||
{formatTimeAgo(new Date(party.created_at), locale)}
|
||||
{formatTimeAgo(new Date(party.timestamps.createdAt), locale)}
|
||||
</time>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import CharacterRep from '~components/reps/CharacterRep'
|
|||
import WeaponRep from '~components/reps/WeaponRep'
|
||||
import SummonRep from '~components/reps/SummonRep'
|
||||
|
||||
import { ElementMap } from '~utils/elements'
|
||||
import { GridType } from '~utils/enums'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
|
@ -30,26 +31,27 @@ const PartySegmentedControl = (props: Props) => {
|
|||
// Set up translations
|
||||
const { t } = useTranslation('common')
|
||||
|
||||
const { party, grid } = useSnapshot(appState)
|
||||
const { party } = useSnapshot(appState)
|
||||
|
||||
const getElement = () => {
|
||||
let element: number = 0
|
||||
if (party.element == 0 && grid.weapons.mainWeapon)
|
||||
element = grid.weapons.mainWeapon.element
|
||||
else element = party.element
|
||||
let element: GranblueElement
|
||||
if (party.element === ElementMap.null && party.grid.weapons.mainWeapon)
|
||||
element = party.grid.weapons.mainWeapon?.element
|
||||
else if (party.element) element = party.element
|
||||
else element = ElementMap.null
|
||||
|
||||
switch (element) {
|
||||
case 1:
|
||||
case ElementMap.wind:
|
||||
return 'wind'
|
||||
case 2:
|
||||
case ElementMap.fire:
|
||||
return 'fire'
|
||||
case 3:
|
||||
case ElementMap.water:
|
||||
return 'water'
|
||||
case 4:
|
||||
case ElementMap.earth:
|
||||
return 'earth'
|
||||
case 5:
|
||||
case ElementMap.dark:
|
||||
return 'dark'
|
||||
case 6:
|
||||
case ElementMap.light:
|
||||
return 'light'
|
||||
}
|
||||
}
|
||||
|
|
@ -64,12 +66,12 @@ const PartySegmentedControl = (props: Props) => {
|
|||
onClick={props.onClick}
|
||||
>
|
||||
<CharacterRep
|
||||
job={party.job}
|
||||
job={party.protagonist.job}
|
||||
element={party.element}
|
||||
gender={
|
||||
accountState.account.user ? accountState.account.user.gender : 0
|
||||
}
|
||||
grid={grid.characters}
|
||||
grid={party.grid.characters}
|
||||
/>
|
||||
</RepSegment>
|
||||
)
|
||||
|
|
@ -85,7 +87,7 @@ const PartySegmentedControl = (props: Props) => {
|
|||
selected={props.selectedTab === GridType.Weapon}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<WeaponRep grid={grid.weapons} />
|
||||
<WeaponRep grid={party.grid.weapons} />
|
||||
</RepSegment>
|
||||
)
|
||||
}
|
||||
|
|
@ -100,7 +102,7 @@ const PartySegmentedControl = (props: Props) => {
|
|||
selected={props.selectedTab === GridType.Summon}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<SummonRep grid={grid.summons} />
|
||||
<SummonRep grid={party.grid.summons} />
|
||||
</RepSegment>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import { useRouter } from 'next/router'
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import { Command, CommandGroup, CommandInput } from 'cmdk'
|
||||
import Popover from '~components/common/Popover'
|
||||
import SegmentedControl from '~components/common/SegmentedControl'
|
||||
|
|
@ -50,7 +52,7 @@ const allRaidsOption: Raid = {
|
|||
group: untitledGroup,
|
||||
slug: 'all',
|
||||
level: 0,
|
||||
element: 0,
|
||||
element: ElementMap.null,
|
||||
}
|
||||
|
||||
interface Props {
|
||||
|
|
@ -112,7 +114,6 @@ const RaidCombobox = (props: Props) => {
|
|||
useEffect(() => {
|
||||
const sections: [RaidGroup[], RaidGroup[], RaidGroup[]] = [[], [], []]
|
||||
|
||||
|
||||
props.raidGroups.forEach((group) => {
|
||||
if (group.section > 0) sections[group.section - 1].push(group)
|
||||
})
|
||||
|
|
@ -354,7 +355,8 @@ const RaidCombobox = (props: Props) => {
|
|||
function generateRaidItems(raids: Raid[]) {
|
||||
return raids
|
||||
.sort((a, b) => {
|
||||
if (a.element > 0 && b.element > 0) return a.element - b.element
|
||||
if (a.element.id > 0 && b.element.id > 0)
|
||||
return a.element.id - b.element.id
|
||||
if (a.name.en.includes('NM') && b.name.en.includes('NM'))
|
||||
return a.level - b.level
|
||||
return a.name.en.localeCompare(b.name.en)
|
||||
|
|
@ -521,12 +523,12 @@ const RaidCombobox = (props: Props) => {
|
|||
// Methods: Utility
|
||||
// ----------------------------------------------
|
||||
const linkClass = classNames({
|
||||
wind: currentRaid && currentRaid.element == 1,
|
||||
fire: currentRaid && currentRaid.element == 2,
|
||||
water: currentRaid && currentRaid.element == 3,
|
||||
earth: currentRaid && currentRaid.element == 4,
|
||||
dark: currentRaid && currentRaid.element == 5,
|
||||
light: currentRaid && currentRaid.element == 6,
|
||||
wind: currentRaid && currentRaid.element == ElementMap.wind,
|
||||
fire: currentRaid && currentRaid.element == ElementMap.fire,
|
||||
water: currentRaid && currentRaid.element == ElementMap.water,
|
||||
earth: currentRaid && currentRaid.element == ElementMap.earth,
|
||||
dark: currentRaid && currentRaid.element == ElementMap.dark,
|
||||
light: currentRaid && currentRaid.element == ElementMap.light,
|
||||
})
|
||||
|
||||
// ----------------------------------------------
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@ import { useRouter } from 'next/router'
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import 'fix-date'
|
||||
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
import classNames from 'classnames'
|
||||
|
||||
interface Props {
|
||||
job?: Job
|
||||
gender?: number
|
||||
element?: number
|
||||
element?: GranblueElement
|
||||
grid: GridArray<GridCharacter>
|
||||
}
|
||||
|
||||
|
|
@ -47,17 +49,17 @@ const CharacterRep = (props: Props) => {
|
|||
// Convert element to string
|
||||
function numberToElement() {
|
||||
switch (props.element) {
|
||||
case 1:
|
||||
case ElementMap.wind:
|
||||
return 'wind'
|
||||
case 2:
|
||||
case ElementMap.fire:
|
||||
return 'fire'
|
||||
case 3:
|
||||
case ElementMap.water:
|
||||
return 'water'
|
||||
case 4:
|
||||
case ElementMap.earth:
|
||||
return 'earth'
|
||||
case 5:
|
||||
case ElementMap.dark:
|
||||
return 'dark'
|
||||
case 6:
|
||||
case ElementMap.light:
|
||||
return 'light'
|
||||
default:
|
||||
return ''
|
||||
|
|
@ -91,21 +93,21 @@ const CharacterRep = (props: Props) => {
|
|||
if (character && gridCharacter) {
|
||||
// Change the image based on the uncap level
|
||||
let suffix = '01'
|
||||
if (gridCharacter.transcendence_step > 0) suffix = '04'
|
||||
else if (gridCharacter.uncap_level >= 5) suffix = '03'
|
||||
else if (gridCharacter.uncap_level > 2) suffix = '02'
|
||||
if (gridCharacter.transcendenceStep > 0) suffix = '04'
|
||||
else if (gridCharacter.uncapLevel >= 5) suffix = '03'
|
||||
else if (gridCharacter.uncapLevel > 2) suffix = '02'
|
||||
|
||||
if (character.element == 0) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblue_id}_${props.element}.jpg`
|
||||
if (character.element === ElementMap.null) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblueId}_${props.element}.jpg`
|
||||
} else {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblue_id}_${suffix}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/character-main/${character.granblueId}_${suffix}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
return characters[position] ? (
|
||||
<img alt={characters[position]?.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
characters[position] && (
|
||||
<img alt={characters[position]?.name[locale]} src={url} />
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import styles from './index.module.scss'
|
|||
|
||||
interface Props {
|
||||
grid: {
|
||||
mainSummon: GridSummon | undefined
|
||||
friendSummon: GridSummon | undefined
|
||||
mainSummon?: GridSummon | undefined
|
||||
friendSummon?: GridSummon | undefined
|
||||
allSummons: GridArray<GridSummon>
|
||||
}
|
||||
}
|
||||
|
|
@ -70,31 +70,27 @@ const SummonRep = (props: Props) => {
|
|||
if (mainSummon) {
|
||||
// Change the image based on the uncap level
|
||||
let suffix = ''
|
||||
if (mainSummon.object.uncap.xlb && mainSummon.uncap_level == 6) {
|
||||
if (mainSummon.object.uncap.xlb && mainSummon.uncapLevel == 6) {
|
||||
if (
|
||||
mainSummon.transcendence_step >= 1 &&
|
||||
mainSummon.transcendence_step < 5
|
||||
mainSummon.transcendenceStep >= 1 &&
|
||||
mainSummon.transcendenceStep < 5
|
||||
) {
|
||||
suffix = '_03'
|
||||
} else if (mainSummon.transcendence_step === 5) {
|
||||
} else if (mainSummon.transcendenceStep === 5) {
|
||||
suffix = '_04'
|
||||
}
|
||||
} else if (
|
||||
upgradedSummons.indexOf(mainSummon.object.granblue_id.toString()) !=
|
||||
upgradedSummons.indexOf(mainSummon.object.granblueId.toString()) !=
|
||||
-1 &&
|
||||
mainSummon.uncap_level == 5
|
||||
mainSummon.uncapLevel == 5
|
||||
) {
|
||||
suffix = '_02'
|
||||
}
|
||||
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${mainSummon.object.granblue_id}${suffix}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${mainSummon.object.granblueId}${suffix}.jpg`
|
||||
}
|
||||
|
||||
return mainSummon ? (
|
||||
<img alt={mainSummon.object.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
)
|
||||
return mainSummon && <img alt={mainSummon.object.name[locale]} src={url} />
|
||||
}
|
||||
|
||||
function generateGridImage(position: number) {
|
||||
|
|
@ -123,29 +119,29 @@ const SummonRep = (props: Props) => {
|
|||
if (summon && gridSummon) {
|
||||
// Change the image based on the uncap level
|
||||
let suffix = ''
|
||||
if (gridSummon.object.uncap.xlb && gridSummon.uncap_level == 6) {
|
||||
if (gridSummon.object.uncap.xlb && gridSummon.uncapLevel == 6) {
|
||||
if (
|
||||
gridSummon.transcendence_step >= 1 &&
|
||||
gridSummon.transcendence_step < 5
|
||||
gridSummon.transcendenceStep >= 1 &&
|
||||
gridSummon.transcendenceStep < 5
|
||||
) {
|
||||
suffix = '_03'
|
||||
} else if (gridSummon.transcendence_step === 5) {
|
||||
} else if (gridSummon.transcendenceStep === 5) {
|
||||
suffix = '_04'
|
||||
}
|
||||
} else if (
|
||||
upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 &&
|
||||
gridSummon.uncap_level == 5
|
||||
upgradedSummons.indexOf(summon.granblueId.toString()) != -1 &&
|
||||
gridSummon.uncapLevel == 5
|
||||
) {
|
||||
suffix = '_02'
|
||||
}
|
||||
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblueId}${suffix}.jpg`
|
||||
}
|
||||
|
||||
return summons[position] ? (
|
||||
<img alt={summons[position]?.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
summons[position] && (
|
||||
<img alt={summons[position]?.name[locale]} src={url} />
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { useRouter } from 'next/router'
|
||||
|
||||
import { ElementMap } from '~utils/elements'
|
||||
import styles from './index.module.scss'
|
||||
import classNames from 'classnames'
|
||||
|
||||
interface Props {
|
||||
grid: {
|
||||
mainWeapon: GridWeapon | undefined
|
||||
mainWeapon?: GridWeapon | undefined
|
||||
allWeapons: GridArray<GridWeapon>
|
||||
}
|
||||
}
|
||||
|
|
@ -53,14 +52,14 @@ const WeaponRep = (props: Props) => {
|
|||
let url = ''
|
||||
|
||||
if (mainhand && mainhand.object) {
|
||||
if (mainhand.object.element == 0 && mainhand.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.object.granblue_id}_${mainhand.element}.jpg`
|
||||
if (mainhand.object.element === ElementMap.null && mainhand.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.object.granblueId}_${mainhand.element}.jpg`
|
||||
} else {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.object.granblue_id}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand.object.granblueId}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
return mainhand ? <img alt={mainhand.object.name[locale]} src={url} /> : ''
|
||||
return mainhand && <img alt={mainhand.object.name[locale]} src={url} />
|
||||
}
|
||||
|
||||
function generateGridImage(position: number) {
|
||||
|
|
@ -70,17 +69,17 @@ const WeaponRep = (props: Props) => {
|
|||
const gridWeapon = grid[position]
|
||||
|
||||
if (weapon && gridWeapon) {
|
||||
if (weapon.element == 0 && gridWeapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||
if (weapon.element === ElementMap.null && gridWeapon.element) {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}_${gridWeapon.element}.jpg`
|
||||
} else {
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`
|
||||
url = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
return weapons[position] ? (
|
||||
<img alt={weapons[position]?.name[locale]} src={url} />
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
weapons[position] && (
|
||||
<img alt={weapons[position]?.name[locale]} src={url} />
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,12 @@ import WeaponSearchFilterBar from '~components/weapon/WeaponSearchFilterBar'
|
|||
import SummonSearchFilterBar from '~components/summon/SummonSearchFilterBar'
|
||||
import JobSkillSearchFilterBar from '~components/job/JobSkillSearchFilterBar'
|
||||
|
||||
import * as WeaponTransformer from '~transformers/WeaponTransformer'
|
||||
import * as SummonTransformer from '~transformers/SummonTransformer'
|
||||
import * as CharacterTransformer from '~transformers/CharacterTransformer'
|
||||
import * as JobSkillTransformer from '~transformers/JobSkillTransformer'
|
||||
import * as GuidebookTransformer from '~transformers/GuidebookTransformer'
|
||||
|
||||
import CharacterResult from '~components/character/CharacterResult'
|
||||
import WeaponResult from '~components/weapon/WeaponResult'
|
||||
import SummonResult from '~components/summon/SummonResult'
|
||||
|
|
@ -126,7 +132,7 @@ const SearchModal = (props: Props) => {
|
|||
if (
|
||||
!recents.find(
|
||||
(item) =>
|
||||
(item as Weapon).granblue_id === (result as Weapon).granblue_id
|
||||
(item as Weapon).granblueId === (result as Weapon).granblueId
|
||||
)
|
||||
) {
|
||||
recents.unshift(result as Weapon)
|
||||
|
|
@ -136,7 +142,7 @@ const SearchModal = (props: Props) => {
|
|||
if (
|
||||
!recents.find(
|
||||
(item) =>
|
||||
(item as Summon).granblue_id === (result as Summon).granblue_id
|
||||
(item as Summon).granblueId === (result as Summon).granblueId
|
||||
)
|
||||
) {
|
||||
recents.unshift(result as Summon)
|
||||
|
|
@ -270,13 +276,14 @@ const SearchModal = (props: Props) => {
|
|||
|
||||
const castResults: Weapon[] = results as Weapon[]
|
||||
if (castResults && Object.keys(castResults).length > 0) {
|
||||
jsx = castResults.map((result: Weapon) => {
|
||||
jsx = castResults.map((result: any) => {
|
||||
const weapon = WeaponTransformer.toObject(result)
|
||||
return (
|
||||
<WeaponResult
|
||||
key={result.id}
|
||||
data={result}
|
||||
key={weapon.id}
|
||||
data={weapon}
|
||||
onClick={() => {
|
||||
storeRecentResult(result)
|
||||
storeRecentResult(weapon)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
@ -291,13 +298,14 @@ const SearchModal = (props: Props) => {
|
|||
|
||||
const castResults: Summon[] = results as Summon[]
|
||||
if (castResults && Object.keys(castResults).length > 0) {
|
||||
jsx = castResults.map((result: Summon) => {
|
||||
jsx = castResults.map((result: any) => {
|
||||
const summon = SummonTransformer.toObject(result)
|
||||
return (
|
||||
<SummonResult
|
||||
key={result.id}
|
||||
data={result}
|
||||
key={summon.id}
|
||||
data={summon}
|
||||
onClick={() => {
|
||||
storeRecentResult(result)
|
||||
storeRecentResult(summon)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
@ -312,13 +320,14 @@ const SearchModal = (props: Props) => {
|
|||
|
||||
const castResults: Character[] = results as Character[]
|
||||
if (castResults && Object.keys(castResults).length > 0) {
|
||||
jsx = castResults.map((result: Character) => {
|
||||
jsx = castResults.map((result: any) => {
|
||||
const character = CharacterTransformer.toObject(result)
|
||||
return (
|
||||
<CharacterResult
|
||||
key={result.id}
|
||||
data={result}
|
||||
key={character.id}
|
||||
data={character}
|
||||
onClick={() => {
|
||||
storeRecentResult(result)
|
||||
storeRecentResult(character)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
@ -334,12 +343,13 @@ const SearchModal = (props: Props) => {
|
|||
const castResults: JobSkill[] = results as JobSkill[]
|
||||
if (castResults && Object.keys(castResults).length > 0) {
|
||||
jsx = castResults.map((result: JobSkill) => {
|
||||
const jobSkill = JobSkillTransformer.toObject(result)
|
||||
return (
|
||||
<JobSkillResult
|
||||
key={result.id}
|
||||
data={result}
|
||||
key={jobSkill.id}
|
||||
data={jobSkill}
|
||||
onClick={() => {
|
||||
storeRecentResult(result)
|
||||
storeRecentResult(jobSkill)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
@ -355,12 +365,13 @@ const SearchModal = (props: Props) => {
|
|||
const castResults: Guidebook[] = results as Guidebook[]
|
||||
if (castResults && Object.keys(castResults).length > 0) {
|
||||
jsx = castResults.map((result: Guidebook) => {
|
||||
const guidebook = GuidebookTransformer.toObject(result)
|
||||
return (
|
||||
<GuidebookResult
|
||||
key={result.id}
|
||||
data={result}
|
||||
key={guidebook.id}
|
||||
data={guidebook}
|
||||
onClick={() => {
|
||||
storeRecentResult(result)
|
||||
storeRecentResult(guidebook)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import ExtraSummonsGrid from '~components/extra/ExtraSummonsGrid'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import * as GridSummonTransformer from '~transformers/GridSummonTransformer'
|
||||
import type { DetailsObject, SearchableObject } from '~types'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
|
@ -22,7 +23,11 @@ import styles from './index.module.scss'
|
|||
interface Props {
|
||||
new: boolean
|
||||
editable: boolean
|
||||
summons?: GridSummon[]
|
||||
summons?: {
|
||||
mainSummon?: GridSummon
|
||||
friendSummon?: GridSummon
|
||||
allSummons: GridArray<GridSummon>
|
||||
}
|
||||
createParty: (details?: DetailsObject) => Promise<Party>
|
||||
pushHistory?: (path: string) => void
|
||||
}
|
||||
|
|
@ -45,7 +50,7 @@ const SummonGrid = (props: Props) => {
|
|||
const [errorAlertOpen, setErrorAlertOpen] = useState(false)
|
||||
|
||||
// Set up state for view management
|
||||
const { party, grid } = useSnapshot(appState)
|
||||
const { party } = useSnapshot(appState)
|
||||
|
||||
// Create a temporary state to store previous weapon uncap values and transcendence stages
|
||||
const [previousUncapValues, setPreviousUncapValues] = useState<{
|
||||
|
|
@ -60,23 +65,23 @@ const SummonGrid = (props: Props) => {
|
|||
useEffect(() => {
|
||||
let initialPreviousUncapValues: { [key: number]: number } = {}
|
||||
|
||||
if (appState.grid.summons.mainSummon)
|
||||
if (appState.party.grid.summons.mainSummon)
|
||||
initialPreviousUncapValues[-1] =
|
||||
appState.grid.summons.mainSummon.uncap_level
|
||||
appState.party.grid.summons.mainSummon.uncapLevel
|
||||
|
||||
if (appState.grid.summons.friendSummon)
|
||||
if (appState.party.grid.summons.friendSummon)
|
||||
initialPreviousUncapValues[6] =
|
||||
appState.grid.summons.friendSummon.uncap_level
|
||||
appState.party.grid.summons.friendSummon.uncapLevel
|
||||
|
||||
Object.values(appState.grid.summons.allSummons).map((o) =>
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncap_level) : 0
|
||||
Object.values(appState.party.grid.summons.allSummons).map((o) =>
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncapLevel) : 0
|
||||
)
|
||||
|
||||
setPreviousUncapValues(initialPreviousUncapValues)
|
||||
}, [
|
||||
appState.grid.summons.mainSummon,
|
||||
appState.grid.summons.friendSummon,
|
||||
appState.grid.summons.allSummons,
|
||||
appState.party.grid.summons.mainSummon,
|
||||
appState.party.grid.summons.friendSummon,
|
||||
appState.party.grid.summons.allSummons,
|
||||
])
|
||||
|
||||
// Methods: Adding an object from search
|
||||
|
|
@ -115,11 +120,11 @@ const SummonGrid = (props: Props) => {
|
|||
const position = data.meta['replaced']
|
||||
|
||||
if (position == -1) {
|
||||
appState.grid.summons.mainSummon = undefined
|
||||
appState.party.grid.summons.mainSummon = null
|
||||
} else if (position == 6) {
|
||||
appState.grid.summons.friendSummon = undefined
|
||||
appState.party.grid.summons.friendSummon = null
|
||||
} else {
|
||||
appState.grid.summons.allSummons[position] = undefined
|
||||
appState.party.grid.summons.allSummons[position] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -137,16 +142,20 @@ const SummonGrid = (props: Props) => {
|
|||
position: position,
|
||||
main: position == -1,
|
||||
friend: position == 6,
|
||||
uncap_level: uncapLevel,
|
||||
uncapLevel: uncapLevel,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function storeGridSummon(gridSummon: GridSummon) {
|
||||
if (gridSummon.position == -1) appState.grid.summons.mainSummon = gridSummon
|
||||
function storeGridSummon(data: GridSummon) {
|
||||
const gridSummon = GridSummonTransformer.toObject(data)
|
||||
|
||||
if (gridSummon.position == -1)
|
||||
appState.party.grid.summons.mainSummon = gridSummon
|
||||
else if (gridSummon.position == 6)
|
||||
appState.grid.summons.friendSummon = gridSummon
|
||||
else appState.grid.summons.allSummons[gridSummon.position] = gridSummon
|
||||
appState.party.grid.summons.friendSummon = gridSummon
|
||||
else
|
||||
appState.party.grid.summons.allSummons[gridSummon.position] = gridSummon
|
||||
}
|
||||
|
||||
// Methods: Updating uncap level
|
||||
|
|
@ -212,15 +221,15 @@ const SummonGrid = (props: Props) => {
|
|||
)
|
||||
|
||||
const updateUncapLevel = (position: number, uncapLevel: number) => {
|
||||
if (appState.grid.summons.mainSummon && position == -1)
|
||||
appState.grid.summons.mainSummon.uncap_level = uncapLevel
|
||||
else if (appState.grid.summons.friendSummon && position == 6)
|
||||
appState.grid.summons.friendSummon.uncap_level = uncapLevel
|
||||
if (appState.party.grid.summons.mainSummon && position == -1)
|
||||
appState.party.grid.summons.mainSummon.uncapLevel = uncapLevel
|
||||
else if (appState.party.grid.summons.friendSummon && position == 6)
|
||||
appState.party.grid.summons.friendSummon.uncapLevel = uncapLevel
|
||||
else {
|
||||
const summon = appState.grid.summons.allSummons[position]
|
||||
const summon = appState.party.grid.summons.allSummons[position]
|
||||
if (summon) {
|
||||
summon.uncap_level = uncapLevel
|
||||
appState.grid.summons.allSummons[position] = summon
|
||||
summon.uncapLevel = uncapLevel
|
||||
appState.party.grid.summons.allSummons[position] = summon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -229,14 +238,15 @@ const SummonGrid = (props: Props) => {
|
|||
// Save the current value in case of an unexpected result
|
||||
let newPreviousValues = { ...previousUncapValues }
|
||||
|
||||
if (appState.grid.summons.mainSummon && position == -1)
|
||||
newPreviousValues[position] = appState.grid.summons.mainSummon.uncap_level
|
||||
else if (appState.grid.summons.friendSummon && position == 6)
|
||||
if (appState.party.grid.summons.mainSummon && position == -1)
|
||||
newPreviousValues[position] =
|
||||
appState.grid.summons.friendSummon.uncap_level
|
||||
appState.party.grid.summons.mainSummon.uncapLevel
|
||||
else if (appState.party.grid.summons.friendSummon && position == 6)
|
||||
newPreviousValues[position] =
|
||||
appState.party.grid.summons.friendSummon.uncapLevel
|
||||
else {
|
||||
const summon = appState.grid.summons.allSummons[position]
|
||||
newPreviousValues[position] = summon ? summon.uncap_level : 0
|
||||
const summon = appState.party.grid.summons.allSummons[position]
|
||||
newPreviousValues[position] = summon ? summon.uncapLevel : 0
|
||||
}
|
||||
|
||||
setPreviousUncapValues(newPreviousValues)
|
||||
|
|
@ -254,18 +264,16 @@ const SummonGrid = (props: Props) => {
|
|||
|
||||
const payload = {
|
||||
summon: {
|
||||
uncap_level: stage > 0 ? 6 : 5,
|
||||
uncapLevel: stage > 0 ? 6 : 5,
|
||||
transcendence_step: stage,
|
||||
},
|
||||
}
|
||||
|
||||
try {
|
||||
if (stage != previousTranscendenceStages[position])
|
||||
await api.endpoints.grid_summons
|
||||
.update(id, payload)
|
||||
.then((response) => {
|
||||
storeGridSummon(response.data.grid_summon)
|
||||
})
|
||||
await api.updateTranscendence('summon', id, stage).then((response) => {
|
||||
storeGridSummon(response.data.grid_summon)
|
||||
})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
|
|
@ -318,15 +326,15 @@ const SummonGrid = (props: Props) => {
|
|||
)
|
||||
|
||||
const updateTranscendenceStage = (position: number, stage: number) => {
|
||||
if (appState.grid.summons.mainSummon && position == -1)
|
||||
appState.grid.summons.mainSummon.transcendence_step = stage
|
||||
else if (appState.grid.summons.friendSummon && position == 6)
|
||||
appState.grid.summons.friendSummon.transcendence_step = stage
|
||||
if (appState.party.grid.summons.mainSummon && position == -1)
|
||||
appState.party.grid.summons.mainSummon.transcendenceStep = stage
|
||||
else if (appState.party.grid.summons.friendSummon && position == 6)
|
||||
appState.party.grid.summons.friendSummon.transcendenceStep = stage
|
||||
else {
|
||||
const summon = appState.grid.summons.allSummons[position]
|
||||
const summon = appState.party.grid.summons.allSummons[position]
|
||||
if (summon) {
|
||||
summon.transcendence_step = stage
|
||||
appState.grid.summons.allSummons[position] = summon
|
||||
summon.transcendenceStep = stage
|
||||
appState.party.grid.summons.allSummons[position] = summon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -335,14 +343,15 @@ const SummonGrid = (props: Props) => {
|
|||
// Save the current value in case of an unexpected result
|
||||
let newPreviousValues = { ...previousUncapValues }
|
||||
|
||||
if (appState.grid.summons.mainSummon && position == -1)
|
||||
newPreviousValues[position] = appState.grid.summons.mainSummon.uncap_level
|
||||
else if (appState.grid.summons.friendSummon && position == 6)
|
||||
if (appState.party.grid.summons.mainSummon && position == -1)
|
||||
newPreviousValues[position] =
|
||||
appState.grid.summons.friendSummon.uncap_level
|
||||
appState.party.grid.summons.mainSummon.uncapLevel
|
||||
else if (appState.party.grid.summons.friendSummon && position == 6)
|
||||
newPreviousValues[position] =
|
||||
appState.party.grid.summons.friendSummon.uncapLevel
|
||||
else {
|
||||
const summon = appState.grid.summons.allSummons[position]
|
||||
newPreviousValues[position] = summon ? summon.uncap_level : 0
|
||||
const summon = appState.party.grid.summons.allSummons[position]
|
||||
newPreviousValues[position] = summon ? summon.uncapLevel : 0
|
||||
}
|
||||
|
||||
setPreviousUncapValues(newPreviousValues)
|
||||
|
|
@ -354,11 +363,11 @@ const SummonGrid = (props: Props) => {
|
|||
const data = response.data
|
||||
|
||||
if (data.position === -1) {
|
||||
appState.grid.summons.mainSummon = undefined
|
||||
appState.party.grid.summons.mainSummon = null
|
||||
} else if (data.position === 6) {
|
||||
appState.grid.summons.friendSummon = undefined
|
||||
appState.party.grid.summons.friendSummon = null
|
||||
} else {
|
||||
appState.grid.summons.allSummons[response.data.position] = undefined
|
||||
appState.party.grid.summons.allSummons[response.data.position] = null
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
@ -382,7 +391,7 @@ const SummonGrid = (props: Props) => {
|
|||
<div className="LabeledUnit">
|
||||
<div className={styles.label}>{t('summons.main')}</div>
|
||||
<SummonUnit
|
||||
gridSummon={grid.summons.mainSummon}
|
||||
gridSummon={party.grid.summons.mainSummon}
|
||||
editable={props.editable}
|
||||
key="grid_main_summon"
|
||||
position={-1}
|
||||
|
|
@ -406,7 +415,7 @@ const SummonGrid = (props: Props) => {
|
|||
{t('summons.friend')}
|
||||
</div>
|
||||
<SummonUnit
|
||||
gridSummon={grid.summons.friendSummon}
|
||||
gridSummon={party.grid.summons.friendSummon}
|
||||
editable={props.editable}
|
||||
key="grid_friend_summon"
|
||||
position={6}
|
||||
|
|
@ -427,7 +436,7 @@ const SummonGrid = (props: Props) => {
|
|||
return (
|
||||
<li key={`grid_unit_${i}`}>
|
||||
<SummonUnit
|
||||
gridSummon={grid.summons.allSummons[i]}
|
||||
gridSummon={party.grid.summons.allSummons[i]}
|
||||
editable={props.editable}
|
||||
position={i}
|
||||
unitType={1}
|
||||
|
|
@ -445,7 +454,7 @@ const SummonGrid = (props: Props) => {
|
|||
|
||||
const subAuraSummonElement = (
|
||||
<ExtraSummonsGrid
|
||||
grid={grid.summons.allSummons}
|
||||
grid={party.grid.summons.allSummons}
|
||||
editable={props.editable}
|
||||
exists={false}
|
||||
offset={numSummons}
|
||||
|
|
|
|||
|
|
@ -20,14 +20,9 @@ interface Props {
|
|||
}
|
||||
|
||||
const SummonHovercard = (props: Props) => {
|
||||
const router = useRouter()
|
||||
const { t } = useTranslation('common')
|
||||
const locale =
|
||||
router.locale && ['en', 'ja'].includes(router.locale) ? router.locale : 'en'
|
||||
|
||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||
|
||||
const tintElement = Element[props.gridSummon.object.element]
|
||||
const tintElement = props.gridSummon.object.element.slug
|
||||
|
||||
function goTo() {
|
||||
const urlSafeName = props.gridSummon.object.name.en.replaceAll(' ', '_')
|
||||
|
|
@ -55,19 +50,19 @@ const SummonHovercard = (props: Props) => {
|
|||
|
||||
let suffix = ''
|
||||
if (
|
||||
upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 &&
|
||||
props.gridSummon.uncap_level == 5
|
||||
upgradedSummons.indexOf(summon.granblueId.toString()) != -1 &&
|
||||
props.gridSummon.uncapLevel == 5
|
||||
) {
|
||||
suffix = '_02'
|
||||
} else if (
|
||||
props.gridSummon.object.uncap.xlb &&
|
||||
props.gridSummon.transcendence_step > 0
|
||||
props.gridSummon.transcendenceStep > 0
|
||||
) {
|
||||
suffix = '_03'
|
||||
}
|
||||
|
||||
// Generate the correct source for the summon
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg`
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblueId}${suffix}.jpg`
|
||||
}
|
||||
|
||||
return imgSrc
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ interface Props {
|
|||
onClick: () => void
|
||||
}
|
||||
|
||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||
|
||||
const SummonResult = (props: Props) => {
|
||||
const router = useRouter()
|
||||
const locale =
|
||||
|
|
@ -24,18 +22,21 @@ const SummonResult = (props: Props) => {
|
|||
<li className={styles.result} onClick={props.onClick}>
|
||||
<img
|
||||
alt={summon.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}.jpg`}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblueId}.jpg`}
|
||||
/>
|
||||
<div className={styles.info}>
|
||||
<h5>{summon.name[locale]}</h5>
|
||||
<UncapIndicator
|
||||
type="summon"
|
||||
flb={summon.uncap.flb}
|
||||
ulb={summon.uncap.ulb}
|
||||
ulb={summon.uncap.ulb || false}
|
||||
flb={summon.uncap.flb || false}
|
||||
xlb={summon.uncap.xlb || false}
|
||||
uncapLevel={6}
|
||||
transcendenceStage={5}
|
||||
special={false}
|
||||
/>
|
||||
<div className={styles.tags}>
|
||||
<WeaponLabelIcon labelType={Element[summon.element]} />
|
||||
<WeaponLabelIcon labelType={summon.element.slug} />
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import { useTranslation } from 'next-i18next'
|
|||
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
|
||||
import SearchFilter from '~components/search/SearchFilter'
|
||||
import SearchFilterCheckboxItem from '~components/search/SearchFilterCheckboxItem'
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import classNames from 'classnames'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import * as GridSummonTransformer from '~transformers/GridSummonTransformer'
|
||||
|
||||
import Alert from '~components/common/Alert'
|
||||
import Button from '~components/common/Button'
|
||||
|
|
@ -26,7 +27,7 @@ import SettingsIcon from '~public/icons/Settings.svg'
|
|||
import styles from './index.module.scss'
|
||||
|
||||
interface Props {
|
||||
gridSummon: GridSummon | undefined
|
||||
gridSummon: GridSummon | null
|
||||
unitType: 0 | 1 | 2
|
||||
position: number
|
||||
editable: boolean
|
||||
|
|
@ -95,7 +96,7 @@ const SummonUnit = ({
|
|||
}
|
||||
|
||||
function handleQuickSummonClick() {
|
||||
if (gridSummon) updateQuickSummon(!gridSummon.quick_summon)
|
||||
if (gridSummon) updateQuickSummon(!gridSummon.quickSummon)
|
||||
}
|
||||
|
||||
// Methods: Handle open change
|
||||
|
|
@ -125,13 +126,23 @@ const SummonUnit = ({
|
|||
// If a user sets a quick summon while one is already set,
|
||||
// the previous one will be unset.
|
||||
const gridSummons: GridSummon[] = response.data.summons
|
||||
|
||||
const mainSummon = gridSummons.find((summon) =>
|
||||
GridSummonTransformer.toObject(summon)
|
||||
)
|
||||
const friendSummon = gridSummons.find((summon) =>
|
||||
GridSummonTransformer.toObject(summon)
|
||||
)
|
||||
|
||||
for (const gridSummon of gridSummons) {
|
||||
if (gridSummon.main) {
|
||||
appState.grid.summons.mainSummon = gridSummon
|
||||
appState.grid.summons.mainSummon = mainSummon
|
||||
} else if (gridSummon.friend) {
|
||||
appState.grid.summons.friendSummon = gridSummon
|
||||
appState.grid.summons.friendSummon = friendSummon
|
||||
} else {
|
||||
appState.grid.summons.allSummons[gridSummon.position] = gridSummon
|
||||
appState.party.grid.summons.allSummons[gridSummon.position] = gridSummon
|
||||
? GridSummonTransformer.toObject(gridSummon)
|
||||
: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -157,8 +168,7 @@ const SummonUnit = ({
|
|||
function generateImageUrl() {
|
||||
let imgSrc = ''
|
||||
if (gridSummon) {
|
||||
const summon = gridSummon.object!
|
||||
|
||||
const summon = gridSummon.object
|
||||
const upgradedSummons = [
|
||||
'2040094000',
|
||||
'2040100000',
|
||||
|
|
@ -177,27 +187,28 @@ const SummonUnit = ({
|
|||
]
|
||||
|
||||
let suffix = ''
|
||||
if (gridSummon.object.uncap.xlb && gridSummon.uncap_level == 6) {
|
||||
if (gridSummon.object.uncap.xlb && gridSummon.uncapLevel == 6) {
|
||||
if (
|
||||
gridSummon.transcendence_step >= 1 &&
|
||||
gridSummon.transcendence_step < 5
|
||||
gridSummon.transcendenceStep &&
|
||||
gridSummon.transcendenceStep >= 1 &&
|
||||
gridSummon.transcendenceStep < 5
|
||||
) {
|
||||
suffix = '_03'
|
||||
} else if (gridSummon.transcendence_step === 5) {
|
||||
} else if (gridSummon.transcendenceStep === 5) {
|
||||
suffix = '_04'
|
||||
}
|
||||
} else if (
|
||||
upgradedSummons.indexOf(summon.granblue_id.toString()) != -1 &&
|
||||
gridSummon.uncap_level == 5
|
||||
upgradedSummons.indexOf(summon.granblueId) != -1 &&
|
||||
gridSummon.uncapLevel == 5
|
||||
) {
|
||||
suffix = '_02'
|
||||
}
|
||||
|
||||
// Generate the correct source for the summon
|
||||
if (unitType == 0 || unitType == 2)
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblue_id}${suffix}.jpg`
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-main/${summon.granblueId}${suffix}.jpg`
|
||||
else
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}${suffix}.jpg`
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblueId}${suffix}.jpg`
|
||||
}
|
||||
|
||||
setImageUrl(imgSrc)
|
||||
|
|
@ -273,7 +284,7 @@ const SummonUnit = ({
|
|||
if (gridSummon) {
|
||||
const classes = classNames({
|
||||
[styles.quickSummon]: true,
|
||||
[styles.empty]: !gridSummon.quick_summon,
|
||||
[styles.empty]: !gridSummon.quickSummon,
|
||||
})
|
||||
|
||||
return <i className={classes} onClick={handleQuickSummonClick} />
|
||||
|
|
@ -327,8 +338,8 @@ const SummonUnit = ({
|
|||
flb={gridSummon.object.uncap.flb || false}
|
||||
xlb={gridSummon.object.uncap.xlb || false}
|
||||
editable={editable}
|
||||
uncapLevel={gridSummon.uncap_level}
|
||||
transcendenceStage={gridSummon.transcendence_step}
|
||||
uncapLevel={gridSummon.uncapLevel}
|
||||
transcendenceStage={gridSummon.transcendenceStep}
|
||||
position={gridSummon.position}
|
||||
updateUncap={passUncapData}
|
||||
updateTranscendence={passTranscendenceData}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.Fragment {
|
||||
.fragment {
|
||||
$degrees: 72deg;
|
||||
|
||||
$origWidth: 29px;
|
||||
|
|
@ -28,11 +28,11 @@
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.Visible {
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&.Stage1 {
|
||||
&.stage1 {
|
||||
top: 3px;
|
||||
left: 18px;
|
||||
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
// }
|
||||
}
|
||||
|
||||
&.Stage2 {
|
||||
&.stage2 {
|
||||
top: 10px;
|
||||
left: 27px;
|
||||
transform: rotate($degrees);
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
// }
|
||||
}
|
||||
|
||||
&.Stage3 {
|
||||
&.stage3 {
|
||||
top: 21px;
|
||||
left: 24px;
|
||||
transform: rotate($degrees * 2);
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
// }
|
||||
}
|
||||
|
||||
&.Stage4 {
|
||||
&.stage4 {
|
||||
top: 21px;
|
||||
left: 12px;
|
||||
transform: rotate($degrees * 3);
|
||||
|
|
@ -71,7 +71,7 @@
|
|||
// }
|
||||
}
|
||||
|
||||
&.Stage5 {
|
||||
&.stage5 {
|
||||
top: 10px;
|
||||
left: 8px;
|
||||
transform: rotate($degrees * 4);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react'
|
||||
import classnames from 'classnames'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
|
|
@ -18,14 +18,14 @@ const TranscendenceFragment = ({
|
|||
onClick,
|
||||
onHover,
|
||||
}: Props) => {
|
||||
const classes = classnames({
|
||||
Fragment: true,
|
||||
Visible: visible,
|
||||
Stage1: stage === 1,
|
||||
Stage2: stage === 2,
|
||||
Stage3: stage === 3,
|
||||
Stage4: stage === 4,
|
||||
Stage5: stage === 5,
|
||||
const classes = classNames({
|
||||
[styles.fragment]: true,
|
||||
[styles.visible]: visible,
|
||||
[styles.stage1]: stage === 1,
|
||||
[styles.stage2]: stage === 2,
|
||||
[styles.stage3]: stage === 3,
|
||||
[styles.stage4]: stage === 4,
|
||||
[styles.stage5]: stage === 5,
|
||||
})
|
||||
|
||||
function handleClick() {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,20 @@
|
|||
.Transcendence.Popover {
|
||||
align-items: center;
|
||||
.transcendence {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-half;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: $unit-10x;
|
||||
height: $unit-10x;
|
||||
justify-content: center;
|
||||
|
||||
animation: scaleIn $duration-zoom ease-out;
|
||||
background: var(--dialog-bg);
|
||||
border-radius: $card-corner;
|
||||
border: 0.5px solid rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.24);
|
||||
outline: none;
|
||||
padding: $unit;
|
||||
transform-origin: var(--radix-popover-content-transform-origin);
|
||||
z-index: 32;
|
||||
|
||||
&.open {
|
||||
|
|
@ -18,7 +27,50 @@
|
|||
font-weight: $medium;
|
||||
}
|
||||
|
||||
.Pending {
|
||||
.pending {
|
||||
color: $yellow;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scaleIn {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: scale(0);
|
||||
}
|
||||
20% {
|
||||
opacity: 0.2;
|
||||
transform: scale(0.4);
|
||||
}
|
||||
40% {
|
||||
opacity: 0.4;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
60% {
|
||||
opacity: 0.6;
|
||||
transform: scale(1);
|
||||
}
|
||||
65% {
|
||||
opacity: 0.65;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
70% {
|
||||
opacity: 0.7;
|
||||
transform: scale(1);
|
||||
}
|
||||
75% {
|
||||
opacity: 0.75;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
80% {
|
||||
opacity: 0.8;
|
||||
transform: scale(1.02);
|
||||
}
|
||||
90% {
|
||||
opacity: 0.9;
|
||||
transform: scale(0.96);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import React, { PropsWithChildren, useEffect, useState } from 'react'
|
|||
import { useTranslation } from 'next-i18next'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { Popover } from '@radix-ui/react-popover'
|
||||
import {
|
||||
Popover,
|
||||
PopoverAnchor,
|
||||
PopoverContent,
|
||||
} from '~components/common/PopoverContent'
|
||||
|
|
@ -40,12 +40,8 @@ const TranscendencePopover = ({
|
|||
|
||||
const popoverRef = React.createRef<HTMLDivElement>()
|
||||
|
||||
const classes = classNames({
|
||||
Transcendence: true,
|
||||
})
|
||||
|
||||
const levelClasses = classNames({
|
||||
Pending: stage != currentStage,
|
||||
[styles.pending]: stage != currentStage,
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -77,16 +73,20 @@ const TranscendencePopover = ({
|
|||
return (
|
||||
<Popover open={open} onOpenChange={onOpenChange}>
|
||||
<PopoverAnchor>{children}</PopoverAnchor>
|
||||
<PopoverContent className={classes} ref={popoverRef} tabIndex={tabIndex}>
|
||||
<PopoverContent
|
||||
className={styles.transcendence}
|
||||
ref={popoverRef}
|
||||
tabIndex={tabIndex}
|
||||
>
|
||||
<TranscendenceStar
|
||||
className="Interactive Base"
|
||||
className="interactive base"
|
||||
editable={true}
|
||||
interactive={true}
|
||||
stage={stage}
|
||||
onFragmentClick={handleFragmentClicked}
|
||||
onFragmentHover={handleFragmentHovered}
|
||||
/>
|
||||
<h4>
|
||||
<h4 className="name">
|
||||
<span>{t('level')} </span>
|
||||
<span className={levelClasses}>{baseLevel + 10 * currentStage}</span>
|
||||
</h4>
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ const TranscendenceStar = ({
|
|||
const starClasses = classnames({
|
||||
[styles.star]: true,
|
||||
[styles.immutable]: immutable,
|
||||
[styles.empty]: stage === 0,
|
||||
[styles.empty]: true,
|
||||
[styles.stage1]: stage === 1,
|
||||
[styles.stage2]: stage === 2,
|
||||
[styles.stage3]: stage === 3,
|
||||
|
|
@ -46,9 +46,12 @@ const TranscendenceStar = ({
|
|||
[styles.stage5]: stage === 5,
|
||||
})
|
||||
|
||||
const baseImageClasses = classnames(className, {
|
||||
[styles.figure]: true,
|
||||
})
|
||||
const baseImageClasses = classnames(
|
||||
{
|
||||
[styles.figure]: true,
|
||||
},
|
||||
className?.split(' ').map((c) => styles[c])
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
setVisibleStage(stage)
|
||||
|
|
@ -87,7 +90,7 @@ const TranscendenceStar = ({
|
|||
onMouseLeave={interactive ? handleMouseLeave : () => {}}
|
||||
tabIndex={tabIndex}
|
||||
>
|
||||
<div className="Fragments">
|
||||
<div className={styles.fragments}>
|
||||
{[...Array(NUM_FRAGMENTS)].map((e, i) => {
|
||||
const loopStage = i + 1
|
||||
return interactive ? (
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState } from 'react'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import UncapStar from '~components/uncap/UncapStar'
|
||||
import TranscendencePopover from '~components/uncap/TranscendencePopover'
|
||||
import TranscendenceStar from '~components/uncap/TranscendenceStar'
|
||||
|
|
@ -82,7 +82,11 @@ const UncapIndicator = (props: Props) => {
|
|||
return props.type === 'character' || props.type === 'summon' ? (
|
||||
<TranscendencePopover
|
||||
open={popoverOpen}
|
||||
stage={props.transcendenceStage ? props.transcendenceStage : 0}
|
||||
stage={
|
||||
props.transcendenceStage && props.transcendenceStage !== null
|
||||
? props.transcendenceStage
|
||||
: 0
|
||||
}
|
||||
type={props.type}
|
||||
onOpenChange={togglePopover}
|
||||
sendValue={sendTranscendenceStage}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const WeaponConflictModal = (props: Props) => {
|
|||
}, [setOpen, props.open])
|
||||
|
||||
function imageUrl(weapon?: Weapon) {
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-square/${weapon?.granblue_id}.jpg`
|
||||
return `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-square/${weapon?.granblueId}.jpg`
|
||||
}
|
||||
|
||||
function openChange(open: boolean) {
|
||||
|
|
|
|||
|
|
@ -18,16 +18,21 @@ import WeaponConflictModal from '~components/weapon/WeaponConflictModal'
|
|||
|
||||
import api from '~utils/api'
|
||||
import { appState } from '~utils/appState'
|
||||
import * as GridWeaponTransformer from '~transformers/GridWeaponTransformer'
|
||||
|
||||
import type { DetailsObject, SearchableObject } from '~types'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
// Props
|
||||
interface Props {
|
||||
new: boolean
|
||||
editable: boolean
|
||||
weapons?: GridWeapon[]
|
||||
weapons?: {
|
||||
mainWeapon?: GridWeapon
|
||||
allWeapons: GridArray<GridWeapon>
|
||||
}
|
||||
guidebooks?: GuidebookList
|
||||
createParty: (details: DetailsObject) => Promise<Party>
|
||||
pushHistory?: (path: string) => void
|
||||
|
|
@ -54,7 +59,7 @@ const WeaponGrid = (props: Props) => {
|
|||
const [showIncompatibleAlert, setShowIncompatibleAlert] = useState(false)
|
||||
|
||||
// Set up state for view management
|
||||
const { party, grid } = useSnapshot(appState)
|
||||
const { party } = useSnapshot(appState)
|
||||
const [modalOpen, setModalOpen] = useState(false)
|
||||
|
||||
// Set up state for conflict management
|
||||
|
|
@ -71,16 +76,19 @@ const WeaponGrid = (props: Props) => {
|
|||
useEffect(() => {
|
||||
let initialPreviousUncapValues: { [key: number]: number } = {}
|
||||
|
||||
if (appState.grid.weapons.mainWeapon)
|
||||
if (appState.party.grid.weapons.mainWeapon)
|
||||
initialPreviousUncapValues[-1] =
|
||||
appState.grid.weapons.mainWeapon.uncap_level
|
||||
appState.party.grid.weapons.mainWeapon.uncapLevel
|
||||
|
||||
Object.values(appState.grid.weapons.allWeapons).map((o) =>
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncap_level) : 0
|
||||
Object.values(appState.party.grid.weapons.allWeapons).map((o) =>
|
||||
o ? (initialPreviousUncapValues[o.position] = o.uncapLevel) : 0
|
||||
)
|
||||
|
||||
setPreviousUncapValues(initialPreviousUncapValues)
|
||||
}, [appState.grid.weapons.mainWeapon, appState.grid.weapons.allWeapons])
|
||||
}, [
|
||||
appState.party.grid.weapons.mainWeapon,
|
||||
appState.party.grid.weapons.allWeapons,
|
||||
])
|
||||
|
||||
// Methods: Adding an object from search
|
||||
function receiveWeaponFromSearch(object: SearchableObject, position: number) {
|
||||
|
|
@ -88,7 +96,7 @@ const WeaponGrid = (props: Props) => {
|
|||
if (position == 1) appState.party.element = weapon.element
|
||||
|
||||
if (!party.id) {
|
||||
const payload: DetailsObject = { extra: party.extra }
|
||||
const payload: DetailsObject = { extra: party.details.extra }
|
||||
props.createParty(payload).then((team) => {
|
||||
saveWeapon(team.id, weapon, position).then((response) => {
|
||||
if (response) storeGridWeapon(response.data.grid_weapon)
|
||||
|
|
@ -143,10 +151,10 @@ const WeaponGrid = (props: Props) => {
|
|||
const position = data.meta['replaced']
|
||||
|
||||
if (position == -1) {
|
||||
appState.grid.weapons.mainWeapon = undefined
|
||||
appState.party.element = 0
|
||||
appState.party.grid.weapons.mainWeapon = null
|
||||
appState.party.element = ElementMap.null
|
||||
} else {
|
||||
appState.grid.weapons.allWeapons[position] = undefined
|
||||
appState.party.grid.weapons.allWeapons[position] = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -160,16 +168,17 @@ const WeaponGrid = (props: Props) => {
|
|||
let post = false
|
||||
if (
|
||||
position === -1 &&
|
||||
(!appState.grid.weapons.mainWeapon ||
|
||||
(appState.grid.weapons.mainWeapon &&
|
||||
appState.grid.weapons.mainWeapon.object.id !== weapon.id))
|
||||
(!appState.party.grid.weapons.mainWeapon ||
|
||||
(appState.party.grid.weapons.mainWeapon &&
|
||||
appState.party.grid.weapons.mainWeapon.object.id !== weapon.id))
|
||||
) {
|
||||
post = true
|
||||
} else if (
|
||||
position !== -1 &&
|
||||
(!appState.grid.weapons.allWeapons[position] ||
|
||||
(appState.grid.weapons.allWeapons[position] &&
|
||||
appState.grid.weapons.allWeapons[position]?.object.id !== weapon.id))
|
||||
(!appState.party.grid.weapons.allWeapons[position] ||
|
||||
(appState.party.grid.weapons.allWeapons[position] &&
|
||||
appState.party.grid.weapons.allWeapons[position]?.object.id !==
|
||||
weapon.id))
|
||||
) {
|
||||
post = true
|
||||
}
|
||||
|
|
@ -181,19 +190,20 @@ const WeaponGrid = (props: Props) => {
|
|||
weapon_id: weapon.id,
|
||||
position: position,
|
||||
mainhand: position == -1,
|
||||
uncap_level: uncapLevel,
|
||||
uncapLevel: uncapLevel,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function storeGridWeapon(gridWeapon: GridWeapon) {
|
||||
function storeGridWeapon(data: GridWeapon) {
|
||||
const gridWeapon = GridWeaponTransformer.toObject(data)
|
||||
if (gridWeapon.position === -1) {
|
||||
appState.grid.weapons.mainWeapon = gridWeapon
|
||||
appState.party.grid.weapons.mainWeapon = gridWeapon
|
||||
appState.party.element = gridWeapon.object.element
|
||||
} else {
|
||||
// Store the grid unit at the correct position
|
||||
appState.grid.weapons.allWeapons[gridWeapon.position] = gridWeapon
|
||||
appState.party.grid.weapons.allWeapons[gridWeapon.position] = gridWeapon
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,11 +219,13 @@ const WeaponGrid = (props: Props) => {
|
|||
.then((response) => {
|
||||
// Remove conflicting characters from state
|
||||
conflicts.forEach((c) => {
|
||||
if (appState.grid.weapons.mainWeapon?.object.id === c.object.id) {
|
||||
appState.grid.weapons.mainWeapon = undefined
|
||||
appState.party.element = 0
|
||||
if (
|
||||
appState.party.grid.weapons.mainWeapon?.object.id === c.object.id
|
||||
) {
|
||||
appState.party.grid.weapons.mainWeapon = null
|
||||
appState.party.element = ElementMap.null
|
||||
} else {
|
||||
appState.grid.weapons.allWeapons[c.position] = undefined
|
||||
appState.party.grid.weapons.allWeapons[c.position] = null
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -241,9 +253,9 @@ const WeaponGrid = (props: Props) => {
|
|||
const data = response.data
|
||||
|
||||
if (data.position === -1) {
|
||||
appState.grid.weapons.mainWeapon = undefined
|
||||
appState.party.grid.weapons.mainWeapon = null
|
||||
} else {
|
||||
appState.grid.weapons.allWeapons[response.data.position] = undefined
|
||||
appState.party.grid.weapons.allWeapons[response.data.position] = null
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
@ -307,13 +319,13 @@ const WeaponGrid = (props: Props) => {
|
|||
|
||||
const updateUncapLevel = (position: number, uncapLevel: number) => {
|
||||
// console.log(`Updating uncap level at position ${position} to ${uncapLevel}`)
|
||||
if (appState.grid.weapons.mainWeapon && position == -1)
|
||||
appState.grid.weapons.mainWeapon.uncap_level = uncapLevel
|
||||
if (appState.party.grid.weapons.mainWeapon && position == -1)
|
||||
appState.party.grid.weapons.mainWeapon.uncapLevel = uncapLevel
|
||||
else {
|
||||
const weapon = appState.grid.weapons.allWeapons[position]
|
||||
const weapon = appState.party.grid.weapons.allWeapons[position]
|
||||
if (weapon) {
|
||||
weapon.uncap_level = uncapLevel
|
||||
appState.grid.weapons.allWeapons[position] = weapon
|
||||
weapon.uncapLevel = uncapLevel
|
||||
appState.party.grid.weapons.allWeapons[position] = weapon
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -322,12 +334,13 @@ const WeaponGrid = (props: Props) => {
|
|||
// Save the current value in case of an unexpected result
|
||||
let newPreviousValues = { ...previousUncapValues }
|
||||
|
||||
if (appState.grid.weapons.mainWeapon && position == -1) {
|
||||
newPreviousValues[position] = appState.grid.weapons.mainWeapon.uncap_level
|
||||
if (appState.party.grid.weapons.mainWeapon && position == -1) {
|
||||
newPreviousValues[position] =
|
||||
appState.party.grid.weapons.mainWeapon.uncapLevel
|
||||
} else {
|
||||
const weapon = appState.grid.weapons.allWeapons[position]
|
||||
const weapon = appState.party.grid.weapons.allWeapons[position]
|
||||
if (weapon) {
|
||||
newPreviousValues[position] = weapon.uncap_level
|
||||
newPreviousValues[position] = weapon.uncapLevel
|
||||
} else {
|
||||
newPreviousValues[position] = 0
|
||||
}
|
||||
|
|
@ -339,13 +352,13 @@ const WeaponGrid = (props: Props) => {
|
|||
// Methods: Convenience
|
||||
const displayExtraContainer =
|
||||
props.editable ||
|
||||
appState.party.extra ||
|
||||
appState.party.details.extra ||
|
||||
Object.values(appState.party.guidebooks).every((el) => el === undefined)
|
||||
|
||||
// Render: JSX components
|
||||
const mainhandElement = (
|
||||
<WeaponUnit
|
||||
gridWeapon={appState.grid.weapons.mainWeapon}
|
||||
gridWeapon={appState.party.grid.weapons.mainWeapon}
|
||||
editable={props.editable}
|
||||
key="grid_mainhand"
|
||||
position={-1}
|
||||
|
|
@ -358,13 +371,13 @@ const WeaponGrid = (props: Props) => {
|
|||
|
||||
const weaponGridElement = Array.from(Array(numWeapons)).map((x, i) => {
|
||||
const itemClasses = classNames({
|
||||
Empty: appState.grid.weapons.allWeapons[i] === undefined,
|
||||
Empty: appState.party.grid.weapons.allWeapons[i] === undefined,
|
||||
})
|
||||
|
||||
return (
|
||||
<li className={itemClasses} key={`grid_unit_${i}`}>
|
||||
<WeaponUnit
|
||||
gridWeapon={appState.grid.weapons.allWeapons[i]}
|
||||
gridWeapon={party.grid.weapons.allWeapons[i]}
|
||||
editable={props.editable}
|
||||
position={i}
|
||||
unitType={1}
|
||||
|
|
@ -377,13 +390,13 @@ const WeaponGrid = (props: Props) => {
|
|||
})
|
||||
|
||||
const extraElement = () => {
|
||||
if (appState.party.raid && appState.party.raid.group.extra) {
|
||||
if (appState.party.raid && appState.party.raid.group?.extra) {
|
||||
return (
|
||||
<ExtraContainer>
|
||||
<ExtraContainerItem title={t('extra_weapons')} className="weapons">
|
||||
{appState.party.raid && appState.party.raid.group.extra && (
|
||||
<ExtraWeaponsGrid
|
||||
grid={appState.grid.weapons.allWeapons}
|
||||
grid={appState.party.grid.weapons.allWeapons}
|
||||
editable={props.editable}
|
||||
offset={numWeapons}
|
||||
removeWeapon={removeWeapon}
|
||||
|
|
@ -411,30 +424,31 @@ const WeaponGrid = (props: Props) => {
|
|||
}
|
||||
|
||||
const conflictModal = () => {
|
||||
return incoming && conflicts ? (
|
||||
<WeaponConflictModal
|
||||
open={modalOpen}
|
||||
incomingWeapon={incoming}
|
||||
conflictingWeapons={conflicts}
|
||||
desiredPosition={position}
|
||||
resolveConflict={resolveConflict}
|
||||
resetConflict={resetConflict}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
incoming &&
|
||||
conflicts && (
|
||||
<WeaponConflictModal
|
||||
open={modalOpen}
|
||||
incomingWeapon={incoming}
|
||||
conflictingWeapons={conflicts}
|
||||
desiredPosition={position}
|
||||
resolveConflict={resolveConflict}
|
||||
resetConflict={resetConflict}
|
||||
/>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
const incompatibleAlert = () => {
|
||||
return showIncompatibleAlert ? (
|
||||
<Alert
|
||||
open={showIncompatibleAlert}
|
||||
cancelAction={() => setShowIncompatibleAlert(!showIncompatibleAlert)}
|
||||
cancelActionText={t('buttons.confirm')}
|
||||
message={t('alert.incompatible_weapon')}
|
||||
/>
|
||||
) : (
|
||||
''
|
||||
return (
|
||||
showIncompatibleAlert && (
|
||||
<Alert
|
||||
open={showIncompatibleAlert}
|
||||
cancelAction={() => setShowIncompatibleAlert(!showIncompatibleAlert)}
|
||||
cancelActionText={t('buttons.confirm')}
|
||||
message={t('alert.incompatible_weapon')}
|
||||
/>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import HovercardHeader from '~components/HovercardHeader'
|
|||
import Button from '~components/common/Button'
|
||||
|
||||
import ax from '~data/ax'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
|
|
@ -36,7 +37,6 @@ const WeaponHovercard = (props: Props) => {
|
|||
|
||||
const { t } = useTranslation('common')
|
||||
|
||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||
const WeaponKeyNames: KeyNames = {
|
||||
'2': {
|
||||
en: 'Pendulum',
|
||||
|
|
@ -57,9 +57,10 @@ const WeaponHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const tintElement =
|
||||
props.gridWeapon.object.element == 0 && props.gridWeapon.element
|
||||
? Element[props.gridWeapon.element]
|
||||
: Element[props.gridWeapon.object.element]
|
||||
props.gridWeapon.object.element === ElementMap.null &&
|
||||
props.gridWeapon.element
|
||||
? props.gridWeapon.element.slug
|
||||
: props.gridWeapon.object.element.slug
|
||||
|
||||
function goTo() {
|
||||
const urlSafeName = props.gridWeapon.object.name.en.replaceAll(' ', '_')
|
||||
|
|
@ -76,7 +77,7 @@ const WeaponHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const createPrimaryAxSkillString = () => {
|
||||
const primaryAxSkills = ax[props.gridWeapon.object.ax_type - 1]
|
||||
const primaryAxSkills = ax[props.gridWeapon.object.axType - 1]
|
||||
|
||||
if (props.gridWeapon.ax) {
|
||||
const simpleAxSkill = props.gridWeapon.ax[0]
|
||||
|
|
@ -93,7 +94,7 @@ const WeaponHovercard = (props: Props) => {
|
|||
}
|
||||
|
||||
const createSecondaryAxSkillString = () => {
|
||||
const primaryAxSkills = ax[props.gridWeapon.object.ax_type - 1]
|
||||
const primaryAxSkills = ax[props.gridWeapon.object.axType - 1]
|
||||
|
||||
if (props.gridWeapon.ax) {
|
||||
const primarySimpleAxSkill = props.gridWeapon.ax[0]
|
||||
|
|
@ -135,27 +136,24 @@ const WeaponHovercard = (props: Props) => {
|
|||
|
||||
const keysSection = (
|
||||
<section className={styles.weaponKeys}>
|
||||
{WeaponKeyNames[props.gridWeapon.object.series] ? (
|
||||
{WeaponKeyNames[props.gridWeapon.object.series] && (
|
||||
<h5 className={tintElement}>
|
||||
{WeaponKeyNames[props.gridWeapon.object.series][locale]}
|
||||
{locale === 'en' ? 's' : ''}
|
||||
</h5>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
|
||||
{props.gridWeapon.weapon_keys
|
||||
? Array.from(Array(props.gridWeapon.weapon_keys.length)).map((x, i) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.weaponKey}
|
||||
key={props.gridWeapon.weapon_keys![i].id}
|
||||
>
|
||||
<span>{props.gridWeapon.weapon_keys![i].name[locale]}</span>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
: ''}
|
||||
{props.gridWeapon.weaponKeys &&
|
||||
Array.from(Array(props.gridWeapon.weaponKeys?.length)).map((x, i) => {
|
||||
return (
|
||||
<div
|
||||
className={styles.weaponKey}
|
||||
key={props.gridWeapon.weaponKeys![i].id}
|
||||
>
|
||||
<span>{props.gridWeapon.weaponKeys![i].name[locale]}</span>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</section>
|
||||
)
|
||||
|
||||
|
|
@ -181,28 +179,26 @@ const WeaponHovercard = (props: Props) => {
|
|||
</div>
|
||||
|
||||
{props.gridWeapon.ax &&
|
||||
props.gridWeapon.ax[1].modifier &&
|
||||
props.gridWeapon.ax[1].strength ? (
|
||||
<div
|
||||
className={classNames({
|
||||
[styles.secondary]: true,
|
||||
[styles.axSkill]: true,
|
||||
[styles.skill]: true,
|
||||
})}
|
||||
>
|
||||
<div className={styles.axImageWrapper}>
|
||||
<img
|
||||
alt="AX2"
|
||||
src={`/icons/ax/secondary_${
|
||||
props.gridWeapon.ax ? props.gridWeapon.ax[1].modifier : ''
|
||||
}.png`}
|
||||
/>
|
||||
props.gridWeapon.ax[1].modifier &&
|
||||
props.gridWeapon.ax[1].strength && (
|
||||
<div
|
||||
className={classNames({
|
||||
[styles.secondary]: true,
|
||||
[styles.axSkill]: true,
|
||||
[styles.skill]: true,
|
||||
})}
|
||||
>
|
||||
<div className={styles.axImageWrapper}>
|
||||
<img
|
||||
alt="AX2"
|
||||
src={`/icons/ax/secondary_${
|
||||
props.gridWeapon.ax ? props.gridWeapon.ax[1].modifier : ''
|
||||
}.png`}
|
||||
/>
|
||||
</div>
|
||||
<span>{createSecondaryAxSkillString()}</span>
|
||||
</div>
|
||||
<span>{createSecondaryAxSkillString()}</span>
|
||||
</div>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
|
@ -233,8 +229,8 @@ const WeaponHovercard = (props: Props) => {
|
|||
props.gridWeapon.ax[0].strength !== undefined &&
|
||||
axSection}
|
||||
{props.gridWeapon.awakening && awakeningSection}
|
||||
{props.gridWeapon.weapon_keys &&
|
||||
props.gridWeapon.weapon_keys.length > 0 &&
|
||||
{props.gridWeapon.weaponKeys &&
|
||||
props.gridWeapon.weaponKeys.length > 0 &&
|
||||
keysSection}
|
||||
{wikiButton}
|
||||
</HovercardContent>
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ const gauphNames = [
|
|||
|
||||
const emptyWeaponKey: WeaponKey = {
|
||||
id: 'no-key',
|
||||
granblue_id: '-1',
|
||||
granblueId: '-1',
|
||||
series: 0,
|
||||
slot: 0,
|
||||
slug: '',
|
||||
|
|
@ -104,7 +104,7 @@ const WeaponKeySelect = React.forwardRef<HTMLButtonElement, Props>(
|
|||
<SelectItem
|
||||
key={i}
|
||||
value={item.id}
|
||||
data-granblue-id={item.granblue_id}
|
||||
data-granblue-id={item.granblueId}
|
||||
>
|
||||
{item.name.en}
|
||||
</SelectItem>
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import WeaponKeySelect from '~components/weapon/WeaponKeySelect'
|
|||
import Button from '~components/common/Button'
|
||||
|
||||
import { NO_AWAKENING } from '~data/awakening'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import styles from './index.module.scss'
|
||||
|
||||
|
|
@ -63,7 +64,7 @@ const WeaponModal = ({
|
|||
|
||||
// State: Data
|
||||
|
||||
const [element, setElement] = useState<number>(0)
|
||||
const [element, setElement] = useState<GranblueElement>(ElementMap.null)
|
||||
const [awakening, setAwakening] = useState<Awakening>()
|
||||
const [awakeningLevel, setAwakeningLevel] = useState(1)
|
||||
const [primaryAxModifier, setPrimaryAxModifier] = useState(-1)
|
||||
|
|
@ -84,8 +85,8 @@ const WeaponModal = ({
|
|||
useEffect(() => {
|
||||
setElement(gridWeapon.element)
|
||||
|
||||
if (gridWeapon.weapon_keys) {
|
||||
gridWeapon.weapon_keys.forEach((key) => {
|
||||
if (gridWeapon.weaponKeys) {
|
||||
gridWeapon.weaponKeys.forEach((key) => {
|
||||
if (key.slot + 1 === 1) {
|
||||
setWeaponKey1(key)
|
||||
} else if (key.slot + 1 === 2) {
|
||||
|
|
@ -111,8 +112,8 @@ const WeaponModal = ({
|
|||
// Methods: Data retrieval
|
||||
|
||||
// Receive values from ElementToggle
|
||||
function receiveElementValue(elementId: number) {
|
||||
setElement(elementId)
|
||||
function receiveElementValue(element: GranblueElement) {
|
||||
setElement(element)
|
||||
}
|
||||
|
||||
// Receive values from AXSelect
|
||||
|
|
@ -153,7 +154,8 @@ const WeaponModal = ({
|
|||
function prepareObject() {
|
||||
let object: GridWeaponObject = { weapon: {} }
|
||||
|
||||
if (gridWeapon.object.element == 0) object.weapon.element = element
|
||||
if (gridWeapon.object.element === ElementMap.null)
|
||||
object.weapon.element = element.id
|
||||
|
||||
if ([2, 3, 17, 24].includes(gridWeapon.object.series) && weaponKey1) {
|
||||
object.weapon.weapon_key1_id = weaponKey1.id
|
||||
|
|
@ -165,7 +167,7 @@ const WeaponModal = ({
|
|||
if (gridWeapon.object.series == 17 && weaponKey3)
|
||||
object.weapon.weapon_key3_id = weaponKey3.id
|
||||
|
||||
if (gridWeapon.object.ax && gridWeapon.object.ax_type > 0) {
|
||||
if (gridWeapon.object.ax && gridWeapon.object.axType > 0) {
|
||||
object.weapon.ax_modifier1 = primaryAxModifier
|
||||
object.weapon.ax_modifier2 = secondaryAxModifier
|
||||
object.weapon.ax_strength1 = primaryAxValue
|
||||
|
|
@ -215,18 +217,18 @@ const WeaponModal = ({
|
|||
// Reset values
|
||||
setElement(gridWeapon.element)
|
||||
setWeaponKey1(
|
||||
gridWeapon.weapon_keys && gridWeapon.weapon_keys[0]
|
||||
? gridWeapon.weapon_keys[0]
|
||||
gridWeapon.weaponKeys && gridWeapon.weaponKeys[0]
|
||||
? gridWeapon.weaponKeys[0]
|
||||
: undefined
|
||||
)
|
||||
setWeaponKey2(
|
||||
gridWeapon.weapon_keys && gridWeapon.weapon_keys[1]
|
||||
? gridWeapon.weapon_keys[1]
|
||||
gridWeapon.weaponKeys && gridWeapon.weaponKeys[1]
|
||||
? gridWeapon.weaponKeys[1]
|
||||
: undefined
|
||||
)
|
||||
setWeaponKey3(
|
||||
gridWeapon.weapon_keys && gridWeapon.weapon_keys[2]
|
||||
? gridWeapon.weapon_keys[2]
|
||||
gridWeapon.weaponKeys && gridWeapon.weaponKeys[2]
|
||||
? gridWeapon.weaponKeys[2]
|
||||
: undefined
|
||||
)
|
||||
setAwakening(gridWeapon.awakening?.type)
|
||||
|
|
@ -276,13 +278,13 @@ const WeaponModal = ({
|
|||
if (weaponKey && weaponKey.id === 'no-key') weaponKey = undefined
|
||||
|
||||
// If the key is empty and the gridWeapon has no keys, nothing has changed
|
||||
if (weaponKey === undefined && !gridWeapon.weapon_keys) return false
|
||||
if (weaponKey === undefined && !gridWeapon.weaponKeys) return false
|
||||
|
||||
// If the key is not empty but the gridWeapon has no keys, the key has changed
|
||||
if (
|
||||
weaponKey !== undefined &&
|
||||
gridWeapon.weapon_keys &&
|
||||
gridWeapon.weapon_keys.length === 0
|
||||
gridWeapon.weaponKeys &&
|
||||
gridWeapon.weaponKeys.length === 0
|
||||
)
|
||||
return true
|
||||
|
||||
|
|
@ -290,15 +292,15 @@ const WeaponModal = ({
|
|||
// then the key has changed
|
||||
const weaponKeyChanged =
|
||||
weaponKey &&
|
||||
gridWeapon.weapon_keys &&
|
||||
gridWeapon.weapon_keys[index] &&
|
||||
weaponKey.id !== gridWeapon.weapon_keys[index].id
|
||||
gridWeapon.weaponKeys &&
|
||||
gridWeapon.weaponKeys[index] &&
|
||||
weaponKey.id !== gridWeapon.weaponKeys[index].id
|
||||
|
||||
return weaponKeyChanged
|
||||
}
|
||||
|
||||
function weaponKeysChanged() {
|
||||
if (!gridWeapon.weapon_keys) return false
|
||||
if (!gridWeapon.weaponKeys) return false
|
||||
|
||||
const weaponKey1Changed = weaponKeyChanged(0)
|
||||
const weaponKey2Changed = weaponKeyChanged(1)
|
||||
|
|
@ -415,7 +417,7 @@ const WeaponModal = ({
|
|||
<section>
|
||||
<h3>{t('modals.weapon.subtitles.ax_skills')}</h3>
|
||||
<AXSelect
|
||||
axType={gridWeapon.object.ax_type}
|
||||
axType={gridWeapon.object.axType}
|
||||
currentSkills={gridWeapon.ax}
|
||||
onOpenChange={receiveAxOpen}
|
||||
sendValidity={receiveValidity}
|
||||
|
|
@ -432,7 +434,7 @@ const WeaponModal = ({
|
|||
awakening={gridWeapon.awakening?.type}
|
||||
level={gridWeapon.awakening?.level}
|
||||
defaultAwakening={NO_AWAKENING}
|
||||
maxLevel={gridWeapon.object.max_awakening_level}
|
||||
maxLevel={gridWeapon.object.maxAwakeningLevel}
|
||||
onOpenChange={receiveAwakeningOpen}
|
||||
sendValidity={receiveValidity}
|
||||
sendValues={receiveAwakeningValues}
|
||||
|
|
@ -479,12 +481,12 @@ const WeaponModal = ({
|
|||
title={gridWeapon.object.name[locale]}
|
||||
subtitle={t('modals.characters.title')}
|
||||
image={{
|
||||
src: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-square/${gridWeapon.object.granblue_id}.jpg`,
|
||||
src: `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-square/${gridWeapon.object.granblueId}.jpg`,
|
||||
alt: gridWeapon.object.name[locale],
|
||||
}}
|
||||
/>
|
||||
<section className={styles.mods}>
|
||||
{gridWeapon.object.element == 0 && elementSelect}
|
||||
{gridWeapon.object.element === ElementMap.null && elementSelect}
|
||||
{[2, 3, 17, 24].includes(gridWeapon.object.series) && keySelect}
|
||||
{gridWeapon.object.ax && axSelect}
|
||||
{gridWeapon.object.awakenings && awakeningSelect}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ interface Props {
|
|||
onClick: () => void
|
||||
}
|
||||
|
||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||
const Proficiency = [
|
||||
'none',
|
||||
'sword',
|
||||
|
|
@ -36,7 +35,7 @@ const WeaponResult = (props: Props) => {
|
|||
<li className={styles.result} onClick={props.onClick}>
|
||||
<img
|
||||
alt={weapon.name[locale]}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`}
|
||||
src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}.jpg`}
|
||||
/>
|
||||
<div className={styles.info}>
|
||||
<h5>{weapon.name[locale]}</h5>
|
||||
|
|
@ -47,7 +46,7 @@ const WeaponResult = (props: Props) => {
|
|||
special={false}
|
||||
/>
|
||||
<div className={styles.tags}>
|
||||
<WeaponLabelIcon labelType={Element[weapon.element]} />
|
||||
<WeaponLabelIcon labelType={weapon.element.slug} />
|
||||
<WeaponLabelIcon labelType={Proficiency[weapon.proficiency]} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ import { useTranslation } from 'next-i18next'
|
|||
|
||||
import cloneDeep from 'lodash.clonedeep'
|
||||
|
||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||
|
||||
import SearchFilter from '~components/search/SearchFilter'
|
||||
import SearchFilterCheckboxItem from '~components/search/SearchFilterCheckboxItem'
|
||||
|
||||
|
|
|
|||
|
|
@ -24,13 +24,14 @@ import Button from '~components/common/Button'
|
|||
import type { GridWeaponObject, SearchableObject } from '~types'
|
||||
|
||||
import ax from '~data/ax'
|
||||
import { ElementMap } from '~utils/elements'
|
||||
|
||||
import PlusIcon from '~public/icons/Add.svg'
|
||||
import SettingsIcon from '~public/icons/Settings.svg'
|
||||
import styles from './index.module.scss'
|
||||
|
||||
interface Props {
|
||||
gridWeapon: GridWeapon | undefined
|
||||
gridWeapon: GridWeapon | null
|
||||
unitType: 0 | 1
|
||||
position: number
|
||||
editable: boolean
|
||||
|
|
@ -154,7 +155,10 @@ const WeaponUnit = ({
|
|||
appState.party.element = gridWeapon.object.element
|
||||
} else if (!gridWeapon.mainhand && gridWeapon.position !== null) {
|
||||
let weapon = clonedeep(gridWeapon)
|
||||
if (weapon.object.element === 0 && weapon.element < 1)
|
||||
if (
|
||||
weapon.object.element === ElementMap.null &&
|
||||
weapon.element === ElementMap.null
|
||||
)
|
||||
weapon.element = gridWeapon.object.element
|
||||
|
||||
appState.grid.weapons.allWeapons[gridWeapon.position] = weapon
|
||||
|
|
@ -170,10 +174,10 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.ax &&
|
||||
gridWeapon.object.ax_type > 0 &&
|
||||
gridWeapon.object.axType > 0 &&
|
||||
gridWeapon.ax
|
||||
) {
|
||||
const axOptions = ax[gridWeapon.object.ax_type - 1]
|
||||
const axOptions = ax[gridWeapon.object.axType - 1]
|
||||
const weaponAxSkill: SimpleAxSkill = gridWeapon.ax[0]
|
||||
|
||||
let axSkill = axOptions.find((ax) => ax.id === weaponAxSkill.modifier)
|
||||
|
|
@ -196,15 +200,15 @@ const WeaponUnit = ({
|
|||
const weapon = gridWeapon.object!
|
||||
|
||||
if (unitType == 0) {
|
||||
if (gridWeapon.object.element == 0 && gridWeapon.element)
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||
if (gridWeapon.object.element === ElementMap.null && gridWeapon.element)
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${weapon.granblueId}_${gridWeapon.element}.jpg`
|
||||
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.granblueId}.jpg`
|
||||
} else {
|
||||
if (gridWeapon.object.element == 0 && gridWeapon.element)
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}_${gridWeapon.element}.jpg`
|
||||
if (gridWeapon.object.element === ElementMap.null && gridWeapon.element)
|
||||
imgSrc = `${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblueId}_${gridWeapon.element}.jpg`
|
||||
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.granblueId}.jpg`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -242,19 +246,15 @@ const WeaponUnit = ({
|
|||
let altText = ''
|
||||
|
||||
// If there is a grid weapon, it is a Draconic Weapon and it has keys
|
||||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 3 &&
|
||||
gridWeapon.weapon_keys
|
||||
) {
|
||||
if (index === 0 && gridWeapon.weapon_keys[0]) {
|
||||
altText = `${gridWeapon.weapon_keys[0].name[locale]}`
|
||||
filename = `${gridWeapon.weapon_keys[0].slug}.png`
|
||||
} else if (index === 1 && gridWeapon.weapon_keys[1]) {
|
||||
altText = `${gridWeapon.weapon_keys[1].name[locale]}`
|
||||
if (gridWeapon && gridWeapon.object.series === 3 && gridWeapon.weaponKeys) {
|
||||
if (index === 0 && gridWeapon.weaponKeys[0]) {
|
||||
altText = `${gridWeapon.weaponKeys[0].name[locale]}`
|
||||
filename = `${gridWeapon.weaponKeys[0].slug}.png`
|
||||
} else if (index === 1 && gridWeapon.weaponKeys[1]) {
|
||||
altText = `${gridWeapon.weaponKeys[1].name[locale]}`
|
||||
|
||||
const element = gridWeapon.object.element
|
||||
filename = `${gridWeapon.weapon_keys[1].slug}-${element}.png`
|
||||
filename = `${gridWeapon.weaponKeys[1].slug}-${element}.png`
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -273,10 +273,10 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 3 &&
|
||||
gridWeapon.weapon_keys &&
|
||||
gridWeapon.weapon_keys.length > 0
|
||||
gridWeapon.weaponKeys &&
|
||||
gridWeapon.weaponKeys.length > 0
|
||||
) {
|
||||
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||
for (let i = 0; i < gridWeapon.weaponKeys.length; i++) {
|
||||
const image = telumaImage(i)
|
||||
if (image) images.push(image)
|
||||
}
|
||||
|
|
@ -294,25 +294,25 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 17 &&
|
||||
gridWeapon.weapon_keys
|
||||
gridWeapon.weaponKeys
|
||||
) {
|
||||
if (
|
||||
gridWeapon.weapon_keys[index] &&
|
||||
(gridWeapon.weapon_keys[index].slot === 1 ||
|
||||
gridWeapon.weapon_keys[index].slot === 2)
|
||||
gridWeapon.weaponKeys[index] &&
|
||||
(gridWeapon.weaponKeys[index].slot === 1 ||
|
||||
gridWeapon.weaponKeys[index].slot === 2)
|
||||
) {
|
||||
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||
altText = `${gridWeapon.weaponKeys[index].name[locale]}`
|
||||
filename = `${gridWeapon.weaponKeys[index].slug}.png`
|
||||
} else if (
|
||||
gridWeapon.weapon_keys[index] &&
|
||||
gridWeapon.weapon_keys[index].slot === 0
|
||||
gridWeapon.weaponKeys[index] &&
|
||||
gridWeapon.weaponKeys[index].slot === 0
|
||||
) {
|
||||
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||
altText = `${gridWeapon.weaponKeys[index].name[locale]}`
|
||||
|
||||
const weapon = gridWeapon.object.proficiency
|
||||
|
||||
const suffix = `${weapon}`
|
||||
filename = `${gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
||||
filename = `${gridWeapon.weaponKeys[index].slug}-${suffix}.png`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -331,10 +331,10 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 17 &&
|
||||
gridWeapon.weapon_keys &&
|
||||
gridWeapon.weapon_keys.length > 0
|
||||
gridWeapon.weaponKeys &&
|
||||
gridWeapon.weaponKeys.length > 0
|
||||
) {
|
||||
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||
for (let i = 0; i < gridWeapon.weaponKeys.length; i++) {
|
||||
const image = ultimaImage(i)
|
||||
if (image) images.push(image)
|
||||
}
|
||||
|
|
@ -349,22 +349,18 @@ const WeaponUnit = ({
|
|||
let altText = ''
|
||||
|
||||
// If there is a grid weapon, it is a Dark Opus Weapon and it has keys
|
||||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 2 &&
|
||||
gridWeapon.weapon_keys
|
||||
) {
|
||||
if (gridWeapon && gridWeapon.object.series === 2 && gridWeapon.weaponKeys) {
|
||||
if (
|
||||
gridWeapon.weapon_keys[index] &&
|
||||
gridWeapon.weapon_keys[index].slot === 0
|
||||
gridWeapon.weaponKeys[index] &&
|
||||
gridWeapon.weaponKeys[index].slot === 0
|
||||
) {
|
||||
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||
altText = `${gridWeapon.weaponKeys[index].name[locale]}`
|
||||
filename = `${gridWeapon.weaponKeys[index].slug}.png`
|
||||
} else if (
|
||||
gridWeapon.weapon_keys[index] &&
|
||||
gridWeapon.weapon_keys[index].slot === 1
|
||||
gridWeapon.weaponKeys[index] &&
|
||||
gridWeapon.weaponKeys[index].slot === 1
|
||||
) {
|
||||
altText = `${gridWeapon.weapon_keys[index].name[locale]}`
|
||||
altText = `${gridWeapon.weaponKeys[index].name[locale]}`
|
||||
|
||||
const element = gridWeapon.object.element
|
||||
const mod = gridWeapon.object.name.en.includes('Repudiation')
|
||||
|
|
@ -372,7 +368,7 @@ const WeaponUnit = ({
|
|||
: 'magna'
|
||||
|
||||
const suffix = `${mod}-${element}`
|
||||
const weaponKey = gridWeapon.weapon_keys[index]
|
||||
const weaponKey = gridWeapon.weaponKeys[index]
|
||||
|
||||
if (
|
||||
[
|
||||
|
|
@ -384,9 +380,9 @@ const WeaponUnit = ({
|
|||
'chain-glorification',
|
||||
].includes(weaponKey.slug)
|
||||
) {
|
||||
filename = `${gridWeapon.weapon_keys[index].slug}-${suffix}.png`
|
||||
filename = `${gridWeapon.weaponKeys[index].slug}-${suffix}.png`
|
||||
} else {
|
||||
filename = `${gridWeapon.weapon_keys[index].slug}.png`
|
||||
filename = `${gridWeapon.weaponKeys[index].slug}.png`
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -406,10 +402,10 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.series === 2 &&
|
||||
gridWeapon.weapon_keys &&
|
||||
gridWeapon.weapon_keys.length > 0
|
||||
gridWeapon.weaponKeys &&
|
||||
gridWeapon.weaponKeys.length > 0
|
||||
) {
|
||||
for (let i = 0; i < gridWeapon.weapon_keys.length; i++) {
|
||||
for (let i = 0; i < gridWeapon.weaponKeys.length; i++) {
|
||||
const image = opusImage(i)
|
||||
if (image) images.push(image)
|
||||
}
|
||||
|
|
@ -424,7 +420,7 @@ const WeaponUnit = ({
|
|||
if (
|
||||
gridWeapon &&
|
||||
gridWeapon.object.ax &&
|
||||
gridWeapon.object.ax_type > 0 &&
|
||||
gridWeapon.object.axType > 0 &&
|
||||
gridWeapon.ax &&
|
||||
axSkill
|
||||
) {
|
||||
|
|
@ -592,7 +588,7 @@ const WeaponUnit = ({
|
|||
type="weapon"
|
||||
ulb={gridWeapon.object.uncap.ulb || false}
|
||||
flb={gridWeapon.object.uncap.flb || false}
|
||||
uncapLevel={gridWeapon.uncap_level}
|
||||
uncapLevel={gridWeapon.uncapLevel}
|
||||
position={gridWeapon.position}
|
||||
updateUncap={passUncapData}
|
||||
special={false}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ export const NO_AWAKENING: Awakening = {
|
|||
id: '0',
|
||||
name: {
|
||||
en: 'No awakening',
|
||||
jp: '覚醒なし',
|
||||
ja: '覚醒なし',
|
||||
},
|
||||
slug: 'no-awakening',
|
||||
order: 0,
|
||||
|
|
|
|||
154
data/ax.tsx
154
data/ax.tsx
|
|
@ -6,7 +6,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '1589',
|
||||
granblueId: '1589',
|
||||
slug: 'atk',
|
||||
minValue: 1,
|
||||
maxValue: 3.5,
|
||||
|
|
@ -19,7 +19,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 4,
|
||||
|
|
@ -32,7 +32,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'DA確率',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '1596',
|
||||
granblueId: '1596',
|
||||
slug: 'da',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -45,7 +45,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'TA確率',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '1597',
|
||||
granblueId: '1597',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -58,7 +58,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'アビ上限',
|
||||
},
|
||||
id: 7,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'skill-cap',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -73,7 +73,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '1590',
|
||||
granblueId: '1590',
|
||||
slug: 'def',
|
||||
minValue: 1,
|
||||
maxValue: 8,
|
||||
|
|
@ -86,7 +86,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'hp',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -99,7 +99,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -112,7 +112,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -125,7 +125,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 11,
|
||||
granblue_id: '1601',
|
||||
granblueId: '1601',
|
||||
slug: 'enmity',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -139,7 +139,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'hp',
|
||||
minValue: 1,
|
||||
maxValue: 11,
|
||||
|
|
@ -152,7 +152,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '1590',
|
||||
granblueId: '1590',
|
||||
slug: 'def',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -165,7 +165,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -178,7 +178,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -191,7 +191,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -205,7 +205,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 8.5,
|
||||
|
|
@ -218,7 +218,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '1589',
|
||||
granblueId: '1589',
|
||||
slug: 'atk',
|
||||
minValue: 1,
|
||||
maxValue: 1.5,
|
||||
|
|
@ -231,7 +231,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '全属性攻撃力',
|
||||
},
|
||||
id: 13,
|
||||
granblue_id: '1594',
|
||||
granblueId: '1594',
|
||||
slug: 'ele-atk',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -244,7 +244,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義上限',
|
||||
},
|
||||
id: 8,
|
||||
granblue_id: '1599',
|
||||
granblueId: '1599',
|
||||
slug: 'ca-cap',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -257,7 +257,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -271,7 +271,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '連撃率',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '1592',
|
||||
granblueId: '1592',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 4,
|
||||
|
|
@ -284,7 +284,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 4,
|
||||
|
|
@ -297,7 +297,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '全属性攻撃力',
|
||||
},
|
||||
id: 13,
|
||||
granblue_id: '1594',
|
||||
granblueId: '1594',
|
||||
slug: 'ele-atk',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -310,7 +310,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'DA確率',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '1596',
|
||||
granblueId: '1596',
|
||||
slug: 'da',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -323,7 +323,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'TA確率',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '1597',
|
||||
granblueId: '1597',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -340,7 +340,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '1589',
|
||||
granblueId: '1589',
|
||||
slug: 'atk',
|
||||
minValue: 1,
|
||||
maxValue: 3.5,
|
||||
|
|
@ -353,7 +353,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 8.5,
|
||||
|
|
@ -366,7 +366,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '連撃確率',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '1592',
|
||||
granblueId: '1592',
|
||||
slug: 'ta',
|
||||
minValue: 1.5,
|
||||
maxValue: 4,
|
||||
|
|
@ -379,7 +379,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '通常ダメ上限',
|
||||
},
|
||||
id: 14,
|
||||
granblue_id: '1722',
|
||||
granblueId: '1722',
|
||||
slug: 'na-dmg',
|
||||
minValue: 0.5,
|
||||
maxValue: 1.5,
|
||||
|
|
@ -392,7 +392,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'アビ与ダメ上昇',
|
||||
},
|
||||
id: 15,
|
||||
granblue_id: '1719',
|
||||
granblueId: '1719',
|
||||
slug: 'skill-supp',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -406,7 +406,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '1590',
|
||||
granblueId: '1590',
|
||||
slug: 'def',
|
||||
minValue: 1,
|
||||
maxValue: 8,
|
||||
|
|
@ -419,7 +419,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '属性ダメ軽減',
|
||||
},
|
||||
id: 17,
|
||||
granblue_id: '1721',
|
||||
granblueId: '1721',
|
||||
slug: 'ele-def',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -432,7 +432,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -445,7 +445,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -458,7 +458,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 11,
|
||||
granblue_id: '1601',
|
||||
granblueId: '1601',
|
||||
slug: 'enmity',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -472,7 +472,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'hp',
|
||||
minValue: 1,
|
||||
maxValue: 11,
|
||||
|
|
@ -485,7 +485,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '属性ダメ軽減',
|
||||
},
|
||||
id: 17,
|
||||
granblue_id: '1721',
|
||||
granblueId: '1721',
|
||||
slug: 'ele-def',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -498,7 +498,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -511,7 +511,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -524,7 +524,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -538,7 +538,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 8.5,
|
||||
|
|
@ -551,7 +551,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '連撃率',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '1592',
|
||||
granblueId: '1592',
|
||||
slug: 'ta',
|
||||
minValue: 1.5,
|
||||
maxValue: 4,
|
||||
|
|
@ -564,7 +564,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'アビ与ダメ上昇',
|
||||
},
|
||||
id: 15,
|
||||
granblue_id: '1719',
|
||||
granblueId: '1719',
|
||||
slug: 'skill-supp',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -576,7 +576,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義与ダメ上昇',
|
||||
},
|
||||
id: 16,
|
||||
granblue_id: '1720',
|
||||
granblueId: '1720',
|
||||
slug: 'ca-supp',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -588,7 +588,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -602,7 +602,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '連撃率',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '1592',
|
||||
granblueId: '1592',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 4,
|
||||
|
|
@ -615,7 +615,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義与ダメ上昇',
|
||||
},
|
||||
id: 16,
|
||||
granblue_id: '1720',
|
||||
granblueId: '1720',
|
||||
slug: 'ca-supp',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -627,7 +627,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '通常ダメ上限',
|
||||
},
|
||||
id: 14,
|
||||
granblue_id: '1722',
|
||||
granblueId: '1722',
|
||||
slug: 'na-cap',
|
||||
minValue: 0.5,
|
||||
maxValue: 1.5,
|
||||
|
|
@ -640,7 +640,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -652,7 +652,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 11,
|
||||
granblue_id: '1601',
|
||||
granblueId: '1601',
|
||||
slug: 'enmity',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -668,7 +668,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '1589',
|
||||
granblueId: '1589',
|
||||
slug: 'atk',
|
||||
minValue: 1,
|
||||
maxValue: 3.5,
|
||||
|
|
@ -681,7 +681,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 4,
|
||||
|
|
@ -694,7 +694,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'DA確率',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '1596',
|
||||
granblueId: '1596',
|
||||
slug: 'da',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -707,7 +707,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'TA確率',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '1597',
|
||||
granblueId: '1597',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -720,7 +720,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'アビ上限',
|
||||
},
|
||||
id: 7,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'skill-cap',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -735,7 +735,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '1590',
|
||||
granblueId: '1590',
|
||||
slug: 'def',
|
||||
minValue: 1,
|
||||
maxValue: 8,
|
||||
|
|
@ -748,7 +748,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'hp',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -761,7 +761,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -774,7 +774,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -787,7 +787,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 11,
|
||||
granblue_id: '1601',
|
||||
granblueId: '1601',
|
||||
slug: 'enmity',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -801,7 +801,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '1588',
|
||||
granblueId: '1588',
|
||||
slug: 'hp',
|
||||
minValue: 1,
|
||||
maxValue: 11,
|
||||
|
|
@ -814,7 +814,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '1590',
|
||||
granblueId: '1590',
|
||||
slug: 'def',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -827,7 +827,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '1593',
|
||||
granblueId: '1593',
|
||||
slug: 'debuff',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -840,7 +840,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '1595',
|
||||
granblueId: '1595',
|
||||
slug: 'healing',
|
||||
minValue: 2,
|
||||
maxValue: 5,
|
||||
|
|
@ -853,7 +853,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -867,7 +867,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 8.5,
|
||||
|
|
@ -880,7 +880,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 0,
|
||||
granblue_id: '1589',
|
||||
granblueId: '1589',
|
||||
slug: 'atk',
|
||||
minValue: 1,
|
||||
maxValue: 1.5,
|
||||
|
|
@ -893,7 +893,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '全属性攻撃力',
|
||||
},
|
||||
id: 13,
|
||||
granblue_id: '1594',
|
||||
granblueId: '1594',
|
||||
slug: 'ele-atk',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -906,7 +906,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義上限',
|
||||
},
|
||||
id: 8,
|
||||
granblue_id: '1599',
|
||||
granblueId: '1599',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -919,7 +919,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '1600',
|
||||
granblueId: '1600',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 3,
|
||||
|
|
@ -933,7 +933,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '連撃率',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '1592',
|
||||
granblueId: '1592',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 4,
|
||||
|
|
@ -946,7 +946,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '奥義ダメ',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '1591',
|
||||
granblueId: '1591',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 2,
|
||||
maxValue: 4,
|
||||
|
|
@ -959,7 +959,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '全属性攻撃力',
|
||||
},
|
||||
id: 13,
|
||||
granblue_id: '1594',
|
||||
granblueId: '1594',
|
||||
slug: 'ele-atk',
|
||||
minValue: 1,
|
||||
maxValue: 5,
|
||||
|
|
@ -972,7 +972,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'DA確率',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '1596',
|
||||
granblueId: '1596',
|
||||
slug: 'da',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -985,7 +985,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'TA確率',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '1597',
|
||||
granblueId: '1597',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 2,
|
||||
|
|
@ -1000,7 +1000,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: 'EXP UP',
|
||||
},
|
||||
id: 18,
|
||||
granblue_id: '1837',
|
||||
granblueId: '1837',
|
||||
slug: 'exp',
|
||||
minValue: 5,
|
||||
maxValue: 10,
|
||||
|
|
@ -1013,7 +1013,7 @@ const ax: ItemSkill[][] = [
|
|||
ja: '獲得ルピ',
|
||||
},
|
||||
id: 19,
|
||||
granblue_id: '1838',
|
||||
granblueId: '1838',
|
||||
slug: 'rupie',
|
||||
minValue: 10,
|
||||
maxValue: 20,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const overMasteryPrimary: ItemSkill[] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'atk',
|
||||
minValue: 300,
|
||||
maxValue: 3000,
|
||||
|
|
@ -19,7 +19,7 @@ const overMasteryPrimary: ItemSkill[] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'hp',
|
||||
minValue: 150,
|
||||
maxValue: 1500,
|
||||
|
|
@ -36,7 +36,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: '弱体成功率',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'debuff-success',
|
||||
minValue: 6,
|
||||
maxValue: 15,
|
||||
|
|
@ -50,7 +50,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: 'アビダメ上限',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'skill-cap',
|
||||
minValue: 6,
|
||||
maxValue: 15,
|
||||
|
|
@ -64,7 +64,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: '奥義ダメージ',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'ca-dmg',
|
||||
minValue: 10,
|
||||
maxValue: 30,
|
||||
|
|
@ -78,7 +78,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: '奥義ダメージ上限',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'ca-cap',
|
||||
minValue: 6,
|
||||
maxValue: 15,
|
||||
|
|
@ -92,7 +92,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 7,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'stamina',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
|
|
@ -106,7 +106,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 8,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'enmity',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
|
|
@ -120,7 +120,7 @@ const overMasterySecondary: ItemSkill[] = [
|
|||
ja: 'クリティカル確率',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'crit',
|
||||
minValue: 10,
|
||||
maxValue: 30,
|
||||
|
|
@ -137,7 +137,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: 'ダブルアタック確率',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'da',
|
||||
minValue: 6,
|
||||
maxValue: 15,
|
||||
|
|
@ -151,7 +151,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: 'トリプルアタック確率',
|
||||
},
|
||||
id: 11,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'ta',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
|
|
@ -165,7 +165,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: '防御',
|
||||
},
|
||||
id: 12,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'def',
|
||||
minValue: 6,
|
||||
maxValue: 20,
|
||||
|
|
@ -179,7 +179,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: '回復性能',
|
||||
},
|
||||
id: 13,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'heal',
|
||||
minValue: 3,
|
||||
maxValue: 30,
|
||||
|
|
@ -193,7 +193,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: '弱体耐性',
|
||||
},
|
||||
id: 14,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'debuff-resist',
|
||||
minValue: 6,
|
||||
maxValue: 15,
|
||||
|
|
@ -207,7 +207,7 @@ const overMasteryTertiary: ItemSkill[] = [
|
|||
ja: '回避',
|
||||
},
|
||||
id: 15,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'dodge',
|
||||
minValue: 1,
|
||||
maxValue: 10,
|
||||
|
|
@ -230,7 +230,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: 'ダブルアタック確率',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'da',
|
||||
minValue: 10,
|
||||
maxValue: 17,
|
||||
|
|
@ -243,7 +243,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: 'トリプルアタック確率',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'ta',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -256,7 +256,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: '{属性}攻撃',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'element-atk',
|
||||
minValue: 15,
|
||||
maxValue: 22,
|
||||
|
|
@ -269,7 +269,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: '{属性}軽減',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'element-resist',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -282,7 +282,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: '渾身',
|
||||
},
|
||||
id: 5,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'stamina',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -295,7 +295,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: '背水',
|
||||
},
|
||||
id: 6,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'enmity',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -308,7 +308,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: '与ダメ上昇',
|
||||
},
|
||||
id: 7,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'supplemental',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -321,7 +321,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: 'クリティカル',
|
||||
},
|
||||
id: 8,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'crit',
|
||||
minValue: 18,
|
||||
maxValue: 35,
|
||||
|
|
@ -334,7 +334,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: 'カウンター(回避)',
|
||||
},
|
||||
id: 9,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'counter-dodge',
|
||||
minValue: 5,
|
||||
maxValue: 12,
|
||||
|
|
@ -347,7 +347,7 @@ export const aetherialMastery: ItemSkill[] = [
|
|||
ja: 'カウンター(被ダメ)',
|
||||
},
|
||||
id: 10,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'counter-dmg',
|
||||
minValue: 10,
|
||||
maxValue: 17,
|
||||
|
|
@ -363,7 +363,7 @@ export const permanentMastery: ItemSkill[] = [
|
|||
ja: 'LB強化回数上限',
|
||||
},
|
||||
id: 1,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'star-cap',
|
||||
minValue: 10,
|
||||
maxValue: 10,
|
||||
|
|
@ -376,7 +376,7 @@ export const permanentMastery: ItemSkill[] = [
|
|||
ja: '攻撃',
|
||||
},
|
||||
id: 2,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'atk',
|
||||
minValue: 10,
|
||||
maxValue: 10,
|
||||
|
|
@ -389,7 +389,7 @@ export const permanentMastery: ItemSkill[] = [
|
|||
ja: 'HP',
|
||||
},
|
||||
id: 3,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'hp',
|
||||
minValue: 10,
|
||||
maxValue: 10,
|
||||
|
|
@ -402,7 +402,7 @@ export const permanentMastery: ItemSkill[] = [
|
|||
ja: 'ダメージ上限',
|
||||
},
|
||||
id: 4,
|
||||
granblue_id: '',
|
||||
granblueId: '',
|
||||
slug: 'dmg-cap',
|
||||
minValue: 5,
|
||||
maxValue: 5,
|
||||
|
|
|
|||
14
package-lock.json
generated
14
package-lock.json
generated
|
|
@ -23,6 +23,7 @@
|
|||
"@tiptap/extension-highlight": "^2.0.3",
|
||||
"@tiptap/extension-link": "^2.0.3",
|
||||
"@tiptap/extension-mention": "^2.0.3",
|
||||
"@tiptap/extension-placeholder": "^2.0.3",
|
||||
"@tiptap/extension-typography": "^2.0.3",
|
||||
"@tiptap/extension-youtube": "^2.0.3",
|
||||
"@tiptap/pm": "^2.0.3",
|
||||
|
|
@ -7348,6 +7349,19 @@
|
|||
"@tiptap/core": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tiptap/extension-placeholder": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-placeholder/-/extension-placeholder-2.0.3.tgz",
|
||||
"integrity": "sha512-Z42jo0termRAf0S0L8oxrts94IWX5waU4isS2CUw8xCUigYyCFslkhQXkWATO1qRbjNFLKN2C9qvCgGf4UeBrw==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/ueberdosis"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tiptap/core": "^2.0.0",
|
||||
"@tiptap/pm": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@tiptap/extension-strike": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-2.0.3.tgz",
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
"@tiptap/extension-highlight": "^2.0.3",
|
||||
"@tiptap/extension-link": "^2.0.3",
|
||||
"@tiptap/extension-mention": "^2.0.3",
|
||||
"@tiptap/extension-placeholder": "^2.0.3",
|
||||
"@tiptap/extension-typography": "^2.0.3",
|
||||
"@tiptap/extension-youtube": "^2.0.3",
|
||||
"@tiptap/pm": "^2.0.3",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import FilterBar from '~components/filters/FilterBar'
|
|||
import ProfileHead from '~components/head/ProfileHead'
|
||||
import UserInfo from '~components/filters/UserInfo'
|
||||
|
||||
import * as RaidGroupTransformer from '~transformers/RaidGroupTransformer'
|
||||
|
||||
import type { AxiosError } from 'axios'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import type {
|
||||
|
|
@ -175,7 +177,11 @@ const ProfileRoute: React.FC<Props> = ({
|
|||
|
||||
function replaceResults(count: number, list: Party[]) {
|
||||
if (count > 0) {
|
||||
setParties(list.sort((a, b) => (a.created_at > b.created_at ? -1 : 1)))
|
||||
setParties(
|
||||
list.sort((a, b) =>
|
||||
a.timestamps.createdAt > b.timestamps.createdAt ? -1 : 1
|
||||
)
|
||||
)
|
||||
} else {
|
||||
setParties([])
|
||||
}
|
||||
|
|
@ -252,13 +258,13 @@ const ProfileRoute: React.FC<Props> = ({
|
|||
id={party.id}
|
||||
shortcode={party.shortcode}
|
||||
name={party.name}
|
||||
createdAt={new Date(party.created_at)}
|
||||
createdAt={new Date(party.timestamps.createdAt)}
|
||||
raid={party.raid}
|
||||
grid={party.weapons}
|
||||
weapons={party.grid.weapons}
|
||||
user={party.user}
|
||||
favorited={party.favorited}
|
||||
fullAuto={party.full_auto}
|
||||
autoGuard={party.auto_guard}
|
||||
favorited={party.social.favorited}
|
||||
fullAuto={party.details.fullAuto}
|
||||
autoGuard={party.details.autoGuard}
|
||||
key={`party-${i}`}
|
||||
onClick={goTo}
|
||||
/>
|
||||
|
|
@ -331,9 +337,11 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
|
|||
|
||||
try {
|
||||
// Fetch and organize raids
|
||||
let raidGroups: RaidGroup[] = await api
|
||||
const raidGroups: RaidGroup[] = await api
|
||||
.raidGroups()
|
||||
.then((response) => response.data)
|
||||
.then((response) =>
|
||||
response.data.map((group: any) => RaidGroupTransformer.toObject(group))
|
||||
)
|
||||
|
||||
// Create filter object
|
||||
const filters: FilterObject = extractFilters(query, raidGroups)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { appWithTranslation } from 'next-i18next'
|
||||
import Head from 'next/head'
|
||||
import Link from 'next/link'
|
||||
import { useTranslation } from 'next-i18next'
|
||||
import { get } from 'local-storage'
|
||||
|
|
@ -131,20 +132,28 @@ function MyApp({ Component, pageProps }: AppProps) {
|
|||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<ToastProvider swipeDirection="right">
|
||||
<TooltipProvider>
|
||||
<Layout>
|
||||
{!appState.version ? (
|
||||
serverUnavailable()
|
||||
) : (
|
||||
<Component {...pageProps} />
|
||||
)}
|
||||
</Layout>
|
||||
<Viewport className="ToastViewport" />
|
||||
</TooltipProvider>
|
||||
</ToastProvider>
|
||||
</ThemeProvider>
|
||||
<>
|
||||
<Head>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="viewport-fit=cover, width=device-width, initial-scale=1.0"
|
||||
/>
|
||||
</Head>
|
||||
<ThemeProvider>
|
||||
<ToastProvider swipeDirection="right">
|
||||
<TooltipProvider>
|
||||
<Layout>
|
||||
{!appState.version ? (
|
||||
serverUnavailable()
|
||||
) : (
|
||||
<Component {...pageProps} />
|
||||
)}
|
||||
</Layout>
|
||||
<Viewport className="ToastViewport" />
|
||||
</TooltipProvider>
|
||||
</ToastProvider>
|
||||
</ThemeProvider>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,13 @@ import elementEmoji from '~utils/elementEmoji'
|
|||
import fetchLatestVersion from '~utils/fetchLatestVersion'
|
||||
import { setHeaders } from '~utils/userToken'
|
||||
import { appState } from '~utils/appState'
|
||||
import { groupWeaponKeys } from '~utils/groupWeaponKeys'
|
||||
import { GroupedWeaponKeys, groupWeaponKeys } from '~utils/groupWeaponKeys'
|
||||
|
||||
import * as JobTransformer from '~transformers/JobTransformer'
|
||||
import * as JobSkillTransformer from '~transformers/JobSkillTransformer'
|
||||
import * as PartyTransformer from '~transformers/PartyTransformer'
|
||||
import * as RaidGroupTransformer from '~transformers/RaidGroupTransformer'
|
||||
import * as WeaponKeyTransformer from '~transformers/WeaponKeyTransformer'
|
||||
|
||||
import { GridType } from '~utils/enums'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
|
|
@ -90,8 +96,8 @@ const PartyRoute: React.FC<Props> = ({
|
|||
break
|
||||
}
|
||||
|
||||
if (router.asPath !== '/new' && router.asPath !== '/')
|
||||
router.replace(path, undefined, { shallow: true })
|
||||
// if (router.asPath !== '/new' && router.asPath !== '/')
|
||||
// router.replace(path, undefined, { shallow: true })
|
||||
}
|
||||
|
||||
// Set the initial data from props
|
||||
|
|
@ -126,7 +132,7 @@ const PartyRoute: React.FC<Props> = ({
|
|||
<React.Fragment key={router.asPath}>
|
||||
{pageHead()}
|
||||
<Party
|
||||
team={context.party}
|
||||
party={context.party}
|
||||
selectedTab={selectedTab}
|
||||
raidGroups={context.raidGroups}
|
||||
handleTabChanged={handleTabChange}
|
||||
|
|
@ -156,34 +162,43 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
|
|||
|
||||
try {
|
||||
// Fetch and organize raids
|
||||
let raidGroups: RaidGroup[] = await api
|
||||
const raidGroups: RaidGroup[] = await api
|
||||
.raidGroups()
|
||||
.then((response) => response.data)
|
||||
.then((response) => response.data.map((group: any) => RaidGroupTransformer.toObject(group)))
|
||||
|
||||
// Fetch jobs and job skills
|
||||
let jobs = await api.endpoints.jobs
|
||||
const jobs: Job[] = await api.endpoints.jobs
|
||||
.getAll()
|
||||
.then((response) => response.data)
|
||||
.then((response) =>
|
||||
response.data.map((job: any) => JobTransformer.toObject(job))
|
||||
)
|
||||
|
||||
let jobSkills = await api.allJobSkills()
|
||||
.then((response) => response.data)
|
||||
const jobSkills: JobSkill[] = await api
|
||||
.allJobSkills()
|
||||
.then((response) =>
|
||||
response.data.map((skill: any) => JobSkillTransformer.toObject(skill))
|
||||
)
|
||||
|
||||
// Fetch and organize weapon keys
|
||||
let weaponKeys = await api.endpoints.weapon_keys
|
||||
const weaponKeys: GroupedWeaponKeys = await api.endpoints.weapon_keys
|
||||
.getAll()
|
||||
.then((response) => groupWeaponKeys(response.data))
|
||||
.then((response) =>
|
||||
response.data.map((key: any) => WeaponKeyTransformer.toObject(key))
|
||||
)
|
||||
.then((keys) => groupWeaponKeys(keys))
|
||||
|
||||
|
||||
// Fetch the party
|
||||
let party: Party | undefined = undefined
|
||||
if (query.party) {
|
||||
let response = await api.endpoints.parties.getOne({
|
||||
id: query.party,
|
||||
})
|
||||
party = response.data.party
|
||||
} else {
|
||||
console.error('No party code')
|
||||
}
|
||||
if (!query.party) throw new Error('No party code')
|
||||
|
||||
const party: Party | undefined = await api.endpoints.parties.getOne({
|
||||
id: query.party,
|
||||
}).then((response) =>
|
||||
PartyTransformer.toObject(response.data.party)
|
||||
)
|
||||
|
||||
console.log(party)
|
||||
|
||||
// Consolidate data into context object
|
||||
const context: PageContextObj = {
|
||||
party: party,
|
||||
|
|
@ -206,6 +221,8 @@ export const getServerSideProps = async ({ req, res, locale, query }: { req: Nex
|
|||
},
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
// Extract the underlying Axios error
|
||||
const axiosError = error as AxiosError
|
||||
const response = axiosError.response
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ const SavedRoute: React.FC<Props> = ({
|
|||
const index = parties.findIndex((p) => p.id === teamId)
|
||||
const party = parties[index]
|
||||
|
||||
party.favorited = true
|
||||
party.social.favorited = true
|
||||
|
||||
let clonedParties = clonedeep(parties)
|
||||
clonedParties[index] = party
|
||||
|
|
@ -254,7 +254,7 @@ const SavedRoute: React.FC<Props> = ({
|
|||
const index = parties.findIndex((p) => p.id === teamId)
|
||||
const party = parties[index]
|
||||
|
||||
party.favorited = false
|
||||
party.social.favorited = false
|
||||
|
||||
let clonedParties = clonedeep(parties)
|
||||
clonedParties.splice(index, 1)
|
||||
|
|
@ -291,13 +291,13 @@ const SavedRoute: React.FC<Props> = ({
|
|||
id={party.id}
|
||||
shortcode={party.shortcode}
|
||||
name={party.name}
|
||||
createdAt={new Date(party.created_at)}
|
||||
createdAt={new Date(party.timestamps.createdAt)}
|
||||
raid={party.raid}
|
||||
grid={party.weapons}
|
||||
weapons={party.grid.weapons}
|
||||
user={party.user}
|
||||
favorited={party.favorited}
|
||||
fullAuto={party.full_auto}
|
||||
autoGuard={party.auto_guard}
|
||||
favorited={party.social.favorited}
|
||||
fullAuto={party.details.fullAuto}
|
||||
autoGuard={party.details.autoGuard}
|
||||
key={`party-${i}`}
|
||||
onClick={goTo}
|
||||
onSave={toggleFavorite}
|
||||
|
|
|
|||
|
|
@ -189,7 +189,11 @@ const TeamsRoute: React.FC<Props> = ({
|
|||
|
||||
function replaceResults(count: number, list: Party[]) {
|
||||
if (count > 0) {
|
||||
setParties(list.sort((a, b) => (a.created_at > b.created_at ? -1 : 1)))
|
||||
setParties(
|
||||
list.sort((a, b) =>
|
||||
a.timestamps.createdAt > b.timestamps.createdAt ? -1 : 1
|
||||
)
|
||||
)
|
||||
} else {
|
||||
setParties([])
|
||||
}
|
||||
|
|
@ -249,7 +253,7 @@ const TeamsRoute: React.FC<Props> = ({
|
|||
const index = parties.findIndex((p) => p.id === teamId)
|
||||
const party = parties[index]
|
||||
|
||||
party.favorited = true
|
||||
party.social.favorited = true
|
||||
|
||||
let clonedParties = clonedeep(parties)
|
||||
clonedParties[index] = party
|
||||
|
|
@ -265,7 +269,7 @@ const TeamsRoute: React.FC<Props> = ({
|
|||
const index = parties.findIndex((p) => p.id === teamId)
|
||||
const party = parties[index]
|
||||
|
||||
party.favorited = false
|
||||
party.social.favorited = false
|
||||
|
||||
let clonedParties = clonedeep(parties)
|
||||
clonedParties[index] = party
|
||||
|
|
@ -302,13 +306,13 @@ const TeamsRoute: React.FC<Props> = ({
|
|||
id={party.id}
|
||||
shortcode={party.shortcode}
|
||||
name={party.name}
|
||||
createdAt={new Date(party.created_at)}
|
||||
createdAt={new Date(party.timestamps.createdAt)}
|
||||
raid={party.raid}
|
||||
grid={party.weapons}
|
||||
weapons={party.grid.weapons}
|
||||
user={party.user}
|
||||
favorited={party.favorited}
|
||||
fullAuto={party.full_auto}
|
||||
autoGuard={party.auto_guard}
|
||||
favorited={party.social.favorited}
|
||||
fullAuto={party.details.fullAuto}
|
||||
autoGuard={party.details.autoGuard}
|
||||
key={`party-${i}`}
|
||||
onClick={goTo}
|
||||
onSave={toggleFavorite}
|
||||
|
|
|
|||
|
|
@ -557,6 +557,19 @@
|
|||
"tokens": {
|
||||
"remix": "Remixed"
|
||||
},
|
||||
"toolbar": {
|
||||
"tooltips": {
|
||||
"bold": "Bold",
|
||||
"italic": "Italic",
|
||||
"strike": "Strikethrough",
|
||||
"highlight": "Highlight",
|
||||
"link": "Add a link",
|
||||
"youtube": "Add a Youtube video",
|
||||
"heading": "Heading {{level}}",
|
||||
"bulletList": "Bullet list",
|
||||
"orderedList": "Numbered list"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
"copy_url": "Copy the URL to this team",
|
||||
"new": "Create a new team",
|
||||
|
|
|
|||
|
|
@ -555,6 +555,19 @@
|
|||
"tokens": {
|
||||
"remix": "リミックスされた"
|
||||
},
|
||||
"toolbar": {
|
||||
"tooltips": {
|
||||
"bold": "太字",
|
||||
"italic": "斜体",
|
||||
"strike": "取り消し線",
|
||||
"highlight": "ハイライト",
|
||||
"link": "リンクを挿入",
|
||||
"youtube": "Youtube動画を埋め込む",
|
||||
"heading": "見出し {{level}}",
|
||||
"bulletList": "箇条書き",
|
||||
"orderedList": "番号リスト"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
"copy_url": "この編成のURLをコピーする",
|
||||
"new": "新しい編成を作成する",
|
||||
|
|
|
|||
|
|
@ -159,6 +159,14 @@
|
|||
--grid-border-color: #{$grid--border--color--light};
|
||||
|
||||
// Light - Element theming
|
||||
--null-bg: #{$null--bg--light};
|
||||
--null-bg-hover: #{$null--bg--hover--light};
|
||||
--null-text: #{$null--text--light};
|
||||
--null-raid-text: #{$null--text--raid--light};
|
||||
--null-text-hover: #{$null--text--hover--light};
|
||||
--null-shadow: #{$null--shadow--light};
|
||||
--null-shadow-hover: #{$null--shadow--light--hover};
|
||||
|
||||
--wind-bg: #{$wind--bg--light};
|
||||
--wind-bg-hover: #{$wind--bg--hover--light};
|
||||
--wind-text: #{$wind--text--light};
|
||||
|
|
@ -373,6 +381,14 @@
|
|||
--grid-border-color: #{$grid--border--color--dark};
|
||||
|
||||
// Dark - Element theming
|
||||
--null-bg: #{$null--bg--dark};
|
||||
--null-bg-hover: #{$null--bg--hover--dark};
|
||||
--null-text: #{$null--text--dark};
|
||||
--null-raid-text: #{$null--text--raid--dark};
|
||||
--null-text-hover: #{$null--text--hover--dark};
|
||||
--null-shadow: #{$null--shadow--dark};
|
||||
--null-shadow-hover: #{$null--shadow--dark--hover};
|
||||
|
||||
--wind-bg: #{$wind--bg--dark};
|
||||
--wind-bg-hover: #{$wind--bg--hover--dark};
|
||||
--wind-text: #{$wind--text--dark};
|
||||
|
|
|
|||
|
|
@ -464,6 +464,28 @@ $wind--shadow--dark: fade-out($wind-text-20, 0.3);
|
|||
$wind--shadow--light--hover: fade-out($wind-text-00, 0.3);
|
||||
$wind--shadow--dark--hover: fade-out($wind-text-00, 0.3);
|
||||
|
||||
// Color Definitions: Element / Null
|
||||
$null--bg--light: $grey-75;
|
||||
$null--bg--dark: $grey-40;
|
||||
|
||||
$null--bg--hover--light: $grey-70;
|
||||
$null--bg--hover--dark: $grey-30;
|
||||
|
||||
$null--text--light: $grey-40;
|
||||
$null--text--dark: $grey-90;
|
||||
|
||||
$null--text--raid--light: $grey-40;
|
||||
$null--text--raid--dark: $grey-90;
|
||||
|
||||
$null--text--hover--light: $grey-20;
|
||||
$null--text--hover--dark: $grey-90;
|
||||
|
||||
$null--shadow--light: fade-out($grey-60, 0.3);
|
||||
$null--shadow--dark: fade-out($grey-25, 0.3);
|
||||
|
||||
$null--shadow--light--hover: fade-out($grey-50, 0.3);
|
||||
$null--shadow--dark--hover: fade-out($grey-10, 0.3);
|
||||
|
||||
// Color Definitions: Element / Fire
|
||||
$fire--bg--light: $fire-bg-10;
|
||||
$fire--bg--dark: $fire-bg-10;
|
||||
|
|
|
|||
13
transformers/AwakeningTransformer.tsx
Normal file
13
transformers/AwakeningTransformer.tsx
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Transforms API response to Awakening object
|
||||
export function toObject(data: any): Awakening {
|
||||
return {
|
||||
id: data.id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.ja,
|
||||
},
|
||||
slug: data.slug,
|
||||
object_type: data.object_type,
|
||||
order: data.order,
|
||||
}
|
||||
}
|
||||
41
transformers/CharacterTransformer.tsx
Normal file
41
transformers/CharacterTransformer.tsx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import * as Awakening from './AwakeningTransformer'
|
||||
import * as Element from './ElementTransformer'
|
||||
|
||||
// Transforms API response to Character object
|
||||
export function toObject(data: any): Character {
|
||||
return {
|
||||
type: 'character',
|
||||
id: data.id,
|
||||
granblueId: data.granblue_id,
|
||||
characterId: data.character_id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.ja,
|
||||
},
|
||||
element: Element.toObject(data.element),
|
||||
rarity: data.rarity,
|
||||
proficiency: data.proficiency,
|
||||
gender: data.gender,
|
||||
race: data.race,
|
||||
hp: {
|
||||
min: data.hp.min_hp,
|
||||
max: data.hp.max_hp,
|
||||
flb: data.hp.max_hp_flb ? data.hp.max_hp_flb : null,
|
||||
ulb: data.hp.max_hp_ulb ? data.hp.max_hp_ulb : null,
|
||||
},
|
||||
atk: {
|
||||
min: data.atk.min_atk,
|
||||
max: data.atk.max_atk,
|
||||
flb: data.atk.max_atk_flb ? data.atk.max_atk_flb : null,
|
||||
ulb: data.atk.max_atk_ulb ? data.atk.max_atk_ulb : null,
|
||||
},
|
||||
uncap: {
|
||||
flb: data.uncap.flb,
|
||||
ulb: data.uncap.ulb,
|
||||
},
|
||||
awakenings: data.awakenings.map((awakening: any) =>
|
||||
Awakening.toObject(awakening)
|
||||
),
|
||||
special: data.special,
|
||||
}
|
||||
}
|
||||
9
transformers/ElementTransformer.tsx
Normal file
9
transformers/ElementTransformer.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
import { elements } from '../utils/elements'
|
||||
|
||||
export function toObject(value: number) {
|
||||
return elements.find((element) => element.id === value) || elements[0]
|
||||
}
|
||||
|
||||
export function toParam(value: string) {
|
||||
return elements.find((element) => element.name.en === value)
|
||||
}
|
||||
53
transformers/GridCharacterTransformer.tsx
Normal file
53
transformers/GridCharacterTransformer.tsx
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import * as Awakening from './AwakeningTransformer'
|
||||
import * as Character from './CharacterTransformer'
|
||||
|
||||
// Transforms API response to GridCharacter object
|
||||
export function toObject(data: any): GridCharacter {
|
||||
return {
|
||||
id: data.id,
|
||||
object: Character.toObject(data.object),
|
||||
position: data.position,
|
||||
uncapLevel: data.uncap_level,
|
||||
transcendenceStep: data.transcendence_step ? data.transcendence_step : null,
|
||||
mastery: {
|
||||
overMastery: data.over_mastery
|
||||
? data.over_mastery
|
||||
: [
|
||||
{
|
||||
modifier: 1,
|
||||
strength: 0,
|
||||
},
|
||||
{
|
||||
modifier: 2,
|
||||
strength: 0,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
],
|
||||
aetherialMastery: data.aetherial_mastery ? data.aetherial_mastery : null,
|
||||
awakening: {
|
||||
type: Awakening.toObject(data.awakening.type),
|
||||
level: data.awakening.level,
|
||||
},
|
||||
perpetuity: data.perpetuity,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Transforms User object into API parameters
|
||||
export function toParams(data: GridCharacter): GridCharacterParams {
|
||||
return {
|
||||
character_id: data.id,
|
||||
position: data.position,
|
||||
uncapLevel: data.uncapLevel,
|
||||
transcendence_step: data.transcendenceStep,
|
||||
ring1: data.mastery.overMastery[1],
|
||||
ring2: data.mastery.overMastery[2],
|
||||
ring3: data.mastery.overMastery[3],
|
||||
ring4: data.mastery.overMastery[4],
|
||||
earring: data.mastery.aetherialMastery,
|
||||
awakening_id: data.mastery.awakening.type.id,
|
||||
awakening_level: data.mastery.awakening.level,
|
||||
perpetuity: data.mastery.perpetuity,
|
||||
}
|
||||
}
|
||||
26
transformers/GridSummonTransformer.tsx
Normal file
26
transformers/GridSummonTransformer.tsx
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import * as Summon from './SummonTransformer'
|
||||
|
||||
// Transforms API response to GridSummon object
|
||||
export function toObject(data: any): GridSummon {
|
||||
return {
|
||||
id: data.id,
|
||||
object: Summon.toObject(data.object),
|
||||
position: data.position,
|
||||
main: data.main,
|
||||
friend: data.friend,
|
||||
uncapLevel: data.uncap_level,
|
||||
transcendenceStep: data.transcendence_step ? data.transcendence_step : null,
|
||||
quickSummon: data.quick_summon,
|
||||
}
|
||||
}
|
||||
|
||||
// Transforms User object into API parameters
|
||||
export function toParams(data: GridSummon): GridSummonParams {
|
||||
return {
|
||||
summon_id: data.id,
|
||||
position: data.position,
|
||||
uncapLevel: data.uncapLevel,
|
||||
transcendence_step: data.transcendenceStep,
|
||||
quick_summon: data.quickSummon,
|
||||
}
|
||||
}
|
||||
64
transformers/GridTransformer.tsx
Normal file
64
transformers/GridTransformer.tsx
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import * as GridWeapon from '~transformers/GridWeaponTransformer'
|
||||
import * as GridSummon from '~transformers/GridSummonTransformer'
|
||||
import * as GridCharacter from '~transformers/GridCharacterTransformer'
|
||||
|
||||
// Transforms API response to Party object
|
||||
export function toObject(data: any): Grid {
|
||||
console.log('----- GridTransformer.tsx -----')
|
||||
console.log(data.summons, data.characters)
|
||||
console.log('----- End GridTransformer.tsx -----')
|
||||
|
||||
const mainSummon = data.summons
|
||||
? data.summons.find((summon: any) => summon.main === true)
|
||||
: null
|
||||
const friendSummon = data.summons
|
||||
? data.summons.find((summon: any) => summon.friend === true)
|
||||
: null
|
||||
const allSummons = data.summons
|
||||
? removeItem(data.summons, [mainSummon, friendSummon])
|
||||
: null
|
||||
|
||||
const mainWeapon = data.weapons
|
||||
? data.weapons.find((weapon: any) => weapon.mainhand === true)
|
||||
: null
|
||||
|
||||
return {
|
||||
characters: data.characters
|
||||
? mapToGridArrayWithTransformer(data.characters, GridCharacter.toObject)
|
||||
: null,
|
||||
summons: {
|
||||
mainSummon: mainSummon ? GridSummon.toObject(mainSummon) : null,
|
||||
friendSummon: friendSummon ? GridSummon.toObject(friendSummon) : null,
|
||||
allSummons: allSummons
|
||||
? mapToGridArrayWithTransformer(allSummons, GridSummon.toObject)
|
||||
: null,
|
||||
},
|
||||
weapons: {
|
||||
mainWeapon: mainWeapon ? GridWeapon.toObject(mainWeapon) : null,
|
||||
allWeapons: data.weapons
|
||||
? mapToGridArrayWithTransformer(data.weapons, GridWeapon.toObject)
|
||||
: null,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function removeItem<T>(arr: Array<T>, values: T[]): Array<T> {
|
||||
values.forEach((value) => {
|
||||
const index = arr.indexOf(value)
|
||||
if (index > -1) {
|
||||
arr.splice(index, 1)
|
||||
}
|
||||
})
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
export function mapToGridArrayWithTransformer<T>(
|
||||
arr: any[],
|
||||
transformer: (data: any) => T
|
||||
): GridArray<T> {
|
||||
return arr.reduce(
|
||||
(gridArray, item) => ({ ...gridArray, [item.position]: transformer(item) }),
|
||||
{} as GridArray<T>
|
||||
)
|
||||
}
|
||||
45
transformers/GridWeaponTransformer.tsx
Normal file
45
transformers/GridWeaponTransformer.tsx
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
import * as Awakening from './AwakeningTransformer'
|
||||
import * as Element from './ElementTransformer'
|
||||
import * as Weapon from './WeaponTransformer'
|
||||
import * as WeaponKey from './WeaponKeyTransformer'
|
||||
|
||||
// Transforms API response to GridWeapon object
|
||||
export function toObject(data: any): GridWeapon {
|
||||
return {
|
||||
id: data.id,
|
||||
object: Weapon.toObject(data.object),
|
||||
position: data.position,
|
||||
mainhand: data.mainhand,
|
||||
uncapLevel: data.uncap_level,
|
||||
element: Element.toObject(data.element),
|
||||
weaponKeys: data.weapon_keys
|
||||
? data.weapon_keys.map((key: any) => WeaponKey.toObject(key))
|
||||
: null,
|
||||
ax: data.ax ? data.ax : null,
|
||||
awakening: data.awakening
|
||||
? {
|
||||
type: Awakening.toObject(data.awakening.type),
|
||||
level: data.awakening.awakening_level,
|
||||
}
|
||||
: null,
|
||||
}
|
||||
}
|
||||
|
||||
// Transforms User object into API parameters
|
||||
export function toParams(data: GridWeapon): GridWeaponParams {
|
||||
return {
|
||||
weapon_id: data.id,
|
||||
position: data.position,
|
||||
uncapLevel: data.uncapLevel,
|
||||
element: data.element.id,
|
||||
weapon_key1_id: data.weaponKeys?.[0].id,
|
||||
weapon_key2_id: data.weaponKeys?.[1].id,
|
||||
weapon_key3_id: data.weaponKeys?.[2].id,
|
||||
ax_modifier1: data.ax?.[0].modifier,
|
||||
ax_modifier2: data.ax?.[1].modifier,
|
||||
ax_strength1: data.ax?.[0].strength,
|
||||
ax_strength2: data.ax?.[1].strength,
|
||||
awakening_id: data.awakening?.type.id,
|
||||
awakening_level: data.awakening?.level,
|
||||
}
|
||||
}
|
||||
15
transformers/GuidebookTransformer.tsx
Normal file
15
transformers/GuidebookTransformer.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
// Transforms API response to Guidebook object
|
||||
export function toObject(data: any): Guidebook {
|
||||
return {
|
||||
id: data.id,
|
||||
granblueId: data.granblue_id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.jp,
|
||||
},
|
||||
description: {
|
||||
en: data.description.en,
|
||||
ja: data.description.jp,
|
||||
},
|
||||
}
|
||||
}
|
||||
15
transformers/JobAccessoryTransformer.tsx
Normal file
15
transformers/JobAccessoryTransformer.tsx
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import * as Job from './JobTransformer'
|
||||
|
||||
// Transforms API response to JobAccessory object
|
||||
export function toObject(data: any): JobAccessory {
|
||||
return {
|
||||
id: data.id,
|
||||
granblueId: data.granblue_id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.jp,
|
||||
},
|
||||
job: Job.toObject(data.job),
|
||||
rarity: data.rarity,
|
||||
}
|
||||
}
|
||||
20
transformers/JobSkillTransformer.tsx
Normal file
20
transformers/JobSkillTransformer.tsx
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import * as Job from './JobTransformer'
|
||||
|
||||
// Transforms API response to JobSkill object
|
||||
export function toObject(data: any): JobSkill {
|
||||
return {
|
||||
id: data.id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.ja,
|
||||
},
|
||||
job: Job.toObject(data.job),
|
||||
slug: data.slug,
|
||||
color: data.color,
|
||||
main: data.main,
|
||||
base: data.base,
|
||||
sub: data.sub,
|
||||
emp: data.emp,
|
||||
order: data.order,
|
||||
}
|
||||
}
|
||||
21
transformers/JobTransformer.tsx
Normal file
21
transformers/JobTransformer.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
// Transforms API response to Job object
|
||||
export function toObject(data: any): Job {
|
||||
return {
|
||||
id: data.id,
|
||||
granblueId: data.granblue_id,
|
||||
name: {
|
||||
en: data.name.en,
|
||||
ja: data.name.ja,
|
||||
},
|
||||
row: data.row,
|
||||
order: data.order,
|
||||
masterLevel: data.master_level,
|
||||
ultimateMastery: data.ultimate_mastery,
|
||||
proficiency: {
|
||||
proficiency1: data.proficiency?.[0] ?? null,
|
||||
proficiency2: data.proficiency?.[1] ?? null,
|
||||
},
|
||||
accessory: data.accessory,
|
||||
accessory_type: data.accessory_type,
|
||||
}
|
||||
}
|
||||
94
transformers/PartyTransformer.tsx
Normal file
94
transformers/PartyTransformer.tsx
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
import * as Grid from './GridTransformer'
|
||||
import * as Guidebook from './GuidebookTransformer'
|
||||
import * as Job from './JobTransformer'
|
||||
import * as JobAccessory from './JobAccessoryTransformer'
|
||||
import * as JobSkill from './JobSkillTransformer'
|
||||
import * as Raid from './RaidTransformer'
|
||||
import * as User from './UserTransformer'
|
||||
|
||||
// Transforms API response to Party object
|
||||
export function toObject(data: any): Party {
|
||||
return {
|
||||
id: data.id,
|
||||
localId: data.local_id ? data.local_id : null,
|
||||
editKey: data.edit_key ? data.edit_key : null,
|
||||
name: data.name,
|
||||
description: data.description ? data.description : null,
|
||||
shortcode: data.shortcode,
|
||||
user: data.user ? User.toObject(data.user) : null,
|
||||
editable: data.editable ?? false,
|
||||
grid: Grid.toObject({
|
||||
characters: data.characters,
|
||||
summons: data.summons,
|
||||
weapons: data.weapons,
|
||||
}),
|
||||
details: {
|
||||
extra: data.extra,
|
||||
fullAuto: data.full_auto,
|
||||
autoGuard: data.auto_guard,
|
||||
autoSummon: data.auto_summon,
|
||||
chargeAttack: data.charge_attack ? data.charge_attack : null,
|
||||
clearTime: data.clear_time ? data.clear_time : null,
|
||||
buttonCount: data.button_count ? data.button_count : null,
|
||||
turnCount: data.turn_count ? data.turn_count : null,
|
||||
chainCount: data.chain_count ? data.chain_count : null,
|
||||
},
|
||||
protagonist: {
|
||||
job: data.job && Job.toObject(data.job),
|
||||
skills: data.job_skills
|
||||
? {
|
||||
0: data.job_skills[0] && JobSkill.toObject(data.job_skills[0]),
|
||||
1: data.job_skills[1] && JobSkill.toObject(data.job_skills[1]),
|
||||
2: data.job_skills[2] && JobSkill.toObject(data.job_skills[2]),
|
||||
3: data.job_skills[3] && JobSkill.toObject(data.job_skills[3]),
|
||||
}
|
||||
: null,
|
||||
masterLevel: data.master_level ? data.master_level : null,
|
||||
ultimateMastery: data.ultimate_mastery ? data.ultimate_mastery : null,
|
||||
accessory: data.accessory ? JobAccessory.toObject(data.accessory) : null,
|
||||
},
|
||||
social: {
|
||||
favorited: data.favorited,
|
||||
remix: data.remix,
|
||||
remixes: data.remixes
|
||||
? data.remixes.map((remix: any) => toObject(remix))
|
||||
: [],
|
||||
sourceParty: data.source_party ? toObject(data.source_party) : null,
|
||||
},
|
||||
timestamps: {
|
||||
createdAt: data.created_at,
|
||||
updatedAt: data.updated_at,
|
||||
},
|
||||
raid: data.raid ? Raid.toObject(data.raid) : null,
|
||||
guidebooks: {
|
||||
0: data.guidebooks[1] && Guidebook.toObject(data.guidebooks[1]),
|
||||
1: data.guidebooks[2] && Guidebook.toObject(data.guidebooks[2]),
|
||||
2: data.guidebooks[3] && Guidebook.toObject(data.guidebooks[3]),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Transforms Party object into API parameters
|
||||
export function toParams(party: Party): PartyParams {
|
||||
return {
|
||||
local_id: party.localId,
|
||||
name: party.name,
|
||||
description: party.description,
|
||||
extra: party.details.extra,
|
||||
full_auto: party.details.fullAuto,
|
||||
auto_guard: party.details.autoGuard,
|
||||
auto_summon: party.details.autoSummon,
|
||||
charge_attack: party.details.chargeAttack,
|
||||
clear_time: party.details.clearTime,
|
||||
button_count: party.details.buttonCount,
|
||||
turn_count: party.details.turnCount,
|
||||
chain_count: party.details.chainCount,
|
||||
raid_id: party.raid?.id,
|
||||
job_id: party.protagonist.job?.id,
|
||||
master_level: party.protagonist.masterLevel,
|
||||
ultimate_mastery: party.protagonist.ultimateMastery,
|
||||
guidebook1_id: party.guidebooks[0]?.id,
|
||||
guidebook2_id: party.guidebooks[1]?.id,
|
||||
guidebook3_id: party.guidebooks[2]?.id,
|
||||
} as PartyParams
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue