Skip to content

Commit

Permalink
added document viewing functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
devsharmagit committed Sep 22, 2024
1 parent cdc14e9 commit bdc80a4
Show file tree
Hide file tree
Showing 17 changed files with 254 additions and 35 deletions.
32 changes: 23 additions & 9 deletions app/api/auth/[...nextauth]/route.ts
Original file line number Diff line number Diff line change
@@ -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 }
const handler = NextAuth(authOption);

export { handler as GET, handler as POST, handler as OPTIONS };
12 changes: 12 additions & 0 deletions app/document/[documentId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import Document from '@/components/Document'
import React from 'react'

const Page = ({params : {documentId}} : {params:{documentId: string}}) => {
return (
<div>
<Document documentId={documentId} />
</div>
)
}

export default Page
4 changes: 2 additions & 2 deletions components/AddDocument.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ const AddDocument = ({ categoryId }: { categoryId: string }) => {
<DialogTrigger asChild>
<Button
variant="outline"
className="flex gap-2 flex-col items-center justify-center h-auto m-auto mt-5"
className="flex gap-2 items-center justify-center h-auto m-auto mt-5"
>
<Upload height={35} width={35} />
<Upload height={20} width={20} />
<p className="text-base text-opacity-70">Add Document</p>
</Button>
</DialogTrigger>
Expand Down
26 changes: 20 additions & 6 deletions components/Category.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
<div className='text-center'>
<p className='text-2xl text-opacity-75 font-bold py-4'>
<div className="py-3 px-4 w-full max-w-7xl m-auto grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<div className='col-span-full'>
<div className='flex justify-between mb-5'>
<p className='text-2xl text-opacity-75 font-bold py-4 ' >
{result?.name}
</p>
<div>
<AddDocument categoryId={categoryId}/>
</div>
</div>

<Separator />
{ count === 0 &&

</div>
<div className='col-span-full text-center'>
<p> {count === 0 && "No document find. Click on the button to add."} </p>
</div>
<div>
<AddDocument categoryId={categoryId}/>
{result &&
<DocumentGroup documents={result.documents} />
}
</div>
}

</div>
)
Expand Down
18 changes: 18 additions & 0 deletions components/Document.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className='flex justify-center'>
<iframe src={result?.url} className='w-[90vw] h-[90vh]' />
</div>
)
}

export default Document
44 changes: 44 additions & 0 deletions components/DocumentGroup.tsx
Original file line number Diff line number Diff line change
@@ -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 ( <Link href={`/document/${id}`} key={id}>
<Card className="min-h-[100px] flex flex-col justify-center items-center text-center cursor-pointer">
<CardHeader>
<CardTitle className="text-left text-2xl ">
{name}
</CardTitle>
</CardHeader>
<CardDescription className="py-2 flex gap-1 items-center ">

<Avatar className="h-6 w-6" >
<AvatarImage src={user?.image || ""} className="w-6 h-6 rounded-full object-cover " />

<AvatarFallback> {user?.email[0]} </AvatarFallback>

</Avatar>
<p className="text-sm text-opacity-50">
{user?.email}
</p>

</CardDescription>
</Card>
</Link>
);
})}
</>
)
}

export default DocumentGroup
7 changes: 7 additions & 0 deletions components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -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 (
Expand All @@ -14,6 +18,9 @@ const Navbar = () => {
</h1>
</Link>
<div className="flex gap-3 items-center">
<Button onClick={()=>signOut()} variant={"ghost"} className="border-opacity-20 border border-white">
Sign out
</Button>
<ThemeToggler />
<Link href={"https://x.com/CodeDevsharma"} target="_blank">
<TwitterIcon />
Expand Down
50 changes: 50 additions & 0 deletions components/ui/avatar.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof AvatarPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
"relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full",
className
)}
{...props}
/>
))
Avatar.displayName = AvatarPrimitive.Root.displayName

const AvatarImage = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Image>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn("aspect-square h-full w-full", className)}
{...props}
/>
))
AvatarImage.displayName = AvatarPrimitive.Image.displayName

const AvatarFallback = React.forwardRef<
React.ElementRef<typeof AvatarPrimitive.Fallback>,
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
"flex h-full w-full items-center justify-center rounded-full bg-muted",
className
)}
{...props}
/>
))
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName

export { Avatar, AvatarImage, AvatarFallback }
50 changes: 33 additions & 17 deletions lib/actions/file.ts
Original file line number Diff line number Diff line change
@@ -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({
Expand All @@ -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)
}




}
14 changes: 14 additions & 0 deletions lib/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
}
1 change: 1 addition & 0 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down
3 changes: 2 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {images:{ domains: ['lh3.googleusercontent.com'],
}};

export default nextConfig;
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit bdc80a4

Please sign in to comment.