7b15cb2c5a
#99 #99 #99 #99 #99 #99 #99 #99 #99 #99 Co-authored-by: miteruzo <miteruzo@naver.com> Reviewed-on: #303
167 lines
4.2 KiB
TypeScript
167 lines
4.2 KiB
TypeScript
import { Fragment, useEffect, useState } from 'react'
|
|
import { Helmet } from 'react-helmet-async'
|
|
import { useLocation } from 'react-router-dom'
|
|
|
|
import nikumaru from '@/assets/fonts/nikumaru.otf'
|
|
import PrefetchLink from '@/components/PrefetchLink'
|
|
import TagLink from '@/components/TagLink'
|
|
import PageTitle from '@/components/common/PageTitle'
|
|
import SectionTitle from '@/components/common/SectionTitle'
|
|
import SubsectionTitle from '@/components/common/SubsectionTitle'
|
|
import MainArea from '@/components/layout/MainArea'
|
|
import { SITE_TITLE } from '@/config'
|
|
import { apiGet } from '@/lib/api'
|
|
|
|
import type { FC } from 'react'
|
|
|
|
import type { Material, Tag } from '@/types'
|
|
|
|
type TagWithMaterial = Omit<Tag, 'children'> & {
|
|
children: TagWithMaterial[]
|
|
material: Material | null }
|
|
|
|
|
|
const MaterialCard = ({ tag }: { tag: TagWithMaterial }) => {
|
|
if (!(tag.material))
|
|
return
|
|
|
|
return (
|
|
<PrefetchLink
|
|
to={`/materials/${ tag.material.id }`}
|
|
className="block w-40 h-40">
|
|
<div
|
|
className="w-full h-full overflow-hidden rounded-xl shadow
|
|
text-center content-center text-4xl"
|
|
style={{ fontFamily: 'Nikumaru' }}>
|
|
{(tag.material.contentType && /image\/.*/.test (tag.material.contentType))
|
|
? <img src={tag.material.file || undefined}/>
|
|
: <span>照会</span>}
|
|
</div>
|
|
</PrefetchLink>)
|
|
}
|
|
|
|
|
|
export default (() => {
|
|
const [loading, setLoading] = useState (false)
|
|
const [tag, setTag] = useState<TagWithMaterial | null> (null)
|
|
|
|
const location = useLocation ()
|
|
const query = new URLSearchParams (location.search)
|
|
const tagQuery = query.get ('tag') ?? ''
|
|
|
|
useEffect (() => {
|
|
if (!(tagQuery))
|
|
{
|
|
setTag (null)
|
|
return
|
|
}
|
|
|
|
void (async () => {
|
|
try
|
|
{
|
|
setLoading (true)
|
|
setTag (
|
|
await apiGet<TagWithMaterial> (
|
|
`/tags/name/${ encodeURIComponent (tagQuery) }/materials`))
|
|
}
|
|
finally
|
|
{
|
|
setLoading (false)
|
|
}
|
|
}) ()
|
|
}, [location.search])
|
|
|
|
return (
|
|
<MainArea>
|
|
<Helmet>
|
|
<style>
|
|
{`
|
|
@font-face
|
|
{
|
|
font-family: 'Nikumaru';
|
|
src: url(${ nikumaru }) format('opentype');
|
|
}`}
|
|
</style>
|
|
<title>{`${ tag ? `${ tag.name } 素材集` : '素材集' } | ${ SITE_TITLE }`}</title>
|
|
</Helmet>
|
|
|
|
{loading ? 'Loading...' : (
|
|
tag
|
|
? (
|
|
<>
|
|
<PageTitle>
|
|
<TagLink
|
|
tag={tag}
|
|
withWiki={false}
|
|
withCount={false}
|
|
to={tag.material
|
|
? `/materials/${ tag.material.id }`
|
|
: `/materials?tag=${ encodeURIComponent (tag.name) }`}/>
|
|
</PageTitle>
|
|
{(!(tag.material) && tag.category !== 'meme') && (
|
|
<div className="-mt-2">
|
|
<PrefetchLink
|
|
to={`/materials/new?tag=${ encodeURIComponent (tag.name) }`}>
|
|
追加
|
|
</PrefetchLink>
|
|
</div>)}
|
|
|
|
<MaterialCard tag={tag}/>
|
|
|
|
<div className="ml-2">
|
|
{tag.children.map (c2 => (
|
|
<Fragment key={c2.id}>
|
|
<SectionTitle>
|
|
<TagLink
|
|
tag={c2}
|
|
withWiki={false}
|
|
withCount={false}
|
|
to={`/materials?tag=${ encodeURIComponent (c2.name) }`}/>
|
|
</SectionTitle>
|
|
{(!(c2.material) && c2.category !== 'meme') && (
|
|
<div className="-mt-4">
|
|
<PrefetchLink
|
|
to={`/materials/new?tag=${ encodeURIComponent (c2.name) }`}>
|
|
追加
|
|
</PrefetchLink>
|
|
</div>)}
|
|
|
|
<MaterialCard tag={c2}/>
|
|
|
|
<div className="ml-2">
|
|
{c2.children.map (c3 => (
|
|
<Fragment key={c3.id}>
|
|
<SubsectionTitle>
|
|
<TagLink
|
|
tag={c3}
|
|
withWiki={false}
|
|
withCount={false}
|
|
to={`/materials?tag=${ encodeURIComponent (c3.name) }`}/>
|
|
</SubsectionTitle>
|
|
{(!(c3.material) && c3.category !== 'meme') && (
|
|
<div className="-mt-2">
|
|
<PrefetchLink
|
|
to={`/materials/new?tag=${
|
|
encodeURIComponent (c3.name) }`}>
|
|
追加
|
|
</PrefetchLink>
|
|
</div>)}
|
|
|
|
<MaterialCard tag={c3}/>
|
|
</Fragment>))}
|
|
</div>
|
|
</Fragment>))}
|
|
</div>
|
|
</>)
|
|
: (
|
|
<>
|
|
<p>左のリストから照会したいタグを選択してください。</p>
|
|
<p>もしくは……</p>
|
|
<ul>
|
|
<li><PrefetchLink to="/materials/new">素材を新規追加する</PrefetchLink></li>
|
|
{/* <li><a href="#">すべての素材をダウンロードする</a></li> */}
|
|
</ul>
|
|
</>))}
|
|
</MainArea>)
|
|
}) satisfies FC
|