import { useMutation, useQueryClient } from '@tanstack/react-query' import { useState } from 'react' import { Helmet } from 'react-helmet-async' import { useLocation } from 'react-router-dom' import { useLocale, useLocaleNavigate } from '@/lib/useLocale' 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 { createMaterial } from '@/lib/materials' import { unlocalisedPath } from '@/lib/locales' import { materialsKeys } from '@/lib/queryKeys' import { inputClass } from '@/lib/utils' import { useValidationErrors } from '@/lib/useValidationErrors' import { useUITranslation } from '@/lib/useUITranslation' import type { FC } from 'react' type MaterialFormField = 'tag' | 'file' | 'url' | 'exportPaths' const MaterialNewPage: FC = () => { const locale = useLocale () const { message, label } = useUITranslation ('materials') const qc = useQueryClient () const location = useLocation () const query = new URLSearchParams (location.search) const tagQuery = query.get ('tag') ?? '' const returnToQuery = query.get ('return_to') ?? '' const safeReturnTo = unlocalisedPath (returnToQuery).startsWith ('/materials') ? returnToQuery : '' const navigate = useLocaleNavigate () const [file, setFile] = useState (null) const [filePreview, setFilePreview] = useState ('') const [tag, setTag] = useState (tagQuery) const [url, setURL] = useState ('') const [exportPath, setExportPath] = useState ('') const { baseErrors, fieldErrors, clearValidationErrors, applyValidationError } = useValidationErrors () const createMutation = useMutation ({ mutationFn: async () => { const formData = new FormData if (tag) formData.append ('tag', tag) if (file) formData.append ('file', file) if (url) formData.append ('url', url) formData.append ('export_paths[legacy_drive]', exportPath) return await createMaterial (formData, locale) }, onSuccess: async () => { await qc.invalidateQueries ({ queryKey: materialsKeys.root }) toast ({ title: label ('sent') }) navigate (safeReturnTo || '/materials') }, onError: error => { applyValidationError (error) toast ({ title: label ('sendFailed'), description: label ('shared:messages.reviewInput') }) }}) const handleSubmit = () => { clearValidationErrors () createMutation.mutate () } return ( {message ('newTitle').text} | {SITE_TITLE}
{label ('newTitle')} {/* タグ */} {({ describedBy, invalid }) => ( )} {/* ファイル */} {({ describedBy, invalid }) => ( <> { const f = e.target.files?.[0] setFile (f ?? null) setFilePreview (f ? URL.createObjectURL (f) : '') }}/> {(file && filePreview) && ( (/image\/.*/.test (file.type) && ( {message)) || (/video\/.*/.test (file.type) && ( {/* 参考 URL */} {({ describedBy, invalid }) => ( setURL (e.target.value)} aria-describedby={describedBy} aria-invalid={invalid} className={inputClass (invalid)}/>)} {({ describedBy, invalid }) => ( setExportPath (e.target.value)} placeholder={message ('exportPlaceholder').text} lang={message ('exportPlaceholder').language} aria-describedby={describedBy} aria-invalid={invalid} className={inputClass (invalid)}/>)} {/* 送信 */}
) } export default MaterialNewPage