import axios from 'axios' import toCamel from 'camelcase-keys' import { useEffect, useRef, useState } from 'react' import { FaThumbsDown, FaThumbsUp } from 'react-icons/fa' import { useParams, useSearchParams } from 'react-router-dom' import ThreadCanvas from '@/components/threads/ThreadCanvas' import { API_BASE_URL } from '@/config' import type { ThreadCanvasHandle } from '@/components/threads/ThreadCanvas' import type { Post, Thread } from '@/types' const Sort = { Newest: 'newest', Oldest: 'oldest', Likes: 'likes', Dislikes: 'dislikes' } as const type Sort = (typeof Sort)[keyof typeof Sort] const reformPost = (post: Post): Post => ({ ...post, createdAt: (new Date (post.createdAt)).toLocaleString ('ja-JP-u-ca-japanese') }) export default () => { const { id } = useParams () const canvasRef = useRef (null) const [searchParams, setSearchParams] = useSearchParams () const sort = searchParams.get ('sort') ?? 'created_at' const order = searchParams.get ('order') ?? 'desc' const sortKey = (() => { if (sort === 'score') { if (order === 'asc') return Sort.Dislikes return Sort.Likes } else { if (order === 'asc') return Sort.Oldest return Sort.Newest } }) () const [loading, setLoading] = useState (true) const [message, setMessage] = useState ('') const [name, setName] = useState ('') const [password, setPassword] = useState ('') const [posts, setPosts] = useState ([]) const [sending, setSending] = useState (false) const [thread, setThread] = useState (null) const [withImage, setWithImage] = useState (false) const handleSend = async () => { if (!(message) && !(withImage)) { alert ('メッセージ書くか画像描くかどっちかはしろ.') return } setSending (true) try { const form = new FormData if (withImage) { if (!(canvasRef.current)) return const { dataURL } = await canvasRef.current.exportAll () const blob = await (await fetch (dataURL)).blob () form.append ('image', new File ([blob], `kekec_${ Date.now () }.png`, { type: 'image/png' })) } form.append ('name', name) form.append ('message', message) form.append ('password', password) const res = await axios.post (`${ API_BASE_URL }/threads/${ id }/posts`, form, { headers: { 'Content-Type': 'multipart/form-data' } }) const data: Post = toCamel (res.data as any, { deep: true }) setPosts(prev => [reformPost (data), ...prev]) setMessage ('') if (withImage) { canvasRef.current!.clear () setWithImage (false) } localStorage.setItem ('name', name) localStorage.setItem ('password', password) } finally { setSending (false) } } useEffect (() => { const nameRaw = localStorage.getItem ('name') nameRaw && setName (nameRaw) const passRaw = localStorage.getItem ('password') passRaw && setPassword (passRaw) const fetchThread = async () => { try { const res = await axios.get (`${ API_BASE_URL }/threads/${ id }`) setThread (toCamel (res.data as any, { deep: true }) as Thread) } catch { setThread (null) } } fetchThread () }, []) useEffect (() => { const fetchPosts = async () => { try { const res = await axios.get (`${ API_BASE_URL }/threads/${ id }/posts`, { params: { sort, order } }) const data = toCamel (res.data as any, { deep: true }) as Post[] setPosts (data.map (reformPost)) } catch { setPosts ([]) } setLoading (false) } fetchPosts () }, [sortKey]) useEffect (() => { if (!(thread)) return document.title = `${ thread.name } - キケッツチャンネル お絵描き掲示板` }, [thread]) return ( <>
setName (ev.target.value)} />
setPassword (ev.target.value)} />