フォームのバリデーションとニコ連携の画面変更 (#090) #355
@@ -79,7 +79,7 @@ const PostEditForm: FC<Props> = ({ post, onSave }) => {
|
||||
|
||||
if (response?.status !== 409)
|
||||
{
|
||||
const validationError = extractValidationError (e)
|
||||
const validationError = extractValidationError<PostFormField> (e)
|
||||
|
||||
if (validationError)
|
||||
{
|
||||
@@ -145,6 +145,8 @@ const PostEditForm: FC<Props> = ({ post, onSave }) => {
|
||||
|
||||
return (
|
||||
<form onSubmit={handleSubmit} className="max-w-xl pt-2 space-y-4">
|
||||
<FieldError messages={baseErrors}/>
|
||||
|
||||
{/* タイトル */}
|
||||
<div>
|
||||
<Label>タイトル</Label>
|
||||
@@ -166,7 +168,7 @@ const PostEditForm: FC<Props> = ({ post, onSave }) => {
|
||||
disabled={disabled}
|
||||
value={parentPostIds}
|
||||
onChange={e => setParentPostIds (e.target.value)}
|
||||
alia-invalid={fieldErrors.parentPostIds && fieldErrors.parentPostIds.length > 0}
|
||||
aria-invalid={fieldErrors.parentPostIds && fieldErrors.parentPostIds.length > 0}
|
||||
className={inputClass (fieldErrors.parentPostIds
|
||||
&& fieldErrors.parentPostIds.length > 0)}/>
|
||||
<FieldError messages={fieldErrors.parentPostIds}/>
|
||||
@@ -189,9 +191,7 @@ const PostEditForm: FC<Props> = ({ post, onSave }) => {
|
||||
errors={fieldErrors.originalCreatedAt}/>
|
||||
|
||||
{/* 送信 */}
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={disabled}>
|
||||
<Button type="submit" disabled={disabled}>
|
||||
更新
|
||||
</Button>
|
||||
</form>)
|
||||
|
||||
@@ -4,7 +4,7 @@ type Props = { messages?: string[] }
|
||||
|
||||
|
||||
export const FieldError: FC<Props> = ({ messages }: Props) => {
|
||||
if (!(messages?.length))
|
||||
if (!(messages) || messages.length === 0)
|
||||
return null
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,11 +2,12 @@ import toCamel from 'camelcase-keys'
|
||||
|
||||
import { isApiError } from '@/lib/api'
|
||||
|
||||
export type FieldErrors = Partial<Record<string, string[]>>
|
||||
export type FieldErrors<T extends string = string> = Partial<Record<T, string[]>>
|
||||
|
||||
export type ValidationError = { message: string
|
||||
fieldErrors: FieldErrors
|
||||
baseErrors: string[] }
|
||||
export type ValidationError<T extends string = string> =
|
||||
{ message: string
|
||||
fieldErrors: FieldErrors<T>
|
||||
baseErrors: string[] }
|
||||
|
||||
type RawValidationError = { type?: string
|
||||
message?: string
|
||||
@@ -14,7 +15,7 @@ type RawValidationError = { type?: string
|
||||
baseErrors?: string[] }
|
||||
|
||||
|
||||
export const extractValidationError = (err: unknown) => {
|
||||
export const extractValidationError = <T extends string = string> (err: unknown) => {
|
||||
if (!(isApiError (err)) || err.response?.status !== 422)
|
||||
return null
|
||||
|
||||
@@ -25,6 +26,6 @@ export const extractValidationError = (err: unknown) => {
|
||||
return null
|
||||
|
||||
return { message: data.message ?? '入力内容を確認してください.',
|
||||
fieldErrors: (data.errors ?? { }) as FieldErrors,
|
||||
fieldErrors: (data.errors ?? { }) as FieldErrors<T>,
|
||||
baseErrors: data.baseErrors ?? [] }
|
||||
}
|
||||
|
||||
新しい課題から参照
ユーザをブロックする