From 2dcd6c01567eeebc90540d26abf944bace2e300b Mon Sep 17 00:00:00 2001 From: mrevanzak Date: Sun, 26 May 2024 15:01:27 +0700 Subject: [PATCH] feat(web): download file feature on admin --- .../src/app/api/documents/[fileId]/route.ts | 12 +++++ apps/web/src/components/documents-table.tsx | 52 +++++++++++++------ .../web/src/components/dropzone-container.tsx | 2 +- .../routers/documents/documents.procedure.ts | 30 +++++------ .../api/routers/documents/documents.schema.ts | 13 +++-- 5 files changed, 70 insertions(+), 39 deletions(-) create mode 100644 apps/web/src/app/api/documents/[fileId]/route.ts diff --git a/apps/web/src/app/api/documents/[fileId]/route.ts b/apps/web/src/app/api/documents/[fileId]/route.ts new file mode 100644 index 0000000..e8c3aaf --- /dev/null +++ b/apps/web/src/app/api/documents/[fileId]/route.ts @@ -0,0 +1,12 @@ +import { env } from "@/env"; +import { auth } from "@/server/auth"; + +export async function GET({ params }: { params: { fileId: string } }) { + const session = await auth(); + if (session?.user.role !== "admin") { + return new Response("Unauthorized", { status: 401 }); + } + + const res = await fetch(env.BACKEND_URL + "/files/download/" + params.fileId); + return res; +} diff --git a/apps/web/src/components/documents-table.tsx b/apps/web/src/components/documents-table.tsx index b35c87e..a7a28e1 100644 --- a/apps/web/src/components/documents-table.tsx +++ b/apps/web/src/components/documents-table.tsx @@ -26,6 +26,7 @@ import { MdOutlineDownloadForOffline } from "react-icons/md"; import { RiDeleteBin2Line } from "react-icons/ri"; import { Button } from "@tanya.in/ui/button"; +import { toast } from "@tanya.in/ui/toast"; const columns = [ { @@ -33,7 +34,7 @@ const columns = [ label: "NAME", }, { - key: "createdAt" as const, + key: "created" as const, label: "CREATED AT", }, { @@ -48,24 +49,18 @@ export function DocumentsTable() { const searchParams = useSearchParams(); const showModal = searchParams.get("delete") === "true"; - const [document, setDocument] = React.useState(); + const [selectedDocument, setSelectedDocument] = React.useState(); const { data, isLoading } = api.documents.get.useQuery(); const renderCell = React.useCallback( - (document: Document, columnKey: ColumnKey) => { + (file: Document, columnKey: ColumnKey) => { switch (columnKey) { - case "createdAt": + case "created": return ( - + - {document[columnKey] - ? moment(document[columnKey]).fromNow() - : "Never"} + {moment(file[columnKey]).fromNow()} ); @@ -77,14 +72,37 @@ export function DocumentsTable() { color="primary" className="p-2" > - setDocument(document)} + onClick={() => setSelectedDocument(file)} className="pointer-events-auto" > @@ -93,7 +111,7 @@ export function DocumentsTable() { ); default: - return document[columnKey]; + return file[columnKey]; } }, [], @@ -123,7 +141,7 @@ export function DocumentsTable() { emptyContent={ !isLoading && (

- No files found
Drag and drop a file to upload + No documents found
Drag and drop a document to upload

) } @@ -148,7 +166,7 @@ export function DocumentsTable() { <> Delete Document -

Are you sure you want to delete {document?.name}?

+

Are you sure you want to delete {selectedDocument?.name}?

diff --git a/apps/web/src/server/api/routers/documents/documents.procedure.ts b/apps/web/src/server/api/routers/documents/documents.procedure.ts index 64f600f..c7434a0 100644 --- a/apps/web/src/server/api/routers/documents/documents.procedure.ts +++ b/apps/web/src/server/api/routers/documents/documents.procedure.ts @@ -1,24 +1,20 @@ -import type { Document } from "@/server/api/routers/documents/documents.schema"; +import { env } from "@/env"; import { adminProcedure, createTRPCRouter } from "@/server/api/trpc"; +import { z } from "zod"; + +import { documentSchema } from "./documents.schema"; export const documentsRouter = createTRPCRouter({ - get: adminProcedure.query(() => { - const documents: Document[] = [ - { - id: "1", - name: "Document 1.pdf", - createdAt: new Date(), - uploadedBy: "3152ffe5-6496-4214-8fcd-b69fb4f70fd5", - }, + get: adminProcedure.query(async () => { + const res = await fetch(env.BACKEND_URL + "/files"); - { - id: "2", - name: "Document 2.pdf", - createdAt: new Date(), - uploadedBy: "3152ffe5-6496-4214-8fcd-b69fb4f70fd5", - }, - ]; + const validate = z + .object({ + status: z.string(), + files: documentSchema.array(), + }) + .parse(await res.json()); - return documents; + return validate.files; }), }); diff --git a/apps/web/src/server/api/routers/documents/documents.schema.ts b/apps/web/src/server/api/routers/documents/documents.schema.ts index 4e89ed7..1c5cd53 100644 --- a/apps/web/src/server/api/routers/documents/documents.schema.ts +++ b/apps/web/src/server/api/routers/documents/documents.schema.ts @@ -1,6 +1,11 @@ -import type { z } from "zod"; -import { documents } from "@/server/db/schema"; -import { createSelectSchema } from "drizzle-zod"; +import { z } from "zod"; + +export const documentSchema = z.object({ + id: z.number(), + name: z.string(), + filename: z.string(), + created: z.coerce.date(), + lastModified: z.coerce.date(), +}); -export const documentSchema = createSelectSchema(documents); export type Document = z.infer;