#49 ちょろちょろ

This commit is contained in:
2025-06-26 07:59:08 +09:00
parent 6e6ee73857
commit f49640727f
12 changed files with 138 additions and 38 deletions
@@ -0,0 +1,25 @@
import React, { useEffect, useState } from 'react'
type Props = { tabs: { [key: string]: React.ReactNode }
init?: string }
export default ({ tabs, init }: Props) => {
const [current, setCurrent] = useState<string> (init
?? Object.keys (tabs)?.[0]
?? '')
return (
<div className="mt-4">
{Object.entries (tabs).map (([name, element]) => (
<a href="#"
className="text-blue-400 hover:underline cursor-pointer"
onClick={(event) => {
event.preventDefault ()
setCurrent (name)
}}>
{name}
</a>))}
{current && tabs[current]}
</div>)
}
+12 -20
View File
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '@/config'
@@ -9,6 +10,7 @@ import { cn } from '@/lib/utils'
import MainArea from '@/components/layout/MainArea'
import TagDetailSidebar from '@/components/TagDetailSidebar'
import PostEditForm from '@/components/PostEditForm'
import TabControl from '@/components/common/TabControl'
import type { Post, Tag, User } from '@/types'
@@ -69,20 +71,13 @@ export default ({ user }: Props) => {
setEditing (true)
}, [editing])
if (!(post))
return (
<>
<TagDetailSidebar post={null} />
<MainArea>Loading...</MainArea>
</>)
if (post)
document.title = `${ post.title || post.url } | ${ SITE_TITLE }`
const url = post ? new URL (post.url) : undefined
return (
<>
<Helmet>
{post && <title>{`${ post.title || post.url } | ${ SITE_TITLE }`}</title>}
</Helmet>
<TagDetailSidebar post={post} />
<MainArea>
{post
@@ -107,16 +102,13 @@ export default ({ user }: Props) => {
{post.viewed ? '閲覧済' : '未閲覧'}
</Button>
{(['admin', 'member'].includes (user.role) && editing) &&
<div className="mt-4">
<span className="text-blue-400 hover:underline cursor-pointer">
</span>
<PostEditForm post={post}
onSave={newPost => {
setPost (newPost)
toast ({ description: '更新しました.' })
}} />
</div>}
<TabControl tabs={{
['編輯']: (
<PostEditForm post={post}
onSave={newPost => {
setPost (newPost)
toast ({ description: '更新しました.' })
}} />) }} />}
</div>)
: 'Loading...'}
</MainArea>
+4 -2
View File
@@ -1,4 +1,5 @@
import React, { useEffect, useState, useRef } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '@/config'
@@ -48,8 +49,6 @@ export default () => {
description: '入力を確認してください。' })))
}
document.title = `広場に投稿を追加 | ${ SITE_TITLE }`
useEffect (() => {
void (axios.get ('/api/tags')
.then (res => setTags (res.data))
@@ -113,6 +112,9 @@ export default () => {
return (
<MainArea>
<Helmet>
<title>{`広場に投稿を追加 | ${ SITE_TITLE }`}</title>
</Helmet>
<div className="max-w-xl mx-auto p-4 space-y-4">
<h1 className="text-2xl font-bold mb-2">稿</h1>
+8 -4
View File
@@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '@/config'
@@ -17,10 +18,6 @@ export default () => {
// const anyFlg = query.get ('match') === 'any'
const anyFlg = false
const tags = tagsQuery.split (' ').filter (e => e !== '')
if (tags.length)
document.title = `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }`
else
document.title = `${ SITE_TITLE } 〜 ぼざクリも、ぼざろ外も、外伝もあるんだよ`
useEffect(() => {
const fetchPosts = async () => {
@@ -42,6 +39,13 @@ export default () => {
return (
<>
<Helmet>
<title>
{tags.length
? `${ tags.join (anyFlg ? ' or ' : ' and ') } | ${ SITE_TITLE }`
: `${ SITE_TITLE } 〜 ぼざクリも、ぼざろ外も、外伝もあるんだよ`}
</title>
</Helmet>
<TagSidebar posts={posts} />
<MainArea>
<div className="flex flex-wrap gap-4 p-4">
+5 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
import ReactMarkdown from 'react-markdown'
import axios from 'axios'
import { API_BASE_URL } from '@/config'
import { API_BASE_URL, SITE_TITLE } from '@/config'
import MainArea from '@/components/layout/MainArea'
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
@@ -38,6 +39,9 @@ export default () => {
return (
<MainArea>
<Helmet>
<title>{`${ title } Wiki | ${ SITE_TITLE }`}</title>
</Helmet>
{(wikiPage && version) && (
<div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4">
{wikiPage.pred ? (
+5 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams } from 'react-router-dom'
import axios from 'axios'
import MainArea from '@/components/layout/MainArea'
import { API_BASE_URL } from '@/config'
import { API_BASE_URL, SITE_TITLE } from '@/config'
import type { WikiPageDiff } from '@/types'
@@ -25,6 +26,9 @@ export default () => {
return (
<MainArea>
<Helmet>
<title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title>
</Helmet>
<h1>{diff?.title}</h1>
<div className="prose mx-auto p-4">
{diff ? (
+4 -2
View File
@@ -1,4 +1,5 @@
import React, { useEffect, useState, useRef } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '@/config'
@@ -47,12 +48,13 @@ export default () => {
setTitle (res.data.title)
setBody (res.data.body)
}))
document.title = `Wiki ページを編輯 | ${ SITE_TITLE }`
}, [id])
return (
<MainArea>
<Helmet>
<title>{`Wiki ページを編輯 | ${ SITE_TITLE }`}</title>
</Helmet>
<div className="max-w-xl mx-auto p-4 space-y-4">
<h1 className="text-2xl font-bold mb-2">Wiki </h1>
+5 -1
View File
@@ -1,8 +1,9 @@
import { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams } from 'react-router-dom'
import MainArea from '@/components/layout/MainArea'
import axios from 'axios'
import { API_BASE_URL } from '@/config'
import { API_BASE_URL, SITE_TITLE } from '@/config'
import type { WikiPageChange } from '@/types'
@@ -21,6 +22,9 @@ export default () => {
return (
<MainArea>
<Helmet>
<title>{`Wiki 変更履歴 | ${ SITE_TITLE }`}</title>
</Helmet>
<table className="table-auto w-full border-collapse">
<thead>
<tr>
+4 -4
View File
@@ -1,4 +1,5 @@
import React, { useEffect, useState, useRef } from 'react'
import { Helmet } from 'react-helmet'
import { Link, useLocation, useParams, useNavigate } from 'react-router-dom'
import axios from 'axios'
import { API_BASE_URL, SITE_TITLE } from '@/config'
@@ -42,12 +43,11 @@ export default () => {
description: '入力を確認してください。' })))
}
useEffect (() => {
document.title = `新規 Wiki ページ | ${ SITE_TITLE }`
}, [])
return (
<MainArea>
<Helmet>
<title>{`新規 Wiki ページ | ${ SITE_TITLE }`}</title>
</Helmet>
<div className="max-w-xl mx-auto p-4 space-y-4">
<h1 className="text-2xl font-bold mb-2"> Wiki </h1>
+5 -1
View File
@@ -1,8 +1,9 @@
import React, { useEffect, useState } from 'react'
import { Helmet } from 'react-helmet'
import { Link } from 'react-router-dom'
import axios from 'axios'
import MainArea from '@/components/layout/MainArea'
import { API_BASE_URL } from '@/config'
import { API_BASE_URL, SITE_TITLE } from '@/config'
import type { Category, WikiPage } from '@/types'
@@ -29,6 +30,9 @@ export default () => {
return (
<MainArea>
<Helmet>
<title>{`Wiki | ${ SITE_TITLE }`}</title>
</Helmet>
<div className="max-w-xl">
<h2 className="text-xl mb-4">Wiki</h2>
<form onSubmit={handleSearch} className="space-y-2">