このコミットが含まれているのは:
@@ -46,7 +46,7 @@ describe ('extractValidationError', () => {
|
||||
})
|
||||
|
||||
expect (validationError?.fieldErrors).toEqual ({
|
||||
'deerjikists.0.platform': ['プラットフォームを入力してください.'],
|
||||
'deerjikists0Platform': ['プラットフォームを入力してください.'],
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import toCamel from 'camelcase-keys'
|
||||
|
||||
import { isApiError } from '@/lib/api'
|
||||
|
||||
export type FieldErrors<T extends string = string> = Partial<Record<T, string[]>>
|
||||
@@ -17,13 +19,13 @@ export const extractValidationError = <T extends string = string> (err: unknown)
|
||||
if (!(isApiError (err)) || err.response?.status !== 422)
|
||||
return null
|
||||
|
||||
const rawData = (err.response.data ?? { }) as Record<string, unknown>
|
||||
const rawData = toCamel ((err.response.data ?? { }) as Record<string, unknown>,
|
||||
{ deep: true }) as RawValidationError
|
||||
const data: RawValidationError = {
|
||||
type: rawData.type as string | undefined,
|
||||
message: rawData.message as string | undefined,
|
||||
errors: rawData.errors as Record<string, string[]> | undefined,
|
||||
baseErrors: rawData.base_errors as string[] | undefined,
|
||||
}
|
||||
type: rawData.type as string | undefined,
|
||||
message: rawData.message as string | undefined,
|
||||
errors: rawData.errors as Record<string, string[]> | undefined,
|
||||
baseErrors: rawData.baseErrors as string[] | undefined }
|
||||
|
||||
if (data.type !== 'validation_error' && !(data.errors))
|
||||
return null
|
||||
|
||||
@@ -20,7 +20,7 @@ import type { FC, FormEvent } from 'react'
|
||||
import type { Deerjikist, Platform } from '@/types'
|
||||
|
||||
type DeerjikistFormField =
|
||||
'deerjikists' | `deerjikists.${ number }.platform` | `deerjikists.${ number }.code`
|
||||
'deerjikists' | `deerjikists${ number }Platform` | `deerjikists${ number }Code`
|
||||
|
||||
|
||||
const DeerjikistDetailPage: FC = () => {
|
||||
@@ -105,45 +105,45 @@ const DeerjikistDetailPage: FC = () => {
|
||||
{/* プラットフォーム */}
|
||||
<FormField
|
||||
label="プラットフォーム"
|
||||
messages={fieldErrors[`deerjikists.${ i }.platform`]}>
|
||||
messages={fieldErrors[`deerjikists${ i }Platform`]}>
|
||||
{({ describedBy, invalid }) => (
|
||||
<select
|
||||
disabled={disabled}
|
||||
value={datum.platform ?? ''}
|
||||
aria-describedby={describedBy}
|
||||
aria-invalid={invalid}
|
||||
className={inputClass (invalid)}
|
||||
onChange={e => setData (prev => {
|
||||
const rtn = [...prev]
|
||||
rtn[i] = { ...rtn[i],
|
||||
platform: (e.target.value || null) as Platform | null }
|
||||
return rtn
|
||||
})}>
|
||||
<option value=""> </option>
|
||||
{PLATFORMS.map (p => (
|
||||
<option key={p} value={p}>
|
||||
{PLATFORM_NAMES[p]}
|
||||
</option>))}
|
||||
</select>)}
|
||||
<select
|
||||
disabled={disabled}
|
||||
value={datum.platform ?? ''}
|
||||
aria-describedby={describedBy}
|
||||
aria-invalid={invalid}
|
||||
className={inputClass (invalid)}
|
||||
onChange={e => setData (prev => {
|
||||
const rtn = [...prev]
|
||||
rtn[i] = { ...rtn[i],
|
||||
platform: (e.target.value || null) as Platform | null }
|
||||
return rtn
|
||||
})}>
|
||||
<option value=""> </option>
|
||||
{PLATFORMS.map (p => (
|
||||
<option key={p} value={p}>
|
||||
{PLATFORM_NAMES[p]}
|
||||
</option>))}
|
||||
</select>)}
|
||||
</FormField>
|
||||
|
||||
{/* コード */}
|
||||
<FormField
|
||||
label="コード"
|
||||
messages={fieldErrors[`deerjikists.${ i }.code`]}>
|
||||
messages={fieldErrors[`deerjikists${ i }Code`]}>
|
||||
{({ describedBy, invalid }) => (
|
||||
<input
|
||||
type="text"
|
||||
disabled={disabled}
|
||||
value={datum.code}
|
||||
aria-describedby={describedBy}
|
||||
aria-invalid={invalid}
|
||||
className={inputClass (invalid)}
|
||||
onChange={e => setData (prev => {
|
||||
const rtn = [...prev]
|
||||
rtn[i] = { ...rtn[i], code: e.target.value }
|
||||
return rtn
|
||||
})}/>)}
|
||||
<input
|
||||
type="text"
|
||||
disabled={disabled}
|
||||
value={datum.code}
|
||||
aria-describedby={describedBy}
|
||||
aria-invalid={invalid}
|
||||
className={inputClass (invalid)}
|
||||
onChange={e => setData (prev => {
|
||||
const rtn = [...prev]
|
||||
rtn[i] = { ...rtn[i], code: e.target.value }
|
||||
return rtn
|
||||
})}/>)}
|
||||
</FormField>
|
||||
</fieldset>
|
||||
))}
|
||||
|
||||
新しい課題から参照
ユーザをブロックする