Merge pull request #24 from jedmund/i18n
Add internationalization support
|
|
@ -1,21 +1,24 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import * as Dialog from '@radix-ui/react-dialog'
|
import * as Dialog from '@radix-ui/react-dialog'
|
||||||
|
|
||||||
import CrossIcon from '~public/icons/Cross.svg'
|
import CrossIcon from '~public/icons/Cross.svg'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
const AboutModal = () => {
|
const AboutModal = () => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog.Root>
|
<Dialog.Root>
|
||||||
<Dialog.Trigger asChild>
|
<Dialog.Trigger asChild>
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<span>About</span>
|
<span>{t('modals.about.title')}</span>
|
||||||
</li>
|
</li>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal>
|
<Dialog.Portal>
|
||||||
<Dialog.Content className="About Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
<Dialog.Content className="About Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||||
<div className="DialogHeader">
|
<div className="DialogHeader">
|
||||||
<Dialog.Title className="DialogTitle">About</Dialog.Title>
|
<Dialog.Title className="DialogTitle">{t('menu.about')}</Dialog.Title>
|
||||||
<Dialog.Close className="DialogClose" asChild>
|
<Dialog.Close className="DialogClose" asChild>
|
||||||
<span>
|
<span>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,10 @@
|
||||||
font-size: $font-small;
|
font-size: $font-small;
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
|
|
||||||
|
&.jp {
|
||||||
|
max-width: 270px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import * as Dialog from '@radix-ui/react-dialog'
|
import * as Dialog from '@radix-ui/react-dialog'
|
||||||
import * as Switch from '@radix-ui/react-switch'
|
import * as Switch from '@radix-ui/react-switch'
|
||||||
|
|
@ -17,13 +19,16 @@ import './index.scss'
|
||||||
const AccountModal = () => {
|
const AccountModal = () => {
|
||||||
const { account } = useSnapshot(accountState)
|
const { account } = useSnapshot(accountState)
|
||||||
|
|
||||||
// Cookies
|
const router = useRouter()
|
||||||
const [accountCookies] = useCookies(['account'])
|
const { t } = useTranslation('common')
|
||||||
const [userCookies, setUserCookies] = useCookies(['user'])
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const headers = (accountCookies.account != null) ? {
|
// Cookies
|
||||||
|
const [cookies, setCookies] = useCookies()
|
||||||
|
|
||||||
|
const headers = (cookies.account != null) ? {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${accountCookies.account.access_token}`
|
'Authorization': `Bearer ${cookies.account.access_token}`
|
||||||
}
|
}
|
||||||
} : {}
|
} : {}
|
||||||
|
|
||||||
|
|
@ -39,14 +44,15 @@ const AccountModal = () => {
|
||||||
const privateSelect = React.createRef<HTMLInputElement>()
|
const privateSelect = React.createRef<HTMLInputElement>()
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (userCookies.user) setPicture(userCookies.user.picture)
|
console.log(cookies.user)
|
||||||
if (userCookies.user) setLanguage(userCookies.user.language)
|
if (cookies.user) setPicture(cookies.user.picture)
|
||||||
}, [userCookies])
|
if (cookies.user) setLanguage(cookies.user.language)
|
||||||
|
}, [cookies])
|
||||||
|
|
||||||
const pictureOptions = (
|
const pictureOptions = (
|
||||||
pictureData.sort((a, b) => (a.name.en > b.name.en) ? 1 : -1).map((item, i) => {
|
pictureData.sort((a, b) => (a.name.en > b.name.en) ? 1 : -1).map((item, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={`picture-${i}`} value={item.filename}>{item.name.en}</option>
|
<option key={`picture-${i}`} value={item.filename}>{item.name[locale]}</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
@ -77,7 +83,7 @@ const AccountModal = () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
api.endpoints.users.update(accountCookies.account.user_id, object, headers)
|
api.endpoints.users.update(cookies.account.user_id, object, headers)
|
||||||
.then(response => {
|
.then(response => {
|
||||||
const user = response.data.user
|
const user = response.data.user
|
||||||
|
|
||||||
|
|
@ -87,9 +93,8 @@ const AccountModal = () => {
|
||||||
language: user.language,
|
language: user.language,
|
||||||
}
|
}
|
||||||
|
|
||||||
setUserCookies('user', cookieObj, { path: '/'})
|
setCookies('user', cookieObj, { path: '/'})
|
||||||
|
|
||||||
accountState.account.language = user.language
|
|
||||||
accountState.account.user = {
|
accountState.account.user = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
|
|
@ -98,9 +103,17 @@ const AccountModal = () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
changeLanguage(user.language)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeLanguage(newLanguage: string) {
|
||||||
|
if (newLanguage !== router.locale) {
|
||||||
|
setCookies('NEXT_LOCALE', newLanguage, { path: '/'})
|
||||||
|
router.push(router.asPath, undefined, { locale: newLanguage })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function openChange(open: boolean) {
|
function openChange(open: boolean) {
|
||||||
setOpen(open)
|
setOpen(open)
|
||||||
}
|
}
|
||||||
|
|
@ -109,14 +122,14 @@ const AccountModal = () => {
|
||||||
<Dialog.Root open={open} onOpenChange={openChange}>
|
<Dialog.Root open={open} onOpenChange={openChange}>
|
||||||
<Dialog.Trigger asChild>
|
<Dialog.Trigger asChild>
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<span>Settings</span>
|
<span>{t('menu.settings')}</span>
|
||||||
</li>
|
</li>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal>
|
<Dialog.Portal>
|
||||||
<Dialog.Content className="Account Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
<Dialog.Content className="Account Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||||
<div className="DialogHeader">
|
<div className="DialogHeader">
|
||||||
<div className="DialogTop">
|
<div className="DialogTop">
|
||||||
<Dialog.Title className="SubTitle">Account Settings</Dialog.Title>
|
<Dialog.Title className="SubTitle">{t('modals.settings.title')}</Dialog.Title>
|
||||||
<Dialog.Title className="DialogTitle">@{account.user?.username}</Dialog.Title>
|
<Dialog.Title className="DialogTitle">@{account.user?.username}</Dialog.Title>
|
||||||
</div>
|
</div>
|
||||||
<Dialog.Close className="DialogClose" asChild>
|
<Dialog.Close className="DialogClose" asChild>
|
||||||
|
|
@ -129,7 +142,7 @@ const AccountModal = () => {
|
||||||
<form onSubmit={update}>
|
<form onSubmit={update}>
|
||||||
<div className="field">
|
<div className="field">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<label>Picture</label>
|
<label>{t('modals.settings.labels.picture')}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={`preview ${pictureData.find(i => i.filename === picture)?.element}`}>
|
<div className={`preview ${pictureData.find(i => i.filename === picture)?.element}`}>
|
||||||
|
|
@ -147,18 +160,18 @@ const AccountModal = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="field">
|
<div className="field">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<label>Language</label>
|
<label>{t('modals.settings.labels.language')}</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<select name="language" onChange={handleLanguageChange} value={language} ref={languageSelect}>
|
<select name="language" onChange={handleLanguageChange} value={language} ref={languageSelect}>
|
||||||
<option key="en" value="en">English</option>
|
<option key="en" value="en">{t('modals.settings.language.english')}</option>
|
||||||
<option key="jp" value="jp">Japanese</option>
|
<option key="jp" value="ja">{t('modals.settings.language.japanese')}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="field">
|
<div className="field">
|
||||||
<div className="left">
|
<div className="left">
|
||||||
<label>Private</label>
|
<label>{t('modals.settings.labels.private')}</label>
|
||||||
<p>Hide your profile and prevent your grids from showing up in collections</p>
|
<p className={locale}>{t('modals.settings.descriptions.private')}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Switch.Root className="Switch" onCheckedChange={handlePrivateChange} checked={privateProfile}>
|
<Switch.Root className="Switch" onCheckedChange={handlePrivateChange} checked={privateProfile}>
|
||||||
|
|
@ -166,7 +179,7 @@ const AccountModal = () => {
|
||||||
</Switch.Root>
|
</Switch.Root>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Button>Save settings</Button>
|
<Button>{t('modals.settings.buttons.confirm')}</Button>
|
||||||
</form>
|
</form>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
<Dialog.Overlay className="Overlay" />
|
<Dialog.Overlay className="Overlay" />
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import { axData } from '~utils/axData'
|
import { axData } from '~utils/axData'
|
||||||
|
|
@ -19,6 +22,10 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const AXSelect = (props: Props) => {
|
const AXSelect = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Set up form states and error handling
|
// Set up form states and error handling
|
||||||
const [errors, setErrors] = useState<ErrorMap>({
|
const [errors, setErrors] = useState<ErrorMap>({
|
||||||
axValue1: '',
|
axValue1: '',
|
||||||
|
|
@ -84,7 +91,7 @@ const AXSelect = (props: Props) => {
|
||||||
if (modifierSet == 0) {
|
if (modifierSet == 0) {
|
||||||
axOptionElements = axOptions.map((ax, i) => {
|
axOptionElements = axOptions.map((ax, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={i} value={ax.id}>{ax.name.en}</option>
|
<option key={i} value={ax.id}>{ax.name[locale]}</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -103,14 +110,14 @@ const AXSelect = (props: Props) => {
|
||||||
const secondaryAxOptions = primarySkill.secondary
|
const secondaryAxOptions = primarySkill.secondary
|
||||||
axOptionElements = secondaryAxOptions.map((ax, i) => {
|
axOptionElements = secondaryAxOptions.map((ax, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={i} value={ax.id}>{ax.name.en}</option>
|
<option key={i} value={ax.id}>{ax.name[locale]}</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
axOptionElements?.unshift(<option key={-1} value={-1}>No AX Skill</option>)
|
axOptionElements?.unshift(<option key={-1} value={-1}>{t('ax.no_skill')}</option>)
|
||||||
return axOptionElements
|
return axOptionElements
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,11 +163,19 @@ const AXSelect = (props: Props) => {
|
||||||
let newErrors = {...errors}
|
let newErrors = {...errors}
|
||||||
|
|
||||||
if (value < primaryAxSkill.minValue) {
|
if (value < primaryAxSkill.minValue) {
|
||||||
newErrors.axValue1 = `${primaryAxSkill.name.en} must be at least ${primaryAxSkill.minValue}${ (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''}`
|
newErrors.axValue1 = t('ax.errors.value_too_low', {
|
||||||
|
name: primaryAxSkill.name[locale],
|
||||||
|
minValue: primaryAxSkill.minValue,
|
||||||
|
suffix: (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''
|
||||||
|
})
|
||||||
} else if (value > primaryAxSkill.maxValue) {
|
} else if (value > primaryAxSkill.maxValue) {
|
||||||
newErrors.axValue1 = `${primaryAxSkill.name.en} cannot be greater than ${primaryAxSkill.maxValue}${ (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''}`
|
newErrors.axValue1 = t('ax.errors.value_too_high', {
|
||||||
|
name: primaryAxSkill.name[locale],
|
||||||
|
maxValue: primaryAxSkill.minValue,
|
||||||
|
suffix: (primaryAxSkill.suffix) ? primaryAxSkill.suffix : ''
|
||||||
|
})
|
||||||
} else if (!value || value <= 0) {
|
} else if (!value || value <= 0) {
|
||||||
newErrors.axValue1 = `${primaryAxSkill.name.en} must have a value`
|
newErrors.axValue1 = t('ax.errors.value_empty', { name: primaryAxSkill.name[locale] })
|
||||||
} else {
|
} else {
|
||||||
newErrors.axValue1 = ''
|
newErrors.axValue1 = ''
|
||||||
}
|
}
|
||||||
|
|
@ -179,13 +194,21 @@ const AXSelect = (props: Props) => {
|
||||||
|
|
||||||
if (secondaryAxSkill) {
|
if (secondaryAxSkill) {
|
||||||
if (value < secondaryAxSkill.minValue) {
|
if (value < secondaryAxSkill.minValue) {
|
||||||
newErrors.axValue2 = `${secondaryAxSkill.name.en} must be at least ${secondaryAxSkill.minValue}${ (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''}`
|
newErrors.axValue2 = t('ax.errors.value_too_low', {
|
||||||
|
name: secondaryAxSkill.name[locale],
|
||||||
|
minValue: secondaryAxSkill.minValue,
|
||||||
|
suffix: (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''
|
||||||
|
})
|
||||||
} else if (value > secondaryAxSkill.maxValue) {
|
} else if (value > secondaryAxSkill.maxValue) {
|
||||||
newErrors.axValue2 = `${secondaryAxSkill.name.en} cannot be greater than ${secondaryAxSkill.maxValue}${ (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''}`
|
newErrors.axValue2 = t('ax.errors.value_too_high', {
|
||||||
|
name: secondaryAxSkill.name[locale],
|
||||||
|
maxValue: secondaryAxSkill.minValue,
|
||||||
|
suffix: (secondaryAxSkill.suffix) ? secondaryAxSkill.suffix : ''
|
||||||
|
})
|
||||||
} else if (!secondaryAxSkill.suffix && value % 1 !== 0) {
|
} else if (!secondaryAxSkill.suffix && value % 1 !== 0) {
|
||||||
newErrors.axValue2 = `${secondaryAxSkill.name.en} must be a whole number`
|
newErrors.axValue2 = t('ax.errors.value_not_whole', { name: secondaryAxSkill.name[locale] })
|
||||||
} else if (primaryAxValue <= 0) {
|
} else if (primaryAxValue <= 0) {
|
||||||
newErrors.axValue1 = `${primaryAxSkill.name.en} must have a value`
|
newErrors.axValue1 = t('ax.errors.value_empty', { name: primaryAxSkill.name[locale] })
|
||||||
} else {
|
} else {
|
||||||
newErrors.axValue2 = ''
|
newErrors.axValue2 = ''
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +247,7 @@ const AXSelect = (props: Props) => {
|
||||||
<div className="AXSet">
|
<div className="AXSet">
|
||||||
<div className="fields">
|
<div className="fields">
|
||||||
<select key="ax1" defaultValue={ (props.currentSkills && props.currentSkills[0]) ? props.currentSkills[0].modifier : -1 } onChange={handleSelectChange} ref={primaryAxModifierSelect}>{ generateOptions(0) }</select>
|
<select key="ax1" defaultValue={ (props.currentSkills && props.currentSkills[0]) ? props.currentSkills[0].modifier : -1 } onChange={handleSelectChange} ref={primaryAxModifierSelect}>{ generateOptions(0) }</select>
|
||||||
<input defaultValue={ (props.currentSkills && props.currentSkills[0]) ? props.currentSkills[0].strength : 0 } className="Input" type="number" onChange={handleInputChange} ref={primaryAxValueInput} disabled />
|
<input defaultValue={ (props.currentSkills && props.currentSkills[0]) ? props.currentSkills[0].strength : 0 } className="Input" type="number" onChange={handleInputChange} ref={primaryAxValueInput} disabled={primaryAxValue != 0} />
|
||||||
</div>
|
</div>
|
||||||
<p className={primaryErrorClasses}>{errors.axValue1}</p>
|
<p className={primaryErrorClasses}>{errors.axValue1}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -232,7 +255,7 @@ const AXSelect = (props: Props) => {
|
||||||
<div className={secondarySetClasses}>
|
<div className={secondarySetClasses}>
|
||||||
<div className="fields">
|
<div className="fields">
|
||||||
<select key="ax2" defaultValue={ (props.currentSkills && props.currentSkills[1]) ? props.currentSkills[1].modifier : -1 } onChange={handleSelectChange} ref={secondaryAxModifierSelect}>{ generateOptions(1) }</select>
|
<select key="ax2" defaultValue={ (props.currentSkills && props.currentSkills[1]) ? props.currentSkills[1].modifier : -1 } onChange={handleSelectChange} ref={secondaryAxModifierSelect}>{ generateOptions(1) }</select>
|
||||||
<input defaultValue={ (props.currentSkills && props.currentSkills[1]) ? props.currentSkills[1].strength : 0 } className="Input" type="number" onChange={handleInputChange} ref={secondaryAxValueInput} disabled />
|
<input defaultValue={ (props.currentSkills && props.currentSkills[1]) ? props.currentSkills[1].strength : 0 } className="Input" type="number" onChange={handleInputChange} ref={secondaryAxValueInput} disabled={secondaryAxValue != 0} />
|
||||||
</div>
|
</div>
|
||||||
<p className={secondaryErrorClasses}>{errors.axValue2}</p>
|
<p className={secondaryErrorClasses}>{errors.axValue2}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import React from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import clonedeep from 'lodash.clonedeep'
|
import clonedeep from 'lodash.clonedeep'
|
||||||
import * as Scroll from 'react-scroll'
|
import * as Scroll from 'react-scroll'
|
||||||
|
|
||||||
|
|
@ -11,15 +13,13 @@ import Header from '~components/Header'
|
||||||
import Button from '~components/Button'
|
import Button from '~components/Button'
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
import { accountState } from '~utils/accountState'
|
|
||||||
import { appState, initialAppState } from '~utils/appState'
|
import { appState, initialAppState } from '~utils/appState'
|
||||||
|
|
||||||
import { ButtonType } from '~utils/enums'
|
|
||||||
import CrossIcon from '~public/icons/Cross.svg'
|
import CrossIcon from '~public/icons/Cross.svg'
|
||||||
import { route } from 'next/dist/server/router'
|
|
||||||
|
|
||||||
const BottomHeader = () => {
|
const BottomHeader = () => {
|
||||||
const account = useSnapshot(accountState)
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const app = useSnapshot(appState)
|
const app = useSnapshot(appState)
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
@ -67,9 +67,9 @@ const BottomHeader = () => {
|
||||||
const leftNav = () => {
|
const leftNav = () => {
|
||||||
if (router.pathname === '/p/[party]' || router.pathname === '/new') {
|
if (router.pathname === '/p/[party]' || router.pathname === '/new') {
|
||||||
if (app.party.detailsVisible) {
|
if (app.party.detailsVisible) {
|
||||||
return (<Button icon="edit" active={true} onClick={toggleDetails}>Hide info</Button>)
|
return (<Button icon="edit" active={true} onClick={toggleDetails}>{t('buttons.hide_info')}</Button>)
|
||||||
} else {
|
} else {
|
||||||
return (<Button icon="edit" onClick={toggleDetails}>Edit info</Button>)
|
return (<Button icon="edit" onClick={toggleDetails}>{t('buttons.show_info')}</Button>)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return (<div />)
|
return (<div />)
|
||||||
|
|
@ -84,20 +84,20 @@ const BottomHeader = () => {
|
||||||
<span className='icon'>
|
<span className='icon'>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
</span>
|
</span>
|
||||||
<span className="text">Delete team</span>
|
<span className="text">{t('buttons.delete')}</span>
|
||||||
</AlertDialog.Trigger>
|
</AlertDialog.Trigger>
|
||||||
<AlertDialog.Portal>
|
<AlertDialog.Portal>
|
||||||
<AlertDialog.Overlay className="Overlay" />
|
<AlertDialog.Overlay className="Overlay" />
|
||||||
<AlertDialog.Content className="Dialog">
|
<AlertDialog.Content className="Dialog">
|
||||||
<AlertDialog.Title className="DialogTitle">
|
<AlertDialog.Title className="DialogTitle">
|
||||||
Delete team
|
{t('modals.delete_team.title')}
|
||||||
</AlertDialog.Title>
|
</AlertDialog.Title>
|
||||||
<AlertDialog.Description className="DialogDescription">
|
<AlertDialog.Description className="DialogDescription">
|
||||||
Are you sure you want to permanently delete this team?
|
{t('modals.delete_team.description')}
|
||||||
</AlertDialog.Description>
|
</AlertDialog.Description>
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
<AlertDialog.Cancel className="Button modal">Nevermind</AlertDialog.Cancel>
|
<AlertDialog.Cancel className="Button modal">{t('modals.delete_team.buttons.cancel')}</AlertDialog.Cancel>
|
||||||
<AlertDialog.Action className="Button modal destructive" onClick={(e) => deleteTeam(e)}>Yes, delete</AlertDialog.Action>
|
<AlertDialog.Action className="Button modal destructive" onClick={(e) => deleteTeam(e)}>{t('modals.delete_team.buttons.confirm')}</AlertDialog.Action>
|
||||||
</div>
|
</div>
|
||||||
</AlertDialog.Content>
|
</AlertDialog.Content>
|
||||||
</AlertDialog.Portal>
|
</AlertDialog.Portal>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||||
|
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
|
|
||||||
import { axData } from '~utils/axData'
|
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -21,6 +22,10 @@ interface KeyNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CharacterHovercard = (props: Props) => {
|
const CharacterHovercard = (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 Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
||||||
|
|
||||||
|
|
@ -56,8 +61,8 @@ const CharacterHovercard = (props: Props) => {
|
||||||
<HoverCard.Content className="Weapon Hovercard">
|
<HoverCard.Content className="Weapon Hovercard">
|
||||||
<div className="top">
|
<div className="top">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h4>{ props.gridCharacter.object.name.en }</h4>
|
<h4>{ props.gridCharacter.object.name[locale] }</h4>
|
||||||
<img alt={props.gridCharacter.object.name.en} src={characterImage()} />
|
<img alt={props.gridCharacter.object.name[locale]} src={characterImage()} />
|
||||||
</div>
|
</div>
|
||||||
<div className="subInfo">
|
<div className="subInfo">
|
||||||
<div className="icons">
|
<div className="icons">
|
||||||
|
|
@ -76,7 +81,7 @@ const CharacterHovercard = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">View more on gbf.wiki</a>
|
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">{t('buttons.wiki')}</a>
|
||||||
<HoverCard.Arrow />
|
<HoverCard.Arrow />
|
||||||
</HoverCard.Content>
|
</HoverCard.Content>
|
||||||
</HoverCard.Root>
|
</HoverCard.Root>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
|
|
||||||
|
|
@ -11,28 +13,29 @@ interface Props {
|
||||||
|
|
||||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
|
|
||||||
class CharacterResult extends React.Component<Props> {
|
const CharacterResult = (props: Props) => {
|
||||||
render() {
|
const router = useRouter()
|
||||||
const character = this.props.data
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
return (
|
const character = props.data
|
||||||
<li className="CharacterResult" onClick={this.props.onClick}>
|
|
||||||
<img alt={character.name.en} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-grid/${character.granblue_id}_01.jpg`} />
|
return(
|
||||||
<div className="Info">
|
<li className="CharacterResult" onClick={props.onClick}>
|
||||||
<h5>{character.name.en}</h5>
|
<img alt={character.name[locale]} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/chara-grid/${character.granblue_id}_01.jpg`} />
|
||||||
<UncapIndicator
|
<div className="Info">
|
||||||
type="character"
|
<h5>{character.name[locale]}</h5>
|
||||||
flb={character.uncap.flb}
|
<UncapIndicator
|
||||||
ulb={character.uncap.ulb}
|
type="character"
|
||||||
special={character.special}
|
flb={character.uncap.flb}
|
||||||
/>
|
ulb={character.uncap.ulb}
|
||||||
<div className="tags">
|
special={character.special}
|
||||||
<WeaponLabelIcon labelType={Element[character.element]} />
|
/>
|
||||||
</div>
|
<div className="tags">
|
||||||
|
<WeaponLabelIcon labelType={Element[character.element]} />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
)
|
</li>
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CharacterResult
|
export default CharacterResult
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
import SearchModal from '~components/SearchModal'
|
import SearchModal from '~components/SearchModal'
|
||||||
|
|
@ -18,6 +20,11 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const CharacterUnit = (props: Props) => {
|
const CharacterUnit = (props: Props) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const [imageUrl, setImageUrl] = useState('')
|
const [imageUrl, setImageUrl] = useState('')
|
||||||
|
|
||||||
const classes = classnames({
|
const classes = classnames({
|
||||||
|
|
@ -68,7 +75,7 @@ const CharacterUnit = (props: Props) => {
|
||||||
|
|
||||||
const editableImage = (
|
const editableImage = (
|
||||||
<SearchModal
|
<SearchModal
|
||||||
placeholderText="Search for a character..."
|
placeholderText={t('search.placeholders.character')}
|
||||||
fromPosition={props.position}
|
fromPosition={props.position}
|
||||||
object="characters"
|
object="characters"
|
||||||
send={props.updateObject}>
|
send={props.updateObject}>
|
||||||
|
|
@ -88,7 +95,7 @@ const CharacterUnit = (props: Props) => {
|
||||||
updateUncap={passUncapData}
|
updateUncap={passUncapData}
|
||||||
special={character.special}
|
special={character.special}
|
||||||
/> : '' }
|
/> : '' }
|
||||||
<h3 className="CharacterName">{character?.name.en}</h3>
|
<h3 className="CharacterName">{character?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,11 @@
|
||||||
font-size: $font-regular;
|
font-size: $font-regular;
|
||||||
padding: ($unit) $unit * 2;
|
padding: ($unit) $unit * 2;
|
||||||
|
|
||||||
|
&.ja {
|
||||||
|
padding-top: 6px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import * as ToggleGroup from '@radix-ui/react-toggle-group'
|
import * as ToggleGroup from '@radix-ui/react-toggle-group'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
@ -9,28 +12,32 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const ElementToggle = (props: Props) => {
|
const ElementToggle = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ToggleGroup.Root className="ToggleGroup" type="single" defaultValue={`${props.currentElement}`} aria-label="Element" onValueChange={props.sendValue}>
|
<ToggleGroup.Root className="ToggleGroup" type="single" defaultValue={`${props.currentElement}`} aria-label="Element" onValueChange={props.sendValue}>
|
||||||
<ToggleGroup.Item className="ToggleItem" value="0" aria-label="null">
|
<ToggleGroup.Item className={`ToggleItem ${locale}`} value="0" aria-label="null">
|
||||||
Null
|
{t('elements.null')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem wind" value="1" aria-label="wind">
|
<ToggleGroup.Item className={`ToggleItem wind ${locale}`} value="1" aria-label="wind">
|
||||||
Wind
|
{t('elements.wind')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem fire" value="2" aria-label="fire">
|
<ToggleGroup.Item className={`ToggleItem fire ${locale}`} value="2" aria-label="fire">
|
||||||
Fire
|
{t('elements.fire')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem water" value="3" aria-label="water">
|
<ToggleGroup.Item className={`ToggleItem water ${locale}`} value="3" aria-label="water">
|
||||||
Water
|
{t('elements.water')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem earth" value="4" aria-label="earth">
|
<ToggleGroup.Item className={`ToggleItem earth ${locale}`} value="4" aria-label="earth">
|
||||||
Earth
|
{t('elements.earth')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem dark" value="5" aria-label="dark">
|
<ToggleGroup.Item className={`ToggleItem dark ${locale}`} value="5" aria-label="dark">
|
||||||
Dark
|
{t('elements.dark')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
<ToggleGroup.Item className="ToggleItem light" value="6" aria-label="light">
|
<ToggleGroup.Item className={`ToggleItem light ${locale}`} value="6" aria-label="light">
|
||||||
Light
|
{t('elements.light')}
|
||||||
</ToggleGroup.Item>
|
</ToggleGroup.Item>
|
||||||
</ToggleGroup.Root>
|
</ToggleGroup.Root>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import SummonUnit from '~components/SummonUnit'
|
import SummonUnit from '~components/SummonUnit'
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
|
|
@ -16,9 +17,11 @@ interface Props {
|
||||||
const ExtraSummons = (props: Props) => {
|
const ExtraSummons = (props: Props) => {
|
||||||
const numSummons: number = 2
|
const numSummons: number = 2
|
||||||
|
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="ExtraSummons">
|
<div id="ExtraSummons">
|
||||||
<span>Sub Aura Summons</span>
|
<span>{t('summons.subaura')}</span>
|
||||||
<ul id="grid_summons">
|
<ul id="grid_summons">
|
||||||
{
|
{
|
||||||
Array.from(Array(numSummons)).map((x, i) => {
|
Array.from(Array(numSummons)).map((x, i) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import WeaponUnit from '~components/WeaponUnit'
|
import WeaponUnit from '~components/WeaponUnit'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
@ -15,10 +16,11 @@ interface Props {
|
||||||
|
|
||||||
const ExtraWeapons = (props: Props) => {
|
const ExtraWeapons = (props: Props) => {
|
||||||
const numWeapons: number = 3
|
const numWeapons: number = 3
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="ExtraGrid">
|
<div id="ExtraGrid">
|
||||||
<span>Additional<br />Weapons</span>
|
<span>{t('extra_weapons')}</span>
|
||||||
<ul className="grid_weapons">
|
<ul className="grid_weapons">
|
||||||
{
|
{
|
||||||
Array.from(Array(numWeapons)).map((x, i) => {
|
Array.from(Array(numWeapons)).map((x, i) => {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import RaidDropdown from '~components/RaidDropdown'
|
import RaidDropdown from '~components/RaidDropdown'
|
||||||
|
|
@ -12,6 +13,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterBar = (props: Props) => {
|
const FilterBar = (props: Props) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const elementSelect = React.createRef<HTMLSelectElement>()
|
const elementSelect = React.createRef<HTMLSelectElement>()
|
||||||
const raidSelect = React.createRef<HTMLSelectElement>()
|
const raidSelect = React.createRef<HTMLSelectElement>()
|
||||||
const recencySelect = React.createRef<HTMLSelectElement>()
|
const recencySelect = React.createRef<HTMLSelectElement>()
|
||||||
|
|
@ -33,14 +36,14 @@ const FilterBar = (props: Props) => {
|
||||||
<div className={classes}>
|
<div className={classes}>
|
||||||
{props.children}
|
{props.children}
|
||||||
<select onChange={selectChanged} ref={elementSelect}>
|
<select onChange={selectChanged} ref={elementSelect}>
|
||||||
<option key={-1} value={-1}>All elements</option>
|
<option key={-1} value={-1}>{t('elements.full.all')}</option>
|
||||||
<option key={-0} value={0}>Null</option>
|
<option key={-0} value={0}>{t('elements.full.null')}</option>
|
||||||
<option key={1}value={1}>Wind</option>
|
<option key={1}value={1}>{t('elements.full.wind')}</option>
|
||||||
<option key={2}value={2}>Fire</option>
|
<option key={2}value={2}>{t('elements.full.fire')}</option>
|
||||||
<option key={3}value={3}>Water</option>
|
<option key={3}value={3}>{t('elements.full.water')}</option>
|
||||||
<option key={4}value={4}>Earth</option>
|
<option key={4}value={4}>{t('elements.full.earth')}</option>
|
||||||
<option key={5}value={5}>Dark</option>
|
<option key={5}value={5}>{t('elements.full.dark')}</option>
|
||||||
<option key={6}value={6}>Light</option>
|
<option key={6}value={6}>{t('elements.full.light')}</option>
|
||||||
</select>
|
</select>
|
||||||
<RaidDropdown
|
<RaidDropdown
|
||||||
allOption={true}
|
allOption={true}
|
||||||
|
|
@ -48,13 +51,13 @@ const FilterBar = (props: Props) => {
|
||||||
ref={raidSelect}
|
ref={raidSelect}
|
||||||
/>
|
/>
|
||||||
<select onChange={selectChanged} ref={recencySelect}>
|
<select onChange={selectChanged} ref={recencySelect}>
|
||||||
<option key={-1} value={-1}>All time</option>
|
<option key={-1} value={-1}>{t('recency.all_time')}</option>
|
||||||
<option key={86400} value={86400}>Last day</option>
|
<option key={86400} value={86400}>{t('recency.last_day')}</option>
|
||||||
<option key={604800} value={604800}>Last week </option>
|
<option key={604800} value={604800}>{t('recency.last_week')}</option>
|
||||||
<option key={2629746} value={2629746}>Last month</option>
|
<option key={2629746} value={2629746}>{t('recency.last_month')}</option>
|
||||||
<option key={7889238} value={7889238}>Last 3 months</option>
|
<option key={7889238} value={7889238}>{t('recency.last_3_months')}</option>
|
||||||
<option key={15778476} value={15778476}>Last 6 months</option>
|
<option key={15778476} value={15778476}>{t('recency.last_6_months')}</option>
|
||||||
<option key={31556952} value={31556952}>Last year</option>
|
<option key={31556952} value={31556952}>{t('recency.last_year')}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
|
|
||||||
import { accountState } from '~utils/accountState'
|
import { accountState } from '~utils/accountState'
|
||||||
|
|
@ -30,6 +32,10 @@ const GridRep = (props: Props) => {
|
||||||
|
|
||||||
const { account } = useSnapshot(accountState)
|
const { account } = useSnapshot(accountState)
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const [mainhand, setMainhand] = useState<Weapon>()
|
const [mainhand, setMainhand] = useState<Weapon>()
|
||||||
const [weapons, setWeapons] = useState<GridArray<Weapon>>({})
|
const [weapons, setWeapons] = useState<GridArray<Weapon>>({})
|
||||||
|
|
||||||
|
|
@ -66,12 +72,12 @@ const GridRep = (props: Props) => {
|
||||||
|
|
||||||
function generateMainhandImage() {
|
function generateMainhandImage() {
|
||||||
return (mainhand) ?
|
return (mainhand) ?
|
||||||
<img alt={mainhand?.name.en} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand?.granblue_id}.jpg`} /> : ''
|
<img alt={mainhand?.name[locale]} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-main/${mainhand?.granblue_id}.jpg`} /> : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateGridImage(position: number) {
|
function generateGridImage(position: number) {
|
||||||
return (weapons[position]) ?
|
return (weapons[position]) ?
|
||||||
<img alt={weapons[position]?.name.en} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapons[position]?.granblue_id}.jpg`} /> : ''
|
<img alt={weapons[position]?.name[locale]} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapons[position]?.granblue_id}.jpg`} /> : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function sendSaveData() {
|
function sendSaveData() {
|
||||||
|
|
@ -96,10 +102,10 @@ const GridRep = (props: Props) => {
|
||||||
|
|
||||||
const details = (
|
const details = (
|
||||||
<div className="Details">
|
<div className="Details">
|
||||||
<h2 className={titleClass} onClick={navigate}>{ (props.name) ? props.name : 'Untitled' }</h2>
|
<h2 className={titleClass} onClick={navigate}>{ (props.name) ? props.name : t('no_title') }</h2>
|
||||||
<div className="bottom">
|
<div className="bottom">
|
||||||
<div className={raidClass}>{ (props.raid) ? props.raid.name.en : 'No raid set' }</div>
|
<div className={raidClass}>{ (props.raid) ? props.raid.name[locale] : t('no_raid') }</div>
|
||||||
<time className="last-updated" dateTime={props.createdAt.toISOString()}>{formatTimeAgo(props.createdAt, 'en-us')}</time>
|
<time className="last-updated" dateTime={props.createdAt.toISOString()}>{formatTimeAgo(props.createdAt, locale)}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
@ -108,10 +114,10 @@ const GridRep = (props: Props) => {
|
||||||
<div className="Details">
|
<div className="Details">
|
||||||
<div className="top">
|
<div className="top">
|
||||||
<div className="info">
|
<div className="info">
|
||||||
<h2 className={titleClass} onClick={navigate}>{ (props.name) ? props.name : 'Untitled' }</h2>
|
<h2 className={titleClass} onClick={navigate}>{ (props.name) ? props.name : t('no_title') }</h2>
|
||||||
<div className={raidClass}>{ (props.raid) ? props.raid.name.en : 'No raid set' }</div>
|
<div className={raidClass}>{ (props.raid) ? props.raid.name[locale] : t('no_raid') }</div>
|
||||||
</div>
|
</div>
|
||||||
{ (!props.user || (account.user && account.user.id !== props.user.id)) ?
|
{ (account.authorized && (props.user && account.user && account.user.id !== props.user.id)) ?
|
||||||
<Button
|
<Button
|
||||||
active={props.favorited}
|
active={props.favorited}
|
||||||
icon="save"
|
icon="save"
|
||||||
|
|
@ -122,9 +128,9 @@ const GridRep = (props: Props) => {
|
||||||
<div className="bottom">
|
<div className="bottom">
|
||||||
<div className={userClass}>
|
<div className={userClass}>
|
||||||
{ userImage() }
|
{ userImage() }
|
||||||
{ (props.user) ? props.user.username : 'Anonymous' }
|
{ (props.user) ? props.user.username : t('no_user') }
|
||||||
</div>
|
</div>
|
||||||
<time className="last-updated" dateTime={props.createdAt.toISOString()}>{formatTimeAgo(props.createdAt, 'en-us')}</time>
|
<time className="last-updated" dateTime={props.createdAt.toISOString()}>{formatTimeAgo(props.createdAt, locale)}</time>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,73 @@
|
||||||
padding: 6px 12px;
|
padding: 6px 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.language {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
gap: $unit;
|
||||||
|
padding-right: $unit;
|
||||||
|
|
||||||
|
span {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Switch {
|
||||||
|
$height: 24px;
|
||||||
|
|
||||||
|
background: $grey-60;
|
||||||
|
border-radius: calc($height / 2);
|
||||||
|
border: none;
|
||||||
|
position: relative;
|
||||||
|
width: 44px;
|
||||||
|
height: $height;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Thumb {
|
||||||
|
$diameter: 18px;
|
||||||
|
|
||||||
|
background: white;
|
||||||
|
border-radius: calc($diameter / 2);
|
||||||
|
display: block;
|
||||||
|
height: $diameter;
|
||||||
|
width: $diameter;
|
||||||
|
transition: transform 100ms;
|
||||||
|
transform: translateX(-2px);
|
||||||
|
z-index: 3;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-state="checked"] {
|
||||||
|
background: white;
|
||||||
|
transform: translateX(17px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.left, .right {
|
||||||
|
color: white;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: $bold;
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
top: 6px;
|
||||||
|
left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
top: 6px;
|
||||||
|
right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: $grey-40;
|
color: $grey-40;
|
||||||
}
|
}
|
||||||
|
|
@ -54,7 +121,7 @@
|
||||||
|
|
||||||
img {
|
img {
|
||||||
$diameter: 32px;
|
$diameter: 32px;
|
||||||
border-radius: $diameter / 2;
|
border-radius: calc($diameter / 2);
|
||||||
height: $diameter;
|
height: $diameter;
|
||||||
width: $diameter;
|
width: $diameter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import React from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import Link from 'next/link'
|
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import Router, { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
|
import Link from 'next/link'
|
||||||
|
import * as Switch from '@radix-ui/react-switch'
|
||||||
|
|
||||||
import AboutModal from '~components/AboutModal'
|
import AboutModal from '~components/AboutModal'
|
||||||
import AccountModal from '~components/AccountModal'
|
import AccountModal from '~components/AccountModal'
|
||||||
|
|
@ -16,8 +20,27 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const HeaderMenu = (props: Props) => {
|
const HeaderMenu = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const [accountCookies] = useCookies(['account'])
|
const [accountCookies] = useCookies(['account'])
|
||||||
const [userCookies] = useCookies(['user'])
|
const [userCookies] = useCookies(['user'])
|
||||||
|
const [cookies, setCookies] = useCookies()
|
||||||
|
|
||||||
|
const [checked, setChecked] = useState(false)
|
||||||
|
|
||||||
|
// console.log(`Currently: ${checked} ${cookies['NEXT_LOCALE']}`)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const locale = cookies['NEXT_LOCALE']
|
||||||
|
setChecked((locale === 'ja') ? true : false)
|
||||||
|
}, [cookies])
|
||||||
|
|
||||||
|
function handleCheckedChange(value: boolean) {
|
||||||
|
const language = (value) ? 'ja' : 'en'
|
||||||
|
setCookies('NEXT_LOCALE', language, { path: '/'})
|
||||||
|
router.push(router.asPath, undefined, { locale: language })
|
||||||
|
}
|
||||||
|
|
||||||
function authItems() {
|
function authItems() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -35,22 +58,22 @@ const HeaderMenu = (props: Props) => {
|
||||||
/profile/${userCookies.user.picture}@2x.png 2x`}
|
/profile/${userCookies.user.picture}@2x.png 2x`}
|
||||||
src={`/profile/${userCookies.user.picture}.png`}
|
src={`/profile/${userCookies.user.picture}.png`}
|
||||||
/>
|
/>
|
||||||
</div
|
</div>
|
||||||
></Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<Link href={`/saved` || ''}>Saved</Link>
|
<Link href={`/saved` || ''}>{t('menu.saved')}</Link>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
<div className="MenuGroup">
|
<div className="MenuGroup">
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<Link href='/teams'>Teams</Link>
|
<Link href='/teams'>{t('menu.teams')}</Link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="MenuItem disabled">
|
<li className="MenuItem disabled">
|
||||||
<div>
|
<div>
|
||||||
<span>Guides</span>
|
<span>{t('menu.guides')}</span>
|
||||||
<i className="tag">Coming Soon</i>
|
<i className="tag">{t('coming_soon')}</i>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -58,7 +81,7 @@ const HeaderMenu = (props: Props) => {
|
||||||
<AboutModal />
|
<AboutModal />
|
||||||
<AccountModal />
|
<AccountModal />
|
||||||
<li className="MenuItem" onClick={props.logout}>
|
<li className="MenuItem" onClick={props.logout}>
|
||||||
<span>Logout</span>
|
<span>{t('menu.logout')}</span>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -70,20 +93,30 @@ const HeaderMenu = (props: Props) => {
|
||||||
return (
|
return (
|
||||||
<ul className="Menu unauth">
|
<ul className="Menu unauth">
|
||||||
<div className="MenuGroup">
|
<div className="MenuGroup">
|
||||||
<AboutModal />
|
<li className="MenuItem language">
|
||||||
|
<span>{t('menu.language')}</span>
|
||||||
|
<Switch.Root className="Switch" onCheckedChange={handleCheckedChange} checked={checked}>
|
||||||
|
<Switch.Thumb className="Thumb" />
|
||||||
|
<span className="left">JP</span>
|
||||||
|
<span className="right">EN</span>
|
||||||
|
</Switch.Root>
|
||||||
|
</li>
|
||||||
</div>
|
</div>
|
||||||
<div className="MenuGroup">
|
<div className="MenuGroup">
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<Link href='/teams'>Teams</Link>
|
<Link href='/teams'>{t('menu.teams')}</Link>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li className="MenuItem disabled">
|
<li className="MenuItem disabled">
|
||||||
<div>
|
<div>
|
||||||
<span>Guides</span>
|
<span>{t('menu.guides')}</span>
|
||||||
<i className="tag">Coming Soon</i>
|
<i className="tag">{t('coming_soon')}</i>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="MenuGroup">
|
||||||
|
<AboutModal />
|
||||||
|
</div>
|
||||||
<div className="MenuGroup">
|
<div className="MenuGroup">
|
||||||
<LoginModal />
|
<LoginModal />
|
||||||
<SignupModal />
|
<SignupModal />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import Router, { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'react-i18next'
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosResponse } from 'axios'
|
||||||
|
|
||||||
import * as Dialog from '@radix-ui/react-dialog'
|
import * as Dialog from '@radix-ui/react-dialog'
|
||||||
|
|
@ -24,6 +26,9 @@ interface ErrorMap {
|
||||||
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||||
|
|
||||||
const LoginModal = (props: Props) => {
|
const LoginModal = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Set up form states and error handling
|
// Set up form states and error handling
|
||||||
const [formValid, setFormValid] = useState(false)
|
const [formValid, setFormValid] = useState(false)
|
||||||
const [errors, setErrors] = useState<ErrorMap>({
|
const [errors, setErrors] = useState<ErrorMap>({
|
||||||
|
|
@ -49,16 +54,16 @@ const LoginModal = (props: Props) => {
|
||||||
switch(name) {
|
switch(name) {
|
||||||
case 'email':
|
case 'email':
|
||||||
if (value.length == 0)
|
if (value.length == 0)
|
||||||
newErrors.email = 'Please enter your email'
|
newErrors.email = t('modals.login.errors.empty_email')
|
||||||
else if (!emailRegex.test(value))
|
else if (!emailRegex.test(value))
|
||||||
newErrors.email = 'That email address is not valid'
|
newErrors.email = t('modals.login.errors.invalid_email')
|
||||||
else
|
else
|
||||||
newErrors.email = ''
|
newErrors.email = ''
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'password':
|
case 'password':
|
||||||
newErrors.password = value.length == 0
|
newErrors.password = value.length == 0
|
||||||
? 'Please enter your password'
|
? t('modals.login.errors.empty_password')
|
||||||
: ''
|
: ''
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
@ -117,7 +122,7 @@ const LoginModal = (props: Props) => {
|
||||||
access_token: response.data.access_token
|
access_token: response.data.access_token
|
||||||
}
|
}
|
||||||
|
|
||||||
setCookies('account', cookieObj, { path: '/'})
|
setCookies('account', cookieObj, { path: '/' })
|
||||||
}
|
}
|
||||||
|
|
||||||
function storeUserInfo(response: AxiosResponse) {
|
function storeUserInfo(response: AxiosResponse) {
|
||||||
|
|
@ -129,9 +134,8 @@ const LoginModal = (props: Props) => {
|
||||||
language: user.language,
|
language: user.language,
|
||||||
}
|
}
|
||||||
|
|
||||||
setCookies('user', cookieObj, { path: '/'})
|
setCookies('user', cookieObj, { path: '/' })
|
||||||
|
|
||||||
accountState.account.language = user.language
|
|
||||||
accountState.account.user = {
|
accountState.account.user = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
|
|
@ -140,7 +144,16 @@ const LoginModal = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
accountState.account.authorized = true
|
accountState.account.authorized = true
|
||||||
|
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
|
changeLanguage(user.language)
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeLanguage(newLanguage: string) {
|
||||||
|
if (newLanguage !== router.locale) {
|
||||||
|
setCookies('NEXT_LOCALE', newLanguage, { path: '/'})
|
||||||
|
router.push(router.asPath, undefined, { locale: newLanguage })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openChange(open: boolean) {
|
function openChange(open: boolean) {
|
||||||
|
|
@ -155,13 +168,13 @@ const LoginModal = (props: Props) => {
|
||||||
<Dialog.Root open={open} onOpenChange={openChange}>
|
<Dialog.Root open={open} onOpenChange={openChange}>
|
||||||
<Dialog.Trigger asChild>
|
<Dialog.Trigger asChild>
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<span>Log in</span>
|
<span>{t('menu.login')}</span>
|
||||||
</li>
|
</li>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal>
|
<Dialog.Portal>
|
||||||
<Dialog.Content className="Login Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
<Dialog.Content className="Login Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||||
<div className="DialogHeader">
|
<div className="DialogHeader">
|
||||||
<Dialog.Title className="DialogTitle">Log in</Dialog.Title>
|
<Dialog.Title className="DialogTitle">{t('modals.login.title')}</Dialog.Title>
|
||||||
<Dialog.Close className="DialogClose" asChild>
|
<Dialog.Close className="DialogClose" asChild>
|
||||||
<span>
|
<span>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
|
|
@ -172,7 +185,7 @@ const LoginModal = (props: Props) => {
|
||||||
<form className="form" onSubmit={login}>
|
<form className="form" onSubmit={login}>
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="email"
|
fieldName="email"
|
||||||
placeholder="Email address"
|
placeholder={t('modals.login.placeholders.email')}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
error={errors.email}
|
error={errors.email}
|
||||||
ref={emailInput}
|
ref={emailInput}
|
||||||
|
|
@ -180,13 +193,13 @@ const LoginModal = (props: Props) => {
|
||||||
|
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="password"
|
fieldName="password"
|
||||||
placeholder="Password"
|
placeholder={t('modals.login.placeholders.password')}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
error={errors.password}
|
error={errors.password}
|
||||||
ref={passwordInput}
|
ref={passwordInput}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button>Log in</Button>
|
<Button>{t('modals.login.buttons.confirm')}</Button>
|
||||||
</form>
|
</form>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
<Dialog.Overlay className="Overlay" />
|
<Dialog.Overlay className="Overlay" />
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import './index.scss'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { appState } from '~utils/appState'
|
import { appState } from '~utils/appState'
|
||||||
|
|
||||||
|
|
@ -8,7 +9,9 @@ import Segment from '~components/Segment'
|
||||||
import ToggleSwitch from '~components/ToggleSwitch'
|
import ToggleSwitch from '~components/ToggleSwitch'
|
||||||
|
|
||||||
import { GridType } from '~utils/enums'
|
import { GridType } from '~utils/enums'
|
||||||
import { useSnapshot } from 'valtio'
|
|
||||||
|
|
||||||
|
import './index.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
selectedTab: GridType
|
selectedTab: GridType
|
||||||
|
|
@ -17,6 +20,8 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const PartySegmentedControl = (props: Props) => {
|
const PartySegmentedControl = (props: Props) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const { party, grid } = useSnapshot(appState)
|
const { party, grid } = useSnapshot(appState)
|
||||||
|
|
||||||
function getElement() {
|
function getElement() {
|
||||||
|
|
@ -62,21 +67,21 @@ const PartySegmentedControl = (props: Props) => {
|
||||||
name="characters"
|
name="characters"
|
||||||
selected={props.selectedTab == GridType.Character}
|
selected={props.selectedTab == GridType.Character}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
>Characters</Segment>
|
>{t('party.segmented_control.characters')}</Segment>
|
||||||
|
|
||||||
<Segment
|
<Segment
|
||||||
groupName="grid"
|
groupName="grid"
|
||||||
name="weapons"
|
name="weapons"
|
||||||
selected={props.selectedTab == GridType.Weapon}
|
selected={props.selectedTab == GridType.Weapon}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
>Weapons</Segment>
|
>{t('party.segmented_control.weapons')}</Segment>
|
||||||
|
|
||||||
<Segment
|
<Segment
|
||||||
groupName="grid"
|
groupName="grid"
|
||||||
name="summons"
|
name="summons"
|
||||||
selected={props.selectedTab == GridType.Summon}
|
selected={props.selectedTab == GridType.Summon}
|
||||||
onClick={props.onClick}
|
onClick={props.onClick}
|
||||||
>Summons</Segment>
|
>{t('party.segmented_control.summons')}</Segment>
|
||||||
</SegmentedControl>
|
</SegmentedControl>
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { appState } from '~utils/appState'
|
import { appState } from '~utils/appState'
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
|
|
@ -14,6 +16,10 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFieldSet(props, ref) {
|
const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFieldSet(props, ref) {
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const [raids, setRaids] = useState<Raid[][]>()
|
const [raids, setRaids] = useState<Raid[][]>()
|
||||||
|
|
||||||
const raidGroups = [
|
const raidGroups = [
|
||||||
|
|
@ -37,7 +43,7 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
id: '0',
|
id: '0',
|
||||||
name: {
|
name: {
|
||||||
en: 'All raids',
|
en: 'All raids',
|
||||||
jp: '全て'
|
ja: '全てのマルチ'
|
||||||
},
|
},
|
||||||
level: 0,
|
level: 0,
|
||||||
group: 0,
|
group: 0,
|
||||||
|
|
@ -65,7 +71,7 @@ const RaidDropdown = React.forwardRef<HTMLSelectElement, Props>(function useFiel
|
||||||
const options = raids && raids.length > 0 && raids[index].length > 0 &&
|
const options = raids && raids.length > 0 && raids[index].length > 0 &&
|
||||||
raids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
raids[index].sort((a, b) => a.element - b.element).map((item, i) => {
|
||||||
return (
|
return (
|
||||||
<option key={i} value={item.id}>{item.name.en}</option>
|
<option key={i} value={item.id}>{item.name[locale]}</option>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import Link from 'next/link'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { Trans, useTranslation } from 'next-i18next'
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosResponse } from 'axios'
|
||||||
|
|
||||||
import * as Dialog from '@radix-ui/react-dialog'
|
import * as Dialog from '@radix-ui/react-dialog'
|
||||||
|
|
@ -26,6 +29,9 @@ interface ErrorMap {
|
||||||
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
const emailRegex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||||
|
|
||||||
const SignupModal = (props: Props) => {
|
const SignupModal = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Set up form states and error handling
|
// Set up form states and error handling
|
||||||
const [formValid, setFormValid] = useState(false)
|
const [formValid, setFormValid] = useState(false)
|
||||||
const [errors, setErrors] = useState<ErrorMap>({
|
const [errors, setErrors] = useState<ErrorMap>({
|
||||||
|
|
@ -56,7 +62,8 @@ const SignupModal = (props: Props) => {
|
||||||
username: usernameInput.current?.value,
|
username: usernameInput.current?.value,
|
||||||
email: emailInput.current?.value,
|
email: emailInput.current?.value,
|
||||||
password: passwordInput.current?.value,
|
password: passwordInput.current?.value,
|
||||||
password_confirmation: passwordConfirmationInput.current?.value
|
password_confirmation: passwordConfirmationInput.current?.value,
|
||||||
|
language: router.locale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -95,9 +102,9 @@ const SignupModal = (props: Props) => {
|
||||||
language: user.language,
|
language: user.language,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Set language
|
||||||
setCookies('user', cookieObj, { path: '/'})
|
setCookies('user', cookieObj, { path: '/'})
|
||||||
|
|
||||||
accountState.account.language = user.language
|
|
||||||
accountState.account.user = {
|
accountState.account.user = {
|
||||||
id: user.id,
|
id: user.id,
|
||||||
username: user.username,
|
username: user.username,
|
||||||
|
|
@ -138,7 +145,7 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
validateName(fieldName, value)
|
validateName(fieldName, value)
|
||||||
} else {
|
} else {
|
||||||
newErrors[fieldName] = `This ${fieldName} is already in use`
|
newErrors[fieldName] = t('modals.signup.errors.field_in_use', { field: fieldName})
|
||||||
setErrors(newErrors)
|
setErrors(newErrors)
|
||||||
setFormValid(false)
|
setFormValid(false)
|
||||||
}
|
}
|
||||||
|
|
@ -150,9 +157,9 @@ const SignupModal = (props: Props) => {
|
||||||
switch(fieldName) {
|
switch(fieldName) {
|
||||||
case 'username':
|
case 'username':
|
||||||
if (value.length < 3)
|
if (value.length < 3)
|
||||||
newErrors.username = 'Username must be at least 3 characters'
|
newErrors.username = t('modals.signup.errors.username_too_short')
|
||||||
else if (value.length > 20)
|
else if (value.length > 20)
|
||||||
newErrors.username = 'Username must be less than 20 characters'
|
newErrors.username = t('modals.signup.errors.username_too_long')
|
||||||
else
|
else
|
||||||
newErrors.username = ''
|
newErrors.username = ''
|
||||||
|
|
||||||
|
|
@ -161,7 +168,7 @@ const SignupModal = (props: Props) => {
|
||||||
case 'email':
|
case 'email':
|
||||||
newErrors.email = emailRegex.test(value)
|
newErrors.email = emailRegex.test(value)
|
||||||
? ''
|
? ''
|
||||||
: 'That email address is not valid'
|
: t('modals.signup.errors.invalid_email')
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -180,20 +187,20 @@ const SignupModal = (props: Props) => {
|
||||||
switch(name) {
|
switch(name) {
|
||||||
case 'password':
|
case 'password':
|
||||||
newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!)
|
newErrors.password = passwordInput.current?.value.includes(usernameInput.current?.value!)
|
||||||
? 'Your password should not contain your username'
|
? t('modals.signup.errors.password_contains_username')
|
||||||
: ''
|
: ''
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'password':
|
case 'password':
|
||||||
newErrors.password = value.length < 8
|
newErrors.password = value.length < 8
|
||||||
? 'Password must be at least 8 characters'
|
? t('modals.signup.errors.password_too_short')
|
||||||
: ''
|
: ''
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'confirm_password':
|
case 'confirm_password':
|
||||||
newErrors.passwordConfirmation = passwordInput.current?.value === passwordConfirmationInput.current?.value
|
newErrors.passwordConfirmation = passwordInput.current?.value === passwordConfirmationInput.current?.value
|
||||||
? ''
|
? ''
|
||||||
: 'Your passwords don\'t match'
|
: t('modals.signup.errors.passwords_dont_match')
|
||||||
break
|
break
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -231,13 +238,13 @@ const SignupModal = (props: Props) => {
|
||||||
<Dialog.Root open={open} onOpenChange={openChange}>
|
<Dialog.Root open={open} onOpenChange={openChange}>
|
||||||
<Dialog.Trigger asChild>
|
<Dialog.Trigger asChild>
|
||||||
<li className="MenuItem">
|
<li className="MenuItem">
|
||||||
<span>Sign up</span>
|
<span>{t('menu.signup')}</span>
|
||||||
</li>
|
</li>
|
||||||
</Dialog.Trigger>
|
</Dialog.Trigger>
|
||||||
<Dialog.Portal>
|
<Dialog.Portal>
|
||||||
<Dialog.Content className="Signup Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
<Dialog.Content className="Signup Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||||
<div className="DialogHeader">
|
<div className="DialogHeader">
|
||||||
<Dialog.Title className="DialogTitle">Sign up</Dialog.Title>
|
<Dialog.Title className="DialogTitle">{t('modals.signup.title')}</Dialog.Title>
|
||||||
<Dialog.Close className="DialogClose" asChild>
|
<Dialog.Close className="DialogClose" asChild>
|
||||||
<span>
|
<span>
|
||||||
<CrossIcon />
|
<CrossIcon />
|
||||||
|
|
@ -248,7 +255,7 @@ const SignupModal = (props: Props) => {
|
||||||
<form className="form" onSubmit={register}>
|
<form className="form" onSubmit={register}>
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="username"
|
fieldName="username"
|
||||||
placeholder="Username"
|
placeholder={t('modals.signup.placeholders.username')}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
error={errors.username}
|
error={errors.username}
|
||||||
ref={usernameInput}
|
ref={usernameInput}
|
||||||
|
|
@ -256,7 +263,7 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="email"
|
fieldName="email"
|
||||||
placeholder="Email address"
|
placeholder={t('modals.signup.placeholders.email')}
|
||||||
onChange={handleNameChange}
|
onChange={handleNameChange}
|
||||||
error={errors.email}
|
error={errors.email}
|
||||||
ref={emailInput}
|
ref={emailInput}
|
||||||
|
|
@ -264,7 +271,7 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="password"
|
fieldName="password"
|
||||||
placeholder="Password"
|
placeholder={t('modals.signup.placeholders.password')}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
error={errors.password}
|
error={errors.password}
|
||||||
ref={passwordInput}
|
ref={passwordInput}
|
||||||
|
|
@ -272,16 +279,18 @@ const SignupModal = (props: Props) => {
|
||||||
|
|
||||||
<Fieldset
|
<Fieldset
|
||||||
fieldName="confirm_password"
|
fieldName="confirm_password"
|
||||||
placeholder="Password (again)"
|
placeholder={t('modals.signup.placeholders.password_confirm')}
|
||||||
onChange={handlePasswordChange}
|
onChange={handlePasswordChange}
|
||||||
error={errors.passwordConfirmation}
|
error={errors.passwordConfirmation}
|
||||||
ref={passwordConfirmationInput}
|
ref={passwordConfirmationInput}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button>Sign up</Button>
|
<Button>{t('modals.signup.buttons.confirm')}</Button>
|
||||||
|
|
||||||
<Dialog.Description className="terms">
|
<Dialog.Description className="terms">
|
||||||
By signing up, I agree to the<br /><a href="#">Terms and Conditions</a> and <a href="#">Usage Guidelines</a>.
|
<Trans i18nKey="modals.signup.agreement">
|
||||||
|
By signing up, I agree to the <Link href="/privacy">Privacy Policy</Link><Link href="/usage">Usage Guidelines</Link>.
|
||||||
|
</Trans>
|
||||||
</Dialog.Description>
|
</Dialog.Description>
|
||||||
</form>
|
</form>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosResponse } from 'axios'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
|
@ -26,6 +27,8 @@ const SummonGrid = (props: Props) => {
|
||||||
// Constants
|
// Constants
|
||||||
const numSummons: number = 4
|
const numSummons: number = 4
|
||||||
|
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [cookies, _] = useCookies(['account'])
|
const [cookies, _] = useCookies(['account'])
|
||||||
const headers = (cookies.account != null) ? {
|
const headers = (cookies.account != null) ? {
|
||||||
|
|
@ -239,7 +242,7 @@ const SummonGrid = (props: Props) => {
|
||||||
// Render: JSX components
|
// Render: JSX components
|
||||||
const mainSummonElement = (
|
const mainSummonElement = (
|
||||||
<div className="LabeledUnit">
|
<div className="LabeledUnit">
|
||||||
<div className="Label">Main Summon</div>
|
<div className="Label">{t('summons.main')}</div>
|
||||||
<SummonUnit
|
<SummonUnit
|
||||||
gridSummon={grid.summons.mainSummon}
|
gridSummon={grid.summons.mainSummon}
|
||||||
editable={party.editable}
|
editable={party.editable}
|
||||||
|
|
@ -254,7 +257,7 @@ const SummonGrid = (props: Props) => {
|
||||||
|
|
||||||
const friendSummonElement = (
|
const friendSummonElement = (
|
||||||
<div className="LabeledUnit">
|
<div className="LabeledUnit">
|
||||||
<div className="Label">Friend Summon</div>
|
<div className="Label">{t('summons.friend')}</div>
|
||||||
<SummonUnit
|
<SummonUnit
|
||||||
gridSummon={grid.summons.friendSummon}
|
gridSummon={grid.summons.friendSummon}
|
||||||
editable={party.editable}
|
editable={party.editable}
|
||||||
|
|
@ -268,7 +271,7 @@ const SummonGrid = (props: Props) => {
|
||||||
)
|
)
|
||||||
const summonGridElement = (
|
const summonGridElement = (
|
||||||
<div id="LabeledGrid">
|
<div id="LabeledGrid">
|
||||||
<div className="Label">Summons</div>
|
<div className="Label">{t('summons.summons')}</div>
|
||||||
<ul id="grid_summons">
|
<ul id="grid_summons">
|
||||||
{Array.from(Array(numSummons)).map((x, i) => {
|
{Array.from(Array(numSummons)).map((x, i) => {
|
||||||
return (<li key={`grid_unit_${i}`} >
|
return (<li key={`grid_unit_${i}`} >
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||||
|
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
|
|
||||||
import { axData } from '~utils/axData'
|
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -21,8 +22,11 @@ interface KeyNames {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SummonHovercard = (props: 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 Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
|
||||||
|
|
||||||
const tintElement = Element[props.gridSummon.object.element]
|
const tintElement = Element[props.gridSummon.object.element]
|
||||||
const wikiUrl = `https://gbf.wiki/${props.gridSummon.object.name.en.replaceAll(' ', '_')}`
|
const wikiUrl = `https://gbf.wiki/${props.gridSummon.object.name.en.replaceAll(' ', '_')}`
|
||||||
|
|
@ -57,8 +61,8 @@ const SummonHovercard = (props: Props) => {
|
||||||
<HoverCard.Content className="Weapon Hovercard">
|
<HoverCard.Content className="Weapon Hovercard">
|
||||||
<div className="top">
|
<div className="top">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h4>{ props.gridSummon.object.name.en }</h4>
|
<h4>{ props.gridSummon.object.name[locale] }</h4>
|
||||||
<img alt={props.gridSummon.object.name.en} src={summonImage()} />
|
<img alt={props.gridSummon.object.name[locale]} src={summonImage()} />
|
||||||
</div>
|
</div>
|
||||||
<div className="subInfo">
|
<div className="subInfo">
|
||||||
<div className="icons">
|
<div className="icons">
|
||||||
|
|
@ -72,7 +76,7 @@ const SummonHovercard = (props: Props) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">View more on gbf.wiki</a>
|
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">{t('buttons.wiki')}</a>
|
||||||
<HoverCard.Arrow />
|
<HoverCard.Arrow />
|
||||||
</HoverCard.Content>
|
</HoverCard.Content>
|
||||||
</HoverCard.Root>
|
</HoverCard.Root>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
|
|
||||||
|
|
@ -11,28 +13,29 @@ interface Props {
|
||||||
|
|
||||||
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
|
|
||||||
class SummonResult extends React.Component<Props> {
|
const SummonResult = (props: Props) => {
|
||||||
render() {
|
const router = useRouter()
|
||||||
const summon = this.props.data
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
return (
|
const summon = props.data
|
||||||
<li className="SummonResult" onClick={this.props.onClick}>
|
|
||||||
<img alt={summon.name.en} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}.jpg`} />
|
return (
|
||||||
<div className="Info">
|
<li className="SummonResult" onClick={props.onClick}>
|
||||||
<h5>{summon.name.en}</h5>
|
<img alt={summon.name[locale]} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/summon-grid/${summon.granblue_id}.jpg`} />
|
||||||
<UncapIndicator
|
<div className="Info">
|
||||||
type="summon"
|
<h5>{summon.name[locale]}</h5>
|
||||||
flb={summon.uncap.flb}
|
<UncapIndicator
|
||||||
ulb={summon.uncap.ulb}
|
type="summon"
|
||||||
special={false}
|
flb={summon.uncap.flb}
|
||||||
/>
|
ulb={summon.uncap.ulb}
|
||||||
<div className="tags">
|
special={false}
|
||||||
<WeaponLabelIcon labelType={Element[summon.element]} />
|
/>
|
||||||
</div>
|
<div className="tags">
|
||||||
|
<WeaponLabelIcon labelType={Element[summon.element]} />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
)
|
</li>
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SummonResult
|
export default SummonResult
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
import SearchModal from '~components/SearchModal'
|
import SearchModal from '~components/SearchModal'
|
||||||
|
|
@ -18,8 +20,13 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SummonUnit = (props: Props) => {
|
const SummonUnit = (props: Props) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const [imageUrl, setImageUrl] = useState('')
|
const [imageUrl, setImageUrl] = useState('')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const classes = classnames({
|
const classes = classnames({
|
||||||
SummonUnit: true,
|
SummonUnit: true,
|
||||||
'main': props.unitType == 0,
|
'main': props.unitType == 0,
|
||||||
|
|
@ -76,7 +83,7 @@ const SummonUnit = (props: Props) => {
|
||||||
|
|
||||||
const editableImage = (
|
const editableImage = (
|
||||||
<SearchModal
|
<SearchModal
|
||||||
placeholderText="Search for a summon..."
|
placeholderText={t('search.placeholders.summon')}
|
||||||
fromPosition={props.position}
|
fromPosition={props.position}
|
||||||
object="summons"
|
object="summons"
|
||||||
send={props.updateObject}>
|
send={props.updateObject}>
|
||||||
|
|
@ -97,7 +104,7 @@ const SummonUnit = (props: Props) => {
|
||||||
special={false}
|
special={false}
|
||||||
/> : ''
|
/> : ''
|
||||||
}
|
}
|
||||||
<h3 className="SummonName">{summon?.name.en}</h3>
|
<h3 className="SummonName">{summon?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
import { useSnapshot } from 'valtio'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import clonedeep from 'lodash.clonedeep'
|
import clonedeep from 'lodash.clonedeep'
|
||||||
import { useSnapshot } from 'valtio'
|
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
import { accountState, initialAccountState } from '~utils/accountState'
|
import { accountState, initialAccountState } from '~utils/accountState'
|
||||||
|
|
@ -13,6 +15,8 @@ import Button from '~components/Button'
|
||||||
import HeaderMenu from '~components/HeaderMenu'
|
import HeaderMenu from '~components/HeaderMenu'
|
||||||
|
|
||||||
const TopHeader = () => {
|
const TopHeader = () => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [accountCookies, setAccountCookie, removeAccountCookie] = useCookies(['account'])
|
const [accountCookies, setAccountCookie, removeAccountCookie] = useCookies(['account'])
|
||||||
const [userCookies, setUserCookies, removeUserCookie] = useCookies(['user'])
|
const [userCookies, setUserCookies, removeUserCookie] = useCookies(['user'])
|
||||||
|
|
@ -100,7 +104,7 @@ const TopHeader = () => {
|
||||||
const leftNav = () => {
|
const leftNav = () => {
|
||||||
return (
|
return (
|
||||||
<div className="dropdown">
|
<div className="dropdown">
|
||||||
<Button icon="menu">Menu</Button>
|
<Button icon="menu">{t('buttons.menu')}</Button>
|
||||||
{ (account.user) ?
|
{ (account.user) ?
|
||||||
<HeaderMenu authenticated={account.authorized} username={account.user.username} logout={logout} /> :
|
<HeaderMenu authenticated={account.authorized} username={account.user.username} logout={logout} /> :
|
||||||
<HeaderMenu authenticated={account.authorized} />
|
<HeaderMenu authenticated={account.authorized} />
|
||||||
|
|
@ -123,9 +127,9 @@ const TopHeader = () => {
|
||||||
saveButton() : ''
|
saveButton() : ''
|
||||||
}
|
}
|
||||||
{ (router.route === '/p/[party]') ?
|
{ (router.route === '/p/[party]') ?
|
||||||
<Button icon="link" onClick={copyToClipboard}>Copy link</Button> : ''
|
<Button icon="link" onClick={copyToClipboard}>{t('buttons.copy')}</Button> : ''
|
||||||
}
|
}
|
||||||
<Button icon="new" onClick={newParty}>New</Button>
|
<Button icon="new" onClick={newParty}>{t('buttons.new')}</Button>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import * as HoverCard from '@radix-ui/react-hover-card'
|
import * as HoverCard from '@radix-ui/react-hover-card'
|
||||||
|
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
|
|
@ -15,30 +18,35 @@ interface Props {
|
||||||
|
|
||||||
interface KeyNames {
|
interface KeyNames {
|
||||||
[key: string]: {
|
[key: string]: {
|
||||||
|
[key: string]: string
|
||||||
en: string,
|
en: string,
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponHovercard = (props: Props) => {
|
const WeaponHovercard = (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 Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
||||||
const WeaponKeyNames: KeyNames = {
|
const WeaponKeyNames: KeyNames = {
|
||||||
'2': {
|
'2': {
|
||||||
en: 'Pendulum',
|
en: 'Pendulum',
|
||||||
jp: ''
|
ja: 'ペンデュラム'
|
||||||
},
|
},
|
||||||
'3': {
|
'3': {
|
||||||
en: 'Teluma',
|
en: 'Teluma',
|
||||||
jp: ''
|
ja: 'テルマ'
|
||||||
},
|
},
|
||||||
'17': {
|
'17': {
|
||||||
en: 'Gauph Key',
|
en: 'Gauph Key',
|
||||||
jp: ''
|
ja: 'ガフスキー'
|
||||||
},
|
},
|
||||||
'22': {
|
'22': {
|
||||||
en: 'Emblem',
|
en: 'Emblem',
|
||||||
jp: ''
|
ja: 'エンブレム'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +69,7 @@ const WeaponHovercard = (props: Props) => {
|
||||||
const simpleAxSkill = props.gridWeapon.ax[0]
|
const simpleAxSkill = props.gridWeapon.ax[0]
|
||||||
const axSkill = primaryAxSkills.find(skill => skill.id == simpleAxSkill.modifier)
|
const axSkill = primaryAxSkills.find(skill => skill.id == simpleAxSkill.modifier)
|
||||||
|
|
||||||
return `${axSkill?.name.en} +${simpleAxSkill.strength}${ (axSkill?.suffix) ? axSkill.suffix : '' }`
|
return `${axSkill?.name[locale]} +${simpleAxSkill.strength}${ (axSkill?.suffix) ? axSkill.suffix : '' }`
|
||||||
}
|
}
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
|
@ -78,7 +86,7 @@ const WeaponHovercard = (props: Props) => {
|
||||||
|
|
||||||
if (primaryAxSkill && primaryAxSkill.secondary) {
|
if (primaryAxSkill && primaryAxSkill.secondary) {
|
||||||
const secondaryAxSkill = primaryAxSkill.secondary.find(skill => skill.id == secondarySimpleAxSkill.modifier)
|
const secondaryAxSkill = primaryAxSkill.secondary.find(skill => skill.id == secondarySimpleAxSkill.modifier)
|
||||||
return `${secondaryAxSkill?.name.en} +${secondarySimpleAxSkill.strength}${ (secondaryAxSkill?.suffix) ? secondaryAxSkill.suffix : '' }`
|
return `${secondaryAxSkill?.name[locale]} +${secondarySimpleAxSkill.strength}${ (secondaryAxSkill?.suffix) ? secondaryAxSkill.suffix : '' }`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -97,14 +105,14 @@ const WeaponHovercard = (props: Props) => {
|
||||||
const keysSection = (
|
const keysSection = (
|
||||||
<section className="weaponKeys">
|
<section className="weaponKeys">
|
||||||
{ (WeaponKeyNames[props.gridWeapon.object.series]) ?
|
{ (WeaponKeyNames[props.gridWeapon.object.series]) ?
|
||||||
<h5 className={tintElement}>{ WeaponKeyNames[props.gridWeapon.object.series].en }s</h5> : ''
|
<h5 className={tintElement}>{ WeaponKeyNames[props.gridWeapon.object.series][locale] }{ (locale === 'en') ? 's' : '' }</h5> : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
{ (props.gridWeapon.weapon_keys) ?
|
{ (props.gridWeapon.weapon_keys) ?
|
||||||
Array.from(Array(props.gridWeapon.weapon_keys.length)).map((x, i) => {
|
Array.from(Array(props.gridWeapon.weapon_keys.length)).map((x, i) => {
|
||||||
return (
|
return (
|
||||||
<div className="weaponKey" key={props.gridWeapon.weapon_keys![i].id}>
|
<div className="weaponKey" key={props.gridWeapon.weapon_keys![i].id}>
|
||||||
<span>{props.gridWeapon.weapon_keys![i].name.en}</span>
|
<span>{props.gridWeapon.weapon_keys![i].name[locale]}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}) : '' }
|
}) : '' }
|
||||||
|
|
@ -113,16 +121,16 @@ const WeaponHovercard = (props: Props) => {
|
||||||
|
|
||||||
const axSection = (
|
const axSection = (
|
||||||
<section className="axSkills">
|
<section className="axSkills">
|
||||||
<h5 className={tintElement}>AX Skills</h5>
|
<h5 className={tintElement}>{t('modals.weapon.subtitles.ax_skills')}</h5>
|
||||||
<div className="skills">
|
<div className="skills">
|
||||||
<div className="primary axSkill">
|
<div className="primary axSkill">
|
||||||
<img src={`/icons/ax/primary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[0].modifier : '' }.png`} />
|
<img alt="AX1" src={`/icons/ax/primary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[0].modifier : '' }.png`} />
|
||||||
<span>{createPrimaryAxSkillString()}</span>
|
<span>{createPrimaryAxSkillString()}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ (props.gridWeapon.ax && props.gridWeapon.ax[1].modifier && props.gridWeapon.ax[1].strength) ?
|
{ (props.gridWeapon.ax && props.gridWeapon.ax[1].modifier && props.gridWeapon.ax[1].strength) ?
|
||||||
<div className="secondary axSkill">
|
<div className="secondary axSkill">
|
||||||
<img src={`/icons/ax/secondary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[1].modifier : '' }.png`} />
|
<img alt="AX2" src={`/icons/ax/secondary_${ (props.gridWeapon.ax) ? props.gridWeapon.ax[1].modifier : '' }.png`} />
|
||||||
<span>{createSecondaryAxSkillString()}</span>
|
<span>{createSecondaryAxSkillString()}</span>
|
||||||
</div> : ''}
|
</div> : ''}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -137,8 +145,8 @@ const WeaponHovercard = (props: Props) => {
|
||||||
<HoverCard.Content className="Weapon Hovercard" side={hovercardSide()}>
|
<HoverCard.Content className="Weapon Hovercard" side={hovercardSide()}>
|
||||||
<div className="top">
|
<div className="top">
|
||||||
<div className="title">
|
<div className="title">
|
||||||
<h4>{ props.gridWeapon.object.name.en }</h4>
|
<h4>{ props.gridWeapon.object.name[locale] }</h4>
|
||||||
<img alt={props.gridWeapon.object.name.en} src={weaponImage()} />
|
<img alt={props.gridWeapon.object.name[locale]} src={weaponImage()} />
|
||||||
</div>
|
</div>
|
||||||
<div className="subInfo">
|
<div className="subInfo">
|
||||||
<div className="icons">
|
<div className="icons">
|
||||||
|
|
@ -158,7 +166,7 @@ const WeaponHovercard = (props: Props) => {
|
||||||
|
|
||||||
{ (props.gridWeapon.object.ax > 0 && props.gridWeapon.ax && props.gridWeapon.ax[0].modifier && props.gridWeapon.ax[0].strength ) ? axSection : '' }
|
{ (props.gridWeapon.object.ax > 0 && props.gridWeapon.ax && props.gridWeapon.ax[0].modifier && props.gridWeapon.ax[0].strength ) ? axSection : '' }
|
||||||
{ (props.gridWeapon.weapon_keys && props.gridWeapon.weapon_keys.length > 0) ? keysSection : '' }
|
{ (props.gridWeapon.weapon_keys && props.gridWeapon.weapon_keys.length > 0) ? keysSection : '' }
|
||||||
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">View more on gbf.wiki</a>
|
<a className={`Button ${tintElement}`} href={wikiUrl} target="_new">{t('buttons.wiki')}</a>
|
||||||
<HoverCard.Arrow />
|
<HoverCard.Arrow />
|
||||||
</HoverCard.Content>
|
</HoverCard.Content>
|
||||||
</HoverCard.Root>
|
</HoverCard.Root>
|
||||||
|
|
|
||||||
|
|
@ -6,74 +6,142 @@
|
||||||
|
|
||||||
/* Elements */
|
/* Elements */
|
||||||
|
|
||||||
&.fire {
|
&.fire.en {
|
||||||
background-image: url('/labels/element/Label_Element_Fire.png')
|
background-image: url('/labels/element/fire_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.water {
|
&.fire.ja {
|
||||||
background-image: url('/labels/element/Label_Element_Water.png')
|
background-image: url('/labels/element/fire_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.earth {
|
&.water.en {
|
||||||
background-image: url('/labels/element/Label_Element_Earth.png')
|
background-image: url('/labels/element/water_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.wind {
|
&.water.ja {
|
||||||
background-image: url('/labels/element/Label_Element_Wind.png')
|
background-image: url('/labels/element/water_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dark {
|
&.earth.en {
|
||||||
background-image: url('/labels/element/Label_Element_Dark.png')
|
background-image: url('/labels/element/earth_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.light {
|
&.earth.ja {
|
||||||
background-image: url('/labels/element/Label_Element_Light.png')
|
background-image: url('/labels/element/earth_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.null {
|
&.wind.en {
|
||||||
background-image: url('/labels/element/Label_Element_Any.png')
|
background-image: url('/labels/element/wind_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.wind.ja {
|
||||||
|
background-image: url('/labels/element/wind_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark.en {
|
||||||
|
background-image: url('/labels/element/dark_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dark.ja {
|
||||||
|
background-image: url('/labels/element/dark_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.light.en {
|
||||||
|
background-image: url('/labels/element/light_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.light.ja {
|
||||||
|
background-image: url('/labels/element/light_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.null.en {
|
||||||
|
background-image: url('/labels/element/any_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.null.ja {
|
||||||
|
background-image: url('/labels/element/any_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Proficiencies */
|
/* Proficiencies */
|
||||||
|
|
||||||
&.sword {
|
&.sword.en {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Sabre.png')
|
background-image: url('/labels/proficiency/sabre_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.dagger {
|
&.sword.ja {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Dagger.png')
|
background-image: url('/labels/proficiency/sabre_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.axe {
|
&.dagger.en {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Axe.png')
|
background-image: url('/labels/proficiency/dagger_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.spear {
|
&.dagger.ja {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Spear.png')
|
background-image: url('/labels/proficiency/dagger_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.staff {
|
&.axe.en {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Staff.png')
|
background-image: url('/labels/proficiency/axe_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.fist {
|
&.axe.ja {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Melee.png')
|
background-image: url('/labels/proficiency/axe_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.harp {
|
&.spear.en {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Harp.png')
|
background-image: url('/labels/proficiency/spear_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.gun {
|
&.spear.ja {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Gun.png')
|
background-image: url('/labels/proficiency/spear_ja.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.bow {
|
&.staff.en {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Bow.png')
|
background-image: url('/labels/proficiency/staff_en.png')
|
||||||
}
|
}
|
||||||
|
|
||||||
&.katana {
|
&.staff.ja {
|
||||||
background-image: url('/labels/proficiency/Label_Weapon_Katana.png')
|
background-image: url('/labels/proficiency/staff_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fist.en {
|
||||||
|
background-image: url('/labels/proficiency/melee_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.fist.ja {
|
||||||
|
background-image: url('/labels/proficiency/melee_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.harp.en {
|
||||||
|
background-image: url('/labels/proficiency/harp_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.harp.ja {
|
||||||
|
background-image: url('/labels/proficiency/harp_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.gun.en {
|
||||||
|
background-image: url('/labels/proficiency/gun_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.gun.ja {
|
||||||
|
background-image: url('/labels/proficiency/gun_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bow.en {
|
||||||
|
background-image: url('/labels/proficiency/bow_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.bow.ja {
|
||||||
|
background-image: url('/labels/proficiency/bow_ja.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.katana.en {
|
||||||
|
background-image: url('/labels/proficiency/katana_en.png')
|
||||||
|
}
|
||||||
|
|
||||||
|
&.katana.ja {
|
||||||
|
background-image: url('/labels/proficiency/katana_ja.png')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import './index.scss'
|
import './index.scss'
|
||||||
|
|
||||||
|
|
@ -6,12 +7,12 @@ interface Props {
|
||||||
labelType: string
|
labelType: string
|
||||||
}
|
}
|
||||||
|
|
||||||
class WeaponLabelIcon extends React.Component<Props> {
|
const WeaponLabelIcon = (props: Props) => {
|
||||||
render() {
|
const router = useRouter()
|
||||||
return (
|
|
||||||
<i className={`WeaponLabelIcon ${this.props.labelType}`} />
|
return (
|
||||||
)
|
<i className={`WeaponLabelIcon ${props.labelType} ${router.locale}`} />
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WeaponLabelIcon
|
export default WeaponLabelIcon
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosResponse } from 'axios'
|
||||||
|
|
||||||
import * as Dialog from '@radix-ui/react-dialog'
|
import * as Dialog from '@radix-ui/react-dialog'
|
||||||
|
|
||||||
import AXSelect from '~components/AxSelect'
|
import AXSelect from '~components/AxSelect'
|
||||||
|
|
@ -33,6 +36,10 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponModal = (props: Props) => {
|
const WeaponModal = (props: Props) => {
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [cookies] = useCookies(['account'])
|
const [cookies] = useCookies(['account'])
|
||||||
const headers = (cookies.account != null) ? {
|
const headers = (cookies.account != null) ? {
|
||||||
|
|
@ -122,7 +129,7 @@ const WeaponModal = (props: Props) => {
|
||||||
const elementSelect = () => {
|
const elementSelect = () => {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<h3>Element</h3>
|
<h3>{t('modals.weapon.subtitles.element')}</h3>
|
||||||
<ElementToggle
|
<ElementToggle
|
||||||
currentElement={props.gridWeapon.element}
|
currentElement={props.gridWeapon.element}
|
||||||
sendValue={receiveElementValue}
|
sendValue={receiveElementValue}
|
||||||
|
|
@ -134,7 +141,7 @@ const WeaponModal = (props: Props) => {
|
||||||
const keySelect = () => {
|
const keySelect = () => {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<h3>Weapon Keys</h3>
|
<h3>{t('modals.weapon.subtitles.weapon_keys')}</h3>
|
||||||
{ ([2, 3, 17, 22].includes(props.gridWeapon.object.series)) ?
|
{ ([2, 3, 17, 22].includes(props.gridWeapon.object.series)) ?
|
||||||
<WeaponKeyDropdown
|
<WeaponKeyDropdown
|
||||||
currentValue={ (props.gridWeapon.weapon_keys) ? props.gridWeapon.weapon_keys[0] : undefined }
|
currentValue={ (props.gridWeapon.weapon_keys) ? props.gridWeapon.weapon_keys[0] : undefined }
|
||||||
|
|
@ -165,6 +172,7 @@ const WeaponModal = (props: Props) => {
|
||||||
const axSelect = () => {
|
const axSelect = () => {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
|
<h3>{t('modals.weapon.subtitles.ax_skills')}</h3>
|
||||||
<AXSelect
|
<AXSelect
|
||||||
axType={props.gridWeapon.object.ax}
|
axType={props.gridWeapon.object.ax}
|
||||||
currentSkills={props.gridWeapon.ax}
|
currentSkills={props.gridWeapon.ax}
|
||||||
|
|
@ -189,8 +197,8 @@ const WeaponModal = (props: Props) => {
|
||||||
<Dialog.Content className="Weapon Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
<Dialog.Content className="Weapon Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||||
<div className="DialogHeader">
|
<div className="DialogHeader">
|
||||||
<div className="DialogTop">
|
<div className="DialogTop">
|
||||||
<Dialog.Title className="SubTitle">Modify Weapon</Dialog.Title>
|
<Dialog.Title className="SubTitle">{t('modals.weapon.title')}</Dialog.Title>
|
||||||
<Dialog.Title className="DialogTitle">{props.gridWeapon.object.name.en}</Dialog.Title>
|
<Dialog.Title className="DialogTitle">{props.gridWeapon.object.name[locale]}</Dialog.Title>
|
||||||
</div>
|
</div>
|
||||||
<Dialog.Close className="DialogClose" asChild>
|
<Dialog.Close className="DialogClose" asChild>
|
||||||
<span>
|
<span>
|
||||||
|
|
@ -203,7 +211,7 @@ const WeaponModal = (props: Props) => {
|
||||||
{ (props.gridWeapon.object.element == 0) ? elementSelect() : '' }
|
{ (props.gridWeapon.object.element == 0) ? elementSelect() : '' }
|
||||||
{ ([2, 3, 17, 24].includes(props.gridWeapon.object.series)) ? keySelect() : '' }
|
{ ([2, 3, 17, 24].includes(props.gridWeapon.object.series)) ? keySelect() : '' }
|
||||||
{ (props.gridWeapon.object.ax > 0) ? axSelect() : '' }
|
{ (props.gridWeapon.object.ax > 0) ? axSelect() : '' }
|
||||||
<Button onClick={updateWeapon} disabled={props.gridWeapon.object.ax > 0 && !formValid}>Save Weapon</Button>
|
<Button onClick={updateWeapon} disabled={props.gridWeapon.object.ax > 0 && !formValid}>{t('modals.weapon.buttons.confirm')}</Button>
|
||||||
</div>
|
</div>
|
||||||
</Dialog.Content>
|
</Dialog.Content>
|
||||||
<Dialog.Overlay className="Overlay" />
|
<Dialog.Overlay className="Overlay" />
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
|
||||||
import UncapIndicator from '~components/UncapIndicator'
|
import UncapIndicator from '~components/UncapIndicator'
|
||||||
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
import WeaponLabelIcon from '~components/WeaponLabelIcon'
|
||||||
|
|
||||||
|
|
@ -13,29 +15,29 @@ const Element = ['null', 'wind', 'fire', 'water', 'earth', 'dark', 'light']
|
||||||
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
const Proficiency = ['none', 'sword', 'dagger', 'axe', 'spear', 'bow', 'staff', 'fist', 'harp', 'gun', 'katana']
|
||||||
const Series = ['seraphic', 'grand', 'opus', 'draconic', 'revenant', 'primal', 'beast','regalia', 'omega', 'olden_primal', 'hollowsky', 'xeno', 'astral', 'rose', 'ultima', 'bahamut', 'epic', 'ennead', 'cosmos', 'ancestral', 'superlative', 'vintage', 'class_champion', 'sephira', 'new_world_foundation']
|
const Series = ['seraphic', 'grand', 'opus', 'draconic', 'revenant', 'primal', 'beast','regalia', 'omega', 'olden_primal', 'hollowsky', 'xeno', 'astral', 'rose', 'ultima', 'bahamut', 'epic', 'ennead', 'cosmos', 'ancestral', 'superlative', 'vintage', 'class_champion', 'sephira', 'new_world_foundation']
|
||||||
|
|
||||||
class WeaponResult extends React.Component<Props> {
|
const WeaponResult = (props: Props) => {
|
||||||
render() {
|
const router = useRouter()
|
||||||
const weapon = this.props.data
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
const weapon = props.data
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li className="WeaponResult" onClick={this.props.onClick}>
|
<li className="WeaponResult" onClick={props.onClick}>
|
||||||
<img alt={weapon.name.en} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`} />
|
<img alt={weapon.name[locale]} src={`${process.env.NEXT_PUBLIC_SIERO_IMG_URL}/weapon-grid/${weapon.granblue_id}.jpg`} />
|
||||||
<div className="Info">
|
<div className="Info">
|
||||||
<h5>{weapon.name.en}</h5>
|
<h5>{weapon.name[locale]}</h5>
|
||||||
<UncapIndicator
|
<UncapIndicator
|
||||||
type="weapon"
|
type="weapon"
|
||||||
flb={weapon.uncap.flb}
|
flb={weapon.uncap.flb}
|
||||||
ulb={weapon.uncap.ulb}
|
ulb={weapon.uncap.ulb}
|
||||||
special={false}
|
special={false}
|
||||||
/>
|
/>
|
||||||
<div className="tags">
|
<div className="tags">
|
||||||
<WeaponLabelIcon labelType={Element[weapon.element]} />
|
<WeaponLabelIcon labelType={Element[weapon.element]} />
|
||||||
<WeaponLabelIcon labelType={Proficiency[weapon.proficiency]} />
|
<WeaponLabelIcon labelType={Proficiency[weapon.proficiency]} />
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</div>
|
||||||
)
|
</li>
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default WeaponResult
|
export default WeaponResult
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
import SearchModal from '~components/SearchModal'
|
import SearchModal from '~components/SearchModal'
|
||||||
|
|
@ -22,8 +24,13 @@ interface Props {
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponUnit = (props: Props) => {
|
const WeaponUnit = (props: Props) => {
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
const [imageUrl, setImageUrl] = useState('')
|
const [imageUrl, setImageUrl] = useState('')
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const locale = (router.locale && ['en', 'ja'].includes(router.locale)) ? router.locale : 'en'
|
||||||
|
|
||||||
const classes = classnames({
|
const classes = classnames({
|
||||||
WeaponUnit: true,
|
WeaponUnit: true,
|
||||||
'mainhand': props.unitType == 0,
|
'mainhand': props.unitType == 0,
|
||||||
|
|
@ -81,7 +88,7 @@ const WeaponUnit = (props: Props) => {
|
||||||
|
|
||||||
const editableImage = (
|
const editableImage = (
|
||||||
<SearchModal
|
<SearchModal
|
||||||
placeholderText="Search for a weapon..."
|
placeholderText={t('search.placeholders.weapon')}
|
||||||
fromPosition={props.position}
|
fromPosition={props.position}
|
||||||
object="weapons"
|
object="weapons"
|
||||||
send={props.updateObject}>
|
send={props.updateObject}>
|
||||||
|
|
@ -108,7 +115,7 @@ const WeaponUnit = (props: Props) => {
|
||||||
special={false}
|
special={false}
|
||||||
/> : ''
|
/> : ''
|
||||||
}
|
}
|
||||||
<h3 className="WeaponName">{weapon?.name.en}</h3>
|
<h3 className="WeaponName">{weapon?.name[locale]}</h3>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
6
next-i18next.config.js
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
i18n: {
|
||||||
|
defaultLocale: 'en',
|
||||||
|
locales: ['en', 'ja']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
/** @type {import('next').NextConfig} */
|
/** @type {import('next').NextConfig} */
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
const { i18n } = require('./next-i18next.config')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
|
|
@ -7,6 +8,7 @@ module.exports = {
|
||||||
prependData: '@import "variables";',
|
prependData: '@import "variables";',
|
||||||
includePaths: [path.join(__dirname, 'styles')],
|
includePaths: [path.join(__dirname, 'styles')],
|
||||||
},
|
},
|
||||||
|
i18n,
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
1271
package-lock.json
generated
|
|
@ -22,14 +22,19 @@
|
||||||
"@types/axios": "^0.14.0",
|
"@types/axios": "^0.14.0",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
|
"i18next": "^21.6.13",
|
||||||
|
"i18next-browser-languagedetector": "^6.1.3",
|
||||||
|
"i18next-http-backend": "^1.3.2",
|
||||||
"lodash.clonedeep": "^4.5.0",
|
"lodash.clonedeep": "^4.5.0",
|
||||||
"lodash.debounce": "^4.0.8",
|
"lodash.debounce": "^4.0.8",
|
||||||
"meyer-reset-scss": "^2.0.4",
|
"meyer-reset-scss": "^2.0.4",
|
||||||
"next": "12.0.8",
|
"next": "12.0.8",
|
||||||
|
"next-i18next": "^10.5.0",
|
||||||
|
"next-remote-watch": "^1.0.0",
|
||||||
"react": "17.0.2",
|
"react": "17.0.2",
|
||||||
"react-cookie": "^4.1.1",
|
"react-cookie": "^4.1.1",
|
||||||
"react-dom": "^17.0.2",
|
"react-dom": "^17.0.2",
|
||||||
"react-i18next": "^11.15.3",
|
"react-i18next": "^11.15.5",
|
||||||
"react-linkify": "^1.0.0-alpha",
|
"react-linkify": "^1.0.0-alpha",
|
||||||
"react-scroll": "^1.8.5",
|
"react-scroll": "^1.8.5",
|
||||||
"sass": "^1.49.0",
|
"sass": "^1.49.0",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
|
|
||||||
|
|
@ -13,6 +16,7 @@ const ProfileRoute: React.FC = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const { username } = router.query
|
const { username } = router.query
|
||||||
|
|
||||||
|
const { t } = useTranslation('common')
|
||||||
const [cookies] = useCookies(['account'])
|
const [cookies] = useCookies(['account'])
|
||||||
|
|
||||||
const [found, setFound] = useState(false)
|
const [found, setFound] = useState(false)
|
||||||
|
|
@ -169,7 +173,7 @@ const ProfileRoute: React.FC = () => {
|
||||||
</GridRepCollection>
|
</GridRepCollection>
|
||||||
{ (parties.length == 0) ?
|
{ (parties.length == 0) ?
|
||||||
<div id="NotFound">
|
<div id="NotFound">
|
||||||
<h2>{ (loading) ? 'Loading teams...' : 'No teams found' }</h2>
|
<h2>{ (loading) ? t('teams.loading') : t('teams.not_found') }</h2>
|
||||||
</div>
|
</div>
|
||||||
: '' }
|
: '' }
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -177,4 +181,23 @@ const ProfileRoute: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
return {
|
||||||
|
paths: [
|
||||||
|
// Object variant:
|
||||||
|
{ params: { username: 'string' } },
|
||||||
|
],
|
||||||
|
fallback: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ locale }: { locale: string }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, ['common'])),
|
||||||
|
// Will be passed to the page component as props
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default ProfileRoute
|
export default ProfileRoute
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import { useCookies, CookiesProvider } from 'react-cookie'
|
import { useCookies, CookiesProvider } from 'react-cookie'
|
||||||
|
import { appWithTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import type { AppProps } from 'next/app'
|
import type { AppProps } from 'next/app'
|
||||||
import Layout from '~components/Layout'
|
import Layout from '~components/Layout'
|
||||||
|
|
@ -16,7 +17,6 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||||
console.log(`Logged in as user "${cookies.account.username}"`)
|
console.log(`Logged in as user "${cookies.account.username}"`)
|
||||||
|
|
||||||
accountState.account.authorized = true
|
accountState.account.authorized = true
|
||||||
accountState.account.language = cookies.account.language
|
|
||||||
accountState.account.user = {
|
accountState.account.user = {
|
||||||
id: cookies.account.user_id,
|
id: cookies.account.user_id,
|
||||||
username: cookies.account.username,
|
username: cookies.account.username,
|
||||||
|
|
@ -37,4 +37,4 @@ function MyApp({ Component, pageProps }: AppProps) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MyApp
|
export default appWithTranslation(MyApp)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import Party from '~components/Party'
|
import Party from '~components/Party'
|
||||||
|
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
|
|
||||||
const NewRoute = () => {
|
const NewRoute = () => {
|
||||||
function callback(path: string) {
|
function callback(path: string) {
|
||||||
// This is scuffed, how do we do this natively?
|
// This is scuffed, how do we do this natively?
|
||||||
|
|
@ -14,4 +16,13 @@ const NewRoute = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ locale }: { locale: string }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, ['common'])),
|
||||||
|
// Will be passed to the page component as props
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default NewRoute
|
export default NewRoute
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
|
|
||||||
import Party from '~components/Party'
|
import Party from '~components/Party'
|
||||||
|
|
||||||
|
|
@ -30,4 +31,23 @@ const PartyRoute: React.FC = () => {
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getStaticPaths() {
|
||||||
|
return {
|
||||||
|
paths: [
|
||||||
|
// Object variant:
|
||||||
|
{ params: { party: 'string' } },
|
||||||
|
],
|
||||||
|
fallback: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ locale }: { locale: string }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, ['common'])),
|
||||||
|
// Will be passed to the page component as props
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default PartyRoute
|
export default PartyRoute
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useRouter } from 'next/router'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import clonedeep from 'lodash.clonedeep'
|
import clonedeep from 'lodash.clonedeep'
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
|
|
||||||
|
|
@ -12,6 +15,7 @@ import FilterBar from '~components/FilterBar'
|
||||||
|
|
||||||
const SavedRoute: React.FC = () => {
|
const SavedRoute: React.FC = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [cookies] = useCookies(['account'])
|
const [cookies] = useCookies(['account'])
|
||||||
|
|
@ -143,7 +147,7 @@ const SavedRoute: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div id="Teams">
|
<div id="Teams">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Your saved Teams</title>
|
<title>{t('saved.title')}</title>
|
||||||
|
|
||||||
<meta property="og:title" content="Your saved Teams" />
|
<meta property="og:title" content="Your saved Teams" />
|
||||||
<meta property="og:url" content="https://app.granblue.team/saved" />
|
<meta property="og:url" content="https://app.granblue.team/saved" />
|
||||||
|
|
@ -155,7 +159,7 @@ const SavedRoute: React.FC = () => {
|
||||||
</Head>
|
</Head>
|
||||||
|
|
||||||
<FilterBar onFilter={receiveFilters} scrolled={scrolled}>
|
<FilterBar onFilter={receiveFilters} scrolled={scrolled}>
|
||||||
<h1>Your saved Teams</h1>
|
<h1>{t('saved.title')}</h1>
|
||||||
</FilterBar>
|
</FilterBar>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
@ -182,7 +186,7 @@ const SavedRoute: React.FC = () => {
|
||||||
|
|
||||||
{ (parties.length == 0) ?
|
{ (parties.length == 0) ?
|
||||||
<div id="NotFound">
|
<div id="NotFound">
|
||||||
<h2>{ (loading) ? 'Loading saved teams...' : 'You haven't saved any teams yet' }</h2>
|
<h2>{ (loading) ? t('saved.loading') : t('saved.not_found') }</h2>
|
||||||
</div>
|
</div>
|
||||||
: '' }
|
: '' }
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -190,4 +194,13 @@ const SavedRoute: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ locale }: { locale: string }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, ['common'])),
|
||||||
|
// Will be passed to the page component as props
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default SavedRoute
|
export default SavedRoute
|
||||||
|
|
@ -1,9 +1,15 @@
|
||||||
import React, { useCallback, useEffect, useState } from 'react'
|
import React, { useCallback, useEffect, useState } from 'react'
|
||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
|
|
||||||
import { useRouter } from 'next/router'
|
import { useRouter } from 'next/router'
|
||||||
import { useCookies } from 'react-cookie'
|
import { useCookies } from 'react-cookie'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations'
|
||||||
|
|
||||||
import clonedeep from 'lodash.clonedeep'
|
import clonedeep from 'lodash.clonedeep'
|
||||||
|
|
||||||
|
|
||||||
import api from '~utils/api'
|
import api from '~utils/api'
|
||||||
|
|
||||||
import GridRep from '~components/GridRep'
|
import GridRep from '~components/GridRep'
|
||||||
|
|
@ -12,6 +18,7 @@ import FilterBar from '~components/FilterBar'
|
||||||
|
|
||||||
const TeamsRoute: React.FC = () => {
|
const TeamsRoute: React.FC = () => {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const [cookies] = useCookies(['account'])
|
const [cookies] = useCookies(['account'])
|
||||||
|
|
@ -148,7 +155,7 @@ const TeamsRoute: React.FC = () => {
|
||||||
return (
|
return (
|
||||||
<div id="Teams">
|
<div id="Teams">
|
||||||
<Head>
|
<Head>
|
||||||
<title>Discover Teams</title>
|
<title>{ t('teams.title') }</title>
|
||||||
|
|
||||||
<meta property="og:title" content="Discover Teams" />
|
<meta property="og:title" content="Discover Teams" />
|
||||||
<meta property="og:description" content="Find different Granblue Fantasy teams by raid, element or recency" />
|
<meta property="og:description" content="Find different Granblue Fantasy teams by raid, element or recency" />
|
||||||
|
|
@ -161,7 +168,7 @@ const TeamsRoute: React.FC = () => {
|
||||||
<meta name="twitter:description" content="Find different Granblue Fantasy teams by raid, element or recency" />
|
<meta name="twitter:description" content="Find different Granblue Fantasy teams by raid, element or recency" />
|
||||||
</Head>
|
</Head>
|
||||||
<FilterBar onFilter={receiveFilters} scrolled={scrolled}>
|
<FilterBar onFilter={receiveFilters} scrolled={scrolled}>
|
||||||
<h1>Discover Teams</h1>
|
<h1>{t('teams.title')}</h1>
|
||||||
</FilterBar>
|
</FilterBar>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
@ -188,7 +195,7 @@ const TeamsRoute: React.FC = () => {
|
||||||
|
|
||||||
{ (parties.length == 0) ?
|
{ (parties.length == 0) ?
|
||||||
<div id="NotFound">
|
<div id="NotFound">
|
||||||
<h2>{ (loading) ? 'Loading teams...' : 'No teams found' }</h2>
|
<h2>{ (loading) ? t('teams.loading') : t('teams.not_found') }</h2>
|
||||||
</div>
|
</div>
|
||||||
: '' }
|
: '' }
|
||||||
</section>
|
</section>
|
||||||
|
|
@ -196,4 +203,13 @@ const TeamsRoute: React.FC = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getStaticProps({ locale }: { locale: string }) {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
...(await serverSideTranslations(locale, ['common'])),
|
||||||
|
// Will be passed to the page component as props
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default TeamsRoute
|
export default TeamsRoute
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
BIN
public/labels/element/any_ja.png
Normal file
|
After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
public/labels/element/dark_ja.png
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
public/labels/element/earth_ja.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
public/labels/element/fire_ja.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
public/labels/element/light_ja.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 4.9 KiB |
BIN
public/labels/element/water_ja.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
public/labels/element/wind_ja.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.5 KiB |
BIN
public/labels/proficiency/axe_ja.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
BIN
public/labels/proficiency/bow_ja.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
public/labels/proficiency/dagger_ja.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
BIN
public/labels/proficiency/gun_ja.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
public/labels/proficiency/harp_ja.png
Normal file
|
After Width: | Height: | Size: 6 KiB |
|
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 6 KiB |
BIN
public/labels/proficiency/katana_ja.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
BIN
public/labels/proficiency/melee_ja.png
Normal file
|
After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 5.7 KiB |
BIN
public/labels/proficiency/sabre_ja.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
BIN
public/labels/proficiency/spear_ja.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 5.8 KiB |
BIN
public/labels/proficiency/staff_ja.png
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
182
public/locales/en/common.json
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
{
|
||||||
|
"ax": {
|
||||||
|
"no_skill": "No AX Skill",
|
||||||
|
"errors": {
|
||||||
|
"value_too_low": "{{name}} must be at least {{minValue}}{{suffix}}",
|
||||||
|
"value_too_high": "{{name}} cannot be greater than {{maxValue}}{{suffix}}",
|
||||||
|
"value_not_whole": "{{name}} must be a whole number",
|
||||||
|
"value_empty": "{{name}} must have a value"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"copy": "Copy link",
|
||||||
|
"delete": "Delete team",
|
||||||
|
"show_info": "Edit info",
|
||||||
|
"hide_info": "Hide info",
|
||||||
|
"menu": "Menu",
|
||||||
|
"new": "New",
|
||||||
|
"wiki": "View more on gbf.wiki"
|
||||||
|
},
|
||||||
|
"elements": {
|
||||||
|
"null": "Null",
|
||||||
|
"wind": "Wind",
|
||||||
|
"fire": "Fire",
|
||||||
|
"water": "Water",
|
||||||
|
"earth": "Earth",
|
||||||
|
"dark": "Dark",
|
||||||
|
"light": "Light",
|
||||||
|
"full": {
|
||||||
|
"all": "All elements",
|
||||||
|
"null": "Null",
|
||||||
|
"wind": "Wind",
|
||||||
|
"fire": "Fire",
|
||||||
|
"water": "Water",
|
||||||
|
"earth": "Earth",
|
||||||
|
"dark": "Dark",
|
||||||
|
"light": "Light"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recency": {
|
||||||
|
"all_time": "All time",
|
||||||
|
"last_day": "Last day",
|
||||||
|
"last_week": "Last week",
|
||||||
|
"last_month": "Last month",
|
||||||
|
"last_3_months": "Last 3 months",
|
||||||
|
"last_6_months": "Last 6 months",
|
||||||
|
"last_year": "Last year"
|
||||||
|
},
|
||||||
|
"summons": {
|
||||||
|
"main": "Main Summon",
|
||||||
|
"friend": "Friend Summon",
|
||||||
|
"summons": "Summons",
|
||||||
|
"subaura": "Sub Aura Summons"
|
||||||
|
},
|
||||||
|
"modals": {
|
||||||
|
"about": {
|
||||||
|
"title": "About"
|
||||||
|
},
|
||||||
|
"delete_team": {
|
||||||
|
"title": "Delete team",
|
||||||
|
"description": "Are you sure you want to permanently delete this team?",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "Yes, delete",
|
||||||
|
"cancel": "Nevermind"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "Log in",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "Log in"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"empty_email": "Please enter your email",
|
||||||
|
"empty_password": "Please enter your password",
|
||||||
|
"invalid_email": "That email address is not valid",
|
||||||
|
"invalid_credentials": "Your email address or password is incorrect"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"email": "Email address",
|
||||||
|
"password": "Password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "Account Settings",
|
||||||
|
"labels": {
|
||||||
|
"picture": "Picture",
|
||||||
|
"language": "Language",
|
||||||
|
"private": "Private"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"private": "Hide your profile and prevent your grids from showing up in collections"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"english": "English",
|
||||||
|
"japanese": "Japanese"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "Save settings"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"signup": {
|
||||||
|
"title": "Create an account",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "Sign up"
|
||||||
|
},
|
||||||
|
"agreement": "By signing up, I agree to the <br/><2>Privacy Policy</2> and <1>Usage Guidelines</1>.",
|
||||||
|
"errors": {
|
||||||
|
"field_in_use": "This {{field}} is already in use",
|
||||||
|
"empty_email": "Please enter your email",
|
||||||
|
"invalid_email": "That email address is not valid",
|
||||||
|
"username_too_short": "Username must be at least 3 characters",
|
||||||
|
"username_too_long": "Username must be less than 20 characters",
|
||||||
|
"empty_password": "Please enter your password",
|
||||||
|
"password_contains_username": "Your password should not contain your username",
|
||||||
|
"password_too_short": "Password must be at least 8 characters",
|
||||||
|
"mismatched_passwords": "Your passwords don't match"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"username": "Username",
|
||||||
|
"email": "Email address",
|
||||||
|
"password": "Password",
|
||||||
|
"password_confirm": "Password (again)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"weapon": {
|
||||||
|
"title": "Modify Weapon",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "Save weapon"
|
||||||
|
},
|
||||||
|
"subtitles": {
|
||||||
|
"element": "Element",
|
||||||
|
"ax_skills": "AX Skills",
|
||||||
|
"weapon_keys": "Weapon Keys"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"menu": {
|
||||||
|
"about": "About",
|
||||||
|
"guides": "Guides",
|
||||||
|
"language": "Language",
|
||||||
|
"login": "Log in",
|
||||||
|
"saved": "Saved",
|
||||||
|
"settings": "Settings",
|
||||||
|
"signup": "Sign up",
|
||||||
|
"teams": "Teams",
|
||||||
|
"logout": "Logout"
|
||||||
|
},
|
||||||
|
"party": {
|
||||||
|
"segmented_control": {
|
||||||
|
"class": "Class",
|
||||||
|
"characters": "Characters",
|
||||||
|
"weapons": "Weapons",
|
||||||
|
"summons": "Summons"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"saved": {
|
||||||
|
"title": "Your saved Teams",
|
||||||
|
"loading": "Loading saved teams...",
|
||||||
|
"not_found": "You haven't saved any teams"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"errors": {
|
||||||
|
"start_typing": "Start typing the name of a {{object}}",
|
||||||
|
"min_length": "Type at least 3 characters",
|
||||||
|
"no_results": "No results found for '{{query}}'"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"weapon": "Search for a weapon...",
|
||||||
|
"summon": "Search for a summon...",
|
||||||
|
"character": "Search for a weapon..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"teams": {
|
||||||
|
"title": "Discover Teams",
|
||||||
|
"loading": "Loading teams...",
|
||||||
|
"not_found": "No teams found"
|
||||||
|
},
|
||||||
|
"extra_weapons": "Additional<br/>Weapons",
|
||||||
|
"coming_soon": "Coming Soon",
|
||||||
|
"no_title": "Untitled",
|
||||||
|
"no_raid": "No raid",
|
||||||
|
"no_user": "Anonymous"
|
||||||
|
}
|
||||||
184
public/locales/ja/common.json
Normal file
|
|
@ -0,0 +1,184 @@
|
||||||
|
{
|
||||||
|
"ax": {
|
||||||
|
"no_skill": "EXスキルなし",
|
||||||
|
"errors": {
|
||||||
|
"value_too_low": "{{name}}は最低{{minValue}}{{suffix}}を入力してください",
|
||||||
|
"value_too_high": "{{name}}は最大{{maxValue}}を入力してください",
|
||||||
|
"value_not_whole": "{{name}}は整数でなければなりません",
|
||||||
|
"value_empty": "{{name}}を入力してください"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"copy": "リンクをコピー",
|
||||||
|
"delete": "編成を削除",
|
||||||
|
"show_info": "詳細を編集",
|
||||||
|
"hide_info": "詳細を非表示",
|
||||||
|
"menu": "メニュー",
|
||||||
|
"new": "作成",
|
||||||
|
"wiki": "gbf.wikiで詳しく見る"
|
||||||
|
},
|
||||||
|
"elements": {
|
||||||
|
"null": "無",
|
||||||
|
"wind": "風",
|
||||||
|
"fire": "火",
|
||||||
|
"water": "水",
|
||||||
|
"earth": "土",
|
||||||
|
"dark": "闇",
|
||||||
|
"light": "光",
|
||||||
|
"full": {
|
||||||
|
"all": "全属性",
|
||||||
|
"null": "無属性",
|
||||||
|
"wind": "風属性",
|
||||||
|
"fire": "火属性",
|
||||||
|
"water": "水属性",
|
||||||
|
"earth": "土属性",
|
||||||
|
"dark": "闇属性",
|
||||||
|
"light": "光属性"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recency": {
|
||||||
|
"all_time": "全ての期間",
|
||||||
|
"last_day": "1日",
|
||||||
|
"last_week": "7日",
|
||||||
|
"last_month": "1ヶ月",
|
||||||
|
"last_3_months": "3ヶ月",
|
||||||
|
"last_6_months": "6ヶ月",
|
||||||
|
"last_year": "1年"
|
||||||
|
},
|
||||||
|
"summons": {
|
||||||
|
"main": "メイン",
|
||||||
|
"friend": "フレンド",
|
||||||
|
"summons": "召喚石",
|
||||||
|
"subaura": "サブ加護召喚石"
|
||||||
|
},
|
||||||
|
"modals": {
|
||||||
|
"about": {
|
||||||
|
"title": "このサイトについて"
|
||||||
|
},
|
||||||
|
"delete_team": {
|
||||||
|
"title": "編成を削除しますか",
|
||||||
|
"description": "編成を削除する操作は取り消せません。",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "削除",
|
||||||
|
"cancel": "キャンセル"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"login": {
|
||||||
|
"title": "ログイン",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "ログイン"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"empty_email": "メールアドレスを入力して下さい",
|
||||||
|
"empty_password": "パスワードを入力して下さい",
|
||||||
|
"invalid_email": "メールアドレスは有効ではありません",
|
||||||
|
"invalid_credentials": "パスワードまたはメールアドレスが違います"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"email": "メールアドレス",
|
||||||
|
"password": "パスワード"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"title": "アカウント設定",
|
||||||
|
"labels": {
|
||||||
|
"picture": "プロフィール画像",
|
||||||
|
"language": "言語",
|
||||||
|
"private": "プライベート"
|
||||||
|
},
|
||||||
|
"descriptions": {
|
||||||
|
"private": "プロフィールを隠し、編成をコレクションに表示されないようにします"
|
||||||
|
},
|
||||||
|
"language": {
|
||||||
|
"english": "英語",
|
||||||
|
"japanese": "日本語"
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "設定を保存する"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"signup": {
|
||||||
|
"title": "アカウント登録",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "登録する"
|
||||||
|
},
|
||||||
|
"agreement": "続行することで<1>利用規約</1>に同意し、<br/><1>プライバシーポリシー</1>を読んだものとみなされます。",
|
||||||
|
"errors": {
|
||||||
|
"field_in_use": "入力された{{field}}は既に登録済みです",
|
||||||
|
"empty_email": "メールアドレスを入力して下さい",
|
||||||
|
"invalid_email": "メールアドレスは有効ではありません",
|
||||||
|
"username_too_short": "ユーザーネームは3文字以上で入力してください",
|
||||||
|
"username_too_long": "ユーザーネームは20文字以内で入力してください",
|
||||||
|
"empty_password": "パスワードを入力して下さい",
|
||||||
|
"password_contains_username": "パスワードにはユーザー名を含めないでください",
|
||||||
|
"password_too_short": "パスワードは8文字以上で入力してください",
|
||||||
|
"mismatched_passwords": "パスワードとパスワード確認を確かめてください",
|
||||||
|
"invalid_credentials": "パスワードまたはメールアドレスが違います"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"username": "ユーザー名",
|
||||||
|
"email": "メールアドレス",
|
||||||
|
"password": "パスワード",
|
||||||
|
"password_confirm": "パスワード確認"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"weapon": {
|
||||||
|
"title": "武器変更",
|
||||||
|
"buttons": {
|
||||||
|
"confirm": "武器を変更する"
|
||||||
|
},
|
||||||
|
"subtitles": {
|
||||||
|
"element": "属性",
|
||||||
|
"ax_skills": "EXスキル",
|
||||||
|
"weapon_keys": "武器スキル"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"menu": {
|
||||||
|
"about": "このサイトについて",
|
||||||
|
"guides": "攻略",
|
||||||
|
"language": "言語",
|
||||||
|
"login": "ログイン",
|
||||||
|
"saved": "保存した編成",
|
||||||
|
"settings": "アカウント設定",
|
||||||
|
"signup": "登録",
|
||||||
|
"teams": "編成一覧",
|
||||||
|
"logout": "ログアウト"
|
||||||
|
},
|
||||||
|
"party": {
|
||||||
|
"segmented_control": {
|
||||||
|
"class": "ジョブ",
|
||||||
|
"characters": "キャラ",
|
||||||
|
"weapons": "武器",
|
||||||
|
"summons": "召喚石"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"saved": {
|
||||||
|
"title": "保存した編成",
|
||||||
|
"loading": "ロード中...",
|
||||||
|
"not_found": "編成はまだ保存していません"
|
||||||
|
},
|
||||||
|
"search": {
|
||||||
|
"errors": {
|
||||||
|
"start_typing": "{{object}}名を入力してください",
|
||||||
|
"min_length": "3文字以上を入力してください",
|
||||||
|
"no_results": "'{{query}}'の検索結果が見つかりませんでした"
|
||||||
|
},
|
||||||
|
"placeholders": {
|
||||||
|
"weapon": "武器を検索...",
|
||||||
|
"summon": "召喚石を検索...",
|
||||||
|
"character": "キャラを検索..."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"teams": {
|
||||||
|
"title": "編成一覧",
|
||||||
|
"loading": "ロード中...",
|
||||||
|
"not_found": "編成は見つかりませんでした"
|
||||||
|
},
|
||||||
|
"extra_weapons": "Additional<br/>Weapons",
|
||||||
|
"coming_soon": "開発中",
|
||||||
|
"no_title": "無題",
|
||||||
|
"no_raid": "マルチなし",
|
||||||
|
"no_user": "無名"
|
||||||
|
}
|
||||||
|
|
||||||
3
types/AxSkill.d.ts
vendored
|
|
@ -1,7 +1,8 @@
|
||||||
interface AxSkill {
|
interface AxSkill {
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string,
|
en: string,
|
||||||
jp: string
|
ja: string
|
||||||
},
|
},
|
||||||
id: number,
|
id: number,
|
||||||
minValue: number,
|
minValue: number,
|
||||||
|
|
|
||||||
3
types/Character.d.ts
vendored
|
|
@ -8,8 +8,9 @@ interface Character {
|
||||||
gender: number
|
gender: number
|
||||||
max_level: number
|
max_level: number
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string
|
en: string
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
hp: {
|
hp: {
|
||||||
min_hp: number
|
min_hp: number
|
||||||
|
|
|
||||||
3
types/Raid.d.ts
vendored
|
|
@ -1,8 +1,9 @@
|
||||||
interface Raid {
|
interface Raid {
|
||||||
id: string
|
id: string
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string
|
en: string
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
level: number
|
level: number
|
||||||
group: number
|
group: number
|
||||||
|
|
|
||||||
3
types/Summon.d.ts
vendored
|
|
@ -6,8 +6,9 @@ interface Summon {
|
||||||
element: number
|
element: number
|
||||||
max_level: number
|
max_level: number
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string
|
en: string
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
hp: {
|
hp: {
|
||||||
min_hp: number
|
min_hp: number
|
||||||
|
|
|
||||||
3
types/Weapon.d.ts
vendored
|
|
@ -10,8 +10,9 @@ interface Weapon {
|
||||||
series: number
|
series: number
|
||||||
ax: number
|
ax: number
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string
|
en: string
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
hp: {
|
hp: {
|
||||||
min_hp: number
|
min_hp: number
|
||||||
|
|
|
||||||
3
types/WeaponKey.d.ts
vendored
|
|
@ -1,8 +1,9 @@
|
||||||
interface WeaponKey {
|
interface WeaponKey {
|
||||||
id: string
|
id: string
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string,
|
en: string,
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
series: integer
|
series: integer
|
||||||
slot: integer
|
slot: integer
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ interface AccountState {
|
||||||
|
|
||||||
account: {
|
account: {
|
||||||
authorized: boolean
|
authorized: boolean
|
||||||
language: 'en' | 'jp'
|
|
||||||
user: {
|
user: {
|
||||||
id: string
|
id: string
|
||||||
username: string
|
username: string
|
||||||
|
|
@ -18,7 +17,6 @@ interface AccountState {
|
||||||
export const initialAccountState: AccountState = {
|
export const initialAccountState: AccountState = {
|
||||||
account: {
|
account: {
|
||||||
authorized: false,
|
authorized: false,
|
||||||
language: 'en',
|
|
||||||
user: undefined
|
user: undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
154
utils/axData.tsx
|
|
@ -3,7 +3,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "ATK",
|
"en": "ATK",
|
||||||
"jp": "攻撃"
|
"ja": "攻撃"
|
||||||
},
|
},
|
||||||
id: 0,
|
id: 0,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -13,7 +13,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -23,7 +23,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Double Attack Rate",
|
"en": "Double Attack Rate",
|
||||||
"jp": "DA確率"
|
"ja": "DA確率"
|
||||||
},
|
},
|
||||||
id: 5,
|
id: 5,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -33,7 +33,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Triple Attack Rate",
|
"en": "Triple Attack Rate",
|
||||||
"jp": "TA確率"
|
"ja": "TA確率"
|
||||||
},
|
},
|
||||||
id: 6,
|
id: 6,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -43,7 +43,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Skill DMG Cap",
|
"en": "Skill DMG Cap",
|
||||||
"jp": "アビ上限"
|
"ja": "アビ上限"
|
||||||
},
|
},
|
||||||
id: 7,
|
id: 7,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -55,7 +55,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "DEF",
|
"en": "DEF",
|
||||||
"jp": "防御"
|
"ja": "防御"
|
||||||
},
|
},
|
||||||
id: 1,
|
id: 1,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -65,7 +65,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "HP",
|
"en": "HP",
|
||||||
"jp": "HP"
|
"ja": "HP"
|
||||||
},
|
},
|
||||||
id: 2,
|
id: 2,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -75,7 +75,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -85,7 +85,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -95,7 +95,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Enmity",
|
"en": "Enmity",
|
||||||
"jp": "背水"
|
"ja": "背水"
|
||||||
},
|
},
|
||||||
id: 11,
|
id: 11,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -106,7 +106,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "HP",
|
"en": "HP",
|
||||||
"jp": "HP"
|
"ja": "HP"
|
||||||
},
|
},
|
||||||
id: 2,
|
id: 2,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -116,7 +116,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "DEF",
|
"en": "DEF",
|
||||||
"jp": "防御"
|
"ja": "防御"
|
||||||
},
|
},
|
||||||
id: 1,
|
id: 1,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -126,7 +126,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -136,7 +136,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -146,7 +146,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -157,7 +157,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -167,7 +167,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "ATK",
|
"en": "ATK",
|
||||||
"jp": "攻撃"
|
"ja": "攻撃"
|
||||||
},
|
},
|
||||||
id: 0,
|
id: 0,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -177,7 +177,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental ATK",
|
"en": "Elemental ATK",
|
||||||
"jp": "全属性攻撃力"
|
"ja": "全属性攻撃力"
|
||||||
},
|
},
|
||||||
id: 13,
|
id: 13,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -187,7 +187,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG Cap",
|
"en": "C.A. DMG Cap",
|
||||||
"jp": "奥義上限"
|
"ja": "奥義上限"
|
||||||
},
|
},
|
||||||
id: 8,
|
id: 8,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -197,7 +197,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -208,7 +208,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Multiattack Rate",
|
"en": "Multiattack Rate",
|
||||||
"jp": "連撃率"
|
"ja": "連撃率"
|
||||||
},
|
},
|
||||||
id: 4,
|
id: 4,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -218,7 +218,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -228,7 +228,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental ATK",
|
"en": "Elemental ATK",
|
||||||
"jp": "全属性攻撃力"
|
"ja": "全属性攻撃力"
|
||||||
},
|
},
|
||||||
id: 13,
|
id: 13,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -238,7 +238,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Double Attack Rate",
|
"en": "Double Attack Rate",
|
||||||
"jp": "DA確率"
|
"ja": "DA確率"
|
||||||
},
|
},
|
||||||
id: 5,
|
id: 5,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -248,7 +248,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Triple Attack Rate",
|
"en": "Triple Attack Rate",
|
||||||
"jp": "TA確率"
|
"ja": "TA確率"
|
||||||
},
|
},
|
||||||
id: 6,
|
id: 6,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -261,7 +261,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "ATK",
|
"en": "ATK",
|
||||||
"jp": "攻撃"
|
"ja": "攻撃"
|
||||||
},
|
},
|
||||||
id: 0,
|
id: 0,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -271,7 +271,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -281,7 +281,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Multiattack Rate",
|
"en": "Multiattack Rate",
|
||||||
"jp": "連撃確率"
|
"ja": "連撃確率"
|
||||||
},
|
},
|
||||||
id: 4,
|
id: 4,
|
||||||
minValue: 1.5,
|
minValue: 1.5,
|
||||||
|
|
@ -291,7 +291,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Normal ATK DMG Cap",
|
"en": "Normal ATK DMG Cap",
|
||||||
"jp": "通常ダメ上限"
|
"ja": "通常ダメ上限"
|
||||||
},
|
},
|
||||||
id: 14,
|
id: 14,
|
||||||
minValue: 0.5,
|
minValue: 0.5,
|
||||||
|
|
@ -301,7 +301,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Supplemental Skill DMG",
|
"en": "Supplemental Skill DMG",
|
||||||
"jp": "アビ与ダメ上昇"
|
"ja": "アビ与ダメ上昇"
|
||||||
},
|
},
|
||||||
id: 15,
|
id: 15,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -312,7 +312,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "DEF",
|
"en": "DEF",
|
||||||
"jp": "防御"
|
"ja": "防御"
|
||||||
},
|
},
|
||||||
id: 1,
|
id: 1,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -322,7 +322,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental DMG Reduction",
|
"en": "Elemental DMG Reduction",
|
||||||
"jp": "属性ダメ軽減"
|
"ja": "属性ダメ軽減"
|
||||||
},
|
},
|
||||||
id: 17,
|
id: 17,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -332,7 +332,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -342,7 +342,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -352,7 +352,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Enmity",
|
"en": "Enmity",
|
||||||
"jp": "背水"
|
"ja": "背水"
|
||||||
},
|
},
|
||||||
id: 11,
|
id: 11,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -363,7 +363,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "HP",
|
"en": "HP",
|
||||||
"jp": "HP"
|
"ja": "HP"
|
||||||
},
|
},
|
||||||
id: 2,
|
id: 2,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -373,7 +373,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental DMG Reduction",
|
"en": "Elemental DMG Reduction",
|
||||||
"jp": "属性ダメ軽減"
|
"ja": "属性ダメ軽減"
|
||||||
},
|
},
|
||||||
id: 17,
|
id: 17,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -383,7 +383,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -393,7 +393,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -403,7 +403,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -414,7 +414,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -424,7 +424,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Multiattack Rate",
|
"en": "Multiattack Rate",
|
||||||
"jp": "連撃率"
|
"ja": "連撃率"
|
||||||
},
|
},
|
||||||
id: 4,
|
id: 4,
|
||||||
minValue: 1.5,
|
minValue: 1.5,
|
||||||
|
|
@ -434,7 +434,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Supplemental Skill DMG",
|
"en": "Supplemental Skill DMG",
|
||||||
"jp": "アビ与ダメ上昇"
|
"ja": "アビ与ダメ上昇"
|
||||||
},
|
},
|
||||||
id: 15,
|
id: 15,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -443,7 +443,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Supplemental C.A. DMG",
|
"en": "Supplemental C.A. DMG",
|
||||||
"jp": "奥義与ダメ上昇"
|
"ja": "奥義与ダメ上昇"
|
||||||
},
|
},
|
||||||
id: 16,
|
id: 16,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -452,7 +452,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -463,7 +463,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Multiattack Rate",
|
"en": "Multiattack Rate",
|
||||||
"jp": "連撃率"
|
"ja": "連撃率"
|
||||||
},
|
},
|
||||||
id: 4,
|
id: 4,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -473,7 +473,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Supplemental C.A. DMG",
|
"en": "Supplemental C.A. DMG",
|
||||||
"jp": "奥義与ダメ上昇"
|
"ja": "奥義与ダメ上昇"
|
||||||
},
|
},
|
||||||
id: 16,
|
id: 16,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -482,7 +482,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Normal ATK DMG Cap",
|
"en": "Normal ATK DMG Cap",
|
||||||
"jp": "通常ダメ上限"
|
"ja": "通常ダメ上限"
|
||||||
},
|
},
|
||||||
id: 14,
|
id: 14,
|
||||||
minValue: 0.5,
|
minValue: 0.5,
|
||||||
|
|
@ -492,7 +492,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -501,7 +501,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Enmity",
|
"en": "Enmity",
|
||||||
"jp": "背水"
|
"ja": "背水"
|
||||||
},
|
},
|
||||||
id: 11,
|
id: 11,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -513,7 +513,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "ATK",
|
"en": "ATK",
|
||||||
"jp": "攻撃"
|
"ja": "攻撃"
|
||||||
},
|
},
|
||||||
id: 0,
|
id: 0,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -523,7 +523,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -533,7 +533,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Double Attack Rate",
|
"en": "Double Attack Rate",
|
||||||
"jp": "DA確率"
|
"ja": "DA確率"
|
||||||
},
|
},
|
||||||
id: 5,
|
id: 5,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -543,7 +543,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Triple Attack Rate",
|
"en": "Triple Attack Rate",
|
||||||
"jp": "TA確率"
|
"ja": "TA確率"
|
||||||
},
|
},
|
||||||
id: 6,
|
id: 6,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -553,7 +553,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Skill DMG Cap",
|
"en": "Skill DMG Cap",
|
||||||
"jp": "アビ上限"
|
"ja": "アビ上限"
|
||||||
},
|
},
|
||||||
id: 7,
|
id: 7,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -565,7 +565,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "DEF",
|
"en": "DEF",
|
||||||
"jp": "防御"
|
"ja": "防御"
|
||||||
},
|
},
|
||||||
id: 1,
|
id: 1,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -575,7 +575,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "HP",
|
"en": "HP",
|
||||||
"jp": "HP"
|
"ja": "HP"
|
||||||
},
|
},
|
||||||
id: 2,
|
id: 2,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -585,7 +585,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -595,7 +595,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -605,7 +605,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Enmity",
|
"en": "Enmity",
|
||||||
"jp": "背水"
|
"ja": "背水"
|
||||||
},
|
},
|
||||||
id: 11,
|
id: 11,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -616,7 +616,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "HP",
|
"en": "HP",
|
||||||
"jp": "HP"
|
"ja": "HP"
|
||||||
},
|
},
|
||||||
id: 2,
|
id: 2,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -626,7 +626,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "DEF",
|
"en": "DEF",
|
||||||
"jp": "防御"
|
"ja": "防御"
|
||||||
},
|
},
|
||||||
id: 1,
|
id: 1,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -636,7 +636,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Debuff Resistance",
|
"en": "Debuff Resistance",
|
||||||
"jp": "弱体耐性"
|
"ja": "弱体耐性"
|
||||||
},
|
},
|
||||||
id: 9,
|
id: 9,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -646,7 +646,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Healing",
|
"en": "Healing",
|
||||||
"jp": "回復性能"
|
"ja": "回復性能"
|
||||||
},
|
},
|
||||||
id: 10,
|
id: 10,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -656,7 +656,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -667,7 +667,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -677,7 +677,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "ATK",
|
"en": "ATK",
|
||||||
"jp": "攻撃"
|
"ja": "攻撃"
|
||||||
},
|
},
|
||||||
id: 0,
|
id: 0,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -687,7 +687,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental ATK",
|
"en": "Elemental ATK",
|
||||||
"jp": "全属性攻撃力"
|
"ja": "全属性攻撃力"
|
||||||
},
|
},
|
||||||
id: 13,
|
id: 13,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -697,7 +697,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG Cap",
|
"en": "C.A. DMG Cap",
|
||||||
"jp": "奥義上限"
|
"ja": "奥義上限"
|
||||||
},
|
},
|
||||||
id: 8,
|
id: 8,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -707,7 +707,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Stamina",
|
"en": "Stamina",
|
||||||
"jp": "渾身"
|
"ja": "渾身"
|
||||||
},
|
},
|
||||||
id: 12,
|
id: 12,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -718,7 +718,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Multiattack Rate",
|
"en": "Multiattack Rate",
|
||||||
"jp": "連撃率"
|
"ja": "連撃率"
|
||||||
},
|
},
|
||||||
id: 4,
|
id: 4,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -728,7 +728,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "C.A. DMG",
|
"en": "C.A. DMG",
|
||||||
"jp": "奥義ダメ"
|
"ja": "奥義ダメ"
|
||||||
},
|
},
|
||||||
id: 3,
|
id: 3,
|
||||||
minValue: 2,
|
minValue: 2,
|
||||||
|
|
@ -738,7 +738,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Elemental ATK",
|
"en": "Elemental ATK",
|
||||||
"jp": "全属性攻撃力"
|
"ja": "全属性攻撃力"
|
||||||
},
|
},
|
||||||
id: 13,
|
id: 13,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -748,7 +748,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Double Attack Rate",
|
"en": "Double Attack Rate",
|
||||||
"jp": "DA確率"
|
"ja": "DA確率"
|
||||||
},
|
},
|
||||||
id: 5,
|
id: 5,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -758,7 +758,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Triple Attack Rate",
|
"en": "Triple Attack Rate",
|
||||||
"jp": "TA確率"
|
"ja": "TA確率"
|
||||||
},
|
},
|
||||||
id: 6,
|
id: 6,
|
||||||
minValue: 1,
|
minValue: 1,
|
||||||
|
|
@ -770,7 +770,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "EXP Up",
|
"en": "EXP Up",
|
||||||
"jp": "EXP UP"
|
"ja": "EXP UP"
|
||||||
},
|
},
|
||||||
id: 18,
|
id: 18,
|
||||||
minValue: 5,
|
minValue: 5,
|
||||||
|
|
@ -780,7 +780,7 @@ export const axData: AxSkill[][] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
"en": "Rupies",
|
"en": "Rupies",
|
||||||
"jp": "獲得ルピ"
|
"ja": "獲得ルピ"
|
||||||
},
|
},
|
||||||
id: 19,
|
id: 19,
|
||||||
minValue: 10,
|
minValue: 10,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
interface Picture {
|
interface Picture {
|
||||||
name: {
|
name: {
|
||||||
|
[key: string]: string
|
||||||
en: string
|
en: string
|
||||||
jp: string
|
ja: string
|
||||||
}
|
}
|
||||||
filename: string
|
filename: string
|
||||||
element: string
|
element: string
|
||||||
|
|
@ -11,7 +12,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Gran 2019",
|
en: "Gran 2019",
|
||||||
jp: "グラン"
|
ja: "グラン"
|
||||||
},
|
},
|
||||||
filename: "gran_19",
|
filename: "gran_19",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -19,7 +20,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Djeeta 2019",
|
en: "Djeeta 2019",
|
||||||
jp: "ジータ"
|
ja: "ジータ"
|
||||||
},
|
},
|
||||||
filename: "djeeta_19",
|
filename: "djeeta_19",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -27,7 +28,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Gran 2020",
|
en: "Gran 2020",
|
||||||
jp: "グラン"
|
ja: "グラン"
|
||||||
},
|
},
|
||||||
filename: "gran_20",
|
filename: "gran_20",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -35,7 +36,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Djeeta 2020",
|
en: "Djeeta 2020",
|
||||||
jp: "ジータ"
|
ja: "ジータ"
|
||||||
},
|
},
|
||||||
filename: "djeeta_20",
|
filename: "djeeta_20",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -43,7 +44,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Gran - Farer of the Skies",
|
en: "Gran - Farer of the Skies",
|
||||||
jp: "空駆ける新鋭 グランver"
|
ja: "空駆ける新鋭 グランver"
|
||||||
},
|
},
|
||||||
filename: "gran",
|
filename: "gran",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -51,7 +52,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Djeeta - Farer of the Skies",
|
en: "Djeeta - Farer of the Skies",
|
||||||
jp: "空駆ける新鋭 ジータver"
|
ja: "空駆ける新鋭 ジータver"
|
||||||
},
|
},
|
||||||
filename: "djeeta",
|
filename: "djeeta",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -59,7 +60,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Cassius",
|
en: "Cassius",
|
||||||
jp: "カシウス"
|
ja: "カシウス"
|
||||||
},
|
},
|
||||||
filename: "cassius",
|
filename: "cassius",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -67,7 +68,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Percival",
|
en: "Percival",
|
||||||
jp: "パーシヴァル"
|
ja: "パーシヴァル"
|
||||||
},
|
},
|
||||||
filename: "percival",
|
filename: "percival",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -75,7 +76,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Vane",
|
en: "Vane",
|
||||||
jp: "ヴェイン"
|
ja: "ヴェイン"
|
||||||
},
|
},
|
||||||
filename: "vane",
|
filename: "vane",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -83,7 +84,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Heles",
|
en: "Heles",
|
||||||
jp: "ヘルエス"
|
ja: "ヘルエス"
|
||||||
},
|
},
|
||||||
filename: "heles",
|
filename: "heles",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -91,7 +92,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Lunalu",
|
en: "Lunalu",
|
||||||
jp: "ルナール"
|
ja: "ルナール"
|
||||||
},
|
},
|
||||||
filename: "lunalu",
|
filename: "lunalu",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -99,7 +100,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Catura",
|
en: "Catura",
|
||||||
jp: "シャトラ"
|
ja: "シャトラ"
|
||||||
},
|
},
|
||||||
filename: "catura",
|
filename: "catura",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -107,7 +108,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Yuisis",
|
en: "Yuisis",
|
||||||
jp: "ユイシス"
|
ja: "ユイシス"
|
||||||
},
|
},
|
||||||
filename: "yuisis",
|
filename: "yuisis",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -115,7 +116,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Meg",
|
en: "Meg",
|
||||||
jp: "メグ"
|
ja: "メグ"
|
||||||
},
|
},
|
||||||
filename: "meg",
|
filename: "meg",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -123,7 +124,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Seofon",
|
en: "Seofon",
|
||||||
jp: "シエテ"
|
ja: "シエテ"
|
||||||
},
|
},
|
||||||
filename: "seofon",
|
filename: "seofon",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -131,7 +132,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Quatre",
|
en: "Quatre",
|
||||||
jp: "カトル"
|
ja: "カトル"
|
||||||
},
|
},
|
||||||
filename: "quatre",
|
filename: "quatre",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -139,7 +140,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Tien",
|
en: "Tien",
|
||||||
jp: "エッセル"
|
ja: "エッセル"
|
||||||
},
|
},
|
||||||
filename: "tien",
|
filename: "tien",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -147,7 +148,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Seox",
|
en: "Seox",
|
||||||
jp: "シス"
|
ja: "シス"
|
||||||
},
|
},
|
||||||
filename: "seox",
|
filename: "seox",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -155,7 +156,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Aoidos",
|
en: "Aoidos",
|
||||||
jp: "アオイドス"
|
ja: "アオイドス"
|
||||||
},
|
},
|
||||||
filename: "aoidos",
|
filename: "aoidos",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -163,7 +164,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Sandalphon",
|
en: "Sandalphon",
|
||||||
jp: "サンダルフォン"
|
ja: "サンダルフォン"
|
||||||
},
|
},
|
||||||
filename: "sandalphon",
|
filename: "sandalphon",
|
||||||
element: "light"
|
element: "light"
|
||||||
|
|
@ -171,7 +172,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Vikala",
|
en: "Vikala",
|
||||||
jp: "ビカラ"
|
ja: "ビカラ"
|
||||||
},
|
},
|
||||||
filename: "vikala",
|
filename: "vikala",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -179,7 +180,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Belial",
|
en: "Belial",
|
||||||
jp: "ベリアル"
|
ja: "ベリアル"
|
||||||
},
|
},
|
||||||
filename: "belial",
|
filename: "belial",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -187,7 +188,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Zeta",
|
en: "Zeta",
|
||||||
jp: "ゼタ"
|
ja: "ゼタ"
|
||||||
},
|
},
|
||||||
filename: "zeta",
|
filename: "zeta",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -195,7 +196,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Beatrix",
|
en: "Beatrix",
|
||||||
jp: "ベアトリックス"
|
ja: "ベアトリックス"
|
||||||
},
|
},
|
||||||
filename: "beatrix",
|
filename: "beatrix",
|
||||||
element: "earth"
|
element: "earth"
|
||||||
|
|
@ -203,7 +204,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Yuel",
|
en: "Yuel",
|
||||||
jp: "ユエル"
|
ja: "ユエル"
|
||||||
},
|
},
|
||||||
filename: "yuel",
|
filename: "yuel",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -211,7 +212,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Societte",
|
en: "Societte",
|
||||||
jp: "ソシエ"
|
ja: "ソシエ"
|
||||||
},
|
},
|
||||||
filename: "societte",
|
filename: "societte",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -219,7 +220,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Kumbhira",
|
en: "Kumbhira",
|
||||||
jp: "クビラ"
|
ja: "クビラ"
|
||||||
},
|
},
|
||||||
filename: "kumbhira",
|
filename: "kumbhira",
|
||||||
element: "light"
|
element: "light"
|
||||||
|
|
@ -227,7 +228,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Narmaya",
|
en: "Narmaya",
|
||||||
jp: "ナルメア"
|
ja: "ナルメア"
|
||||||
},
|
},
|
||||||
filename: "narmaya",
|
filename: "narmaya",
|
||||||
element: "dark"
|
element: "dark"
|
||||||
|
|
@ -235,7 +236,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Siegfried",
|
en: "Siegfried",
|
||||||
jp: "ジークフリード"
|
ja: "ジークフリード"
|
||||||
},
|
},
|
||||||
filename: "siegfried",
|
filename: "siegfried",
|
||||||
element: "earth"
|
element: "earth"
|
||||||
|
|
@ -243,7 +244,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Naoise",
|
en: "Naoise",
|
||||||
jp: "ノイシュ"
|
ja: "ノイシュ"
|
||||||
},
|
},
|
||||||
filename: "naoise",
|
filename: "naoise",
|
||||||
element: "light"
|
element: "light"
|
||||||
|
|
@ -251,7 +252,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Scathacha",
|
en: "Scathacha",
|
||||||
jp: "スカーサハ"
|
ja: "スカーサハ"
|
||||||
},
|
},
|
||||||
filename: "scathacha",
|
filename: "scathacha",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -259,7 +260,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Seruel",
|
en: "Seruel",
|
||||||
jp: "セルエル"
|
ja: "セルエル"
|
||||||
},
|
},
|
||||||
filename: "seruel",
|
filename: "seruel",
|
||||||
element: "light"
|
element: "light"
|
||||||
|
|
@ -267,7 +268,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Shiva",
|
en: "Shiva",
|
||||||
jp: "シヴァ"
|
ja: "シヴァ"
|
||||||
},
|
},
|
||||||
filename: "shiva",
|
filename: "shiva",
|
||||||
element: "fire"
|
element: "fire"
|
||||||
|
|
@ -275,7 +276,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Europa",
|
en: "Europa",
|
||||||
jp: "エウロペ"
|
ja: "エウロペ"
|
||||||
},
|
},
|
||||||
filename: "europa",
|
filename: "europa",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
@ -283,7 +284,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Grimnir",
|
en: "Grimnir",
|
||||||
jp: "グリームニル"
|
ja: "グリームニル"
|
||||||
},
|
},
|
||||||
filename: "grimnir",
|
filename: "grimnir",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -291,7 +292,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Alexiel",
|
en: "Alexiel",
|
||||||
jp: "ブローディア"
|
ja: "ブローディア"
|
||||||
},
|
},
|
||||||
filename: "alexiel",
|
filename: "alexiel",
|
||||||
element: "earth"
|
element: "earth"
|
||||||
|
|
@ -299,7 +300,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Sierokarte",
|
en: "Sierokarte",
|
||||||
jp: "シェロカルテ"
|
ja: "シェロカルテ"
|
||||||
},
|
},
|
||||||
filename: "siero",
|
filename: "siero",
|
||||||
element: "wind"
|
element: "wind"
|
||||||
|
|
@ -307,7 +308,7 @@ export const pictureData: Picture[] = [
|
||||||
{
|
{
|
||||||
name: {
|
name: {
|
||||||
en: "Vajra",
|
en: "Vajra",
|
||||||
jp: "ヴァジラ"
|
ja: "ヴァジラ"
|
||||||
},
|
},
|
||||||
filename: "vajra",
|
filename: "vajra",
|
||||||
element: "water"
|
element: "water"
|
||||||
|
|
|
||||||