diff --git a/README.md b/README.md
index 299c42a..581148b 100644
--- a/README.md
+++ b/README.md
@@ -28,15 +28,15 @@
- [x] Add ownership to files
- [x] Upload fiiles to the correct folder
-- [ ] Delete files button
+- [x] Delete files button
- [x] Allow files thay arent images to be uploaded
- [x] Display file type and file sizes correctly in the view
-- [ ] Retrieve the file type from uploadthing and save it in db
-- [ ] real homepage
+- [x] Retrieve the file type from uploadthing and save it in db
+- [x] real homepage
## notes 2:40.44
- [ ] Real homepage + onboarding
## followup
-[ ] folder deletion - make sure to recursively delete all files and folders.
\ No newline at end of file
+[ ] folder deletion - make sure to recursively delete all files and folders
diff --git a/src/app/(home)/drive/page.tsx b/src/app/(home)/drive/page.tsx
new file mode 100644
index 0000000..928389f
--- /dev/null
+++ b/src/app/(home)/drive/page.tsx
@@ -0,0 +1,52 @@
+import { auth } from "@clerk/nextjs/server";
+import { redirect } from "next/navigation";
+import { Button } from "~/components/ui/button";
+import { MUTATIONS, QUERIES } from "~/server/db/queries";
+
+export default async function DrivePage() {
+ const session = await auth();
+ if (!session.userId) {
+ return redirect("/sign-in");
+ }
+
+ const rootFolder = await QUERIES.getRootFolderForUser(session.userId);
+
+ if (typeof rootFolder === "object" && "error" in rootFolder) {
+ // Handle error case, e.g., show a message to the user
+ console.error("Error fetching root folder:", rootFolder.error);
+ return (
+ <>
+
Error fetching root folder
+ >
+ );
+ }
+
+ if (!rootFolder) {
+ // create the root folder for the user
+ return (
+ <>
+
+ >
+ );
+ }
+
+ return redirect(`/folder/${rootFolder.id}`);
+}
diff --git a/src/app/(home)/layout.tsx b/src/app/(home)/layout.tsx
new file mode 100644
index 0000000..e23ec91
--- /dev/null
+++ b/src/app/(home)/layout.tsx
@@ -0,0 +1,14 @@
+import { auth } from "@clerk/nextjs/server";
+import { redirect } from "next/navigation";
+import { Button } from "~/components/ui/button";
+
+export default function HomeLayout(props: { children: React.ReactNode }) {
+ return (
+
+ {props.children}
+
+
+ );
+}
diff --git a/src/app/(home)/page.tsx b/src/app/(home)/page.tsx
index f0b3cdc..f470415 100644
--- a/src/app/(home)/page.tsx
+++ b/src/app/(home)/page.tsx
@@ -1,8 +1,37 @@
+import { auth } from "@clerk/nextjs/server";
+import { redirect } from "next/navigation";
+import { Button } from "~/components/ui/button";
+export default function HomePage() {
+ return (
+ <>
+
+ M8 Drive
+
+
+ Secure, fast, and easy file storage for the modern web
+
+
+ >
+ );
+}
diff --git a/src/app/(home)/sign-in/page.tsx b/src/app/(home)/sign-in/page.tsx
new file mode 100644
index 0000000..b438fed
--- /dev/null
+++ b/src/app/(home)/sign-in/page.tsx
@@ -0,0 +1,9 @@
+import { SignInButton } from "@clerk/nextjs";
+
+export default function SignInPage() {
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/src/server/db/queries.ts b/src/server/db/queries.ts
index 8db74f9..b9894b3 100644
--- a/src/server/db/queries.ts
+++ b/src/server/db/queries.ts
@@ -1,56 +1,142 @@
-import 'server-only';
+import "server-only";
-import { eq } from "drizzle-orm";
+import { eq, and, isNull } from "drizzle-orm";
import { db } from ".";
-import { DB_FileType, files_table as fileSchema, folders_table as foldersSchema } from "~/server/db/schema"
+import {
+ DB_FileType,
+ files_table as fileSchema,
+ folders_table as foldersSchema,
+} from "~/server/db/schema";
export const QUERIES = {
- getAllParentsForFolder: async function (folderId: number) {
- const parents = [];
- let currentId: number | null = folderId;
- while (currentId !== null && currentId !== 1) {
- const folder = await db
- .selectDistinct()
- .from(foldersSchema)
- .where(eq(foldersSchema.id, currentId));
-
- if (!folder[0]) {
- throw new Error(`Folder with ID ${currentId} not found`);
- }
- parents.unshift(folder[0]);
- currentId = folder[0]?.parent ?? null;
- }
- return parents;
- },
-
- getFiles: async function (folderId: number) {
- const filePromise = await db.select().from(fileSchema).where(eq(fileSchema.parent, folderId)).orderBy(fileSchema.createdAt);
- return filePromise
- },
-
- getFolders: async function (folderId: number) {
- const foldersPromise = await db.select().from(foldersSchema).where(eq(foldersSchema.parent, folderId)).orderBy(foldersSchema.createdAt);
- return foldersPromise
- },
- getFolderById: async function (folderId: number) {
- const folder = await db.select().from(foldersSchema).where(eq(foldersSchema.id, folderId));
- if (!folder[0]) {
- throw new Error(`Folder with ID ${folderId} not found`);
- }
- return folder[0];
+ getAllParentsForFolder: async function (folderId: number) {
+ const parents = [];
+ let currentId: number | null = folderId;
+ while (currentId !== null && currentId !== 1) {
+ const folder = await db
+ .selectDistinct()
+ .from(foldersSchema)
+ .where(eq(foldersSchema.id, currentId));
+
+ if (!folder[0]) {
+ throw new Error(`Folder with ID ${currentId} not found`);
+ }
+ parents.unshift(folder[0]);
+ currentId = folder[0]?.parent ?? null;
+ }
+ return parents;
+ },
+
+ getFiles: async function (folderId: number) {
+ const filePromise = await db
+ .select()
+ .from(fileSchema)
+ .where(eq(fileSchema.parent, folderId))
+ .orderBy(fileSchema.createdAt);
+ return filePromise;
+ },
+
+ getFolders: async function (folderId: number) {
+ const foldersPromise = await db
+ .select()
+ .from(foldersSchema)
+ .where(eq(foldersSchema.parent, folderId))
+ .orderBy(foldersSchema.createdAt);
+ return foldersPromise;
+ },
+ getFolderById: async function (folderId: number) {
+ const folder = await db
+ .select()
+ .from(foldersSchema)
+ .where(eq(foldersSchema.id, folderId));
+ if (!folder[0]) {
+ throw new Error(`Folder with ID ${folderId} not found`);
+ }
+ return folder[0];
+ },
+
+ getRootFolderForUser: async function (userId: string) {
+ // get the root folder for the user
+ if (!userId) {
+ return { error: "Unauthorized" };
}
-}
+ const rootFolder = await db
+ .select()
+ .from(foldersSchema)
+ .where(
+ and(eq(foldersSchema.ownerId, userId), isNull(foldersSchema.parent)),
+ );
+ return rootFolder[0];
+ },
+};
export const MUTATIONS = {
- createFile: async function (input : {
- file: {
- name: string;
- size: number;
- url: string;
- parent: number;
- ownerId: string;
- }, userId: string}) {
- if (!input.userId) throw new Error("Unauthorized");
- return await db.insert(fileSchema).values(input.file)
- },
-}
+ createFile: async function (input: {
+ file: {
+ name: string;
+ size: number;
+ url: string;
+ parent: number;
+ ownerId: string;
+ };
+ userId: string;
+ }) {
+ if (!input.userId) throw new Error("Unauthorized");
+ return await db.insert(fileSchema).values(input.file);
+ },
+
+ createFolder: async function (input: {
+ name: string;
+ parentId: number | null;
+ userId: string;
+ }) {
+ const { name, parentId, userId } = input;
+ if (!userId) throw new Error("Unauthorized");
+ return await db.insert(foldersSchema).values({
+ name,
+ parent: parentId,
+ ownerId: userId,
+ });
+ },
+
+ onboardUser: async function (userId: string) {
+ const isExistingUser = await db
+ .select()
+ .from(foldersSchema)
+ .where(eq(foldersSchema.ownerId, userId))
+ .limit(1);
+ if (isExistingUser[0]) {
+ return { error: "User already exists" };
+ }
+ const rootFolder = await db
+ .insert(foldersSchema)
+ .values({
+ name: "Root",
+ parent: null,
+ ownerId: userId,
+ })
+ .$returningId();
+
+ const rootFolderId = rootFolder[0]!.id;
+
+ await db.insert(foldersSchema).values([
+ {
+ name: "Shared",
+ parent: rootFolderId,
+ ownerId: userId,
+ },
+ {
+ name: "Favourites",
+ parent: rootFolderId,
+ ownerId: userId,
+ },
+ {
+ name: "Documents",
+ parent: rootFolderId,
+ ownerId: userId,
+ },
+ ]);
+
+ return rootFolderId;
+ },
+};