feat: add loading skeleton components for improved user experience during data fetching
This commit is contained in:
		
							parent
							
								
									60925ee6ac
								
							
						
					
					
						commit
						b14acab08f
					
				
							
								
								
									
										21
									
								
								src/app/LoadingSkeleton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/app/LoadingSkeleton.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,21 @@ | |||||||
|  | import React from 'react'; | ||||||
|  | 
 | ||||||
|  | const LoadingSkeleton = () => ( | ||||||
|  |   <div className="container flex flex-col items-center justify-center gap-12 px-4 py-16 animate-pulse"> | ||||||
|  |     {/* Title Skeleton */} | ||||||
|  |     <div className="h-16 w-80 rounded bg-white/20 mb-4" /> | ||||||
|  |     {/* FileGrid Skeleton */} | ||||||
|  |     <div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 w-full max-w-4xl"> | ||||||
|  |       {[...Array(6)].map((_, i) => ( | ||||||
|  |         <div key={i} className="h-32 rounded bg-white/10" /> | ||||||
|  |       ))} | ||||||
|  |     </div> | ||||||
|  |     {/* UploadForm Skeleton */} | ||||||
|  |     <div className="mt-8 w-full max-w-md flex flex-col gap-4"> | ||||||
|  |       <div className="h-10 rounded bg-white/20" /> | ||||||
|  |       <div className="h-10 rounded bg-white/10" /> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | export default LoadingSkeleton; | ||||||
							
								
								
									
										6
									
								
								src/app/loading.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/app/loading.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | import LoadingSkeleton from './LoadingSkeleton'; | ||||||
|  | 
 | ||||||
|  | export default function Loading() { | ||||||
|  |   // You can add any UI inside Loading, including a Skeleton.
 | ||||||
|  |   return <LoadingSkeleton /> | ||||||
|  | } | ||||||
| @ -4,6 +4,7 @@ import { HydrateClient } from "~/trpc/server"; | |||||||
| import FileGrid from "~/app/_components/FileGrid"; | import FileGrid from "~/app/_components/FileGrid"; | ||||||
| import UploadForm from "~/app/_components/UploadForm"; | import UploadForm from "~/app/_components/UploadForm"; | ||||||
| import { Toaster } from "react-hot-toast"; | import { Toaster } from "react-hot-toast"; | ||||||
|  | import { Suspense } from "react"; | ||||||
| 
 | 
 | ||||||
| export default async function Home() { | export default async function Home() { | ||||||
|   const session = await auth(); |   const session = await auth(); | ||||||
| @ -53,7 +54,9 @@ export default async function Home() { | |||||||
|           {/* Conditionally render FileGrid and UploadForm if the user is logged in */} |           {/* Conditionally render FileGrid and UploadForm if the user is logged in */} | ||||||
|           {session?.user ? ( |           {session?.user ? ( | ||||||
|             <> |             <> | ||||||
|               <FileGrid session={session} /> |               <Suspense fallback={<p className="text-center text-2xl text-white">Loading...</p>}> | ||||||
|  |                 <FileGrid session={session} /> | ||||||
|  |               </Suspense> | ||||||
|               <UploadForm /> |               <UploadForm /> | ||||||
|             </> |             </> | ||||||
|           ) : ( |           ) : ( | ||||||
|  | |||||||
							
								
								
									
										51
									
								
								src/app/share/LoadingSkeleton.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/app/share/LoadingSkeleton.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | |||||||
|  | import React, { Suspense } from "react"; | ||||||
|  | import { HomeButton } from "~/app/_components/HomeButton"; // Import the client component
 | ||||||
|  | import { Toaster } from "react-hot-toast"; | ||||||
|  | import { | ||||||
|  |   FileActionsContainer, | ||||||
|  | } from "~/app/_components/ActionButtons"; // Import the client component
 | ||||||
|  | 
 | ||||||
|  | const LoadingSkeleton: React.FC = () => ( | ||||||
|  |     <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"> | ||||||
|  |           {" Loading..."} | ||||||
|  |         </div> | ||||||
|  |         <div className="w-full max-w-md rounded-lg bg-white/10 p-6 text-white shadow-md"> | ||||||
|  |           <p> | ||||||
|  |             <strong>Name:</strong>{" Loading..."} | ||||||
|  |           </p> | ||||||
|  |           <p> | ||||||
|  |             <strong>Size:</strong>{" Loading..."} | ||||||
|  |           </p> | ||||||
|  |           <p> | ||||||
|  |             <strong>Owner:</strong>{" Loading..."} | ||||||
|  |           </p> | ||||||
|  |           <p> | ||||||
|  |             <strong>Upload Date:</strong>{" Loading..."} | ||||||
|  |           </p> | ||||||
|  |           <div> | ||||||
|  |             <strong>Description:</strong>{" Loading..."} | ||||||
|  |           </div> | ||||||
|  |           <div className="mt-4 flex justify-center"> | ||||||
|  |             <FileActionsContainer | ||||||
|  |               fileId={""} | ||||||
|  |               fileName={""} | ||||||
|  |               fileUrl={""} | ||||||
|  |               isOwner={false} | ||||||
|  |               isPublic={false} | ||||||
|  |             /> | ||||||
|  |           </div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |     </main> | ||||||
|  | ); | ||||||
|  | 
 | ||||||
|  | export default LoadingSkeleton; | ||||||
							
								
								
									
										6
									
								
								src/app/share/loading.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/app/share/loading.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | |||||||
|  | import LoadingSkeleton from './LoadingSkeleton'; | ||||||
|  | 
 | ||||||
|  | export default function Loading() { | ||||||
|  |   // You can add any UI inside Loading, including a Skeleton.
 | ||||||
|  |   return <LoadingSkeleton /> | ||||||
|  | } | ||||||
							
								
								
									
										0
									
								
								src/server/api/routers/file.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								src/server/api/routers/file.ts
									
									
									
									
									
										Normal file
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user