Skip to content

Commit

Permalink
feat(tags): separate tags.$tag from tags.nav.$tags
Browse files Browse the repository at this point in the history
  • Loading branch information
jrhender committed Feb 9, 2024
1 parent 453f5c5 commit 93e6ccb
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 76 deletions.
2 changes: 1 addition & 1 deletion app/components/ArticlesDropdown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const ArticlesDropdown = ({toc, categories}: ArticlesDropdownProps) => (
<Link
key={rowId}
className="articles-dropdown-teal-entry"
to={`/tags/${name}`}
to={`/tags/nav/${name}`}
text={name}
/>
))}
Expand Down
79 changes: 4 additions & 75 deletions app/routes/tags.$tag.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import {useState, useEffect, ReactNode} from 'react'
import {LoaderFunction} from '@remix-run/cloudflare'
import {reloadInBackgroundIfNeeded} from '~/server-utils/kv-cache'
import {Tag as TagType, QuestionState, RelatedQuestions, loadTags} from '~/server-utils/stampy'
import {Tag as TagType, QuestionState, RelatedQuestions, loadTag} from '~/server-utils/stampy'
import Dialog from '~/components/dialog'
import Footer from '~/components/Footer'
import Header from '~/components/Header'
import useToC from '~/hooks/useToC'
import {useLoaderData} from '@remix-run/react'
import {ListTable} from '~/components/Table/ListTable'
import {CategoriesNav} from '~/components/CategoriesNav/Menu'

type Props = {
tags: string[]
Expand All @@ -23,15 +17,13 @@ export const loader = async ({request, params}: Parameters<LoaderFunction>[0]) =
}

try {
const tags = await loadTags(request)
return {...tags, tagFromUrl}
return await loadTag(request, tagFromUrl)
} catch (error: unknown) {
console.error(`error fetching tag "${tagFromUrl}":`, error)
return {
error: error?.toString(),
timestamp: new Date().toISOString(),
data: new Array<TagType>(),
tagFromUrl,
data: [],
}
}
}
Expand All @@ -48,11 +40,10 @@ export async function fetchTag(tagName: string): Promise<TagType | never[]> {
const json: Awaited<ReturnType<typeof loader>> = await response.json()
if ('error' in json) console.error(json.error)
const {data, timestamp} = json
const currentTagData = data.filter((tagData) => tagData.name === tagName)[0]

reloadInBackgroundIfNeeded(url, timestamp)

return currentTagData
return data
})
}

Expand Down Expand Up @@ -141,66 +132,4 @@ export function Tags({tags}: Props) {
<div>{tags && tags.map((name) => <Tag key={name} name={name} />)}</div>
</div>
)
}

export default function App() {
const {tagFromUrl, data} = useLoaderData<ReturnType<typeof loader>>()
const [selectedTag, setSelectedTag] = useState<TagType | null>(null)
const [tagsFilter, setTagsFilter] = useState<string>('')
const {toc} = useToC()

const [sortBy] = useState<keyof typeof sortFuncs>('alphabetically')

useEffect(() => {
if (selectedTag === null) {
const dataForUrlTag = data.filter((tagData) => tagData.name === tagFromUrl)[0]
setSelectedTag(dataForUrlTag)
}
}, [selectedTag, data, tagFromUrl])
if (selectedTag === null) {
return null
}
return (
<>
<Header toc={toc} categories={data} />
<div className={'top-margin-large'} />
<main>
<div className={'group-elements'}>
<CategoriesNav
categories={
data
.filter((tag) => tag.questions.length > 0)
.filter((tag) => tag.name.toLowerCase().includes(tagsFilter.toLowerCase()))
.sort(sortFuncs[sortBy])

// {title: "AI Safety", id: 1},
}
active={selectedTag}
onClick={setSelectedTag}
onChange={setTagsFilter}
/>

{selectedTag === null ? null : (
<div>
<h1 style={{marginTop: '0px'}}>{selectedTag.name}</h1>
{selectedTag.questions.length === 0 ? (
<div className={'no-questions'}>No questions found</div>
) : (
<p>
{selectedTag.questions.length} pages tagged {`"${selectedTag.name}"`}
</p>
)}
{selectedTag && <ListTable elements={selectedTag.questions} />}
</div>
)}
</div>
</main>

<div className={'top-margin-large-with-border'} />

<div className={'top-margin-large'} />

<Footer />
</>
)
}
97 changes: 97 additions & 0 deletions app/routes/tags.nav.$tag.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {useState, useEffect} from 'react'
import {LoaderFunction} from '@remix-run/cloudflare'
import {Tag as TagType, loadTags} from '~/server-utils/stampy'
import Footer from '~/components/Footer'
import Header from '~/components/Header'
import useToC from '~/hooks/useToC'
import {useLoaderData} from '@remix-run/react'
import {ListTable} from '~/components/Table/ListTable'
import {CategoriesNav} from '~/components/CategoriesNav/Menu'

export const loader = async ({request, params}: Parameters<LoaderFunction>[0]) => {
const {tag: tagFromUrl} = params
if (!tagFromUrl) {
throw Error('missing tag name')
}

try {
const tags = await loadTags(request)
return {...tags, tagFromUrl}
} catch (error: unknown) {
console.error(`error fetching tag "${tagFromUrl}":`, error)
return {
error: error?.toString(),
timestamp: new Date().toISOString(),
data: new Array<TagType>(),
tagFromUrl,
}
}
}

export const sortFuncs = {
alphabetically: (a: TagType, b: TagType) =>
a.name.toLowerCase().localeCompare(b.name.toLowerCase()),
'by number of questions': (a: TagType, b: TagType) => b.questions.length - a.questions.length,
}

export default function App() {
const {tagFromUrl, data} = useLoaderData<ReturnType<typeof loader>>()
const [selectedTag, setSelectedTag] = useState<TagType | null>(null)
const [tagsFilter, setTagsFilter] = useState<string>('')
const {toc} = useToC()

const [sortBy] = useState<keyof typeof sortFuncs>('alphabetically')

useEffect(() => {
if (selectedTag === null) {
const dataForUrlTag = data.filter((tagData) => tagData.name === tagFromUrl)[0]
setSelectedTag(dataForUrlTag)
}
}, [selectedTag, data, tagFromUrl])
if (selectedTag === null) {
return null
}
return (
<>
<Header toc={toc} categories={data} />
<div className={'top-margin-large'} />
<main>
<div className={'group-elements'}>
<CategoriesNav
categories={
data
.filter((tag) => tag.questions.length > 0)
.filter((tag) => tag.name.toLowerCase().includes(tagsFilter.toLowerCase()))
.sort(sortFuncs[sortBy])

// {title: "AI Safety", id: 1},
}
active={selectedTag}
onClick={setSelectedTag}
onChange={setTagsFilter}
/>

{selectedTag === null ? null : (
<div>
<h1 style={{marginTop: '0px'}}>{selectedTag.name}</h1>
{selectedTag.questions.length === 0 ? (
<div className={'no-questions'}>No questions found</div>
) : (
<p>
{selectedTag.questions.length} pages tagged {`"${selectedTag.name}"`}
</p>
)}
{selectedTag && <ListTable elements={selectedTag.questions} />}
</div>
)}
</div>
</main>

<div className={'top-margin-large-with-border'} />

<div className={'top-margin-large'} />

<Footer />
</>
)
}

0 comments on commit 93e6ccb

Please sign in to comment.