From baea4a4d8727bcbc978759bc940b635380af0d79 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 4 Jun 2025 20:46:17 +0200 Subject: [PATCH 1/4] Rendering Drive Contents --- README.md | 5 +- src/app/drive-contents.tsx | 98 +++++++++++++++++++++++++++++ src/app/f/[folderId]/page.tsx | 14 +++++ src/app/file-row.tsx | 6 +- src/app/page.tsx | 114 ++++------------------------------ src/server/db/schema.ts | 1 + 6 files changed, 130 insertions(+), 108 deletions(-) create mode 100644 src/app/drive-contents.tsx create mode 100644 src/app/f/[folderId]/page.tsx diff --git a/README.md b/README.md index 5ebf872..9f66eaa 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ pnpm run dev Tracking progress on key features and tasks for the project. -- [ ] 🛢️ Set up the database and define data models +- [x] 🛢️ Set up the database and define data models - [ ] 🔗 Sync folder open state with the URL - [ ] 🔐 Implement user authentication - [ ] 📁 Enable file upload functionality @@ -96,5 +96,4 @@ Just finished up the database connection, next steps: - [x] Update schema to show files and folders - [x] Manually insert examples -- [ ] Render them in the UI -- [ ] Push and make sure it all works +- [x] Render them in the UI diff --git a/src/app/drive-contents.tsx b/src/app/drive-contents.tsx new file mode 100644 index 0000000..c7e3d71 --- /dev/null +++ b/src/app/drive-contents.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { ChevronRight, Upload } from "lucide-react"; +import { useMemo, useState } from "react"; + +import { Button } from "~/components/ui/button"; +import type { files, folders } from "~/server/db/schema"; +import { FileRow, FolderRow } from "./file-row"; + +export default function DriveContents(props: { + files: (typeof files.$inferSelect)[]; + folders: (typeof folders.$inferSelect)[]; +}) { + const [currentFolder, setCurrentFolder] = useState(1); + + const handleFolderClick = (folderId: number) => { + setCurrentFolder(folderId); + }; + + const breadcrumbs = useMemo(() => { + const breadcrumbs = []; + let currentId = currentFolder; + + while (currentId !== 1) { + const folder = props.folders.find((file) => file.id === currentId); + if (folder) { + breadcrumbs.unshift(folder); + currentId = folder.parent ?? 1; + } else { + break; + } + } + + return breadcrumbs; + }, [currentFolder, props.folders]); + + const handleUpload = () => { + alert("Upload functionality would be implemented here"); + }; + + return ( +
+
+
+
+ + {breadcrumbs.map((folder) => ( +
+ + +
+ ))} +
+ +
+
+
+
+
Name
+
Type
+
Size
+
+
+
    + {props.folders.map((folder) => ( + handleFolderClick(folder.id)} + /> + ))} + {props.files.map((file) => ( + + ))} +
+
+
+
+ ); +} diff --git a/src/app/f/[folderId]/page.tsx b/src/app/f/[folderId]/page.tsx new file mode 100644 index 0000000..4a6aa52 --- /dev/null +++ b/src/app/f/[folderId]/page.tsx @@ -0,0 +1,14 @@ +import { db } from "~/server/db"; +import { + files as fileSchema, + folders as folderSchema, +} from "~/server/db/schema"; + +import DriveContents from "../../drive-contents"; + +export default async function GoogleDriveClone() { + const folders = await db.select().from(folderSchema); + const files = await db.select().from(fileSchema); + + return ; +} diff --git a/src/app/file-row.tsx b/src/app/file-row.tsx index 01788bb..10cf885 100644 --- a/src/app/file-row.tsx +++ b/src/app/file-row.tsx @@ -1,8 +1,8 @@ import { FileIcon, Folder as FolderIcon } from "lucide-react"; -import type { File, Folder } from "~/lib/mock-data"; +import type { files, folders } from "~/server/db/schema"; -export function FileRow(props: { file: File }) { +export function FileRow(props: { file: typeof files.$inferSelect }) { const { file } = props; return ( @@ -29,7 +29,7 @@ export function FileRow(props: { file: File }) { } export function FolderRow(props: { - folder: Folder; + folder: typeof folders.$inferSelect; onFolderClick: () => void; }) { const { folder, onFolderClick } = props; diff --git a/src/app/page.tsx b/src/app/page.tsx index 47de2c9..a2ba30f 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,103 +1,13 @@ -"use client"; - -import { ChevronRight, Upload } from "lucide-react"; -import { useMemo, useState } from "react"; - -import { Button } from "~/components/ui/button"; -import { mockFiles, mockFolders } from "~/lib/mock-data"; -import { FileRow, FolderRow } from "./file-row"; - -export default function GoogleDriveClone() { - const [currentFolder, setCurrentFolder] = useState("root"); - - const getCurrentFiles = () => { - return mockFiles.filter((file) => file.parent === currentFolder); - }; - - const getCurrentFolders = () => { - return mockFolders.filter((folder) => folder.parent === currentFolder); - }; - - const handleFolderClick = (folderId: string) => { - setCurrentFolder(folderId); - }; - - const breadcrumbs = useMemo(() => { - const breadcrumbs = []; - let currentId = currentFolder; - - while (currentId !== "root") { - const folder = mockFolders.find((file) => file.id === currentId); - if (folder) { - breadcrumbs.unshift(folder); - currentId = folder.parent ?? "root"; - } else { - break; - } - } - - return breadcrumbs; - }, [currentFolder]); - - const handleUpload = () => { - alert("Upload functionality would be implemented here"); - }; - - return ( -
-
-
-
- - {breadcrumbs.map((folder) => ( -
- - -
- ))} -
- -
-
-
-
-
Name
-
Type
-
Size
-
-
-
    - {getCurrentFolders().map((folder) => ( - handleFolderClick(folder.id)} - /> - ))} - {getCurrentFiles().map((file) => ( - - ))} -
-
-
-
- ); +import { db } from "~/server/db"; +import { + files as fileSchema, + folders as folderSchema, +} from "~/server/db/schema"; +import DriveContents from "./drive-contents"; + +export default async function GoogleDriveClone() { + const folders = await db.select().from(folderSchema); + const files = await db.select().from(fileSchema); + + return ; } diff --git a/src/server/db/schema.ts b/src/server/db/schema.ts index 52dba32..30b873a 100644 --- a/src/server/db/schema.ts +++ b/src/server/db/schema.ts @@ -15,6 +15,7 @@ export const files = createTable( .primaryKey() .autoincrement(), name: text("name").notNull(), + url: text("url").notNull(), size: int("size").notNull(), parent: bigint("parent", { mode: "number", unsigned: true }), }, From ff8ad087b044843c9e4a8bfee469c92623170431 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 4 Jun 2025 21:07:48 +0200 Subject: [PATCH 2/4] Getting the Folder ID --- src/app/f/[folderId]/page.tsx | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/app/f/[folderId]/page.tsx b/src/app/f/[folderId]/page.tsx index 4a6aa52..ba696db 100644 --- a/src/app/f/[folderId]/page.tsx +++ b/src/app/f/[folderId]/page.tsx @@ -1,3 +1,5 @@ +import { z } from "zod"; + import { db } from "~/server/db"; import { files as fileSchema, @@ -6,7 +8,19 @@ import { import DriveContents from "../../drive-contents"; -export default async function GoogleDriveClone() { +export default async function GoogleDriveClone(props: { + params: Promise<{ folderId: number }>; +}) { + const params = await props.params; + const { data, success } = z + .object({ folderId: z.coerce.number() }) + .safeParse(params); + + if (!success) return
Invalid Folder ID
; + + const folderId = data.folderId; + console.log(folderId); + const folders = await db.select().from(folderSchema); const files = await db.select().from(fileSchema); From f039f2d5e9f193532881b0fc0622eb38e1d0969b Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 4 Jun 2025 21:10:15 +0200 Subject: [PATCH 3/4] Showing the Right Content --- src/app/f/[folderId]/page.tsx | 11 +++++++++-- src/app/page.tsx | 14 ++------------ 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/app/f/[folderId]/page.tsx b/src/app/f/[folderId]/page.tsx index ba696db..19392fe 100644 --- a/src/app/f/[folderId]/page.tsx +++ b/src/app/f/[folderId]/page.tsx @@ -1,3 +1,4 @@ +import { eq } from "drizzle-orm"; import { z } from "zod"; import { db } from "~/server/db"; @@ -21,8 +22,14 @@ export default async function GoogleDriveClone(props: { const folderId = data.folderId; console.log(folderId); - const folders = await db.select().from(folderSchema); - const files = await db.select().from(fileSchema); + const folders = await db + .select() + .from(folderSchema) + .where(eq(folderSchema.parent, folderId)); + const files = await db + .select() + .from(fileSchema) + .where(eq(fileSchema.parent, folderId)); return ; } diff --git a/src/app/page.tsx b/src/app/page.tsx index a2ba30f..74ab28a 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,13 +1,3 @@ -import { db } from "~/server/db"; -import { - files as fileSchema, - folders as folderSchema, -} from "~/server/db/schema"; -import DriveContents from "./drive-contents"; - -export default async function GoogleDriveClone() { - const folders = await db.select().from(folderSchema); - const files = await db.select().from(fileSchema); - - return ; +export default async function HomePage() { + return

Welcome to your Drive

; } From d7ae14cf345642aa8317bf447c45d9206fefd3a6 Mon Sep 17 00:00:00 2001 From: Thomas Date: Wed, 4 Jun 2025 21:19:03 +0200 Subject: [PATCH 4/4] Update README.md --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9f66eaa..c0bccca 100644 --- a/README.md +++ b/README.md @@ -86,9 +86,10 @@ pnpm run dev Tracking progress on key features and tasks for the project. - [x] 🛢️ Set up the database and define data models -- [ ] 🔗 Sync folder open state with the URL +- [x] 🔗 Sync folder open state with the URL - [ ] 🔐 Implement user authentication - [ ] 📁 Enable file upload functionality +- [ ] 📊 Add analytics tracking ### 📝 Note from 5-28-2025 @@ -97,3 +98,11 @@ Just finished up the database connection, next steps: - [x] Update schema to show files and folders - [x] Manually insert examples - [x] Render them in the UI + +### 📝 Note from 6-4-2025 + +The database and UI are now connected, some improvements to make: + +- [ ] Change folders to link components, remove all client state +- [ ] Clean up the database and data fetching patterns +- [ ] Real homepage