import { useState } from 'react' import { Helmet } from 'react-helmet-async' import { useLocation, useNavigate } from 'react-router-dom' import FieldError from '@/components/common/FieldError' import Form from '@/components/common/Form' import FormField from '@/components/common/FormField' import PageTitle from '@/components/common/PageTitle' import TagInput from '@/components/common/TagInput' import MainArea from '@/components/layout/MainArea' import { Button } from '@/components/ui/button' import { toast } from '@/components/ui/use-toast' import { SITE_TITLE } from '@/config' import { apiPost } from '@/lib/api' import { inputClass } from '@/lib/utils' import { useValidationErrors } from '@/lib/useValidationErrors' import type { FC } from 'react' type MaterialFormField = 'tag' | 'file' | 'url' const MaterialNewPage: FC = () => { const location = useLocation () const query = new URLSearchParams (location.search) const tagQuery = query.get ('tag') ?? '' const navigate = useNavigate () const [file, setFile] = useState (null) const [filePreview, setFilePreview] = useState ('') const [sending, setSending] = useState (false) const [tag, setTag] = useState (tagQuery) const [url, setURL] = useState ('') const { baseErrors, fieldErrors, clearValidationErrors, applyValidationError } = useValidationErrors () const handleSubmit = async () => { clearValidationErrors () const formData = new FormData if (tag) formData.append ('tag', tag) if (file) formData.append ('file', file) if (url) formData.append ('url', url) try { setSending (true) await apiPost ('/materials', formData) toast ({ title: '送信成功!' }) navigate (`/materials?tag=${ encodeURIComponent (tag) }`) } catch (e) { applyValidationError (e) toast ({ title: '送信失敗……', description: '入力を見直してください.' }) } finally { setSending (false) } } return ( {`素材追加 | ${ SITE_TITLE }`}
素材追加 {/* タグ */} {({ describedBy, invalid }) => ( )} {/* ファイル */} {({ describedBy, invalid }) => ( <> { const f = e.target.files?.[0] setFile (f ?? null) setFilePreview (f ? URL.createObjectURL (f) : '') }}/> {(file && filePreview) && ( (/image\/.*/.test (file.type) && ( preview)) || (/video\/.*/.test (file.type) && ( {/* 参考 URL */} {({ describedBy, invalid }) => ( setURL (e.target.value)} aria-describedby={describedBy} aria-invalid={invalid} className={inputClass (invalid)}/>)} {/* 送信 */}
) } export default MaterialNewPage