Add modal for network errors
This commit is contained in:
parent
6da5a4f320
commit
ab928f4429
6 changed files with 104 additions and 17 deletions
|
|
@ -23,7 +23,11 @@ const Alert = (props: Props) => {
|
||||||
<AlertDialog.Overlay className="Overlay" onClick={props.cancelAction} />
|
<AlertDialog.Overlay className="Overlay" onClick={props.cancelAction} />
|
||||||
<div className="AlertWrapper">
|
<div className="AlertWrapper">
|
||||||
<AlertDialog.Content className="Alert">
|
<AlertDialog.Content className="Alert">
|
||||||
{props.title ? <AlertDialog.Title>Error</AlertDialog.Title> : ''}
|
{props.title ? (
|
||||||
|
<AlertDialog.Title>{props.title}</AlertDialog.Title>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
<AlertDialog.Description className="description">
|
<AlertDialog.Description className="description">
|
||||||
{props.message}
|
{props.message}
|
||||||
</AlertDialog.Description>
|
</AlertDialog.Description>
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,9 @@
|
||||||
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
import React, { useCallback, useEffect, useMemo, useState } from 'react'
|
||||||
import { getCookie } from 'cookies-next'
|
import { getCookie } from 'cookies-next'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosError, AxiosResponse } from 'axios'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
|
||||||
import Alert from '~components/Alert'
|
import Alert from '~components/Alert'
|
||||||
|
|
@ -31,12 +32,19 @@ const CharacterGrid = (props: Props) => {
|
||||||
// Constants
|
// Constants
|
||||||
const numCharacters: number = 5
|
const numCharacters: number = 5
|
||||||
|
|
||||||
|
// Localization
|
||||||
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
// Cookies
|
// Cookies
|
||||||
const cookie = getCookie('account')
|
const cookie = getCookie('account')
|
||||||
const accountData: AccountCookie = cookie
|
const accountData: AccountCookie = cookie
|
||||||
? JSON.parse(cookie as string)
|
? JSON.parse(cookie as string)
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
// Set up state for error handling
|
||||||
|
const [axiosError, setAxiosError] = useState<AxiosResponse>()
|
||||||
|
const [errorAlertOpen, setErrorAlertOpen] = useState(false)
|
||||||
|
|
||||||
// Set up state for view management
|
// Set up state for view management
|
||||||
const { party, grid } = useSnapshot(appState)
|
const { party, grid } = useSnapshot(appState)
|
||||||
const [slug, setSlug] = useState()
|
const [slug, setSlug] = useState()
|
||||||
|
|
@ -111,7 +119,15 @@ const CharacterGrid = (props: Props) => {
|
||||||
if (party.editable)
|
if (party.editable)
|
||||||
saveCharacter(party.id, character, position)
|
saveCharacter(party.id, character, position)
|
||||||
.then((response) => handleCharacterResponse(response.data))
|
.then((response) => handleCharacterResponse(response.data))
|
||||||
.catch((error) => console.error(error))
|
.catch((error) => {
|
||||||
|
const axiosError = error as AxiosError
|
||||||
|
const response = axiosError.response
|
||||||
|
|
||||||
|
if (response) {
|
||||||
|
setErrorAlertOpen(true)
|
||||||
|
setAxiosError(response)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,6 +498,19 @@ const CharacterGrid = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render: JSX components
|
// Render: JSX components
|
||||||
|
const errorAlert = () => {
|
||||||
|
console.log(axiosError?.status)
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
open={errorAlertOpen}
|
||||||
|
title={axiosError ? `${axiosError.status}` : 'Error'}
|
||||||
|
message={t(`errors.${axiosError?.statusText.toLowerCase()}`)}
|
||||||
|
cancelAction={() => setErrorAlertOpen(false)}
|
||||||
|
cancelActionText={t('buttons.confirm')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Alert
|
<Alert
|
||||||
|
|
@ -526,6 +555,7 @@ const CharacterGrid = (props: Props) => {
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{errorAlert()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ import { getCookie } from 'cookies-next'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosError, AxiosResponse } from 'axios'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
|
||||||
|
import Alert from '~components/Alert'
|
||||||
import SummonUnit from '~components/SummonUnit'
|
import SummonUnit from '~components/SummonUnit'
|
||||||
import ExtraSummons from '~components/ExtraSummons'
|
import ExtraSummons from '~components/ExtraSummons'
|
||||||
|
|
||||||
|
|
@ -38,6 +39,10 @@ const SummonGrid = (props: Props) => {
|
||||||
// Localization
|
// Localization
|
||||||
const { t } = useTranslation('common')
|
const { t } = useTranslation('common')
|
||||||
|
|
||||||
|
// Set up state for error handling
|
||||||
|
const [axiosError, setAxiosError] = useState<AxiosResponse>()
|
||||||
|
const [errorAlertOpen, setErrorAlertOpen] = useState(false)
|
||||||
|
|
||||||
// Set up state for view management
|
// Set up state for view management
|
||||||
const { party, grid } = useSnapshot(appState)
|
const { party, grid } = useSnapshot(appState)
|
||||||
const [slug, setSlug] = useState()
|
const [slug, setSlug] = useState()
|
||||||
|
|
@ -100,12 +105,12 @@ const SummonGrid = (props: Props) => {
|
||||||
saveSummon(party.id, summon, position)
|
saveSummon(party.id, summon, position)
|
||||||
.then((response) => handleSummonResponse(response.data))
|
.then((response) => handleSummonResponse(response.data))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const code = error.response.status
|
const axiosError = error as AxiosError
|
||||||
const data = error.response.data
|
const response = axiosError.response
|
||||||
if (code === 422) {
|
|
||||||
if (data.code === 'incompatible_summon_for_position') {
|
if (response) {
|
||||||
// setShowIncompatibleAlert(true)
|
setErrorAlertOpen(true)
|
||||||
}
|
setAxiosError(response)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
@ -380,6 +385,19 @@ const SummonGrid = (props: Props) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render: JSX components
|
// Render: JSX components
|
||||||
|
const errorAlert = () => {
|
||||||
|
console.log(axiosError?.status)
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
open={errorAlertOpen}
|
||||||
|
title={axiosError ? `${axiosError.status}` : 'Error'}
|
||||||
|
message={t(`errors.${axiosError?.statusText.toLowerCase()}`)}
|
||||||
|
cancelAction={() => setErrorAlertOpen(false)}
|
||||||
|
cancelActionText={t('buttons.confirm')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
const mainSummonElement = (
|
const mainSummonElement = (
|
||||||
<div className="LabeledUnit">
|
<div className="LabeledUnit">
|
||||||
<div className="Label">{t('summons.main')}</div>
|
<div className="Label">{t('summons.main')}</div>
|
||||||
|
|
@ -460,6 +478,7 @@ const SummonGrid = (props: Props) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{subAuraSummonElement}
|
{subAuraSummonElement}
|
||||||
|
{errorAlert()}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { getCookie } from 'cookies-next'
|
||||||
import { useSnapshot } from 'valtio'
|
import { useSnapshot } from 'valtio'
|
||||||
import { useTranslation } from 'next-i18next'
|
import { useTranslation } from 'next-i18next'
|
||||||
|
|
||||||
import { AxiosResponse } from 'axios'
|
import { AxiosError, AxiosResponse } from 'axios'
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
|
||||||
import Alert from '~components/Alert'
|
import Alert from '~components/Alert'
|
||||||
|
|
@ -41,11 +41,15 @@ const WeaponGrid = (props: Props) => {
|
||||||
? JSON.parse(cookie as string)
|
? JSON.parse(cookie as string)
|
||||||
: null
|
: null
|
||||||
|
|
||||||
|
// Set up state for error handling
|
||||||
|
const [axiosError, setAxiosError] = useState<AxiosResponse>()
|
||||||
|
const [errorAlertOpen, setErrorAlertOpen] = useState(false)
|
||||||
|
const [showIncompatibleAlert, setShowIncompatibleAlert] = useState(false)
|
||||||
|
|
||||||
// Set up state for view management
|
// Set up state for view management
|
||||||
const { party, grid } = useSnapshot(appState)
|
const { party, grid } = useSnapshot(appState)
|
||||||
const [slug, setSlug] = useState()
|
const [slug, setSlug] = useState()
|
||||||
const [modalOpen, setModalOpen] = useState(false)
|
const [modalOpen, setModalOpen] = useState(false)
|
||||||
const [showIncompatibleAlert, setShowIncompatibleAlert] = useState(false)
|
|
||||||
|
|
||||||
// Set up state for conflict management
|
// Set up state for conflict management
|
||||||
const [incoming, setIncoming] = useState<Weapon>()
|
const [incoming, setIncoming] = useState<Weapon>()
|
||||||
|
|
@ -100,11 +104,21 @@ const WeaponGrid = (props: Props) => {
|
||||||
saveWeapon(party.id, weapon, position)
|
saveWeapon(party.id, weapon, position)
|
||||||
.then((response) => handleWeaponResponse(response.data))
|
.then((response) => handleWeaponResponse(response.data))
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const code = error.response.status
|
const axiosError = error as AxiosError
|
||||||
const data = error.response.data
|
const response = axiosError.response
|
||||||
if (code === 422) {
|
|
||||||
if (data.code === 'incompatible_weapon_for_position') {
|
if (response) {
|
||||||
|
const code = response.status
|
||||||
|
const data = response.data
|
||||||
|
|
||||||
|
if (
|
||||||
|
code === 422 &&
|
||||||
|
data.code === 'incompatible_weapon_for_position'
|
||||||
|
) {
|
||||||
setShowIncompatibleAlert(true)
|
setShowIncompatibleAlert(true)
|
||||||
|
} else {
|
||||||
|
setErrorAlertOpen(true)
|
||||||
|
setAxiosError(response)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -362,16 +376,30 @@ const WeaponGrid = (props: Props) => {
|
||||||
cancelAction={() => setShowIncompatibleAlert(!showIncompatibleAlert)}
|
cancelAction={() => setShowIncompatibleAlert(!showIncompatibleAlert)}
|
||||||
cancelActionText={t('buttons.confirm')}
|
cancelActionText={t('buttons.confirm')}
|
||||||
message={t('alert.incompatible_weapon')}
|
message={t('alert.incompatible_weapon')}
|
||||||
></Alert>
|
/>
|
||||||
) : (
|
) : (
|
||||||
''
|
''
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const errorAlert = () => {
|
||||||
|
console.log(axiosError?.status)
|
||||||
|
return (
|
||||||
|
<Alert
|
||||||
|
open={errorAlertOpen}
|
||||||
|
title={axiosError ? `${axiosError.status}` : 'Error'}
|
||||||
|
message={t(`errors.${axiosError?.statusText.toLowerCase()}`)}
|
||||||
|
cancelAction={() => setErrorAlertOpen(false)}
|
||||||
|
cancelActionText={t('buttons.confirm')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id="WeaponGrid">
|
<div id="WeaponGrid">
|
||||||
{conflicts ? conflictModal() : ''}
|
{conflicts ? conflictModal() : ''}
|
||||||
{incompatibleAlert()}
|
{incompatibleAlert()}
|
||||||
|
{errorAlert()}
|
||||||
<div id="MainGrid">
|
<div id="MainGrid">
|
||||||
{mainhandElement}
|
{mainhandElement}
|
||||||
<ul id="Weapons">{weaponGridElement}</ul>
|
<ul id="Weapons">{weaponGridElement}</ul>
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@
|
||||||
},
|
},
|
||||||
"remove": "Remove from grid"
|
"remove": "Remove from grid"
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"unauthorized": "You don't have permission to perform that action"
|
||||||
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"labels": {
|
"labels": {
|
||||||
"element": "Element",
|
"element": "Element",
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,9 @@
|
||||||
"rarity": "レアリティ"
|
"rarity": "レアリティ"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"errors": {
|
||||||
|
"unauthorized": "行ったアクションを実行する権限がありません"
|
||||||
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"anonymous": "無名",
|
"anonymous": "無名",
|
||||||
"untitled_team": "{{username}}さんからの無題編成",
|
"untitled_team": "{{username}}さんからの無題編成",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue