#49 ぼちぼち
This commit is contained in:
@@ -4,9 +4,9 @@ import TagPage from '@/pages/TagPage'
|
|||||||
import TopNav from '@/components/TopNav'
|
import TopNav from '@/components/TopNav'
|
||||||
import TagSidebar from '@/components/TagSidebar'
|
import TagSidebar from '@/components/TagSidebar'
|
||||||
import TagDetailSidebar from '@/components/TagDetailSidebar'
|
import TagDetailSidebar from '@/components/TagDetailSidebar'
|
||||||
import PostPage from '@/pages/PostPage'
|
import PostPage from '@/pages/posts/PostPage'
|
||||||
import PostNewPage from '@/pages/PostNewPage'
|
import PostNewPage from '@/pages/posts/PostNewPage'
|
||||||
import PostDetailPage from '@/pages/PostDetailPage'
|
import PostDetailPage from '@/pages/posts/PostDetailPage'
|
||||||
import WikiPage from '@/pages/WikiPage'
|
import WikiPage from '@/pages/WikiPage'
|
||||||
import WikiNewPage from '@/pages/WikiNewPage'
|
import WikiNewPage from '@/pages/WikiNewPage'
|
||||||
import WikiEditPage from '@/pages/WikiEditPage'
|
import WikiEditPage from '@/pages/WikiEditPage'
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { API_BASE_URL } from '@/config'
|
import { API_BASE_URL } from '@/config'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
|
|
||||||
import type { Post, Tag } from '@/types'
|
import type { Post, Tag } from '@/types'
|
||||||
|
|
||||||
@@ -64,9 +65,9 @@ export default ({ post, onSave }: Props) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 送信 */}
|
{/* 送信 */}
|
||||||
<button onClick={handleSubmit}
|
<Button onClick={handleSubmit}
|
||||||
className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400">
|
className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400">
|
||||||
更新
|
更新
|
||||||
</button>
|
</Button>
|
||||||
</div>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
import { Link, useParams } from 'react-router-dom'
|
import { Link, useParams } from 'react-router-dom'
|
||||||
|
|
||||||
|
import TagSearch from '@/components/TagSearch'
|
||||||
|
import SubsectionTitle from '@/components/common/SubsectionTitle'
|
||||||
|
import SidebarComponent from '@/components/layout/SidebarComponent'
|
||||||
import { API_BASE_URL } from '@/config'
|
import { API_BASE_URL } from '@/config'
|
||||||
import TagSearch from './TagSearch'
|
|
||||||
import SidebarComponent from './layout/SidebarComponent'
|
|
||||||
import { CATEGORIES } from '@/consts'
|
import { CATEGORIES } from '@/consts'
|
||||||
|
|
||||||
import type { Category, Post, Tag } from '@/types'
|
import type { Category, Post, Tag } from '@/types'
|
||||||
@@ -45,17 +47,16 @@ export default ({ post }: Props) => {
|
|||||||
<SidebarComponent>
|
<SidebarComponent>
|
||||||
<TagSearch />
|
<TagSearch />
|
||||||
{CATEGORIES.map ((cat: Category) => cat in tags && (
|
{CATEGORIES.map ((cat: Category) => cat in tags && (
|
||||||
<>
|
<div className="my-3">
|
||||||
<h2>{categoryNames[cat]}</h2>
|
<SubsectionTitle>{categoryNames[cat]}</SubsectionTitle>
|
||||||
<ul>
|
<ul>
|
||||||
{tags[cat].map (tag => (
|
{tags[cat].map (tag => (
|
||||||
<li key={tag.id} className="mb-2">
|
<li key={tag.id} className="mb-1">
|
||||||
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}
|
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}>
|
||||||
className="text-blue-600 hover:underline">
|
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</Link>
|
</Link>
|
||||||
</li>))}
|
</li>))}
|
||||||
</ul>
|
</ul>
|
||||||
</>))}
|
</div>))}
|
||||||
</SidebarComponent>)
|
</SidebarComponent>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Link, useNavigate, useLocation } from 'react-router-dom'
|
import { Link, useNavigate, useLocation } from 'react-router-dom'
|
||||||
import { API_BASE_URL } from '../config'
|
import { API_BASE_URL } from '@/config'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
import type { Tag } from '@/types'
|
import type { Tag } from '@/types'
|
||||||
|
|
||||||
@@ -23,8 +24,10 @@ const TagSearchBox: React.FC = (props: Props) => {
|
|||||||
<ul className="absolute left-0 right-0 z-50 w-full bg-gray-800 border border-gray-600 rounded shadow">
|
<ul className="absolute left-0 right-0 z-50 w-full bg-gray-800 border border-gray-600 rounded shadow">
|
||||||
{suggestions.map ((tag, i) => (
|
{suggestions.map ((tag, i) => (
|
||||||
<li key={tag.id}
|
<li key={tag.id}
|
||||||
className={`px-3 py-2 cursor-pointer ${
|
className={cn ('px-3 py-2 cursor-pointer',
|
||||||
i === activeIndex ? 'bg-blue-600 text-white' : 'hover:bg-gray-700' }`}
|
(i === activeIndex
|
||||||
|
? 'bg-blue-600 text-white'
|
||||||
|
: 'hover:bg-gray-700'))}
|
||||||
onMouseDown={() => onSelect (tag)}
|
onMouseDown={() => onSelect (tag)}
|
||||||
>
|
>
|
||||||
{tag.name}
|
{tag.name}
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ import React, { useEffect, useState } from 'react'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import { Link, useParams } from 'react-router-dom'
|
import { Link, useParams } from 'react-router-dom'
|
||||||
import { API_BASE_URL } from '@/config'
|
import { API_BASE_URL } from '@/config'
|
||||||
import TagSearch from './TagSearch'
|
import TagSearch from '@/components/TagSearch'
|
||||||
import SidebarComponent from './layout/SidebarComponent'
|
import SidebarComponent from '@/components/layout/SidebarComponent'
|
||||||
|
import SectionTitle from '@/components/common/SectionTitle'
|
||||||
|
|
||||||
import type { Post, Tag } from '@/types'
|
import type { Post, Tag } from '@/types'
|
||||||
|
|
||||||
@@ -12,12 +13,6 @@ type TagByCategory = { [key: string]: Tag[] }
|
|||||||
type Props = { posts: Post[] }
|
type Props = { posts: Post[] }
|
||||||
|
|
||||||
|
|
||||||
const tagNameMap: { [key: string]: string } = {
|
|
||||||
general: '一般',
|
|
||||||
deerjikist: 'ニジラー',
|
|
||||||
nico: 'ニコニコタグ' }
|
|
||||||
|
|
||||||
|
|
||||||
export default ({ posts }: Props) => {
|
export default ({ posts }: Props) => {
|
||||||
const [tags, setTags] = useState<TagByCategory> ({ })
|
const [tags, setTags] = useState<TagByCategory> ({ })
|
||||||
const [tagsCounts, setTagsCounts] = useState<{ [key: number]: number }> ({ })
|
const [tagsCounts, setTagsCounts] = useState<{ [key: number]: number }> ({ })
|
||||||
@@ -47,18 +42,20 @@ export default ({ posts }: Props) => {
|
|||||||
return (
|
return (
|
||||||
<SidebarComponent>
|
<SidebarComponent>
|
||||||
<TagSearch />
|
<TagSearch />
|
||||||
{['general', 'deerjikist', 'nico'].map (cat => cat in tags && <>
|
<SectionTitle>タグ</SectionTitle>
|
||||||
<h2>{tagNameMap[cat]}</h2>
|
<ul>
|
||||||
<ul>
|
{['general', 'deerjikist', 'nico'].map (cat => cat in tags && (
|
||||||
{tags[cat].map (tag => (
|
<>
|
||||||
<li key={tag.id} className="mb-2">
|
{tags[cat].map (tag => (
|
||||||
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}
|
<li key={tag.id} className="mb-1">
|
||||||
className="text-blue-600 hover:underline">
|
<Link to={`/posts?${ (new URLSearchParams ({ tags: tag.name })).toString () }`}>
|
||||||
{tag.name}
|
{tag.name}
|
||||||
</Link>
|
</Link>
|
||||||
<span className="ml-1">{tagsCounts[tag.id]}</span>
|
<span className="ml-1">{tagsCounts[tag.id]}</span>
|
||||||
</li>))}
|
</li>))}
|
||||||
</ul>
|
</>))}
|
||||||
</>)}
|
</ul>
|
||||||
|
<SectionTitle>関聯</SectionTitle>
|
||||||
|
<Link>ランダム</Link>
|
||||||
</SidebarComponent>)
|
</SidebarComponent>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
|
|||||||
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
|
import { Link, useLocation, useNavigate, useParams } from 'react-router-dom'
|
||||||
import SettingsDialogue from './SettingsDialogue'
|
import SettingsDialogue from './SettingsDialogue'
|
||||||
import { Button } from './ui/button'
|
import { Button } from './ui/button'
|
||||||
import clsx from 'clsx'
|
import { cn } from '@/lib/utils'
|
||||||
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
||||||
|
|
||||||
import type { User } from '@/types'
|
import type { User } from '@/types'
|
||||||
@@ -33,10 +33,10 @@ const TopNav: React.FC = ({ user, setUser }: Props) => {
|
|||||||
title: string
|
title: string
|
||||||
menu?: Menu
|
menu?: Menu
|
||||||
base?: string }) => (
|
base?: string }) => (
|
||||||
<Link to={to} className={clsx ('hover:text-orange-500 h-full flex items-center',
|
<Link to={to} className={cn ('hover:text-orange-500 h-full flex items-center',
|
||||||
(location.pathname.startsWith (base ?? to)
|
(location.pathname.startsWith (base ?? to)
|
||||||
? 'bg-gray-700 px-4 font-bold'
|
? 'bg-gray-700 px-4 font-bold'
|
||||||
: 'px-2'))}>
|
: 'px-2'))}>
|
||||||
{title}
|
{title}
|
||||||
</Link>)
|
</Link>)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = { children: React.ReactNode }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ children }: Props) => (
|
||||||
|
<div className="max-w-xl mx-auto p-4 space-y-4">
|
||||||
|
{children}
|
||||||
|
</div>)
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = { children: React.ReactNode
|
||||||
|
checkBox?: { label: string
|
||||||
|
checked: boolean
|
||||||
|
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void } }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ children, checkBox }: Props) => {
|
||||||
|
if (!(checkBox))
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<label className="block font-semibold mb-1">
|
||||||
|
{children}
|
||||||
|
</label>)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="flex gap-2 mb-1">
|
||||||
|
<label className="flex-1 block font-semibold">{children}</label>
|
||||||
|
<label className="flex items-center block gap-1">
|
||||||
|
<input type="checkbox"
|
||||||
|
checked={checkBox.checked}
|
||||||
|
onChange={checkBox.onChange} />
|
||||||
|
{checkBox.label}
|
||||||
|
</label>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = { children: React.ReactNode }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ children }: Props) => (
|
||||||
|
<h1 className="text-2xl font-bold mb-2">
|
||||||
|
{children}
|
||||||
|
</h1>)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = { children: React.ReactNode }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ children }: Props) => (
|
||||||
|
<h2 className="text-xl my-4">
|
||||||
|
{children}
|
||||||
|
</h2>)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
type Props = { children: React.ReactNode }
|
||||||
|
|
||||||
|
|
||||||
|
export default ({ children }: Props) => (
|
||||||
|
<h3 className="my-2">
|
||||||
|
{children}
|
||||||
|
</h3>)
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
type TabProps = { name: string
|
type TabProps = { name: string
|
||||||
init?: boolean
|
init?: boolean
|
||||||
@@ -6,7 +7,7 @@ type TabProps = { name: string
|
|||||||
|
|
||||||
type Props = { children: React.ReactElement<{ name: string }>[] }
|
type Props = { children: React.ReactElement<{ name: string }>[] }
|
||||||
|
|
||||||
export const Tab = ({ children }: TabProps) => children
|
export const Tab = ({ children }: TabProps) => <>{children}</>
|
||||||
|
|
||||||
|
|
||||||
export default ({ children }: Props) => {
|
export default ({ children }: Props) => {
|
||||||
@@ -23,7 +24,7 @@ export default ({ children }: Props) => {
|
|||||||
{tabs.map ((tab, i) => (
|
{tabs.map ((tab, i) => (
|
||||||
<a key={i}
|
<a key={i}
|
||||||
href="#"
|
href="#"
|
||||||
className={`text-blue-400 hover:underline ${ i === current ? 'font-bold' : '' }`}
|
className={cn (i === current && 'font-bold')}
|
||||||
onClick={ev => {
|
onClick={ev => {
|
||||||
ev.preventDefault ()
|
ev.preventDefault ()
|
||||||
setCurrent (i)
|
setCurrent (i)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import axios from 'axios'
|
|||||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
import { WikiIdBus } from '@/lib/eventBus/WikiIdBus'
|
||||||
|
import PageTitle from '@/components/common/PageTitle'
|
||||||
|
|
||||||
import type { WikiPage } from '@/types'
|
import type { WikiPage } from '@/types'
|
||||||
|
|
||||||
@@ -45,20 +46,18 @@ export default () => {
|
|||||||
{(wikiPage && version) && (
|
{(wikiPage && version) && (
|
||||||
<div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4">
|
<div className="text-sm flex gap-3 items-center justify-center border border-gray-700 rounded px-2 py-1 mb-4">
|
||||||
{wikiPage.pred ? (
|
{wikiPage.pred ? (
|
||||||
<Link to={`/wiki/${ title }?version=${ wikiPage.pred }`}
|
<Link to={`/wiki/${ title }?version=${ wikiPage.pred }`}>
|
||||||
className="text-blue-400 hover:underline">
|
< 古
|
||||||
< 前
|
</Link>) : <>(最古)</>}
|
||||||
</Link>) : <>< 前</>}
|
|
||||||
|
|
||||||
<span>{wikiPage.updated_at}</span>
|
<span>{wikiPage.updated_at}</span>
|
||||||
|
|
||||||
{wikiPage.succ ? (
|
{wikiPage.succ ? (
|
||||||
<Link to={`/wiki/${ title }?version=${ wikiPage.succ }`}
|
<Link to={`/wiki/${ title }?version=${ wikiPage.succ }`}>
|
||||||
className="text-blue-400 hover:underline">
|
新 >
|
||||||
後 >
|
</Link>) : <>(最新)</>}
|
||||||
</Link>) : <>後 ></>}
|
|
||||||
</div>)}
|
</div>)}
|
||||||
<h1>{title}</h1>
|
<PageTitle>{title}</PageTitle>
|
||||||
<div className="prose mx-auto p-4">
|
<div className="prose mx-auto p-4">
|
||||||
{wikiPage === undefined ? 'Loading...' : (
|
{wikiPage === undefined ? 'Loading...' : (
|
||||||
<>
|
<>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
import axios from 'axios'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { Helmet } from 'react-helmet'
|
import { Helmet } from 'react-helmet'
|
||||||
import { Link, useLocation, useParams } from 'react-router-dom'
|
import { Link, useLocation, useParams } from 'react-router-dom'
|
||||||
import axios from 'axios'
|
|
||||||
|
import PageTitle from '@/components/common/PageTitle'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||||
|
|
||||||
@@ -29,7 +31,7 @@ export default () => {
|
|||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title>
|
<title>{`Wiki 差分: ${ diff?.title } | ${ SITE_TITLE }`}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<h1>{diff?.title}</h1>
|
<PageTitle>{diff?.title}</PageTitle>
|
||||||
<div className="prose mx-auto p-4">
|
<div className="prose mx-auto p-4">
|
||||||
{diff ? (
|
{diff ? (
|
||||||
diff.diff.map (d => (
|
diff.diff.map (d => (
|
||||||
|
|||||||
@@ -44,8 +44,7 @@ export default () => {
|
|||||||
</Link>)}
|
</Link>)}
|
||||||
</td>
|
</td>
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<Link to={`/wiki/${ encodeURIComponent (change.wiki_page.title) }?version=${ change.sha }`}
|
<Link to={`/wiki/${ encodeURIComponent (change.wiki_page.title) }?version=${ change.sha }`}>
|
||||||
className="text-blue-400 hover:underline">
|
|
||||||
{change.wiki_page.title}
|
{change.wiki_page.title}
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
@@ -63,8 +62,7 @@ export default () => {
|
|||||||
}) ()}
|
}) ()}
|
||||||
</td>
|
</td>
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<Link to={`/users/${ change.user.id }`}
|
<Link to={`/users/${ change.user.id }`}>
|
||||||
className="text-blue-400 hover:underline">
|
|
||||||
{change.user.name}
|
{change.user.name}
|
||||||
</Link>
|
</Link>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Link } from 'react-router-dom'
|
|||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
import { API_BASE_URL, SITE_TITLE } from '@/config'
|
||||||
|
import SectionTitle from '@/components/common/SectionTitle'
|
||||||
|
|
||||||
import type { Category, WikiPage } from '@/types'
|
import type { Category, WikiPage } from '@/types'
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ export default () => {
|
|||||||
<title>{`Wiki | ${ SITE_TITLE }`}</title>
|
<title>{`Wiki | ${ SITE_TITLE }`}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="max-w-xl">
|
<div className="max-w-xl">
|
||||||
<h2 className="text-xl mb-4">Wiki</h2>
|
<SectionTitle className="text-xl mb-4">Wiki</SectionTitle>
|
||||||
<form onSubmit={handleSearch} className="space-y-2">
|
<form onSubmit={handleSearch} className="space-y-2">
|
||||||
{/* タイトル */}
|
{/* タイトル */}
|
||||||
<div>
|
<div>
|
||||||
@@ -76,8 +77,7 @@ export default () => {
|
|||||||
{results.map (page => (
|
{results.map (page => (
|
||||||
<tr key={page.id}>
|
<tr key={page.id}>
|
||||||
<td className="p-2">
|
<td className="p-2">
|
||||||
<Link to={`/wiki/${ encodeURIComponent (page.title) }`}
|
<Link to={`/wiki/${ encodeURIComponent (page.title) }`}>
|
||||||
className="text-blue-400 hover:underline">
|
|
||||||
{page.title}
|
{page.title}
|
||||||
</Link>
|
</Link>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
+17
-18
@@ -65,7 +65,14 @@ export default ({ user }: Props) => {
|
|||||||
setEditing (true)
|
setEditing (true)
|
||||||
}, [editing])
|
}, [editing])
|
||||||
|
|
||||||
const url = post ? new URL (post.url) : undefined
|
const url = post ? new URL (post.url) : null
|
||||||
|
const nicoFlg = url?.hostname.split ('.').slice (-2).join ('.') === 'nicovideo.jp'
|
||||||
|
const videoId = (nicoFlg
|
||||||
|
? url.pathname.match (/(?<=\/watch\/)[a-zA-Z0-9]+?(?=\/|$)/)[0]
|
||||||
|
: '')
|
||||||
|
const viewedClass = (post?.viewed
|
||||||
|
? 'bg-blue-600 hover:bg-blue-700'
|
||||||
|
: 'bg-gray-500 hover:bg-gray-600')
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -76,23 +83,15 @@ export default ({ user }: Props) => {
|
|||||||
<MainArea>
|
<MainArea>
|
||||||
{post
|
{post
|
||||||
? (
|
? (
|
||||||
<div className="p-4">
|
<>
|
||||||
{(() => {
|
{nicoFlg
|
||||||
if (url.hostname.split ('.').slice (-2).join ('.') === 'nicovideo.jp')
|
? (
|
||||||
{
|
<NicoViewer id={videoId}
|
||||||
return (
|
width="640"
|
||||||
<NicoViewer
|
height="360" />)
|
||||||
id={url.pathname.match (
|
: <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />}
|
||||||
/(?<=\/watch\/)[a-zA-Z0-9]+?(?=\/|$)/)[0]}
|
|
||||||
width="640"
|
|
||||||
height="360" />)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return <img src={post.thumbnail} alt={post.url} className="mb-4 w-full" />
|
|
||||||
}) ()}
|
|
||||||
<Button onClick={changeViewedFlg}
|
<Button onClick={changeViewedFlg}
|
||||||
className={cn ('text-white',
|
className={cn ('text-white', viewedClass)}>
|
||||||
post.viewed ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-500 hover:bg-gray-600')}>
|
|
||||||
{post.viewed ? '閲覧済' : '未閲覧'}
|
{post.viewed ? '閲覧済' : '未閲覧'}
|
||||||
</Button>
|
</Button>
|
||||||
<TabGroup>
|
<TabGroup>
|
||||||
@@ -105,7 +104,7 @@ export default ({ user }: Props) => {
|
|||||||
}} />
|
}} />
|
||||||
</Tab>}
|
</Tab>}
|
||||||
</TabGroup>
|
</TabGroup>
|
||||||
</div>)
|
</>)
|
||||||
: 'Loading...'}
|
: 'Loading...'}
|
||||||
</MainArea>
|
</MainArea>
|
||||||
</>)
|
</>)
|
||||||
@@ -8,6 +8,9 @@ import { Button } from '@/components/ui/button'
|
|||||||
import { toast } from '@/components/ui/use-toast'
|
import { toast } from '@/components/ui/use-toast'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
|
import Form from '@/components/common/Form'
|
||||||
|
import PageTitle from '@/components/common/PageTitle'
|
||||||
|
import Label from '@/components/common/Label'
|
||||||
|
|
||||||
import type { Post, Tag } from '@/types'
|
import type { Post, Tag } from '@/types'
|
||||||
|
|
||||||
@@ -115,12 +118,12 @@ export default () => {
|
|||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{`広場に投稿を追加 | ${ SITE_TITLE }`}</title>
|
<title>{`広場に投稿を追加 | ${ SITE_TITLE }`}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="max-w-xl mx-auto p-4 space-y-4">
|
<Form>
|
||||||
<h1 className="text-2xl font-bold mb-2">広場に投稿を追加する</h1>
|
<PageTitle>広場に投稿を追加する</PageTitle>
|
||||||
|
|
||||||
{/* URL */}
|
{/* URL */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block font-semibold mb-1">URL</label>
|
<Label>URL</Label>
|
||||||
<input type="text"
|
<input type="text"
|
||||||
placeholder="例:https://www.nicovideo.jp/watch/..."
|
placeholder="例:https://www.nicovideo.jp/watch/..."
|
||||||
value={url}
|
value={url}
|
||||||
@@ -131,15 +134,12 @@ export default () => {
|
|||||||
|
|
||||||
{/* タイトル */}
|
{/* タイトル */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex gap-2 mb-1">
|
<Label checkBox={{
|
||||||
<label className="flex-1 block font-semibold">タイトル</label>
|
label: '自動',
|
||||||
<label className="flex items-center block gap-1">
|
checked: titleAutoFlg,
|
||||||
<input type="checkbox"
|
onChange: ev => setTitleAutoFlg (ev.target.checked)}}>
|
||||||
checked={titleAutoFlg}
|
タイトル
|
||||||
onChange={e => setTitleAutoFlg (e.target.checked)} />
|
</Label>
|
||||||
自動
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<input type="text"
|
<input type="text"
|
||||||
className="w-full border rounded p-2"
|
className="w-full border rounded p-2"
|
||||||
value={title}
|
value={title}
|
||||||
@@ -150,15 +150,12 @@ export default () => {
|
|||||||
|
|
||||||
{/* サムネール */}
|
{/* サムネール */}
|
||||||
<div>
|
<div>
|
||||||
<div className="flex gap-2 mb-1">
|
<Label checkBox={{
|
||||||
<label className="block font-semibold flex-1">サムネール</label>
|
label: '自動',
|
||||||
<label className="flex items-center gap-1">
|
checked: thumbnailAutoFlg,
|
||||||
<input type="checkbox"
|
onChange: ev => setThumbnailAutoFlg (ev.target.checked)}}>
|
||||||
checked={thumbnailAutoFlg}
|
サムネール
|
||||||
onChange={e => setThumbnailAutoFlg (e.target.checked)} />
|
</Label>
|
||||||
自動
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
{thumbnailAutoFlg
|
{thumbnailAutoFlg
|
||||||
? (thumbnailLoading
|
? (thumbnailLoading
|
||||||
? <p className="text-gray-500 text-sm">Loading...</p>
|
? <p className="text-gray-500 text-sm">Loading...</p>
|
||||||
@@ -185,7 +182,7 @@ export default () => {
|
|||||||
|
|
||||||
{/* タグ */}
|
{/* タグ */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block font-semibold">タグ</label>
|
<Label>タグ</Label>
|
||||||
<select multiple
|
<select multiple
|
||||||
value={tagIds.map (String)}
|
value={tagIds.map (String)}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
@@ -201,11 +198,11 @@ export default () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* 送信 */}
|
{/* 送信 */}
|
||||||
<button onClick={handleSubmit}
|
<Button onClick={handleSubmit}
|
||||||
className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400"
|
className="px-4 py-2 bg-blue-600 text-white rounded disabled:bg-gray-400"
|
||||||
disabled={titleLoading || thumbnailLoading}>
|
disabled={titleLoading || thumbnailLoading}>
|
||||||
追加
|
追加
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</Form>
|
||||||
</MainArea>)
|
</MainArea>)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user