| @@ -34,7 +34,7 @@ export default ({ post, onSave }: Props) => { | |||||
| }, []) | }, []) | ||||
| return ( | return ( | ||||
| <div className="max-w-xl p-4 space-y-4"> | |||||
| <div className="max-w-xl pt-2 space-y-4"> | |||||
| {/* タイトル */} | {/* タイトル */} | ||||
| <div> | <div> | ||||
| <div className="flex gap-2 mb-1"> | <div className="flex gap-2 mb-1"> | ||||
| @@ -1,25 +0,0 @@ | |||||
| 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>) | |||||
| } | |||||
| @@ -0,0 +1,38 @@ | |||||
| import React, { useState } from 'react' | |||||
| type TabProps = { name: string | |||||
| init?: boolean | |||||
| children: React.ReactNode } | |||||
| type Props = { children: React.ReactElement<{ name: string }>[] } | |||||
| export const Tab = ({ children }: TabProps) => children | |||||
| export default ({ children }: Props) => { | |||||
| const tabs = React.Children.toArray (children) | |||||
| const [current, setCurrent] = useState<number> (() => { | |||||
| const i = tabs.findIndex (tab => tab.props.init) | |||||
| return i >= 0 ? i : 0 | |||||
| }) | |||||
| return ( | |||||
| <div className="mt-4"> | |||||
| <div className="flex gap-4"> | |||||
| {tabs.map ((tab, i) => ( | |||||
| <a key={i} | |||||
| href="#" | |||||
| className={`text-blue-400 hover:underline ${ i === current ? 'font-bold' : '' }`} | |||||
| onClick={ev => { | |||||
| ev.preventDefault () | |||||
| setCurrent (i) | |||||
| }}> | |||||
| {tab.props.name} | |||||
| </a>))} | |||||
| </div> | |||||
| <div className="mt-2"> | |||||
| {tabs[current]} | |||||
| </div> | |||||
| </div>) | |||||
| } | |||||
| @@ -10,7 +10,7 @@ import { cn } from '@/lib/utils' | |||||
| import MainArea from '@/components/layout/MainArea' | import MainArea from '@/components/layout/MainArea' | ||||
| import TagDetailSidebar from '@/components/TagDetailSidebar' | import TagDetailSidebar from '@/components/TagDetailSidebar' | ||||
| import PostEditForm from '@/components/PostEditForm' | import PostEditForm from '@/components/PostEditForm' | ||||
| import TabControl from '@/components/common/TabControl' | |||||
| import TabGroup, { Tab } from '@/components/common/TabGroup' | |||||
| import type { Post, Tag, User } from '@/types' | import type { Post, Tag, User } from '@/types' | ||||
| @@ -95,14 +95,16 @@ export default ({ user }: Props) => { | |||||
| post.viewed ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-500 hover:bg-gray-600')}> | post.viewed ? 'bg-blue-600 hover:bg-blue-700' : 'bg-gray-500 hover:bg-gray-600')}> | ||||
| {post.viewed ? '閲覧済' : '未閲覧'} | {post.viewed ? '閲覧済' : '未閲覧'} | ||||
| </Button> | </Button> | ||||
| {(['admin', 'member'].includes (user.role) && editing) && | |||||
| <TabControl tabs={{ | |||||
| ['編輯']: ( | |||||
| <PostEditForm post={post} | |||||
| onSave={newPost => { | |||||
| setPost (newPost) | |||||
| toast ({ description: '更新しました.' }) | |||||
| }} />) }} />} | |||||
| <TabGroup> | |||||
| {['admin', 'member'].some (r => r === user.role) && editing && | |||||
| <Tab name="編輯"> | |||||
| <PostEditForm post={post} | |||||
| onSave={newPost => { | |||||
| setPost (newPost) | |||||
| toast ({ description: '更新しました.' }) | |||||
| }} /> | |||||
| </Tab>} | |||||
| </TabGroup> | |||||
| </div>) | </div>) | ||||
| : 'Loading...'} | : 'Loading...'} | ||||
| </MainArea> | </MainArea> | ||||