import { useEffect, useState, useRef } from 'react' import { Helmet } from 'react-helmet-async' import { useNavigate } from 'react-router-dom' import PostFormTagsArea from '@/components/PostFormTagsArea' import PostOriginalCreatedTimeField from '@/components/PostOriginalCreatedTimeField' import Form from '@/components/common/Form' import Label from '@/components/common/Label' import PageTitle from '@/components/common/PageTitle' 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 { apiGet, apiPost } from '@/lib/api' import Forbidden from '@/pages/Forbidden' import type { FC } from 'react' import type { User } from '@/types' type Props = { user: User | null } export default (({ user }: Props) => { if (!(['admin', 'member'].some (r => user?.role === r))) return const navigate = useNavigate () const [originalCreatedBefore, setOriginalCreatedBefore] = useState (null) const [originalCreatedFrom, setOriginalCreatedFrom] = useState (null) const [tags, setTags] = useState ('') const [thumbnailAutoFlg, setThumbnailAutoFlg] = useState (true) const [thumbnailFile, setThumbnailFile] = useState (null) const [thumbnailLoading, setThumbnailLoading] = useState (false) const [thumbnailPreview, setThumbnailPreview] = useState ('') const [title, setTitle] = useState ('') const [titleAutoFlg, setTitleAutoFlg] = useState (true) const [titleLoading, setTitleLoading] = useState (false) const [url, setURL] = useState ('') const previousURLRef = useRef ('') const handleSubmit = async () => { const formData = new FormData formData.append ('title', title) formData.append ('url', url) formData.append ('tags', tags) if (thumbnailFile) formData.append ('thumbnail', thumbnailFile) if (originalCreatedFrom) formData.append ('original_created_from', originalCreatedFrom) if (originalCreatedBefore) formData.append ('original_created_before', originalCreatedBefore) try { await apiPost ('/posts', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) toast ({ title: '投稿成功!' }) navigate ('/posts') } catch { toast ({ title: '投稿失敗', description: '入力を確認してください。' }) } } useEffect (() => { if (titleAutoFlg && url) fetchTitle () }, [titleAutoFlg]) useEffect (() => { if (thumbnailAutoFlg && url) fetchThumbnail () }, [thumbnailAutoFlg]) const handleURLBlur = () => { if (!(url) || url === previousURLRef.current) return if (titleAutoFlg) fetchTitle () if (thumbnailAutoFlg) fetchThumbnail () previousURLRef.current = url } const fetchTitle = async () => { setTitle ('') setTitleLoading (true) const data = await apiGet<{ title: string }> ('/preview/title', { params: { url } }) setTitle (data.title || '') setTitleLoading (false) } const fetchThumbnail = async () => { setThumbnailPreview ('') setThumbnailFile (null) setThumbnailLoading (true) if (thumbnailPreview) URL.revokeObjectURL (thumbnailPreview) const data = await apiGet ('/preview/thumbnail', { params: { url }, responseType: 'blob' }) const imageURL = URL.createObjectURL (data) setThumbnailPreview (imageURL) setThumbnailFile (new File ([data], 'thumbnail.png', { type: data.type || 'image/png' })) setThumbnailLoading (false) } return ( {`広場に投稿を追加 | ${ SITE_TITLE }`}
広場に投稿を追加する {/* URL */}
setURL (e.target.value)} className="w-full border p-2 rounded" onBlur={handleURLBlur}/>
{/* タイトル */}
setTitle (ev.target.value)} disabled={titleAutoFlg}/>
{/* サムネール */}
{thumbnailAutoFlg ? (thumbnailLoading ?

Loading...

: !(thumbnailPreview) && (

URL から自動取得されます。

)) : ( { const file = e.target.files?.[0] if (file) { setThumbnailFile (file) setThumbnailPreview (URL.createObjectURL (file)) } }}/>)} {thumbnailPreview && ( preview)}
{/* タグ */} {/* オリジナルの作成日時 */} {/* 送信 */}
) }) satisfies FC