ぼざクリ タグ広場 https://hub.nizika.monster
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

74 lines
2.5 KiB

  1. import React, { useEffect, useState } from 'react'
  2. import axios from 'axios'
  3. import { API_BASE_URL } from '@/config'
  4. import { Button } from '@/components/ui/button'
  5. import type { Post, Tag } from '@/types'
  6. type Props = { post: Post
  7. onSave: (newPost: Post) => void }
  8. export default ({ post, onSave }: Props) => {
  9. const [title, setTitle] = useState (post.title)
  10. const [tags, setTags] = useState<Tag[]> ([])
  11. const [tagIds, setTagIds] = useState<number[]> (post.tags.map (t => t.id))
  12. const handleSubmit = () => {
  13. void (axios.put (`${ API_BASE_URL }/posts/${ post.id }`,
  14. { title,
  15. tags: JSON.stringify (tagIds) },
  16. { headers: { 'Content-Type': 'multipart/form-data',
  17. 'X-Transfer-Code': localStorage.getItem ('user_code') || '' } } )
  18. .then (res => {
  19. const newPost: Post = res.data
  20. onSave ({ ...post,
  21. title: newPost.title,
  22. tags: newPost.tags } as Post)
  23. }))
  24. }
  25. useEffect (() => {
  26. void (axios.get ('/api/tags')
  27. .then (res => setTags (res.data))
  28. .catch (() => toast ({ title: 'タグ一覧の取得失敗' })))
  29. }, [])
  30. return (
  31. <div className="max-w-xl pt-2 space-y-4">
  32. {/* タイトル */}
  33. <div>
  34. <div className="flex gap-2 mb-1">
  35. <label className="flex-1 block font-semibold">タイトル</label>
  36. </div>
  37. <input type="text"
  38. className="w-full border rounded p-2"
  39. value={title}
  40. onChange={e => setTitle (e.target.value)} />
  41. </div>
  42. {/* タグ */}
  43. <div>
  44. <label className="block font-semibold">タグ</label>
  45. <select multiple
  46. value={tagIds.map (String)}
  47. onChange={e => {
  48. const values = Array.from (e.target.selectedOptions).map (o => Number (o.value))
  49. setTagIds (values)
  50. }}
  51. className="w-full p-2 border rounded h-32">
  52. {tags.map ((tag: Tag) => (
  53. <option key={tag.id} value={tag.id}>
  54. {tag.name}
  55. </option>))}
  56. </select>
  57. </div>
  58. {/* 送信 */}
  59. <Button onClick={handleSubmit}
  60. className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400">
  61. 更新
  62. </Button>
  63. </div>)
  64. }