feat: implement metadata generation for file details and improve error handling
This commit is contained in:
		
							parent
							
								
									011695cf46
								
							
						
					
					
						commit
						6115851147
					
				| @ -2,8 +2,12 @@ import { notFound } from "next/navigation"; | ||||
| import { FilePreview } from "~/app/_components/FilePreview"; | ||||
| import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
 | ||||
| import { Toaster } from "react-hot-toast"; | ||||
| import { FileActionsContainer, FileDescriptionContainer } from "~/app/_components/ActionButtons"; // Import the client component
 | ||||
| import { | ||||
|   FileActionsContainer, | ||||
|   FileDescriptionContainer, | ||||
| } from "~/app/_components/ActionButtons"; // Import the client component
 | ||||
| import Head from "next/head"; | ||||
| import type { Metadata } from "next"; | ||||
| 
 | ||||
| interface FileDetails { | ||||
|   name: string; | ||||
| @ -18,6 +22,46 @@ interface FileDetails { | ||||
|   description: string; | ||||
| } | ||||
| 
 | ||||
| export async function generateMetadata({ | ||||
|   searchParams, | ||||
| }: { | ||||
|   searchParams: { id?: string }; | ||||
| }): Promise<Metadata> { | ||||
|   const fileId = searchParams.id; | ||||
| 
 | ||||
|   if (!fileId) { | ||||
|     return { | ||||
|       title: "File Not Found", | ||||
|       description: "The file you are looking for does not exist.", | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   const fileDetails = await fetchFileDetails(fileId); | ||||
| 
 | ||||
|   if (!fileDetails) { | ||||
|     return { | ||||
|       title: "File Not Found", | ||||
|       description: "The file you are looking for does not exist.", | ||||
|     }; | ||||
|   } | ||||
| 
 | ||||
|   return { | ||||
|     title: fileDetails.name, | ||||
|     description: fileDetails.description || fileDetails.name, | ||||
|     openGraph: { | ||||
|       title: fileDetails.name, | ||||
|       description: fileDetails.description || fileDetails.name, | ||||
|       url: `${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileDetails.id}`, | ||||
|       images: [ | ||||
|         { | ||||
|           url: `${process.env.NEXT_PUBLIC_PAGE_URL}/api/files/serv?id=${fileDetails.id}`, | ||||
|           alt: `${fileDetails.name} preview`, | ||||
|         }, | ||||
|       ], | ||||
|     }, | ||||
|   }; | ||||
| } | ||||
| 
 | ||||
| async function fetchFileDetails(fileId: string): Promise<FileDetails | null> { | ||||
|   try { | ||||
|     const response = await fetch( | ||||
| @ -41,10 +85,9 @@ async function fetchFileDetails(fileId: string): Promise<FileDetails | null> { | ||||
| export default async function FilePreviewContainer({ | ||||
|   searchParams, | ||||
| }: { | ||||
|   searchParams: Promise<{ id?: string }>; | ||||
|   searchParams: { id?: string }; | ||||
| }) { | ||||
|   const resolvedSearchParams = await searchParams; // Resolve the promise
 | ||||
|   const fileId = resolvedSearchParams.id; | ||||
|   const fileId = searchParams.id; | ||||
| 
 | ||||
|   if (!fileId) { | ||||
|     notFound(); | ||||
| @ -54,130 +97,79 @@ export default async function FilePreviewContainer({ | ||||
| 
 | ||||
|   if (!fileDetails) { | ||||
|     return ( | ||||
|       <> | ||||
|         <Head> | ||||
|           <title>No File Found</title> | ||||
|           <meta property="og:title" content="No File Found" /> | ||||
|           <meta | ||||
|             property="og:description" | ||||
|             content="The file you are looking for does not exist." | ||||
|           /> | ||||
|           <meta property="og:type" content="website" /> | ||||
|           <meta property="og:image" content="/images/no-file.png" /> | ||||
|           <meta property="og:image:alt" content="No file found" /> | ||||
|           <meta | ||||
|             property="og:url" | ||||
|             content={`${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileId}`} | ||||
|           /> | ||||
|         </Head> | ||||
|         <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||
|           <Toaster position="top-right" reverseOrder={false} /> | ||||
|           <div className="absolute top-4 left-4"> | ||||
|             <HomeButton /> | ||||
|           </div> | ||||
|           <div className="container flex flex-col items-center gap-12 px-4 py-16"> | ||||
|             <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]"> | ||||
|               <span className="text-[hsl(280,100%,70%)]">No</span> File Found | ||||
|             </h1> | ||||
|           </div> | ||||
|         </main> | ||||
|       </> | ||||
|       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||
|         <Toaster position="top-right" reverseOrder={false} /> | ||||
|         <div className="absolute top-4 left-4"> | ||||
|           <HomeButton /> | ||||
|         </div> | ||||
|         <div className="container flex flex-col items-center gap-12 px-4 py-16"> | ||||
|           <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]"> | ||||
|             <span className="text-[hsl(280,100%,70%)]">No</span> File Found | ||||
|           </h1> | ||||
|         </div> | ||||
|       </main> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <> | ||||
|       <Head> | ||||
|         <title>{fileDetails.name} - File Details</title> | ||||
|         <meta | ||||
|           property="og:title" | ||||
|           content={`${fileDetails.name} - File Details`} | ||||
|         /> | ||||
|         <meta | ||||
|           property="og:description" | ||||
|           content={`Size: ${ | ||||
|             fileDetails.size > 1024 * 1024 * 1024 | ||||
|     <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||
|       <div className="absolute top-4 left-4"> | ||||
|         <HomeButton /> | ||||
|       </div> | ||||
|       <Toaster position="top-right" reverseOrder={false} /> | ||||
|       <div className="container flex flex-col items-center gap-12 px-4 py-16"> | ||||
|         <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]"> | ||||
|           <span className="text-[hsl(280,100%,70%)]">File</span> Details | ||||
|         </h1> | ||||
|         <div className="mt-6"> | ||||
|           {fileDetails.type !== "unknown" && ( | ||||
|             <FilePreview fileId={fileDetails.id} fileType={fileDetails.type} /> | ||||
|           )} | ||||
|         </div> | ||||
|         <div className="w-full max-w-md rounded-lg bg-white/10 p-6 text-white shadow-md"> | ||||
|           <p> | ||||
|             <strong>Name:</strong> {fileDetails.name} | ||||
|           </p> | ||||
|           <p> | ||||
|             <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" | ||||
|           }, Owner: ${fileDetails.owner}, Uploaded on: ${new Date( | ||||
|             fileDetails.uploadDate | ||||
|           ).toLocaleString()}`}
 | ||||
|         /> | ||||
|         <meta property="og:type" content="website" /> | ||||
|         <meta | ||||
|           property="og:image" | ||||
|           content={`${process.env.NEXT_PUBLIC_PAGE_URL}/api/files/serv?id=${fileId}`} | ||||
|         /> | ||||
|         <meta property="og:image:alt" content={`${fileDetails.name} preview`} /> | ||||
|         <meta | ||||
|           property="og:url" | ||||
|           content={`${process.env.NEXT_PUBLIC_PAGE_URL}/share?id=${fileId}`} | ||||
|         /> | ||||
|       </Head> | ||||
|       <main className="flex min-h-screen flex-col items-center justify-center bg-gradient-to-b from-[#2e026d] to-[#15162c] text-white"> | ||||
|         <div className="absolute top-4 left-4"> | ||||
|           <HomeButton /> | ||||
|         </div> | ||||
|         <Toaster position="top-right" reverseOrder={false} /> | ||||
|         <div className="container flex flex-col items-center gap-12 px-4 py-16"> | ||||
|           <h1 className="text-5xl font-extrabold tracking-tight sm:text-[5rem]"> | ||||
|             <span className="text-[hsl(280,100%,70%)]">File</span> Details | ||||
|           </h1> | ||||
|           <div className="mt-6"> | ||||
|             {fileDetails.type !== "unknown" && ( | ||||
|               <FilePreview | ||||
|                 fileId={fileDetails.id} | ||||
|                 fileType={fileDetails.type} | ||||
|               /> | ||||
|             )} | ||||
|           </div> | ||||
|           <div className="bg-white/10 shadow-md rounded-lg p-6 w-full max-w-md text-white"> | ||||
|             <p> | ||||
|               <strong>Name:</strong> {fileDetails.name} | ||||
|             </p> | ||||
|             <p> | ||||
|               <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} | ||||
|               /> | ||||
|             </div> | ||||
|                   ? (fileDetails.size / 1024).toFixed(2) + " KB" | ||||
|                   : fileDetails.size + " Bytes"} | ||||
|           </p> | ||||
|           <p> | ||||
|             <strong>Owner:</strong>{" "} | ||||
|             <img | ||||
|               className="inline size-5 rounded-md" | ||||
|               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} | ||||
|             /> | ||||
|           </div> | ||||
|         </div> | ||||
|       </main> | ||||
|     </> | ||||
|       </div> | ||||
|     </main> | ||||
|   ); | ||||
| } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user