diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts
index 70f1bd1..42d28b4 100644
--- a/app/api/auth/[...nextauth]/route.ts
+++ b/app/api/auth/[...nextauth]/route.ts
@@ -1,18 +1,32 @@
-import NextAuth from "next-auth";
+import NextAuth, { Session, AuthOptions } from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import prisma from "@/lib/db";
+import { JWT } from "next-auth/jwt";
-const handler = NextAuth({
- providers:[
+export const authOption: AuthOptions = {
+ providers: [
GoogleProvider({
- clientId: process.env.GOOGLE_CLIENT_ID!,
- clientSecret: process.env.GOOGLE_CLIENT_SECRET!
- })
+ clientId: process.env.GOOGLE_CLIENT_ID!,
+ clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
+ }),
],
secret: process.env.NEXTAUTH_SECRET!,
- session:{strategy: "jwt"},
+ session: {
+ strategy: "jwt", // This ensures TypeScript recognizes this as a valid strategy
+ },
adapter: PrismaAdapter(prisma),
-})
+ callbacks: {
+ session: async ({ session, token }: { session: Session; token: JWT }) => {
+ if (token && session.user) {
+ session.user.id = token.sub;
+ session.user.email = token.email;
+ }
+ return session;
+ },
+ },
+};
-export { handler as GET, handler as POST }
\ No newline at end of file
+const handler = NextAuth(authOption);
+
+export { handler as GET, handler as POST, handler as OPTIONS };
diff --git a/app/document/[documentId]/page.tsx b/app/document/[documentId]/page.tsx
new file mode 100644
index 0000000..bab0e04
--- /dev/null
+++ b/app/document/[documentId]/page.tsx
@@ -0,0 +1,12 @@
+import Document from '@/components/Document'
+import React from 'react'
+
+const Page = ({params : {documentId}} : {params:{documentId: string}}) => {
+ return (
+
+
+
+ )
+}
+
+export default Page
diff --git a/components/AddDocument.tsx b/components/AddDocument.tsx
index c96148e..19ece7a 100644
--- a/components/AddDocument.tsx
+++ b/components/AddDocument.tsx
@@ -57,9 +57,9 @@ const AddDocument = ({ categoryId }: { categoryId: string }) => {
diff --git a/components/Category.tsx b/components/Category.tsx
index 8b13c01..e2947bf 100644
--- a/components/Category.tsx
+++ b/components/Category.tsx
@@ -2,28 +2,42 @@ import React from 'react'
import prisma from '@/lib/db'
import { Separator } from "@/components/ui/separator"
import AddDocument from './AddDocument'
+import DocumentGroup from './DocumentGroup'
const getDocumentsOfCategory = async(id : string)=>{
-return await prisma.category.findFirst({where: {id: id}, include: {documents: true,}})
+return await prisma.category.findFirst({where: {id: id}, include: {documents: {include: {user: {select: {email: true, image: true}}}}}})
}
const Category = async ({categoryId}: {categoryId : string}) => {
const result = await getDocumentsOfCategory(categoryId)
+ console.log(result)
const count = result?.documents.length
return (
-
-
+
+
+
+
-{ count === 0 &&
+
+
+
+
{count === 0 && "No document find. Click on the button to add."}
+
-}
)
diff --git a/components/Document.tsx b/components/Document.tsx
new file mode 100644
index 0000000..8192091
--- /dev/null
+++ b/components/Document.tsx
@@ -0,0 +1,18 @@
+import prisma from '@/lib/db'
+import React from 'react'
+
+const getDocument = async(id: string)=>{
+return await prisma.document.findFirst({where: {id: id}})
+}
+const Document = async ({documentId}: {documentId: string}) => {
+
+ const result = await getDocument(documentId)
+
+ return (
+
+
+
+ )
+}
+
+export default Document
diff --git a/components/DocumentGroup.tsx b/components/DocumentGroup.tsx
new file mode 100644
index 0000000..0688161
--- /dev/null
+++ b/components/DocumentGroup.tsx
@@ -0,0 +1,44 @@
+
+import React from "react";
+import { DocumentType } from "@/lib/types";
+import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import Link from "next/link";
+import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
+
+
+
+
+const DocumentGroup = ({documents}: {documents :DocumentType[]}) => {
+ return (
+ <>
+ {documents.map(({ name, id, user }) => {
+
+ return (
+
+
+
+ {name}
+
+
+
+
+
+
+
+ {user?.email[0]}
+
+
+
+ {user?.email}
+
+
+
+
+
+ );
+ })}
+ >
+ )
+}
+
+export default DocumentGroup
diff --git a/components/Navbar.tsx b/components/Navbar.tsx
index 8c583ce..9a2cd19 100644
--- a/components/Navbar.tsx
+++ b/components/Navbar.tsx
@@ -1,8 +1,12 @@
+"use client"
import React from "react";
import { ThemeToggler } from "@/components/ThemeToggler";
import { Separator } from "@/components/ui/separator";
import Link from "next/link";
import { GithubIcon, TwitterIcon } from "./icons";
+import { signOut } from "next-auth/react";
+import { Button } from "./ui/button";
+
const Navbar = () => {
return (
@@ -14,6 +18,9 @@ const Navbar = () => {
+
diff --git a/components/ui/avatar.tsx b/components/ui/avatar.tsx
new file mode 100644
index 0000000..51e507b
--- /dev/null
+++ b/components/ui/avatar.tsx
@@ -0,0 +1,50 @@
+"use client"
+
+import * as React from "react"
+import * as AvatarPrimitive from "@radix-ui/react-avatar"
+
+import { cn } from "@/lib/utils"
+
+const Avatar = React.forwardRef<
+ React.ElementRef
,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+Avatar.displayName = AvatarPrimitive.Root.displayName
+
+const AvatarImage = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarImage.displayName = AvatarPrimitive.Image.displayName
+
+const AvatarFallback = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
+
+export { Avatar, AvatarImage, AvatarFallback }
diff --git a/lib/actions/file.ts b/lib/actions/file.ts
index ab66a46..22b4f38 100644
--- a/lib/actions/file.ts
+++ b/lib/actions/file.ts
@@ -1,9 +1,11 @@
"use server";
import { revalidatePath } from "next/cache";
import cloudinary from "cloudinary";
+import fs from "node:fs/promises";
import prisma from "../db";
-import { getServerSession } from "next-auth";
-import { options } from "@/app/api/auth/[...nextauth]/route";
+import {authOption} from "../../app/api/auth/[...nextauth]/route"
+import { getServerSession } from "next-auth";
+
cloudinary.v2.config({
@@ -12,21 +14,35 @@ cloudinary.v2.config({
api_secret: process.env.CLOUD_API_SECERET,
});
+
export async function uploadDocument(formData: FormData) {
- const session = getServerSession(options)
- const file = formData.get("file") as File;
- const result = await cloudinary.v2.uploader.upload(file, {folder: "cms"})
-
- const prismaResult = await prisma.document.create({data: {
- url: result.secure_url,
- publicId: result.public_id,
- name: formData.get("documentName") as string,
- categories: {
- connect: [{id: formData.get("categoryId") as string}]
- },
- userId:
- }})
-
- revalidatePath("/"); // change to category / categoryId
+ try {
+ const session = await getServerSession(authOption)
+ const categoryId = formData.get("categoryId") as string
+ const file = formData.get("file") as File;
+ const arrayBuffer = await file.arrayBuffer();
+ const buffer = new Uint8Array(arrayBuffer)
+ await fs.writeFile(`./public/uploads/${file.name}`, buffer);
+
+ const result = await cloudinary.v2.uploader.upload(`./public/uploads/${file.name}`, {folder: "cms",resource_type: "auto", type: "upload"})
+
+ await prisma.document.create({
+ data:{
+ url: result.secure_url,
+ publicId: result.public_id,
+ userId: session?.user?.id,
+ name: formData.get("documentName") as string,
+ categories: {connect: [{id: categoryId}],
+ }}
+ })
+ fs.unlink(`./public/uploads/${file.name}`)
+ revalidatePath(`/categoryId/${categoryId}`);
+ } catch (error) {
+ console.log(error)
+ }
+
+
+
+
}
\ No newline at end of file
diff --git a/lib/types/index.ts b/lib/types/index.ts
index 847e853..d3d2ab0 100644
--- a/lib/types/index.ts
+++ b/lib/types/index.ts
@@ -2,3 +2,17 @@ export interface Category {
name: string,
id: string,
}
+export interface DocumentType {
+ id: string,
+ name: string,
+ url: string,
+ publicId: string,
+ createdAt: Date,
+ userId: string,
+ user?: {email: string, image: string | null}
+}
+export interface CategoryWithDocument {
+ id: string,
+ name: string,
+documents: DocumentType[]
+}
\ No newline at end of file
diff --git a/middleware.ts b/middleware.ts
index 59c3a42..1c71490 100644
--- a/middleware.ts
+++ b/middleware.ts
@@ -10,6 +10,7 @@ export const config = {
export async function middleware(request: NextRequest) {
const token = await getToken({ req: request });
const url = request.nextUrl;
+ console.log(token)
// if token is present and user is on auth pages then redirect to dahsboard
if (
diff --git a/next.config.mjs b/next.config.mjs
index 4678774..d58a90b 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -1,4 +1,5 @@
/** @type {import('next').NextConfig} */
-const nextConfig = {};
+const nextConfig = {images:{ domains: ['lh3.googleusercontent.com'],
+}};
export default nextConfig;
diff --git a/package-lock.json b/package-lock.json
index 7cc0855..be9eb05 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,6 +10,7 @@
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"@next-auth/prisma-adapter": "^1.0.7",
+ "@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
@@ -675,6 +676,32 @@
}
}
},
+ "node_modules/@radix-ui/react-avatar": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.0.tgz",
+ "integrity": "sha512-Q/PbuSMk/vyAd/UoIShVGZ7StHHeRFYU7wXmi5GV+8cLXflZAEpHL/F697H1klrzxKXNtZ97vWiC0q3RKUH8UA==",
+ "license": "MIT",
+ "dependencies": {
+ "@radix-ui/react-context": "1.1.0",
+ "@radix-ui/react-primitive": "2.0.0",
+ "@radix-ui/react-use-callback-ref": "1.1.0",
+ "@radix-ui/react-use-layout-effect": "1.1.0"
+ },
+ "peerDependencies": {
+ "@types/react": "*",
+ "@types/react-dom": "*",
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
"node_modules/@radix-ui/react-collection": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
diff --git a/package.json b/package.json
index 0576636..c124131 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,7 @@
"dependencies": {
"@hookform/resolvers": "^3.9.0",
"@next-auth/prisma-adapter": "^1.0.7",
+ "@radix-ui/react-avatar": "^1.1.0",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0",
diff --git a/public/uploads/Intelligent-Agents.pdf b/public/uploads/Intelligent-Agents.pdf
new file mode 100644
index 0000000..fa58f56
Binary files /dev/null and b/public/uploads/Intelligent-Agents.pdf differ
diff --git a/public/uploads/dev_resume.pdf b/public/uploads/dev_resume.pdf
new file mode 100644
index 0000000..154f676
Binary files /dev/null and b/public/uploads/dev_resume.pdf differ
diff --git a/public/uploads/dev_resume_new.pdf b/public/uploads/dev_resume_new.pdf
new file mode 100644
index 0000000..410f536
Binary files /dev/null and b/public/uploads/dev_resume_new.pdf differ