Revert "revert 99397e774c41980ef13b3155e13330ad4eaa7753"
This reverts commit b63e3ae77fa6e171e18eae62d65e0b66f23f0fb8.
This commit is contained in:
		
							parent
							
								
									bb89a84ba8
								
							
						
					
					
						commit
						551cf2e2cb
					
				| @ -15,17 +15,6 @@ datasource db { | |||||||
|     url      = env("DATABASE_URL") |     url      = env("DATABASE_URL") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| model Post { |  | ||||||
|     id        Int      @id @default(autoincrement()) |  | ||||||
|     name      String |  | ||||||
|     createdAt DateTime @default(now()) |  | ||||||
|     updatedAt DateTime @updatedAt |  | ||||||
| 
 |  | ||||||
|     createdBy   User   @relation(fields: [createdById], references: [id]) |  | ||||||
|     createdById String |  | ||||||
| 
 |  | ||||||
|     @@index([name]) |  | ||||||
| } |  | ||||||
| 
 | 
 | ||||||
| // Necessary for Next auth | // Necessary for Next auth | ||||||
| model Account { | model Account { | ||||||
| @ -63,7 +52,6 @@ model User { | |||||||
|     image         String? |     image         String? | ||||||
|     accounts      Account[] |     accounts      Account[] | ||||||
|     sessions      Session[] |     sessions      Session[] | ||||||
|     posts         Post[] |  | ||||||
|     files         File[]    // Relation to the File model |     files         File[]    // Relation to the File model | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -85,4 +73,5 @@ model File { | |||||||
|     description String @default("") |     description String @default("") | ||||||
|     uploadedBy User?    @relation(fields: [uploadedById], references: [id], onDelete: SetNull) |     uploadedBy User?    @relation(fields: [uploadedById], references: [id], onDelete: SetNull) | ||||||
|     uploadedById String? |     uploadedById String? | ||||||
|  |     public     Boolean  @default(false) // Indicates if the file is public or private | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| 'use client'; | "use client"; | ||||||
| import { useRef, useState } from "react"; | import { useRef, useState } from "react"; | ||||||
| import { useFileActions } from "~/app/_components/FileActions"; | import { useFileActions } from "~/app/_components/FileActions"; | ||||||
| 
 | 
 | ||||||
| @ -7,11 +7,13 @@ export function FileActionsContainer({ | |||||||
|   fileName, |   fileName, | ||||||
|   fileUrl, |   fileUrl, | ||||||
|   isOwner, |   isOwner, | ||||||
|  |   isPublic, | ||||||
| }: { | }: { | ||||||
|   fileId: string; |   fileId: string; | ||||||
|   fileName: string; |   fileName: string; | ||||||
|   fileUrl: string; |   fileUrl: string; | ||||||
|   isOwner: boolean; |   isOwner: boolean; | ||||||
|  |   isPublic: boolean; | ||||||
| }) { | }) { | ||||||
|   const { handleDownload, handleCopyUrl, handleRemove} = useFileActions(() => fileId, (description: string) => { |   const { handleDownload, handleCopyUrl, handleRemove} = useFileActions(() => fileId, (description: string) => { | ||||||
|     if (isOwner) { |     if (isOwner) { | ||||||
| @ -36,14 +38,55 @@ export function FileActionsContainer({ | |||||||
|       > |       > | ||||||
|         <img src="/icons/copy.svg" alt="Copy URL" className="w-6 h-6" /> |         <img src="/icons/copy.svg" alt="Copy URL" className="w-6 h-6" /> | ||||||
|       </button> |       </button> | ||||||
| 
 |  | ||||||
|       {/* Remove Button */} |       {/* Remove Button */} | ||||||
|  |       {isOwner && ( | ||||||
|       <button |       <button | ||||||
|         onClick={() => handleRemove(fileId)} |         onClick={() => handleRemove(fileId)} | ||||||
|         className="flex items-center justify-center rounded-full bg-red-500 p-2 hover:bg-red-600" |         className="flex items-center justify-center rounded-full bg-red-500 p-2 hover:bg-red-600" | ||||||
|       > |       > | ||||||
|         <img src="/icons/delete.svg" alt="Remove" className="w-6 h-6" /> |         <img src="/icons/delete.svg" alt="Remove" className="w-6 h-6" /> | ||||||
|       </button> |       </button> | ||||||
|  |       )} | ||||||
|  |       {isOwner && ( | ||||||
|  |         <div className="mt-4 flex items-center gap-2"> | ||||||
|  |         <label className="text-sm"> | ||||||
|  |           Public: | ||||||
|  |         </label> | ||||||
|  |         <label | ||||||
|  |           htmlFor={`public-toggle-${fileId}`} | ||||||
|  |           className="relative inline-flex items-center cursor-pointer" | ||||||
|  |         > | ||||||
|  |           <input | ||||||
|  |             id={`public-toggle-${fileId}`} | ||||||
|  |             type="checkbox" | ||||||
|  |             checked={isPublic} // Ensure this reflects the prop
 | ||||||
|  |             onChange={async (e) => { | ||||||
|  |               const newIsPublic = e.target.checked; | ||||||
|  |               try { | ||||||
|  |                 const response = await fetch(`/api/files/update-public`, { | ||||||
|  |                   method: "POST", | ||||||
|  |                   headers: { | ||||||
|  |                     "Content-Type": "application/json", | ||||||
|  |                   }, | ||||||
|  |                   body: JSON.stringify({ fileId: fileId, isPublic: newIsPublic }), | ||||||
|  |                 }); | ||||||
|  |                 if (!response.ok) { | ||||||
|  |                   throw new Error("Failed to update public status"); | ||||||
|  |                 } | ||||||
|  |                 console.log("Public status updated successfully"); | ||||||
|  |               } catch (err) { | ||||||
|  |                 console.error("Error updating public status:", err); | ||||||
|  |               } | ||||||
|  |             }} | ||||||
|  |             className="sr-only peer" | ||||||
|  |           /> | ||||||
|  |           {/* Toggle Background */} | ||||||
|  |           <div className="w-10 h-5 bg-gray-300 rounded-full peer-checked:bg-green-500 peer-focus:ring-2 peer-focus:ring-green-300 transition-colors"></div> | ||||||
|  |           {/* Toggle Handle */} | ||||||
|  |           <div className="absolute top-0.5 left-0.5 w-4 h-4 bg-white rounded-full shadow-md peer-checked:translate-x-5 transition-transform"></div> | ||||||
|  |         </label> | ||||||
|  |       </div> | ||||||
|  |       )} | ||||||
|     </div> |     </div> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ interface FileDetails { | |||||||
|   description: string; |   description: string; | ||||||
|   extension: string; |   extension: string; | ||||||
|   isOwner: boolean; // Indicates if the user owns the file
 |   isOwner: boolean; // Indicates if the user owns the file
 | ||||||
|  |   isPublic: boolean; // Indicates if the file is public
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface FileGridProps { | interface FileGridProps { | ||||||
| @ -116,7 +117,8 @@ export default function FileGrid({ session }: FileGridProps) { | |||||||
|                 fileId={file.id} |                 fileId={file.id} | ||||||
|                 fileName={file.name} |                 fileName={file.name} | ||||||
|                 fileUrl={file.url} |                 fileUrl={file.url} | ||||||
|                 isOwner={file.isOwner} |                 isOwner={true} | ||||||
|  |                 isPublic={file.isPublic} | ||||||
|               /> |               /> | ||||||
|             </div> |             </div> | ||||||
|           </div> |           </div> | ||||||
|  | |||||||
							
								
								
									
										25
									
								
								src/app/api/files/search/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/app/api/files/search/route.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | |||||||
|  | import { NextResponse } from "next/server"; | ||||||
|  | import { db } from "~/server/db"; | ||||||
|  | 
 | ||||||
|  | export async function GET(req: Request) { | ||||||
|  |   const url = new URL(req.url); | ||||||
|  |   const query = url.searchParams.get("query") || ""; | ||||||
|  | 
 | ||||||
|  |   try { | ||||||
|  |     // if query is empty, return no files
 | ||||||
|  |     const files = await db.file.findMany({ | ||||||
|  |       where: { | ||||||
|  |         OR: [ | ||||||
|  |           { name: { contains: query } }, | ||||||
|  |           { description: { contains: query } }, | ||||||
|  |         ], | ||||||
|  |         public: true, | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return NextResponse.json({ files }); | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error("Error fetching files:", error); | ||||||
|  |     return NextResponse.json({ error: "Failed to fetch files" }, { status: 500 }); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -32,6 +32,7 @@ export async function GET(req: Request) { | |||||||
|       type: file.extension, |       type: file.extension, | ||||||
|       url: file.url, |       url: file.url, | ||||||
|       description: file.description, |       description: file.description, | ||||||
|  |       isPublic: file.public, // Ensure this is included
 | ||||||
|     }); |     }); | ||||||
|   } catch (error) { |   } catch (error) { | ||||||
|     console.error("Error fetching file details:", error); |     console.error("Error fetching file details:", error); | ||||||
|  | |||||||
							
								
								
									
										22
									
								
								src/app/api/files/update-public/route.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/app/api/files/update-public/route.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | |||||||
|  | import { NextResponse } from "next/server"; | ||||||
|  | import { db } from "~/server/db"; | ||||||
|  | 
 | ||||||
|  | export async function POST(req: Request) { | ||||||
|  |   try { | ||||||
|  |     const { fileId, isPublic } = await req.json(); | ||||||
|  | 
 | ||||||
|  |     if (!fileId) { | ||||||
|  |       return NextResponse.json({ error: "File ID is required" }, { status: 400 }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     await db.file.update({ | ||||||
|  |       where: { id: fileId }, | ||||||
|  |       data: { public: isPublic }, | ||||||
|  |     }); | ||||||
|  | 
 | ||||||
|  |     return NextResponse.json({ success: true }); | ||||||
|  |   } catch (error) { | ||||||
|  |     console.error("Error updating public status:", error); | ||||||
|  |     return NextResponse.json({ error: "Failed to update public status" }, { status: 500 }); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -8,14 +8,35 @@ import { Toaster } from "react-hot-toast"; | |||||||
| export default async function Home() { | export default async function Home() { | ||||||
|   const session = await auth(); |   const session = await auth(); | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|   return ( |   return ( | ||||||
|     <HydrateClient> |     <HydrateClient> | ||||||
|       <Toaster position="top-right" reverseOrder={false} /> |       <Toaster position="top-right" reverseOrder={false} /> | ||||||
|       <main className="relative flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> |       <main className="relative flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||||
|         {/* Top-right corner sign-out button */} |         {/* Top-right corner sign-out button */} | ||||||
|         {session?.user && ( |         {session?.user && ( | ||||||
|           <div className="absolute top-4 right-4"> |           <div className="absolute top-4 right-4 flex items-center gap-4"> | ||||||
|  |             {/* Search Button */} | ||||||
|  |             <Link | ||||||
|  |               href="/search" | ||||||
|  |               className="rounded-full bg-white/10 p-2 transition hover:bg-white/20" | ||||||
|  |               aria-label="Search" | ||||||
|  |             > | ||||||
|  |               <svg | ||||||
|  |                 xmlns="http://www.w3.org/2000/svg" | ||||||
|  |                 className="h-6 w-6 text-white" | ||||||
|  |                 fill="none" | ||||||
|  |                 viewBox="0 0 24 24" | ||||||
|  |                 stroke="currentColor" | ||||||
|  |               > | ||||||
|  |                 <path | ||||||
|  |                   strokeLinecap="round" | ||||||
|  |                   strokeLinejoin="round" | ||||||
|  |                   strokeWidth={2} | ||||||
|  |                   d="M21 21l-4.35-4.35M16.65 10.65a6 6 0 11-12 0 6 6 0 0112 0z" | ||||||
|  |                 /> | ||||||
|  |               </svg> | ||||||
|  |             </Link> | ||||||
|  | 
 | ||||||
|             <Link |             <Link | ||||||
|               href="/api/auth/signout" |               href="/api/auth/signout" | ||||||
|               className="rounded-full bg-white/10 px-4 py-2 font-semibold no-underline transition hover:bg-white/20" |               className="rounded-full bg-white/10 px-4 py-2 font-semibold no-underline transition hover:bg-white/20" | ||||||
| @ -33,7 +54,7 @@ export default async function Home() { | |||||||
|           {session?.user ? ( |           {session?.user ? ( | ||||||
|             <> |             <> | ||||||
|               <FileGrid session={session} /> |               <FileGrid session={session} /> | ||||||
|               <UploadForm/> |               <UploadForm /> | ||||||
|             </> |             </> | ||||||
|           ) : ( |           ) : ( | ||||||
|             <p className="text-center text-2xl text-white"> |             <p className="text-center text-2xl text-white"> | ||||||
| @ -41,16 +62,16 @@ export default async function Home() { | |||||||
|             </p> |             </p> | ||||||
|           )} |           )} | ||||||
|           {!session?.user && ( |           {!session?.user && ( | ||||||
|           <div className="flex flex-col items-center gap-2"> |             <div className="flex flex-col items-center gap-2"> | ||||||
|             <div className="flex flex-col items-center justify-center gap-4"> |               <div className="flex flex-col items-center justify-center gap-4"> | ||||||
|               <Link |                 <Link | ||||||
|                 href={session ? "/api/auth/signout" : "/api/auth/signin"} |                   href={session ? "/api/auth/signout" : "/api/auth/signin"} | ||||||
|                 className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20" |                   className="rounded-full bg-white/10 px-10 py-3 font-semibold no-underline transition hover:bg-white/20" | ||||||
|               > |                 > | ||||||
|                 {session ? "Sign out" : "Sign in"} |                   {session ? "Sign out" : "Sign in"} | ||||||
|               </Link> |                 </Link> | ||||||
|  |               </div> | ||||||
|             </div> |             </div> | ||||||
|           </div> |  | ||||||
|           )} |           )} | ||||||
|         </div> |         </div> | ||||||
|       </main> |       </main> | ||||||
|  | |||||||
							
								
								
									
										121
									
								
								src/app/search/page.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								src/app/search/page.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | "use client"; | ||||||
|  | import { useEffect, useState } from "react"; | ||||||
|  | import { useRouter } from "next/navigation"; | ||||||
|  | import { env } from "~/env.js"; | ||||||
|  | import { FilePreview } from "~/app/_components/FilePreview"; | ||||||
|  | import { FileActionsContainer } from "~/app/_components/ActionButtons"; | ||||||
|  | import { HomeButton } from "~/app/_components/HomeButton"; | ||||||
|  | 
 | ||||||
|  | interface FileDetails { | ||||||
|  |   name: string; | ||||||
|  |   size: number; | ||||||
|  |   owner: string; | ||||||
|  |   ownerAvatar: string | null; | ||||||
|  |   uploadDate: string; | ||||||
|  |   id: string; | ||||||
|  |   isOwner: boolean; | ||||||
|  |   extension: string; | ||||||
|  |   url: string; | ||||||
|  |   description: string; | ||||||
|  |   isPublic: boolean; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default function SearchFile() { | ||||||
|  |   const [searchQuery, setSearchQuery] = useState<string>(""); | ||||||
|  |   const [files, setFiles] = useState<FileDetails[]>([]); | ||||||
|  |   const [error, setError] = useState<string | null>(null); | ||||||
|  |   const pageUrl = env.NEXT_PUBLIC_PAGE_URL; | ||||||
|  |   const router = useRouter(); | ||||||
|  | 
 | ||||||
|  |   useEffect(() => { | ||||||
|  |     const fetchFiles = async () => { | ||||||
|  |       try { | ||||||
|  |         const response = await fetch( | ||||||
|  |           `/api/files/search?query=${encodeURIComponent(searchQuery)}` | ||||||
|  |         ); | ||||||
|  |         if (!response.ok) { | ||||||
|  |           throw new Error("Failed to fetch files"); | ||||||
|  |         } | ||||||
|  |         const data = await response.json(); | ||||||
|  |         setFiles(data.files); | ||||||
|  |       } catch (err) { | ||||||
|  |         console.error(err); | ||||||
|  |         setError("Failed to load files."); | ||||||
|  |       } | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     fetchFiles(); | ||||||
|  |   }, [searchQuery]); | ||||||
|  | 
 | ||||||
|  |   return ( | ||||||
|  |     <main className="flex min-h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||||
|  |       <div className="absolute top-4 left-4 z-20"> | ||||||
|  |         <HomeButton /> | ||||||
|  |       </div> | ||||||
|  |       {/* Search Bar */} | ||||||
|  |       <div className="sticky top-0 z-10 w-full bg-[#2e026d] px-4 py-4 shadow-md"> | ||||||
|  |         <div className="relative w-full max-w-md mx-auto"> | ||||||
|  |           <input | ||||||
|  |             type="text" | ||||||
|  |             placeholder="Search files..." | ||||||
|  |             value={searchQuery} | ||||||
|  |             onChange={(e) => setSearchQuery(e.target.value)} | ||||||
|  |             className="w-full p-3 pl-12 text-white bg-[#3b0764] rounded-full shadow-md focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent placeholder-gray-400" | ||||||
|  |           /> | ||||||
|  |           <svg | ||||||
|  |             xmlns="http://www.w3.org/2000/svg" | ||||||
|  |             className="absolute left-4 top-1/2 transform -translate-y-1/2 h-6 w-6 text-gray-400" | ||||||
|  |             fill="none" | ||||||
|  |             viewBox="0 0 24 24" | ||||||
|  |             stroke="currentColor" | ||||||
|  |           > | ||||||
|  |             <path | ||||||
|  |               strokeLinecap="round" | ||||||
|  |               strokeLinejoin="round" | ||||||
|  |               strokeWidth={2} | ||||||
|  |               d="M21 21l-4.35-4.35M16.65 10.65a6 6 0 11-12 0 6 6 0 0112 0z" | ||||||
|  |             /> | ||||||
|  |           </svg> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  | 
 | ||||||
|  |       {/* File Grid */} | ||||||
|  |       <div className="flex-grow flex flex-col items-center justify-center w-full px-4"> | ||||||
|  |         {error && <div className="text-red-500">{error}</div>} | ||||||
|  |         <div className="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 w-full max-w-7xl"> | ||||||
|  |           {files.map((file) => { | ||||||
|  |             return ( | ||||||
|  |               <div | ||||||
|  |                 key={file.id} | ||||||
|  |                 className="flex place-content-end w-xxs flex-col gap-4 rounded-xl bg-white/10 p-4 hover:bg-white/20" | ||||||
|  |               > | ||||||
|  |                 <div className="self-center max-w-100 sm:max-w-50"> | ||||||
|  |                   <FilePreview fileId={file.id} fileType={file.extension} /> | ||||||
|  |                 </div> | ||||||
|  | 
 | ||||||
|  |                 <button onClick={() => router.push(pageUrl + file.url)}> | ||||||
|  |                   <h3 className="text-2xl font-bold">{file.name}</h3> | ||||||
|  |                 </button> | ||||||
|  |                 {file.description && ( | ||||||
|  |                   <p className="text-sm text-gray-400"> | ||||||
|  |                     Description: {file.description} | ||||||
|  |                   </p> | ||||||
|  |                 )} | ||||||
|  | 
 | ||||||
|  |                 <div className="flex self-center gap-2"> | ||||||
|  |                   <FileActionsContainer | ||||||
|  |                     fileId={file.id} | ||||||
|  |                     fileName={file.name} | ||||||
|  |                     fileUrl={file.url} | ||||||
|  |                     isOwner={false} // Check if the user is the owner
 | ||||||
|  |                     isPublic={file.isPublic} // Check if the file is public
 | ||||||
|  |                   /> | ||||||
|  |                 </div> | ||||||
|  |               </div> | ||||||
|  |             ); | ||||||
|  |           })} | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </main> | ||||||
|  |   ); | ||||||
|  | } | ||||||
| @ -19,6 +19,7 @@ interface FileDetails { | |||||||
|   type: string; |   type: string; | ||||||
|   url: string; |   url: string; | ||||||
|   description: string; |   description: string; | ||||||
|  |   isPublic: boolean; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export async function generateMetadata({ | export async function generateMetadata({ | ||||||
| @ -96,6 +97,7 @@ export default async function FilePreviewContainer({ | |||||||
| 
 | 
 | ||||||
|   const fileDetails = await fetchFileDetails(fileId); |   const fileDetails = await fetchFileDetails(fileId); | ||||||
|    |    | ||||||
|  | 
 | ||||||
|   if (!fileDetails) { |   if (!fileDetails) { | ||||||
|     return ( |     return ( | ||||||
|       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> |       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||||
| @ -161,13 +163,46 @@ export default async function FilePreviewContainer({ | |||||||
|               fileDescription={fileDetails.description} |               fileDescription={fileDetails.description} | ||||||
|             /> |             /> | ||||||
|           </div> |           </div> | ||||||
|           <div className="mt-4 flex justify-center"> |           <div className="bg-white/10 shadow-md rounded-lg p-6 w-full max-w-md text-white"> | ||||||
|             <FileActionsContainer |             <p> | ||||||
|               fileId={fileDetails.id} |               <strong>Name:</strong> {fileDetails.name} | ||||||
|               fileName={fileDetails.name} |             </p> | ||||||
|               fileUrl={fileDetails.url} |             <p> | ||||||
|               isOwner={fileDetails.isOwner} |               <strong>Size:</strong>{" "} | ||||||
|             /> |               {fileDetails.size > 1024 * 1024 * 1024 | ||||||
|  |                 ? (fileDetails.size / (1024 * 1024 * 1024)).toFixed(2) + " GB" | ||||||
|  |                 : fileDetails.size > 1024 * 1024 | ||||||
|  |                 ? (fileDetails.size / (1024 * 1024)).toFixed(2) + " MB" | ||||||
|  |                 : fileDetails.size > 1024 | ||||||
|  |                 ? (fileDetails.size / 1024).toFixed(2) + " KB" | ||||||
|  |                 : fileDetails.size + " Bytes"} | ||||||
|  |             </p> | ||||||
|  |             <p> | ||||||
|  |               <strong>Owner:</strong>{" "} | ||||||
|  |               <img | ||||||
|  |                 className="rounded-md inline size-5" | ||||||
|  |                 src={fileDetails.ownerAvatar || ""} | ||||||
|  |                 alt="Owner avatar" | ||||||
|  |               />{" "} | ||||||
|  |               {fileDetails.owner} | ||||||
|  |             </p> | ||||||
|  |             <p> | ||||||
|  |               <strong>Upload Date:</strong>{" "} | ||||||
|  |               {new Date(fileDetails.uploadDate).toLocaleString()} | ||||||
|  |             </p> | ||||||
|  |             <div> | ||||||
|  |               <strong>Description:</strong>{" "} | ||||||
|  |               <FileDescriptionContainer fileId={fileDetails.id} fileDescription={fileDetails.description}/> | ||||||
|  |             </div> | ||||||
|  |             <div className="mt-4 flex justify-center"> | ||||||
|  |               <FileActionsContainer | ||||||
|  |                 fileId={fileDetails.id} | ||||||
|  |                 fileName={fileDetails.name} | ||||||
|  |                 fileUrl={fileDetails.url} | ||||||
|  |                 isOwner={fileDetails.isOwner} | ||||||
|  |                 isPublic={fileDetails.isPublic} | ||||||
|  |               /> | ||||||
|  |             </div> | ||||||
|           </div> |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|  | |||||||
| @ -1,6 +0,0 @@ | |||||||
| module.exports = { |  | ||||||
|   content: [ |  | ||||||
|     "./src/**/*.{js,ts,jsx,tsx}", // Ensure your paths are correct
 |  | ||||||
|   ], |  | ||||||
|   plugins: [require("@tailwindcss/typography")], |  | ||||||
| }; |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user