Skip to content

Commit

Permalink
feat: category page
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <i@innei.in>
  • Loading branch information
Innei committed Jun 30, 2023
1 parent 2c56c29 commit fef1be0
Show file tree
Hide file tree
Showing 17 changed files with 239 additions and 80 deletions.
50 changes: 50 additions & 0 deletions src/app/categories/[slug]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { dehydrate } from '@tanstack/react-query'
import type { Metadata } from 'next'

import { QueryHydrate } from '~/components/common/QueryHydrate'
import { NormalContainer } from '~/components/layout/container/Normal'
import { isShallowEqualArray } from '~/lib/_'
import { attachUA } from '~/lib/attach-ua'
import { getQueryClient } from '~/utils/query-client.server'

import { getPageBySlugQuery } from './query'

export const generateMetadata = async (
props: NextPageParams<{
slug: string
}>,
) => {
attachUA()
const queryClient = getQueryClient()

const query = getPageBySlugQuery(props.params.slug)

const data = await queryClient.fetchQuery(query)

return {
title: `分类 · ${data.name}`,
} satisfies Metadata
}
export default async function Layout(
props: NextPageParams<{
slug: string
}>,
) {
attachUA()
const queryClient = getQueryClient()
const query = getPageBySlugQuery(props.params.slug)
const queryKey = query.queryKey
await queryClient.fetchQuery(query)
return (
<QueryHydrate
state={dehydrate(queryClient, {
shouldDehydrateQuery: (query) => {
// @ts-expect-error
return isShallowEqualArray(query.queryKey, queryKey)
},
})}
>
<NormalContainer>{props.children}</NormalContainer>
</QueryHydrate>
)
}
66 changes: 66 additions & 0 deletions src/app/categories/[slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
'use client'

import { useQuery } from '@tanstack/react-query'
import Link from 'next/link'
import { useParams } from 'next/navigation'

import { TimelineList } from '~/components/ui/list/TimelineList'
import { BottomToUpSoftScaleTransitionView } from '~/components/ui/transition/BottomToUpSoftScaleTransitionView'
import { BottomToUpTransitionView } from '~/components/ui/transition/BottomToUpTransitionView'

import { getPageBySlugQuery } from './query'

export default function Page() {
const { slug } = useParams()
const { data } = useQuery({
...getPageBySlugQuery(slug),
enabled: false,
})
if (!data) throw new Error('data is lost :(')
const { name, children } = data

return (
<BottomToUpSoftScaleTransitionView>
<header className="prose">
<h1>分类 - {name}</h1>

<h3 className="font-light">
{children.length
? `当前共有 ${children.length} 篇文章,加油!`
: `这里还有没有内容呢,再接再厉!`}
</h3>
</header>

<main className="mt-10 text-zinc-950/80 dark:text-zinc-50/80">
<TimelineList>
{children.map((child, i) => {
const date = new Date(child.created)

return (
<BottomToUpTransitionView
key={child.id}
delay={700 + 50 * i}
as="li"
className="flex min-w-0 items-center justify-between leading-loose"
>
<Link
prefetch={false}
target="_blank"
href={`/posts/${slug}/${child.slug}`}
className="min-w-0 truncate"
>
{child.title}
</Link>
<span className="meta">
{(date.getMonth() + 1).toString().padStart(2, '0')}/
{date.getDate().toString().padStart(2, '0')}/
{date.getFullYear()}
</span>
</BottomToUpTransitionView>
)
})}
</TimelineList>
</main>
</BottomToUpSoftScaleTransitionView>
)
}
16 changes: 16 additions & 0 deletions src/app/categories/[slug]/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { defineQuery } from '~/queries/helper'
import { apiClient } from '~/utils/request'

export const getPageBySlugQuery = (slug: string) =>
defineQuery({
queryKey: ['category', slug],
queryFn: async ({ queryKey }) => {
const [, slug] = queryKey

const data = await apiClient.category.getCategoryByIdOrSlug(slug)

return {
...data,
}
},
})
2 changes: 2 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ClerkProvider } from '@clerk/nextjs'
import { appConfig } from '~/app.config'
import { Root } from '~/components/layout/root/Root'
import { TocAutoScroll } from '~/components/widgets/toc/TocAutoScroll'
import { attachUA } from '~/lib/attach-ua'
import { defineMetadata } from '~/lib/define-metadata'
import { sansFont, serifFont } from '~/lib/fonts'
import { AggregationProvider } from '~/providers/root/aggregation-data-provider'
Expand Down Expand Up @@ -83,6 +84,7 @@ type Props = {
}

export default async function RootLayout(props: Props) {
attachUA()
const { children } = props

const queryClient = getQueryClient()
Expand Down
2 changes: 2 additions & 0 deletions src/app/timeline/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { TimelineType } from '@mx-space/api-client'

import { QueryHydrate } from '~/components/common/QueryHydrate'
import { REQUEST_QUERY } from '~/constants/system'
import { attachUA } from '~/lib/attach-ua'
import { getQueryClient } from '~/utils/query-client.server'
import { apiClient } from '~/utils/request'

Expand All @@ -14,6 +15,7 @@ export const metadata = {
}

export default async (props: NextPageParams<{}, PropsWithChildren>) => {
attachUA()
const header = headers()
const query = header.get(REQUEST_QUERY)

Expand Down
51 changes: 0 additions & 51 deletions src/components/ui/list/TimelineList.module.css
Original file line number Diff line number Diff line change
@@ -1,51 +0,0 @@
.timeline {
position: relative;

@apply min-w-0 flex-1 list-inside justify-between;

& > li::before {
content: '';
position: absolute;
left: -1.05rem;
bottom: 0;
border-left: 1px solid theme(colors.accent);
}

& > li:first-child:last-child::before {
border-left: 0;
}

& > li:not(:first-child):not(:last-child)::before {
top: 0;
}

& > li:first-child::before {
top: 50%;
}

& > li:last-child::before {
bottom: 50%;
top: 0;
}

& > li {
position: relative;
list-style-type: none;

line-height: 1.6;
padding: 3px 0;
margin: 0 0 0 1rem;
}

& > li::after {
content: '';
left: -1.28rem;
top: 50%;
transform: translateY(-50%);
height: 0.5rem;
width: 0.5rem;
border-radius: 50%;
position: absolute;
background-color: theme(colors.accent);
}
}
4 changes: 1 addition & 3 deletions src/components/ui/list/TimelineList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import clsx from 'clsx'

import styles from './TimelineList.module.css'

export const TimelineList: Component = ({ children, className }) => {
return <ul className={clsx(styles['timeline'], className)}>{children}</ul>
return <ul className={clsx('shiro-timeline', className)}>{children}</ul>
}
19 changes: 0 additions & 19 deletions src/components/ui/markdown/renderers/link.module.css

This file was deleted.

4 changes: 1 addition & 3 deletions src/components/ui/markdown/renderers/link.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { memo, useCallback } from 'react'
import clsx from 'clsx'
import Router from 'next/router'
import type { FC, ReactNode } from 'react'

import { FloatPopover } from '../../float-popover'
import styles from './link.module.css'

export const MLink: FC<{
href: string
Expand Down Expand Up @@ -52,7 +50,7 @@ export const MLink: FC<{
() => (
<span className="inline-flex items-center">
<a
className={clsx(styles['link'])}
className="shiro-link--underline"
href={props.href}
target="_blank"
onClick={handleRedirect}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/_.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,17 @@ export const shuffle = <T>(arr: T[]): T[] => {
}
return result
}

export const isShallowEqualArray = <T>(arr1: T[], arr2: T[]): boolean => {
if (arr1.length !== arr2.length) {
return false
}

for (let i = 0; i < arr1.length; i++) {
if (!Object.is(arr1[i], arr2[i])) {
return false
}
}

return true
}
2 changes: 1 addition & 1 deletion src/queries/definition/aggregation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isServer } from '@tanstack/react-query'

import { apiClient } from '~/utils/request'

import { defineQuery } from './helper'
import { defineQuery } from '../helper'

export const aggregation = {
root: () =>
Expand Down
2 changes: 1 addition & 1 deletion src/queries/definition/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { NoteWrappedPayload } from '@mx-space/api-client'
import { routeBuilder, Routes } from '~/lib/route-builder'
import { apiClient } from '~/utils/request'

import { defineQuery } from './helper'
import { defineQuery } from '../helper'

const LATEST_KEY = 'latest'
export const note = {
Expand Down
2 changes: 1 addition & 1 deletion src/queries/definition/page.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { routeBuilder, Routes } from '~/lib/route-builder'
import { apiClient } from '~/utils/request'

import { defineQuery } from './helper'
import { defineQuery } from '../helper'

export const page = {
bySlug: (slug: string) =>
Expand Down
2 changes: 1 addition & 1 deletion src/queries/definition/post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { routeBuilder, Routes } from '~/lib/route-builder'
import { apiClient } from '~/utils/request'

import { defineQuery } from './helper'
import { defineQuery } from '../helper'

export const post = {
bySlug: (category: string, slug: string) =>
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
@import './clerk.css';
@import './image-zoom.css';
@import './toastify.css';
@import './theme.css';
Loading

0 comments on commit fef1be0

Please sign in to comment.