button style improvements, homepage and navbar refactors
This commit is contained in:
parent
a64cc78eed
commit
f3d588c0eb
19 changed files with 214 additions and 201 deletions
|
@ -132,8 +132,9 @@ function Auth({
|
|||
<Button width={"100%"} type="submit" loading={submitting}>
|
||||
Sign {signText}
|
||||
</Button>
|
||||
{isGithubEnabled ? <hr style={{ width: "100%" }} /> : null}
|
||||
{isGithubEnabled ? (
|
||||
<>
|
||||
<hr style={{ width: "100%" }} />
|
||||
<Button
|
||||
type="submit"
|
||||
width="100%"
|
||||
|
@ -151,6 +152,7 @@ function Auth({
|
|||
>
|
||||
Sign {signText.toLowerCase()} with GitHub
|
||||
</Button>
|
||||
</>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={styles.formContentSpace}>
|
||||
|
|
|
@ -8,12 +8,12 @@ import { fetchWithUser } from "src/app/lib/fetch-with-user"
|
|||
type Props = {
|
||||
height?: number | string
|
||||
fileId?: string
|
||||
content?: string
|
||||
title?: string
|
||||
children?: string
|
||||
}
|
||||
|
||||
function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) {
|
||||
const [preview, setPreview] = useState<string>(content)
|
||||
function MarkdownPreview({ height = 500, fileId, title, children }: Props) {
|
||||
const [preview, setPreview] = useState<string>(children || "")
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true)
|
||||
useEffect(() => {
|
||||
async function fetchPost() {
|
||||
|
@ -24,7 +24,7 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) {
|
|||
? undefined
|
||||
: JSON.stringify({
|
||||
title: title || "",
|
||||
content: content
|
||||
content: children
|
||||
})
|
||||
|
||||
const resp = await fetchWithUser(path, {
|
||||
|
@ -43,14 +43,14 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) {
|
|||
setIsLoading(false)
|
||||
}
|
||||
fetchPost()
|
||||
}, [content, fileId, title])
|
||||
}, [children, fileId, title])
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLoading ? (
|
||||
<Spinner />
|
||||
) : (
|
||||
<StaticPreview preview={preview} height={height} />
|
||||
<StaticPreview height={height}>{preview}</StaticPreview>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
@ -59,16 +59,16 @@ function MarkdownPreview({ height = 500, fileId, content = "", title }: Props) {
|
|||
export default memo(MarkdownPreview)
|
||||
|
||||
export function StaticPreview({
|
||||
preview,
|
||||
children,
|
||||
height = 500
|
||||
}: {
|
||||
preview: string
|
||||
children: string
|
||||
height: string | number
|
||||
}) {
|
||||
return (
|
||||
<article
|
||||
className={styles.markdownPreview}
|
||||
dangerouslySetInnerHTML={{ __html: preview }}
|
||||
dangerouslySetInnerHTML={{ __html: children }}
|
||||
style={{
|
||||
height
|
||||
}}
|
||||
|
|
|
@ -13,8 +13,8 @@ type Props = RadixTabs.TabsProps & {
|
|||
handleOnContentChange?: (e: ChangeEvent<HTMLTextAreaElement>) => void
|
||||
onPaste?: (e: ClipboardEvent<HTMLTextAreaElement>) => void
|
||||
title?: string
|
||||
content?: string
|
||||
preview?: string
|
||||
staticPreview?: string
|
||||
children: string;
|
||||
}
|
||||
|
||||
export default function DocumentTabs({
|
||||
|
@ -23,8 +23,8 @@ export default function DocumentTabs({
|
|||
handleOnContentChange,
|
||||
onPaste,
|
||||
title,
|
||||
content,
|
||||
preview,
|
||||
staticPreview: preview,
|
||||
children,
|
||||
...props
|
||||
}: Props) {
|
||||
const codeEditorRef = useRef<TextareaMarkdownRef>(null)
|
||||
|
@ -72,7 +72,7 @@ export default function DocumentTabs({
|
|||
onPaste={onPaste ? onPaste : undefined}
|
||||
ref={codeEditorRef}
|
||||
placeholder=""
|
||||
value={content}
|
||||
value={children}
|
||||
onChange={handleOnContentChange}
|
||||
// TODO: Textarea should grow to fill parent if height == 100%
|
||||
style={{ flex: 1, minHeight: 350 }}
|
||||
|
@ -83,9 +83,9 @@ export default function DocumentTabs({
|
|||
</RadixTabs.Content>
|
||||
<RadixTabs.Content value="preview">
|
||||
{isEditing ? (
|
||||
<Preview height={"100%"} title={title} content={content} />
|
||||
<Preview height={"100%"} title={title}>{children}</Preview>
|
||||
) : (
|
||||
<StaticPreview height={"100%"} preview={preview || ""} />
|
||||
<StaticPreview height={"100%"}>{preview}</StaticPreview>
|
||||
)}
|
||||
</RadixTabs.Content>
|
||||
</RadixTabs.Root>
|
||||
|
|
|
@ -45,7 +45,6 @@ const PostFiles = ({ post: _initialPost }: Props) => {
|
|||
|
||||
const isProtected = post?.visibility === "protected"
|
||||
const hasFetched = post?.files !== undefined
|
||||
console.log({ isProtected, hasFetched })
|
||||
if (isProtected && !hasFetched) {
|
||||
return (
|
||||
<PasswordModalWrapper
|
||||
|
|
|
@ -112,7 +112,7 @@ const Document = ({ skeleton, ...props }: Props) => {
|
|||
{/* Not /api/ because of rewrites defined in next.config.mjs */}
|
||||
<DocumentTabs
|
||||
defaultTab={initialTab}
|
||||
preview={preview}
|
||||
staticPreview={preview}
|
||||
content={content}
|
||||
isEditing={false}
|
||||
/>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
cursor: pointer;
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border);
|
||||
padding: var(--gap-half) var(--gap);
|
||||
/* padding: var(--gap-half) var(--gap); */
|
||||
color: var(--darker-gray);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,11 +31,12 @@ const Button = forwardRef<HTMLButtonElement, Props>(
|
|||
disabled = false,
|
||||
iconRight,
|
||||
iconLeft,
|
||||
height,
|
||||
height = 40,
|
||||
width,
|
||||
padding,
|
||||
padding = 10,
|
||||
margin,
|
||||
loading,
|
||||
style,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
|
@ -49,7 +50,7 @@ const Button = forwardRef<HTMLButtonElement, Props>(
|
|||
})}
|
||||
disabled={disabled || loading}
|
||||
onClick={onClick}
|
||||
style={{ height, width, margin, padding }}
|
||||
style={{ height, width, margin, padding, ...style }}
|
||||
{...props}
|
||||
>
|
||||
{children && iconLeft && (
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
border-radius: var(--radius);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--light-gray);
|
||||
width: auto;
|
||||
height: auto;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,11 +38,6 @@
|
|||
|
||||
.header {
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.header:not(.loading) {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.selectContent {
|
||||
|
|
|
@ -9,7 +9,6 @@ import Button from "@components/button"
|
|||
import clsx from "clsx"
|
||||
import { useTheme } from "next-themes"
|
||||
import {
|
||||
GitHub,
|
||||
Home,
|
||||
Menu,
|
||||
Moon,
|
||||
|
@ -17,13 +16,13 @@ import {
|
|||
Settings,
|
||||
Sun,
|
||||
User,
|
||||
UserPlus,
|
||||
UserX
|
||||
} from "react-feather"
|
||||
import * as DropdownMenu from "@radix-ui/react-dropdown-menu"
|
||||
import buttonStyles from "@components/button/button.module.css"
|
||||
import { useMemo } from "react"
|
||||
import { useSessionSWR } from "@lib/use-session-swr"
|
||||
import Skeleton from "@components/skeleton"
|
||||
|
||||
type Tab = {
|
||||
name: string
|
||||
|
@ -34,7 +33,7 @@ type Tab = {
|
|||
}
|
||||
|
||||
const Header = () => {
|
||||
const { isAuthenticated, isAdmin, isLoading, mutate } = useSessionSWR()
|
||||
const { isAdmin, isAuthenticated, isLoading, mutate } = useSessionSWR()
|
||||
|
||||
const pathname = usePathname()
|
||||
const { setTheme, resolvedTheme } = useTheme()
|
||||
|
@ -52,6 +51,7 @@ const Header = () => {
|
|||
aria-label={tab.name}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
data-tab={tab.value}
|
||||
width="auto"
|
||||
>
|
||||
{tab.name ? tab.name : undefined}
|
||||
</Button>
|
||||
|
@ -59,7 +59,7 @@ const Header = () => {
|
|||
} else if (tab.href) {
|
||||
return (
|
||||
<Link key={tab.value} href={tab.href} data-tab={tab.value}>
|
||||
<Button className={activeStyle} iconLeft={tab.icon}>
|
||||
<Button className={activeStyle} iconLeft={tab.icon} width="auto">
|
||||
{tab.name ? tab.name : undefined}
|
||||
</Button>
|
||||
</Link>
|
||||
|
@ -69,12 +69,12 @@ const Header = () => {
|
|||
|
||||
const pages = useMemo(() => {
|
||||
const defaultPages: Tab[] = [
|
||||
{
|
||||
name: "GitHub",
|
||||
href: "https://github.com/maxleiter/drift",
|
||||
icon: <GitHub />,
|
||||
value: "github"
|
||||
}
|
||||
// {
|
||||
// name: "GitHub",
|
||||
// href: "https://github.com/maxleiter/drift",
|
||||
// icon: <GitHub />,
|
||||
// value: "github"
|
||||
// }
|
||||
]
|
||||
|
||||
if (isAdmin) {
|
||||
|
@ -95,8 +95,37 @@ const Header = () => {
|
|||
value: "theme"
|
||||
})
|
||||
|
||||
if (isAuthenticated)
|
||||
// the is loading case is handled in the JSX
|
||||
if (!isLoading) {
|
||||
if (isAuthenticated) {
|
||||
defaultPages.push({
|
||||
name: "Sign Out",
|
||||
icon: <UserX />,
|
||||
value: "signout",
|
||||
onClick: () => {
|
||||
mutate(undefined)
|
||||
signOut({
|
||||
callbackUrl: "/"
|
||||
})
|
||||
}
|
||||
})
|
||||
} else {
|
||||
defaultPages.push({
|
||||
name: "Sign in",
|
||||
icon: <User />,
|
||||
value: "signin",
|
||||
href: "/signin"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
name: "Home",
|
||||
icon: <Home />,
|
||||
value: "home",
|
||||
href: "/home"
|
||||
},
|
||||
{
|
||||
name: "New",
|
||||
icon: <PlusCircle />,
|
||||
|
@ -115,56 +144,32 @@ const Header = () => {
|
|||
value: "settings",
|
||||
href: "/settings"
|
||||
},
|
||||
...defaultPages,
|
||||
{
|
||||
name: "Sign Out",
|
||||
icon: <UserX />,
|
||||
value: "signout",
|
||||
onClick: () => {
|
||||
mutate(undefined)
|
||||
signOut({
|
||||
callbackUrl: "/"
|
||||
})
|
||||
}
|
||||
}
|
||||
...defaultPages
|
||||
]
|
||||
else
|
||||
return [
|
||||
{
|
||||
name: "Home",
|
||||
icon: <Home />,
|
||||
value: "home",
|
||||
href: "/"
|
||||
},
|
||||
...defaultPages,
|
||||
{
|
||||
name: "Sign in",
|
||||
icon: <User />,
|
||||
value: "signin",
|
||||
href: "/signin"
|
||||
},
|
||||
{
|
||||
name: "Sign up",
|
||||
icon: <UserPlus />,
|
||||
value: "signup",
|
||||
href: "/signup"
|
||||
}
|
||||
]
|
||||
}, [isAdmin, resolvedTheme, isAuthenticated, setTheme, mutate])
|
||||
}, [isAdmin, resolvedTheme, isLoading, setTheme, isAuthenticated, mutate])
|
||||
|
||||
const buttons = pages.map(getButton)
|
||||
|
||||
if (isLoading) {
|
||||
buttons.push(
|
||||
<Button iconLeft={<User />} key="loading">
|
||||
Sign{" "}
|
||||
<Skeleton
|
||||
width={20}
|
||||
height={15}
|
||||
style={{ display: "inline-block", verticalAlign: "middle" }}
|
||||
/>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: this is a hack to close the radix ui menu when a next link is clicked
|
||||
const onClick = () => {
|
||||
document.dispatchEvent(new KeyboardEvent("keydown", { key: "Escape" }))
|
||||
}
|
||||
|
||||
return (
|
||||
<header
|
||||
className={clsx(styles.header, {
|
||||
[styles.loading]: isLoading
|
||||
})}
|
||||
>
|
||||
<header className={styles.header}>
|
||||
<div className={styles.tabs}>
|
||||
<div className={styles.buttons}>{buttons}</div>
|
||||
</div>
|
||||
|
|
|
@ -10,6 +10,7 @@ import { ListItemSkeleton } from "./list-item-skeleton"
|
|||
import Link from "@components/link"
|
||||
import debounce from "lodash.debounce"
|
||||
import { fetchWithUser } from "src/app/lib/fetch-with-user"
|
||||
import { Stack } from "@components/stack"
|
||||
|
||||
type Props = {
|
||||
initialPosts: string | PostWithFiles[]
|
||||
|
@ -63,7 +64,6 @@ const PostList = ({
|
|||
}
|
||||
)
|
||||
const json = await res.json()
|
||||
console.log(json)
|
||||
setPosts(json)
|
||||
setSearching(false)
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ const PostList = ({
|
|||
)
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Stack className={styles.container} alignItems="center">
|
||||
{!hideSearch && (
|
||||
<div className={styles.searchContainer}>
|
||||
<Input
|
||||
|
@ -122,7 +122,6 @@ const PostList = ({
|
|||
</ul>
|
||||
)}
|
||||
{!showSkeleton && posts && posts.length > 0 ? (
|
||||
<div>
|
||||
<ul>
|
||||
{posts.map((post) => {
|
||||
return (
|
||||
|
@ -136,9 +135,8 @@ const PostList = ({
|
|||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,10 @@
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
.container > * {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container ul li {
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
|
|
|
@ -3,13 +3,18 @@ import styles from "./skeleton.module.css"
|
|||
export default function Skeleton({
|
||||
width = 100,
|
||||
height = 24,
|
||||
borderRadius = 4
|
||||
borderRadius = 4,
|
||||
style
|
||||
}: {
|
||||
width?: number | string
|
||||
height?: number | string
|
||||
borderRadius?: number | string
|
||||
style?: React.CSSProperties
|
||||
}) {
|
||||
return (
|
||||
<div className={styles.skeleton} style={{ width, height, borderRadius }} />
|
||||
<div
|
||||
className={styles.skeleton}
|
||||
style={{ width, height, borderRadius, ...style }}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ import Layout from "@components/layout"
|
|||
import { Toasts } from "@components/toasts"
|
||||
import Header from "@components/header"
|
||||
import { Inter } from "@next/font/google"
|
||||
import { PropsWithChildren } from "react"
|
||||
import { PropsWithChildren, Suspense } from "react"
|
||||
import { Spinner } from "@components/spinner"
|
||||
|
||||
const inter = Inter({ subsets: ["latin"], variable: "--inter-font" })
|
||||
|
||||
|
@ -19,7 +20,9 @@ export default async function RootLayout({
|
|||
<Toasts />
|
||||
<Layout>
|
||||
<Providers>
|
||||
<Suspense fallback={<Spinner />}>
|
||||
<Header />
|
||||
</Suspense>
|
||||
{children}
|
||||
</Providers>
|
||||
</Layout>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { getPostsByUser } from "@lib/server/prisma"
|
|||
import PostList from "@components/post-list"
|
||||
import { getCurrentUser } from "@lib/server/session"
|
||||
import { authOptions } from "@lib/server/auth"
|
||||
import { Suspense } from "react"
|
||||
|
||||
export default async function Mine() {
|
||||
const userId = (await getCurrentUser())?.id
|
||||
|
@ -15,12 +16,14 @@ export default async function Mine() {
|
|||
|
||||
const stringifiedPosts = JSON.stringify(posts)
|
||||
return (
|
||||
<Suspense fallback={<PostList skeleton={true} initialPosts={[]} />}>
|
||||
<PostList
|
||||
userId={userId}
|
||||
initialPosts={stringifiedPosts}
|
||||
isOwner={true}
|
||||
hideSearch={false}
|
||||
/>
|
||||
</Suspense>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
119
src/app/page.tsx
119
src/app/page.tsx
|
@ -2,17 +2,72 @@ import Image from "next/image"
|
|||
import Card from "@components/card"
|
||||
import { getWelcomeContent } from "src/pages/api/welcome"
|
||||
import DocumentTabs from "./(posts)/components/tabs"
|
||||
import { getAllPosts, Post } from "@lib/server/prisma"
|
||||
import { getAllPosts } from "@lib/server/prisma"
|
||||
import PostList, { NoPostsFound } from "@components/post-list"
|
||||
import { Suspense } from "react"
|
||||
import { cache, Suspense } from "react"
|
||||
import ErrorBoundary from "@components/error/fallback"
|
||||
import { Stack } from "@components/stack"
|
||||
|
||||
export async function getWelcomeData() {
|
||||
const getWelcomeData = cache(async () => {
|
||||
const welcomeContent = await getWelcomeContent()
|
||||
return welcomeContent
|
||||
}
|
||||
})
|
||||
|
||||
export default async function Page() {
|
||||
const getPostsPromise = getAllPosts({
|
||||
const { title } = await getWelcomeData()
|
||||
|
||||
return (
|
||||
<Stack direction="column">
|
||||
<Stack direction="row" alignItems="center">
|
||||
<Image
|
||||
src={"/assets/logo.svg"}
|
||||
width={48}
|
||||
height={48}
|
||||
alt=""
|
||||
priority
|
||||
/>
|
||||
<h1 style={{ marginLeft: "var(--gap)" }}>{title}</h1>
|
||||
</Stack>
|
||||
{/* @ts-expect-error because of async RSC */}
|
||||
<WelcomePost />
|
||||
<h2>Recent public posts</h2>
|
||||
<ErrorBoundary>
|
||||
<Suspense
|
||||
fallback={
|
||||
<PostList
|
||||
skeleton
|
||||
hideActions
|
||||
hideSearch
|
||||
initialPosts={JSON.stringify({})}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{/* @ts-expect-error because of async RSC */}
|
||||
<PublicPostList />
|
||||
</Suspense>
|
||||
</ErrorBoundary>
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
async function WelcomePost() {
|
||||
const { content, rendered, title } = await getWelcomeData()
|
||||
return (
|
||||
<Card>
|
||||
<DocumentTabs
|
||||
defaultTab="preview"
|
||||
isEditing={false}
|
||||
staticPreview={rendered as string}
|
||||
title={title}
|
||||
>
|
||||
{content}
|
||||
</DocumentTabs>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
async function PublicPostList() {
|
||||
const posts = await getAllPosts({
|
||||
select: {
|
||||
id: true,
|
||||
title: true,
|
||||
|
@ -38,55 +93,6 @@ export default async function Page() {
|
|||
createdAt: "desc"
|
||||
}
|
||||
})
|
||||
const { content, rendered, title } = await getWelcomeData()
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}
|
||||
>
|
||||
<div
|
||||
style={{ display: "flex", flexDirection: "row", alignItems: "center" }}
|
||||
>
|
||||
<Image
|
||||
src={"/assets/logo.svg"}
|
||||
width={48}
|
||||
height={48}
|
||||
alt=""
|
||||
priority
|
||||
/>
|
||||
<h1 style={{ marginLeft: "var(--gap)" }}>{title}</h1>
|
||||
</div>
|
||||
<Card>
|
||||
<DocumentTabs
|
||||
defaultTab="preview"
|
||||
isEditing={false}
|
||||
content={content}
|
||||
preview={rendered as string}
|
||||
title={title}
|
||||
/>
|
||||
</Card>
|
||||
<div>
|
||||
<h2>Recent public posts</h2>
|
||||
<Suspense
|
||||
fallback={
|
||||
<PostList skeleton hideSearch initialPosts={JSON.stringify({})} />
|
||||
}
|
||||
>
|
||||
{/* @ts-expect-error because of async RSC */}
|
||||
<PublicPostList getPostsPromise={getPostsPromise} />
|
||||
</Suspense>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
async function PublicPostList({
|
||||
getPostsPromise
|
||||
}: {
|
||||
getPostsPromise: Promise<Post[]>
|
||||
}) {
|
||||
try {
|
||||
const posts = await getPostsPromise
|
||||
|
||||
if (posts.length === 0) {
|
||||
return <NoPostsFound />
|
||||
|
@ -95,9 +101,4 @@ async function PublicPostList({
|
|||
return (
|
||||
<PostList initialPosts={JSON.stringify(posts)} hideActions hideSearch />
|
||||
)
|
||||
} catch (error) {
|
||||
return <NoPostsFound />
|
||||
}
|
||||
}
|
||||
|
||||
export const revalidate = 60
|
||||
|
|
|
@ -12,7 +12,6 @@ import { User } from "@prisma/client"
|
|||
|
||||
function Profile() {
|
||||
const { session } = useSessionSWR()
|
||||
console.log(session)
|
||||
const { data: userData } = useSWR<User>(
|
||||
session?.user?.id ? `/api/user/${session?.user?.id}` : null
|
||||
)
|
||||
|
@ -104,7 +103,7 @@ function Profile() {
|
|||
type="email"
|
||||
width={"100%"}
|
||||
placeholder="my@email.io"
|
||||
value={session?.user.email || undefined}
|
||||
value={session?.user.email || ""}
|
||||
disabled
|
||||
aria-label="Email"
|
||||
/>
|
||||
|
|
|
@ -49,7 +49,6 @@ const providers = () => {
|
|||
// @ts-expect-error TODO: fix types
|
||||
credentials: credentialsOptions() as unknown,
|
||||
async authorize(credentials) {
|
||||
console.log("credentials")
|
||||
if (!credentials || !credentials.username || !credentials.password) {
|
||||
throw new Error("Missing credentials")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import { withMethods } from "@lib/api-middleware/with-methods"
|
|||
|
||||
const getRawFile = async (req: NextApiRequest, res: NextApiResponse) => {
|
||||
const { id, download } = req.query
|
||||
|
||||
const file = await prisma.file.findUnique({
|
||||
where: {
|
||||
id: parseQueryParam(id)
|
||||
|
|
Loading…
Reference in a new issue