Merge pull request #22 from jedmund/account-settings
Add account settings and a modal to control them in
160
components/AccountModal/index.scss
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
.Account.Dialog {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit * 2;
|
||||
width: $unit * 60;
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit * 2;
|
||||
|
||||
.Switch {
|
||||
$height: 34px;
|
||||
background: $grey-70;
|
||||
border-radius: $height / 2;
|
||||
border: none;
|
||||
position: relative;
|
||||
width: 58px;
|
||||
height: $height;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px $grey-00;
|
||||
}
|
||||
|
||||
&[data-state="checked"] {
|
||||
background: $grey-00;
|
||||
}
|
||||
}
|
||||
|
||||
.Thumb {
|
||||
background: white;
|
||||
border-radius: 13px;
|
||||
display: block;
|
||||
height: 26px;
|
||||
width: 26px;
|
||||
transition: transform 100ms;
|
||||
transform: translateX(-1px);
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&[data-state="checked"] {
|
||||
background: white;
|
||||
transform: translateX(21px);
|
||||
}
|
||||
}
|
||||
|
||||
.Button {
|
||||
font-size: $font-regular;
|
||||
padding: ($unit * 1.5) ($unit * 2);
|
||||
margin-top: $unit * 2;
|
||||
width: 100%;
|
||||
|
||||
&.btn-disabled {
|
||||
background: $grey-90;
|
||||
color: $grey-70;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
&:not(.btn-disabled) {
|
||||
background: $grey-90;
|
||||
color: $grey-40;
|
||||
|
||||
&:hover {
|
||||
background: $grey-80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.field {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: $unit * 2;
|
||||
|
||||
select {
|
||||
background: no-repeat url('/icons/ArrowDark.svg'), $grey-90;
|
||||
background-position-y: center;
|
||||
background-position-x: 95%;
|
||||
margin: 0;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
gap: $unit / 2;
|
||||
|
||||
label {
|
||||
color: $grey-00;
|
||||
font-size: $font-regular;
|
||||
}
|
||||
|
||||
p {
|
||||
color: $grey-60;
|
||||
font-size: $font-small;
|
||||
line-height: 1.1;
|
||||
max-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.preview {
|
||||
$diameter: 48px;
|
||||
background-color: $grey-90;
|
||||
border-radius: 999px;
|
||||
height: $diameter;
|
||||
width: $diameter;
|
||||
|
||||
img {
|
||||
height: $diameter;
|
||||
width: $diameter;
|
||||
}
|
||||
|
||||
&.fire {
|
||||
background: $fire-bg-light;
|
||||
}
|
||||
|
||||
&.water {
|
||||
background: $water-bg-light;
|
||||
}
|
||||
|
||||
&.wind {
|
||||
background: $wind-bg-light;
|
||||
}
|
||||
|
||||
&.earth {
|
||||
background: $earth-bg-light;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background: $dark-bg-light;
|
||||
}
|
||||
|
||||
&.light {
|
||||
background: $light-bg-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: $unit;
|
||||
|
||||
h2 {
|
||||
margin-bottom: $unit * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.DialogDescription {
|
||||
font-size: $font-regular;
|
||||
line-height: 1.24;
|
||||
margin-bottom: $unit;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
158
components/AccountModal/index.tsx
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import { useCookies } from 'react-cookie'
|
||||
import { useSnapshot } from 'valtio'
|
||||
|
||||
import * as Dialog from '@radix-ui/react-dialog'
|
||||
import * as Switch from '@radix-ui/react-switch'
|
||||
|
||||
import api from '~utils/api'
|
||||
import { accountState } from '~utils/accountState'
|
||||
import { pictureData } from '~utils/pictureData'
|
||||
|
||||
import Button from '~components/Button'
|
||||
|
||||
import CrossIcon from '~public/icons/Cross.svg'
|
||||
import './index.scss'
|
||||
|
||||
const AccountModal = () => {
|
||||
const { account } = useSnapshot(accountState)
|
||||
|
||||
// Cookies
|
||||
const [cookies] = useCookies(['user'])
|
||||
const headers = (cookies.user != null) ? {
|
||||
headers: {
|
||||
'Authorization': `Bearer ${cookies.user.access_token}`
|
||||
}
|
||||
} : {}
|
||||
|
||||
// State
|
||||
const [open, setOpen] = useState(false)
|
||||
const [picture, setPicture] = useState('')
|
||||
const [language, setLanguage] = useState('')
|
||||
const [privateProfile, setPrivateProfile] = useState(false)
|
||||
|
||||
// Refs
|
||||
const pictureSelect = React.createRef<HTMLSelectElement>()
|
||||
const languageSelect = React.createRef<HTMLSelectElement>()
|
||||
const privateSelect = React.createRef<HTMLInputElement>()
|
||||
|
||||
useEffect(() => {
|
||||
if (cookies.user) setPicture(cookies.user.picture)
|
||||
if (cookies.user) setLanguage(cookies.user.language)
|
||||
}, [cookies])
|
||||
|
||||
const pictureOptions = (
|
||||
pictureData.sort((a, b) => (a.name.en > b.name.en) ? 1 : -1).map((item, i) => {
|
||||
return (
|
||||
<option key={`picture-${i}`} value={item.filename}>{item.name.en}</option>
|
||||
)
|
||||
})
|
||||
)
|
||||
|
||||
function handlePictureChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
||||
if (pictureSelect.current)
|
||||
setPicture(pictureSelect.current.value)
|
||||
}
|
||||
|
||||
function handleLanguageChange(event: React.ChangeEvent<HTMLSelectElement>) {
|
||||
if (languageSelect.current)
|
||||
setLanguage(languageSelect.current.value)
|
||||
}
|
||||
|
||||
function handlePrivateChange(checked: boolean) {
|
||||
setPrivateProfile(checked)
|
||||
}
|
||||
|
||||
function update(event: React.FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault()
|
||||
|
||||
const object = {
|
||||
user: {
|
||||
picture: picture,
|
||||
element: pictureData.find(i => i.filename === picture)?.element,
|
||||
language: language,
|
||||
private: privateProfile
|
||||
}
|
||||
}
|
||||
|
||||
api.endpoints.users.update(cookies.user.user_id, object, headers)
|
||||
.then(response => {
|
||||
setOpen(false)
|
||||
})
|
||||
}
|
||||
|
||||
function openChange(open: boolean) {
|
||||
setOpen(open)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog.Root open={open} onOpenChange={openChange}>
|
||||
<Dialog.Trigger asChild>
|
||||
<li className="MenuItem">
|
||||
<span>Settings</span>
|
||||
</li>
|
||||
</Dialog.Trigger>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Content className="Account Dialog" onOpenAutoFocus={ (event) => event.preventDefault() }>
|
||||
<div className="DialogHeader">
|
||||
<div className="DialogTop">
|
||||
<Dialog.Title className="SubTitle">Account Settings</Dialog.Title>
|
||||
<Dialog.Title className="DialogTitle">@{account.user?.username}</Dialog.Title>
|
||||
</div>
|
||||
<Dialog.Close className="DialogClose" asChild>
|
||||
<span>
|
||||
<CrossIcon />
|
||||
</span>
|
||||
</Dialog.Close>
|
||||
</div>
|
||||
|
||||
<form onSubmit={update}>
|
||||
<div className="field">
|
||||
<div className="left">
|
||||
<label>Picture</label>
|
||||
</div>
|
||||
|
||||
<div className={`preview ${pictureData.find(i => i.filename === picture)?.element}`}>
|
||||
<img
|
||||
alt="Profile preview"
|
||||
srcSet={`/profile/${picture}.png,
|
||||
/profile/${picture}@2x.png 2x`}
|
||||
src={`/profile/${picture}.png`}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<select name="picture" onChange={handlePictureChange} value={picture} ref={pictureSelect}>
|
||||
{pictureOptions}
|
||||
</select>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="left">
|
||||
<label>Language</label>
|
||||
</div>
|
||||
|
||||
<select name="language" onChange={handleLanguageChange} value={language} ref={languageSelect}>
|
||||
<option key="en" value="en">English</option>
|
||||
<option key="jp" value="jp">Japanese</option>
|
||||
</select>
|
||||
</div>
|
||||
<div className="field">
|
||||
<div className="left">
|
||||
<label>Private</label>
|
||||
<p>Hide your profile and prevent your grids from showing up in collections</p>
|
||||
</div>
|
||||
|
||||
<Switch.Root className="Switch" onCheckedChange={handlePrivateChange} checked={privateProfile}>
|
||||
<Switch.Thumb className="Thumb" />
|
||||
</Switch.Root>
|
||||
</div>
|
||||
|
||||
<Button>Save settings</Button>
|
||||
</form>
|
||||
</Dialog.Content>
|
||||
<Dialog.Overlay className="Overlay" />
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
)
|
||||
}
|
||||
|
||||
export default AccountModal
|
||||
|
|
@ -83,11 +83,12 @@ const GridRep = (props: Props) => {
|
|||
if (props.user)
|
||||
return (
|
||||
<img
|
||||
alt="Gran"
|
||||
className="gran"
|
||||
srcSet="/profile/gran.png,
|
||||
/profile/gran@2x.png 2x"
|
||||
src="/profile/gran.png" />
|
||||
alt={props.user.picture.picture}
|
||||
className={`profile ${props.user.picture.element}`}
|
||||
srcSet={`/profile/${props.user.picture.picture}.png,
|
||||
/profile/${props.user.picture.picture}@2x.png 2x`}
|
||||
src={`/profile/${props.user.picture.picture}.png`}
|
||||
/>
|
||||
)
|
||||
else
|
||||
return (<div className="no-user" />)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
color: $grey-40;
|
||||
font-weight: $normal;
|
||||
|
||||
&:hover {
|
||||
&:hover:not(.disabled) {
|
||||
background: $grey-100;
|
||||
color: $grey-00;
|
||||
cursor: pointer;
|
||||
|
|
@ -22,13 +22,42 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.profile > div {
|
||||
padding: 6px 12px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $grey-40;
|
||||
}
|
||||
|
||||
a, span {
|
||||
& > a, & > span {
|
||||
display: block;
|
||||
padding: 12px;
|
||||
padding: 12px 12px;
|
||||
}
|
||||
|
||||
& > div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 10px 12px;
|
||||
|
||||
&:hover {
|
||||
i.tag {
|
||||
background: $grey-60;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
img {
|
||||
$diameter: 32px;
|
||||
border-radius: $diameter / 2;
|
||||
height: $diameter;
|
||||
width: $diameter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import React from 'react'
|
||||
import Link from 'next/link'
|
||||
|
||||
import LoginModal from '~components/LoginModal'
|
||||
import SignupModal from '~components/SignupModal'
|
||||
|
||||
import { useModal as useSignupModal } from '~utils/useModal'
|
||||
import { useModal as useLoginModal } from '~utils/useModal'
|
||||
import { useModal as useAboutModal } from '~utils/useModal'
|
||||
import { useCookies } from 'react-cookie'
|
||||
|
||||
import AboutModal from '~components/AboutModal'
|
||||
import AccountModal from '~components/AccountModal'
|
||||
import LoginModal from '~components/LoginModal'
|
||||
import SignupModal from '~components/SignupModal'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
|
|
@ -19,13 +16,27 @@ interface Props {
|
|||
}
|
||||
|
||||
const HeaderMenu = (props: Props) => {
|
||||
|
||||
const [cookies] = useCookies()
|
||||
|
||||
function authItems() {
|
||||
return (
|
||||
<nav>
|
||||
<ul className="Menu auth">
|
||||
<div className="MenuGroup">
|
||||
<li className="MenuItem">
|
||||
<Link href={`/${props.username}` || ''}>{props.username}</Link>
|
||||
<li className="MenuItem profile">
|
||||
<Link href={`/${cookies.user?.username}` || ''}>
|
||||
<div>
|
||||
<span>{cookies.user?.username}</span>
|
||||
<img
|
||||
alt={cookies.user?.picture}
|
||||
className={`profile ${cookies.user?.element}`}
|
||||
srcSet={`/profile/${cookies.user?.picture}.png,
|
||||
/profile/${cookies.user?.picture}@2x.png 2x`}
|
||||
src={`/profile/${cookies.user?.picture}.png`}
|
||||
/>
|
||||
</div
|
||||
></Link>
|
||||
</li>
|
||||
<li className="MenuItem">
|
||||
<Link href={`/saved` || ''}>Saved</Link>
|
||||
|
|
@ -36,15 +47,16 @@ const HeaderMenu = (props: Props) => {
|
|||
<Link href='/teams'>Teams</Link>
|
||||
</li>
|
||||
|
||||
<li className="MenuItem">
|
||||
<Link href='/guides'>Guides</Link>
|
||||
<li className="MenuItem disabled">
|
||||
<div>
|
||||
<span>Guides</span>
|
||||
<i className="tag">Coming Soon</i>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div className="MenuGroup">
|
||||
<AboutModal />
|
||||
<li className="MenuItem">
|
||||
<span>Settings</span>
|
||||
</li>
|
||||
<AccountModal />
|
||||
<li className="MenuItem" onClick={props.logout}>
|
||||
<span>Logout</span>
|
||||
</li>
|
||||
|
|
@ -65,8 +77,11 @@ const HeaderMenu = (props: Props) => {
|
|||
<Link href='/teams'>Teams</Link>
|
||||
</li>
|
||||
|
||||
<li className="MenuItem">
|
||||
<Link href='/guides'>Guides</Link>
|
||||
<li className="MenuItem disabled">
|
||||
<div>
|
||||
<span>Guides</span>
|
||||
<i className="tag">Coming Soon</i>
|
||||
</div>
|
||||
</li>
|
||||
</div>
|
||||
<div className="MenuGroup">
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState } from 'react'
|
||||
import { useCookies } from 'react-cookie'
|
||||
import { AxiosResponse } from 'axios'
|
||||
|
||||
import * as Dialog from '@radix-ui/react-dialog'
|
||||
|
||||
|
|
@ -94,27 +95,42 @@ const LoginModal = (props: Props) => {
|
|||
|
||||
if (formValid) {
|
||||
api.login(body)
|
||||
.then((response) => {
|
||||
const cookieObj = {
|
||||
user_id: response.data.user.id,
|
||||
username: response.data.user.username,
|
||||
access_token: response.data.access_token
|
||||
}
|
||||
|
||||
setCookies('user', cookieObj, { path: '/'})
|
||||
accountState.account.authorized = true
|
||||
accountState.account.user = {
|
||||
id: cookieObj.user_id,
|
||||
username: cookieObj.username
|
||||
}
|
||||
|
||||
setOpen(false)
|
||||
}, (error) => {
|
||||
console.error(error)
|
||||
})
|
||||
.then(response => response.data.user.id)
|
||||
.then(id => fetchUserInfo(id))
|
||||
.then(infoResponse => storeUserInfo(infoResponse))
|
||||
}
|
||||
}
|
||||
|
||||
function fetchUserInfo(id: string) {
|
||||
return api.userInfo(id)
|
||||
}
|
||||
|
||||
function storeUserInfo(response: AxiosResponse) {
|
||||
const user = response.data.user
|
||||
|
||||
const cookieObj = {
|
||||
user_id: user.id,
|
||||
username: user.username,
|
||||
picture: user.picture.picture,
|
||||
element: user.picture.element,
|
||||
language: user.language,
|
||||
access_token: response.data.access_token
|
||||
}
|
||||
|
||||
setCookies('user', cookieObj, { path: '/'})
|
||||
|
||||
accountState.account.language = user.language
|
||||
accountState.account.user = {
|
||||
id: user.id,
|
||||
username: user.username,
|
||||
picture: user.picture.picture,
|
||||
element: user.picture.element
|
||||
}
|
||||
|
||||
accountState.account.authorized = true
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
function openChange(open: boolean) {
|
||||
setOpen(open)
|
||||
setErrors({
|
||||
|
|
@ -158,7 +174,7 @@ const LoginModal = (props: Props) => {
|
|||
ref={passwordInput}
|
||||
/>
|
||||
|
||||
<Button disabled={!formValid}>Log in</Button>
|
||||
<Button disabled={false}>Log in</Button>
|
||||
</form>
|
||||
</Dialog.Content>
|
||||
<Dialog.Overlay className="Overlay" />
|
||||
|
|
|
|||
|
|
@ -58,7 +58,8 @@ const TopHeader = () => {
|
|||
accountState[key] = resetState[key]
|
||||
})
|
||||
|
||||
appState.party.editable = false
|
||||
if (router.route != '/new')
|
||||
appState.party.editable = false
|
||||
|
||||
router.push('/')
|
||||
return false
|
||||
|
|
|
|||
148
package-lock.json
generated
|
|
@ -11,7 +11,7 @@
|
|||
"@radix-ui/react-dropdown-menu": "^0.1.4",
|
||||
"@radix-ui/react-hover-card": "^0.1.5",
|
||||
"@radix-ui/react-label": "^0.1.4",
|
||||
"@radix-ui/react-switch": "^0.1.4",
|
||||
"@radix-ui/react-switch": "^0.1.5",
|
||||
"@radix-ui/react-toggle-group": "^0.1.5",
|
||||
"@svgr/webpack": "^6.2.0",
|
||||
"@types/axios": "^0.14.0",
|
||||
|
|
@ -2590,15 +2590,39 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-0.1.4.tgz",
|
||||
"integrity": "sha512-I59IMdUhHixk6cG4D00UN+oFxTpur9cJQSOl+4EfSTJZs+x4PqDpM7p402/gb9sXJqylsUkDMHDdaPzLwPNf7g==",
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-0.1.5.tgz",
|
||||
"integrity": "sha512-Au9+n4/DhvjR0IHhvZ1LPdx/OW+3CGDie30ZyCkbSHIuLp4/CV4oPPGBwJ1vY99Jog3zyQhsGww9MXj8O9Aj/A==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "0.1.0",
|
||||
"@radix-ui/react-context": "0.1.1",
|
||||
"@radix-ui/react-id": "0.1.4",
|
||||
"@radix-ui/react-primitive": "0.1.3"
|
||||
"@radix-ui/react-id": "0.1.5",
|
||||
"@radix-ui/react-primitive": "0.1.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-id": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-0.1.5.tgz",
|
||||
"integrity": "sha512-IPc4H/63bes0IZ1GJJozSEkSWcDyhNGtKFWUpJ+XtaLyQ1X3x7Mf6fWwWhDcpqlYEP+5WtAvfqcyEsyjP+ZhBQ==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-use-layout-effect": "0.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-label/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz",
|
||||
"integrity": "sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "0.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
|
|
@ -2723,19 +2747,42 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-switch": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-0.1.4.tgz",
|
||||
"integrity": "sha512-GUK0hw/FQX/MJ5Zp5W6e69fqk/KO6bRP0t0Sx89Sl//WSdcgpwk3CimV5seqk8LxL1wwBkDR5zE185U+LdBCOQ==",
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-0.1.5.tgz",
|
||||
"integrity": "sha512-ITtslJPK+Yi34iNf7K9LtsPaLD76oRIVzn0E8JpEO5HW8gpRBGb2NNI9mxKtEB30TVqIcdjdL10AmuIfOMwjtg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "0.1.0",
|
||||
"@radix-ui/react-compose-refs": "0.1.0",
|
||||
"@radix-ui/react-context": "0.1.1",
|
||||
"@radix-ui/react-label": "0.1.4",
|
||||
"@radix-ui/react-primitive": "0.1.3",
|
||||
"@radix-ui/react-label": "0.1.5",
|
||||
"@radix-ui/react-primitive": "0.1.4",
|
||||
"@radix-ui/react-use-controllable-state": "0.1.0",
|
||||
"@radix-ui/react-use-previous": "0.1.0",
|
||||
"@radix-ui/react-use-size": "0.1.0"
|
||||
"@radix-ui/react-use-previous": "0.1.1",
|
||||
"@radix-ui/react-use-size": "0.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-primitive": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz",
|
||||
"integrity": "sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "0.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-switch/node_modules/@radix-ui/react-use-size": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz",
|
||||
"integrity": "sha512-pTgWM5qKBu6C7kfKxrKPoBI2zZYZmp2cSXzpUiGM3qEBQlMLtYhaY2JXdXUCxz+XmD1YEjc8oRwvyfsD4AG4WA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8 || ^17.0"
|
||||
|
|
@ -2912,9 +2959,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-previous": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-0.1.0.tgz",
|
||||
"integrity": "sha512-0fxNc33rYnCzDMPSiSnfS8YklnxQo8WqbAQXPAgIaaA1jRu2qFB916PL4qCIW+avcAAqFD38vWhqDqcVmBharA==",
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-0.1.1.tgz",
|
||||
"integrity": "sha512-O/ZgrDBr11dR8rhO59ED8s5zIXBRFi8MiS+CmFGfi7MJYdLbfqVOmQU90Ghf87aifEgWe6380LA69KBneaShAg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
},
|
||||
|
|
@ -8837,15 +8884,35 @@
|
|||
}
|
||||
},
|
||||
"@radix-ui/react-label": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-0.1.4.tgz",
|
||||
"integrity": "sha512-I59IMdUhHixk6cG4D00UN+oFxTpur9cJQSOl+4EfSTJZs+x4PqDpM7p402/gb9sXJqylsUkDMHDdaPzLwPNf7g==",
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-0.1.5.tgz",
|
||||
"integrity": "sha512-Au9+n4/DhvjR0IHhvZ1LPdx/OW+3CGDie30ZyCkbSHIuLp4/CV4oPPGBwJ1vY99Jog3zyQhsGww9MXj8O9Aj/A==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-compose-refs": "0.1.0",
|
||||
"@radix-ui/react-context": "0.1.1",
|
||||
"@radix-ui/react-id": "0.1.4",
|
||||
"@radix-ui/react-primitive": "0.1.3"
|
||||
"@radix-ui/react-id": "0.1.5",
|
||||
"@radix-ui/react-primitive": "0.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-id": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-0.1.5.tgz",
|
||||
"integrity": "sha512-IPc4H/63bes0IZ1GJJozSEkSWcDyhNGtKFWUpJ+XtaLyQ1X3x7Mf6fWwWhDcpqlYEP+5WtAvfqcyEsyjP+ZhBQ==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-use-layout-effect": "0.1.0"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-primitive": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz",
|
||||
"integrity": "sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "0.1.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-menu": {
|
||||
|
|
@ -8944,19 +9011,38 @@
|
|||
}
|
||||
},
|
||||
"@radix-ui/react-switch": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-0.1.4.tgz",
|
||||
"integrity": "sha512-GUK0hw/FQX/MJ5Zp5W6e69fqk/KO6bRP0t0Sx89Sl//WSdcgpwk3CimV5seqk8LxL1wwBkDR5zE185U+LdBCOQ==",
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-0.1.5.tgz",
|
||||
"integrity": "sha512-ITtslJPK+Yi34iNf7K9LtsPaLD76oRIVzn0E8JpEO5HW8gpRBGb2NNI9mxKtEB30TVqIcdjdL10AmuIfOMwjtg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/primitive": "0.1.0",
|
||||
"@radix-ui/react-compose-refs": "0.1.0",
|
||||
"@radix-ui/react-context": "0.1.1",
|
||||
"@radix-ui/react-label": "0.1.4",
|
||||
"@radix-ui/react-primitive": "0.1.3",
|
||||
"@radix-ui/react-label": "0.1.5",
|
||||
"@radix-ui/react-primitive": "0.1.4",
|
||||
"@radix-ui/react-use-controllable-state": "0.1.0",
|
||||
"@radix-ui/react-use-previous": "0.1.0",
|
||||
"@radix-ui/react-use-size": "0.1.0"
|
||||
"@radix-ui/react-use-previous": "0.1.1",
|
||||
"@radix-ui/react-use-size": "0.1.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-0.1.4.tgz",
|
||||
"integrity": "sha512-6gSl2IidySupIMJFjYnDIkIWRyQdbu/AHK7rbICPani+LW4b0XdxBXc46og/iZvuwW8pjCS8I2SadIerv84xYA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10",
|
||||
"@radix-ui/react-slot": "0.1.2"
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-use-size": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-0.1.1.tgz",
|
||||
"integrity": "sha512-pTgWM5qKBu6C7kfKxrKPoBI2zZYZmp2cSXzpUiGM3qEBQlMLtYhaY2JXdXUCxz+XmD1YEjc8oRwvyfsD4AG4WA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@radix-ui/react-toggle": {
|
||||
|
|
@ -9095,9 +9181,9 @@
|
|||
}
|
||||
},
|
||||
"@radix-ui/react-use-previous": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-0.1.0.tgz",
|
||||
"integrity": "sha512-0fxNc33rYnCzDMPSiSnfS8YklnxQo8WqbAQXPAgIaaA1jRu2qFB916PL4qCIW+avcAAqFD38vWhqDqcVmBharA==",
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-0.1.1.tgz",
|
||||
"integrity": "sha512-O/ZgrDBr11dR8rhO59ED8s5zIXBRFi8MiS+CmFGfi7MJYdLbfqVOmQU90Ghf87aifEgWe6380LA69KBneaShAg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.13.10"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
"@radix-ui/react-dropdown-menu": "^0.1.4",
|
||||
"@radix-ui/react-hover-card": "^0.1.5",
|
||||
"@radix-ui/react-label": "^0.1.4",
|
||||
"@radix-ui/react-switch": "^0.1.4",
|
||||
"@radix-ui/react-switch": "^0.1.5",
|
||||
"@radix-ui/react-toggle-group": "^0.1.5",
|
||||
"@svgr/webpack": "^6.2.0",
|
||||
"@types/axios": "^0.14.0",
|
||||
|
|
|
|||
|
|
@ -22,7 +22,12 @@ const ProfileRoute: React.FC = () => {
|
|||
const [user, setUser] = useState<User>({
|
||||
id: '',
|
||||
username: '',
|
||||
granblueId: 0
|
||||
granblueId: 0,
|
||||
picture: {
|
||||
picture: '',
|
||||
element: ''
|
||||
},
|
||||
private: false
|
||||
})
|
||||
|
||||
// Filter states
|
||||
|
|
@ -63,7 +68,9 @@ const ProfileRoute: React.FC = () => {
|
|||
setUser({
|
||||
id: response.data.user.id,
|
||||
username: response.data.user.username,
|
||||
granblueId: response.data.user.granblue_id
|
||||
granblueId: response.data.user.granblue_id,
|
||||
picture: response.data.user.picture,
|
||||
private: response.data.user.private
|
||||
})
|
||||
|
||||
const parties: Party[] = response.data.user.parties
|
||||
|
|
@ -113,11 +120,12 @@ const ProfileRoute: React.FC = () => {
|
|||
<FilterBar onFilter={receiveFilters} scrolled={scrolled}>
|
||||
<div className="UserInfo">
|
||||
<img
|
||||
alt="Gran"
|
||||
className="gran"
|
||||
srcSet="/profile/gran.png,
|
||||
/profile/gran@2x.png 2x"
|
||||
src="/profile/gran.png" />
|
||||
alt={user.picture.picture}
|
||||
className={`profile ${user.picture.element}`}
|
||||
srcSet={`/profile/${user.picture.picture}.png,
|
||||
/profile/${user.picture.picture}@2x.png 2x`}
|
||||
src={`/profile/${user.picture.picture}.png`}
|
||||
/>
|
||||
<h1>{user.username}</h1>
|
||||
</div>
|
||||
</FilterBar>
|
||||
|
|
|
|||
BIN
public/profile/alexiel.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
public/profile/alexiel@2x.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
public/profile/aoidos.png
Normal file
|
After Width: | Height: | Size: 126 KiB |
BIN
public/profile/aoidos@2x.png
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
public/profile/beatrix.png
Normal file
|
After Width: | Height: | Size: 179 KiB |
BIN
public/profile/beatrix@2x.png
Normal file
|
After Width: | Height: | Size: 285 KiB |
BIN
public/profile/belial.png
Normal file
|
After Width: | Height: | Size: 128 KiB |
BIN
public/profile/belial@2x.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
public/profile/cassius.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
public/profile/cassius@2x.png
Normal file
|
After Width: | Height: | Size: 166 KiB |
BIN
public/profile/catura.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
public/profile/catura@2x.png
Normal file
|
After Width: | Height: | Size: 270 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 77 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 90 KiB |
BIN
public/profile/djeeta_19.png
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
public/profile/djeeta_19@2x.png
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
public/profile/djeeta_20.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
public/profile/djeeta_20@2x.png
Normal file
|
After Width: | Height: | Size: 243 KiB |
BIN
public/profile/europa.png
Normal file
|
After Width: | Height: | Size: 168 KiB |
BIN
public/profile/europa@2x.png
Normal file
|
After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 88 KiB |
BIN
public/profile/gran_19.png
Normal file
|
After Width: | Height: | Size: 102 KiB |
BIN
public/profile/gran_19@2x.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
public/profile/gran_20.png
Normal file
|
After Width: | Height: | Size: 142 KiB |
BIN
public/profile/gran_20@2x.png
Normal file
|
After Width: | Height: | Size: 228 KiB |
BIN
public/profile/grimnir.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
public/profile/grimnir@2x.png
Normal file
|
After Width: | Height: | Size: 64 KiB |
BIN
public/profile/heles.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
public/profile/heles@2x.png
Normal file
|
After Width: | Height: | Size: 182 KiB |
BIN
public/profile/kumbhira.png
Normal file
|
After Width: | Height: | Size: 202 KiB |
BIN
public/profile/kumbhira@2x.png
Normal file
|
After Width: | Height: | Size: 389 KiB |
BIN
public/profile/lunalu.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
public/profile/lunalu@2x.png
Normal file
|
After Width: | Height: | Size: 177 KiB |
BIN
public/profile/meg.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
public/profile/meg@2x.png
Normal file
|
After Width: | Height: | Size: 200 KiB |
BIN
public/profile/naoise.png
Normal file
|
After Width: | Height: | Size: 171 KiB |
BIN
public/profile/naoise@2x.png
Normal file
|
After Width: | Height: | Size: 272 KiB |
BIN
public/profile/narmaya.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
public/profile/narmaya@2x.png
Normal file
|
After Width: | Height: | Size: 316 KiB |
BIN
public/profile/percival.png
Normal file
|
After Width: | Height: | Size: 125 KiB |
BIN
public/profile/percival@2x.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
BIN
public/profile/quatre.png
Normal file
|
After Width: | Height: | Size: 62 KiB |
BIN
public/profile/quatre@2x.png
Normal file
|
After Width: | Height: | Size: 79 KiB |
BIN
public/profile/sandalphon.png
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
public/profile/sandalphon@2x.png
Normal file
|
After Width: | Height: | Size: 133 KiB |
BIN
public/profile/scathacha.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
public/profile/scathacha@2x.png
Normal file
|
After Width: | Height: | Size: 290 KiB |
BIN
public/profile/seofon.png
Normal file
|
After Width: | Height: | Size: 127 KiB |
BIN
public/profile/seofon@2x.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
public/profile/seox.png
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
public/profile/seox@2x.png
Normal file
|
After Width: | Height: | Size: 140 KiB |
BIN
public/profile/seruel.png
Normal file
|
After Width: | Height: | Size: 173 KiB |
BIN
public/profile/seruel@2x.png
Normal file
|
After Width: | Height: | Size: 279 KiB |
BIN
public/profile/shiva.png
Normal file
|
After Width: | Height: | Size: 143 KiB |
BIN
public/profile/shiva@2x.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
BIN
public/profile/siegfried.png
Normal file
|
After Width: | Height: | Size: 131 KiB |
BIN
public/profile/siegfried@2x.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
public/profile/siero.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
public/profile/siero@2x.png
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
public/profile/societte.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
public/profile/societte@2x.png
Normal file
|
After Width: | Height: | Size: 318 KiB |
BIN
public/profile/tien.png
Normal file
|
After Width: | Height: | Size: 58 KiB |
BIN
public/profile/tien@2x.png
Normal file
|
After Width: | Height: | Size: 73 KiB |
BIN
public/profile/vajra.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
public/profile/vajra@2x.png
Normal file
|
After Width: | Height: | Size: 379 KiB |
BIN
public/profile/vane.png
Normal file
|
After Width: | Height: | Size: 107 KiB |
BIN
public/profile/vane@2x.png
Normal file
|
After Width: | Height: | Size: 119 KiB |
BIN
public/profile/vikala.png
Normal file
|
After Width: | Height: | Size: 207 KiB |
BIN
public/profile/vikala@2x.png
Normal file
|
After Width: | Height: | Size: 374 KiB |
BIN
public/profile/yuel.png
Normal file
|
After Width: | Height: | Size: 186 KiB |
BIN
public/profile/yuel@2x.png
Normal file
|
After Width: | Height: | Size: 297 KiB |
BIN
public/profile/yuisis.png
Normal file
|
After Width: | Height: | Size: 151 KiB |
BIN
public/profile/yuisis@2x.png
Normal file
|
After Width: | Height: | Size: 189 KiB |
BIN
public/profile/zeta.png
Normal file
|
After Width: | Height: | Size: 190 KiB |
BIN
public/profile/zeta@2x.png
Normal file
|
After Width: | Height: | Size: 305 KiB |
|
|
@ -290,6 +290,43 @@ select {
|
|||
}
|
||||
}
|
||||
|
||||
img.profile {
|
||||
background: $grey-90;
|
||||
|
||||
&.fire {
|
||||
background: $fire-bg-light;
|
||||
}
|
||||
|
||||
&.water {
|
||||
background: $water-bg-light;
|
||||
}
|
||||
|
||||
&.wind {
|
||||
background: $wind-bg-light;
|
||||
}
|
||||
|
||||
&.earth {
|
||||
background: $earth-bg-light;
|
||||
}
|
||||
|
||||
&.dark {
|
||||
background: $dark-bg-light;
|
||||
}
|
||||
|
||||
&.light {
|
||||
background: $light-bg-light;
|
||||
}
|
||||
}
|
||||
|
||||
i.tag {
|
||||
background: $grey-90;
|
||||
border-radius: $unit / 2;
|
||||
font-size: 10px;
|
||||
font-weight: $bold;
|
||||
padding: 4px 6px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@keyframes openModal {
|
||||
0% {
|
||||
opacity: 0;
|
||||
|
|
|
|||
5
types/User.d.ts
vendored
|
|
@ -2,4 +2,9 @@ interface User {
|
|||
id: string
|
||||
username: string
|
||||
granblueId: number
|
||||
picture: {
|
||||
picture: string
|
||||
element: string
|
||||
}
|
||||
private: boolean
|
||||
}
|
||||
|
|
@ -8,7 +8,9 @@ interface AccountState {
|
|||
language: 'en' | 'jp',
|
||||
user: {
|
||||
id: string,
|
||||
username: string
|
||||
username: string,
|
||||
picture: string,
|
||||
element: string,
|
||||
} | undefined
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,11 @@ class Api {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
userInfo(id: string) {
|
||||
const resourceUrl = `${this.url}/users/info/${id}`
|
||||
return axios.get(resourceUrl)
|
||||
}
|
||||
}
|
||||
|
||||
const api: Api = new Api({ url: process.env.NEXT_PUBLIC_SIERO_API_URL || 'https://localhost:3000/api/v1'})
|
||||
|
|
|
|||
315
utils/pictureData.tsx
Normal file
|
|
@ -0,0 +1,315 @@
|
|||
interface Picture {
|
||||
name: {
|
||||
en: string
|
||||
jp: string
|
||||
}
|
||||
filename: string
|
||||
element: string
|
||||
}
|
||||
|
||||
export const pictureData: Picture[] = [
|
||||
{
|
||||
name: {
|
||||
en: "Gran 2019",
|
||||
jp: "グラン"
|
||||
},
|
||||
filename: "gran_19",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Djeeta 2019",
|
||||
jp: "ジータ"
|
||||
},
|
||||
filename: "djeeta_19",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Gran 2020",
|
||||
jp: "グラン"
|
||||
},
|
||||
filename: "gran_20",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Djeeta 2020",
|
||||
jp: "ジータ"
|
||||
},
|
||||
filename: "djeeta_20",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Gran - Farer of the Skies",
|
||||
jp: "空駆ける新鋭 グランver"
|
||||
},
|
||||
filename: "gran",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Djeeta - Farer of the Skies",
|
||||
jp: "空駆ける新鋭 ジータver"
|
||||
},
|
||||
filename: "djeeta",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Cassius",
|
||||
jp: "カシウス"
|
||||
},
|
||||
filename: "Cassius",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Percival",
|
||||
jp: "パーシヴァル"
|
||||
},
|
||||
filename: "percival",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Vane",
|
||||
jp: "ヴェイン"
|
||||
},
|
||||
filename: "vane",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Heles",
|
||||
jp: "ヘルエス"
|
||||
},
|
||||
filename: "heles",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Lunalu",
|
||||
jp: "ルナール"
|
||||
},
|
||||
filename: "lunalu",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Catura",
|
||||
jp: "シャトラ"
|
||||
},
|
||||
filename: "catura",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Yuisis",
|
||||
jp: "ユイシス"
|
||||
},
|
||||
filename: "yuisis",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Meg",
|
||||
jp: "メグ"
|
||||
},
|
||||
filename: "meg",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Seofon",
|
||||
jp: "シエテ"
|
||||
},
|
||||
filename: "seofon",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Quatre",
|
||||
jp: "カトル"
|
||||
},
|
||||
filename: "quatre",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Tien",
|
||||
jp: "エッセル"
|
||||
},
|
||||
filename: "Tien",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Seox",
|
||||
jp: "シス"
|
||||
},
|
||||
filename: "seox",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Aoidos",
|
||||
jp: "アオイドス"
|
||||
},
|
||||
filename: "aoidos",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Sandalphon",
|
||||
jp: "サンダルフォン"
|
||||
},
|
||||
filename: "sandalphon",
|
||||
element: "light"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Vikala",
|
||||
jp: "ビカラ"
|
||||
},
|
||||
filename: "vikala",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Belial",
|
||||
jp: "ベリアル"
|
||||
},
|
||||
filename: "belial",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Zeta",
|
||||
jp: "ゼタ"
|
||||
},
|
||||
filename: "zeta",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Beatrix",
|
||||
jp: "ベアトリックス"
|
||||
},
|
||||
filename: "beatrix",
|
||||
element: "earth"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Yuel",
|
||||
jp: "ユエル"
|
||||
},
|
||||
filename: "yuel",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Societte",
|
||||
jp: "ソシエ"
|
||||
},
|
||||
filename: "societte",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Kumbhira",
|
||||
jp: "クビラ"
|
||||
},
|
||||
filename: "kumbhira",
|
||||
element: "light"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Narmaya",
|
||||
jp: "ナルメア"
|
||||
},
|
||||
filename: "narmaya",
|
||||
element: "dark"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Siegfried",
|
||||
jp: "ジークフリード"
|
||||
},
|
||||
filename: "siegfried",
|
||||
element: "earth"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Naoise",
|
||||
jp: "ノイシュ"
|
||||
},
|
||||
filename: "naoise",
|
||||
element: "light"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Scathacha",
|
||||
jp: "スカーサハ"
|
||||
},
|
||||
filename: "scathacha",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Seruel",
|
||||
jp: "セルエル"
|
||||
},
|
||||
filename: "seruel",
|
||||
element: "light"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Shiva",
|
||||
jp: "シヴァ"
|
||||
},
|
||||
filename: "shiva",
|
||||
element: "fire"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Europa",
|
||||
jp: "エウロペ"
|
||||
},
|
||||
filename: "europa",
|
||||
element: "water"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Grimnir",
|
||||
jp: "グリームニル"
|
||||
},
|
||||
filename: "grimnir",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Alexiel",
|
||||
jp: "ブローディア"
|
||||
},
|
||||
filename: "alexiel",
|
||||
element: "earth"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Sierokarte",
|
||||
jp: "シェロカルテ"
|
||||
},
|
||||
filename: "siero",
|
||||
element: "wind"
|
||||
},
|
||||
{
|
||||
name: {
|
||||
en: "Vajra",
|
||||
jp: "ヴァジラ"
|
||||
},
|
||||
filename: "vajra",
|
||||
element: "water"
|
||||
}
|
||||
]
|
||||