feat: pages (#151)

* wip

* wip

* wip

* wwip

* wip

* wip

* fix(util): rmeove checking to existing in slug

* wip

* chore: handle create page

* chore: handle page title untitled
This commit is contained in:
Aslam
2024-09-09 17:35:15 +07:00
committed by GitHub
parent 66c96efad8
commit 5f537d5618
14 changed files with 420 additions and 39 deletions

View File

@@ -0,0 +1,38 @@
import React from "react"
import { cn } from "@/lib/utils"
interface ColumnWrapperProps extends React.HTMLAttributes<HTMLDivElement> {
style?: { [key: string]: string }
}
interface ColumnTextProps extends React.HTMLAttributes<HTMLSpanElement> {}
const ColumnWrapper = React.forwardRef<HTMLDivElement, ColumnWrapperProps>(
({ children, className, style, ...props }, ref) => (
<div
className={cn("flex grow flex-row items-center justify-start", className)}
style={{
width: "var(--width)",
minWidth: "var(--min-width, min-content)",
maxWidth: "min(var(--width), var(--max-width))",
flexBasis: "var(--width)",
...style
}}
ref={ref}
{...props}
>
{children}
</div>
)
)
const ColumnText = React.forwardRef<HTMLSpanElement, ColumnTextProps>(({ children, className, ...props }, ref) => (
<span className={cn("text-left text-xs", className)} ref={ref} {...props}>
{children}
</span>
))
export const Column = {
Wrapper: ColumnWrapper,
Text: ColumnText
}

View File

@@ -0,0 +1,59 @@
import React from "react"
import Link from "next/link"
import { cn } from "@/lib/utils"
import { PersonalPage } from "@/lib/schema"
import { Badge } from "@/components/ui/badge"
import { Column } from "./column"
import { useMedia } from "react-use"
import { useColumnStyles } from "../hooks/use-column-styles"
interface PageItemProps {
page: PersonalPage
isActive: boolean
}
export const PageItem = React.forwardRef<HTMLAnchorElement, PageItemProps>(({ page, isActive }, ref) => {
const isTablet = useMedia("(max-width: 640px)")
const columnStyles = useColumnStyles()
return (
<Link
ref={ref}
tabIndex={isActive ? 0 : -1}
className={cn(
"relative block cursor-default outline-none",
"h-12 items-center gap-x-2 py-2 max-lg:px-4 sm:px-6",
{
"bg-muted-foreground/10": isActive,
"hover:bg-muted/50": !isActive
}
)}
href={`/pages/${page.id}`}
role="listitem"
aria-selected={isActive}
>
<div className="flex h-full items-center gap-4">
<Column.Wrapper style={columnStyles.title}>
<Column.Text className="truncate text-[13px] font-medium">{page.title || "Untitled"}</Column.Text>
</Column.Wrapper>
{!isTablet && (
<>
{/* <Column.Wrapper style={columnStyles.content}>
<Column.Text className="text-[13px]">{page.slug}</Column.Text>
</Column.Wrapper> */}
<Column.Wrapper style={columnStyles.topic}>
{page.topic && <Badge variant="secondary">{page.topic.prettyName}</Badge>}
</Column.Wrapper>
</>
)}
<Column.Wrapper style={columnStyles.updated} className="justify-end">
<Column.Text className="text-[13px]">{page.updatedAt.toLocaleDateString()}</Column.Text>
</Column.Wrapper>
</div>
</Link>
)
})
PageItem.displayName = "PageItem"