Bläddra i källkod

refactor: improve App.jsx code structure and readability

Adam Jafarov 1 månad sedan
förälder
incheckning
9398dae542
1 ändrade filer med 112 tillägg och 84 borttagningar
  1. 112 84
      src/App.jsx

+ 112 - 84
src/App.jsx

@@ -114,6 +114,50 @@ function NavHeader() {
     );
 }
 
+// Layout ComponentWrapper
+const Layout = ({ children }) => (
+    <div className="min-h-screen theme-bg font-sans theme-text antialiased flex flex-col">
+        <div className="max-w-5xl mx-auto w-full flex-grow">
+            <NavHeader />
+            <main className="py-10 px-4 sm:px-6 lg:px-8">
+                {children}
+            </main>
+        </div>
+    </div>
+);
+
+// Skeleton Components
+const SkeletonCard = () => (
+    <div className="theme-surface border theme-border rounded-xl p-6 flex flex-col h-full animate-pulse">
+        <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded w-3/4 mb-4"></div>
+        <div className="space-y-2 flex-grow">
+            <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-full"></div>
+            <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-5/6"></div>
+        </div>
+        <div className="mt-4 h-4 bg-gray-200 dark:bg-gray-700 rounded w-1/4"></div>
+    </div>
+);
+
+const SkeletonPost = () => (
+    <div className="w-full animate-pulse">
+        <div className="theme-surface border theme-border rounded-xl p-8 md:p-12 lg:p-16">
+            <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-32 mb-6"></div>
+            <div className="mb-8">
+                <div className="h-10 bg-gray-200 dark:bg-gray-700 rounded w-3/4 mb-4"></div>
+                <div className="h-6 bg-gray-200 dark:bg-gray-700 rounded w-1/2"></div>
+            </div>
+            <hr className="theme-border mb-8" />
+            <div className="space-y-4">
+                <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-full"></div>
+                <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-full"></div>
+                <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-5/6"></div>
+                <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-full"></div>
+                <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-4/5"></div>
+            </div>
+        </div>
+    </div>
+);
+
 // Blog Home Component
 function BlogHome() {
     const [posts, setPosts] = useState([]);
@@ -145,70 +189,63 @@ function BlogHome() {
 
     if (loading) {
         return (
-            <div className="min-h-screen theme-bg flex items-center justify-center">
-                <div className="text-center">
-                    <div className="animate-spin rounded-full h-12 w-12 border-b-2 theme-primary mx-auto"></div>
-                    <p className="mt-4 theme-text-secondary">
-                        Loading posts...
-                    </p>
+            <Layout>
+                <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
+                    {[1, 2, 3, 4, 5, 6].map((i) => (
+                        <SkeletonCard key={i} />
+                    ))}
                 </div>
-            </div>
+            </Layout>
         );
     }
 
     if (error) {
         return (
-            <div className="min-h-screen theme-bg flex items-center justify-center">
+            <Layout>
                 <div className="text-center">
-                    <div className="bg-red-50 border border-red-200 rounded-lg p-6">
+                    <div className="bg-red-50 border border-red-200 rounded-lg p-6 inline-block">
                         <h2 className="text-red-800 font-semibold mb-2">
                             Error
                         </h2>
                         <p className="text-red-600">{error}</p>
                     </div>
                 </div>
-            </div>
+            </Layout>
         );
     }
 
     return (
-        <div className="min-h-screen theme-bg font-sans theme-text antialiased flex flex-col">
-            <div className="max-w-5xl mx-auto w-full flex-grow">
-                <NavHeader />
-
-                <main className="py-10 px-4 sm:px-6 lg:px-8">
-                    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
-                        {posts.map((post) => (
-                            <div
-                                key={post.slug}
-                                className="group cursor-pointer theme-surface border theme-border rounded-xl hover:border-blue-400 transition-colors duration-200 p-6 flex flex-col justify-between h-full"
-                            >
-                                <div>
-                                    <h2 className="text-xl font-semibold theme-text group-hover:theme-primary transition-colors duration-200 mb-2">
-                                        <Link to={`/posts/${post.slug}`}>
-                                            {post.title}
-                                        </Link>
-                                    </h2>
-                                </div>
-                                <div className="flex-grow mt-4">
-                                    <div className="theme-text-secondary leading-relaxed">
-                                        {post.description}
-                                    </div>
-                                </div>
-                                <div className="mt-4">
-                                    <Link
-                                        to={`/posts/${post.slug}`}
-                                        className="theme-primary font-medium hover:underline focus:outline-none"
-                                    >
-                                        Read more →
-                                    </Link>
-                                </div>
+        <Layout>
+            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
+                {posts.map((post) => (
+                    <div
+                        key={post.slug}
+                        className="group cursor-pointer theme-surface border theme-border rounded-xl hover:border-blue-400 transition-colors duration-200 p-6 flex flex-col justify-between h-full"
+                    >
+                        <div>
+                            <h2 className="text-xl font-semibold theme-text group-hover:theme-primary transition-colors duration-200 mb-2">
+                                <Link to={`/posts/${post.slug}`}>
+                                    {post.title}
+                                </Link>
+                            </h2>
+                        </div>
+                        <div className="flex-grow mt-4">
+                            <div className="theme-text-secondary leading-relaxed">
+                                {post.description}
                             </div>
-                        ))}
+                        </div>
+                        <div className="mt-4">
+                            <Link
+                                to={`/posts/${post.slug}`}
+                                className="theme-primary font-medium hover:underline focus:outline-none"
+                            >
+                                Read more →
+                            </Link>
+                        </div>
                     </div>
-                </main>
+                ))}
             </div>
-        </div>
+        </Layout>
     );
 }
 
@@ -438,18 +475,15 @@ function PostView({ onImageClick }) {
 
     if (loading) {
         return (
-            <div className="min-h-screen theme-bg flex items-center justify-center">
-                <div className="text-center">
-                    <div className="animate-spin rounded-full h-12 w-12 border-b-2 theme-primary mx-auto"></div>
-                    <p className="mt-4 theme-text-secondary">Loading post...</p>
-                </div>
-            </div>
+            <Layout>
+                <SkeletonPost />
+            </Layout>
         );
     }
 
     if (error || !post) {
         return (
-            <div className="min-h-screen theme-bg flex items-center justify-center">
+            <Layout>
                 <div className="text-center">
                     <h2 className="text-2xl font-bold theme-text mb-2">
                         Post Not Found
@@ -464,7 +498,7 @@ function PostView({ onImageClick }) {
                         ← Back to Home
                     </Link>
                 </div>
-            </div>
+            </Layout>
         );
     }
 
@@ -519,42 +553,36 @@ function PostView({ onImageClick }) {
     });
 
     return (
-        <div className="min-h-screen theme-bg font-sans theme-text antialiased flex flex-col">
-            <div className="max-w-5xl mx-auto w-full flex-grow">
-                <NavHeader />
-
-                <main className="py-10 px-4 sm:px-6 lg:px-8">
-                    <div className="w-full">
-                        <div className="theme-surface theme-text border theme-border rounded-xl p-8 md:p-12 lg:p-16">
-                            <Link
-                                to="/"
-                                className="theme-text-secondary hover:theme-text transition-colors duration-200 mb-6 flex items-center"
-                            >
-                                ← Back to Home
-                            </Link>
-
-                            <div className="mb-8">
-                                <h1 className="text-3xl md:text-4xl font-bold theme-text mb-2 leading-tight">
-                                    {post.title}
-                                </h1>
-                                <div className="text-lg italic font-light theme-text-secondary">
-                                    {post.description}
-                                </div>
-                            </div>
-
-                            <hr className="theme-border mb-8" />
+        <Layout>
+            <div className="w-full">
+                <div className="theme-surface theme-text border theme-border rounded-xl p-8 md:p-12 lg:p-16">
+                    <Link
+                        to="/"
+                        className="theme-text-secondary hover:theme-text transition-colors duration-200 mb-6 flex items-center"
+                    >
+                        ← Back to Home
+                    </Link>
 
-                            <div
-                                className="markdown-content theme-text leading-relaxed text-lg"
-                                dangerouslySetInnerHTML={{
-                                    __html: sanitizedHtml,
-                                }}
-                            />
+                    <div className="mb-8">
+                        <h1 className="text-3xl md:text-4xl font-bold theme-text mb-2 leading-tight">
+                            {post.title}
+                        </h1>
+                        <div className="text-lg italic font-light theme-text-secondary">
+                            {post.description}
                         </div>
                     </div>
-                </main>
+
+                    <hr className="theme-border mb-8" />
+
+                    <div
+                        className="markdown-content theme-text leading-relaxed text-lg"
+                        dangerouslySetInnerHTML={{
+                            __html: sanitizedHtml,
+                        }}
+                    />
+                </div>
             </div>
-        </div>
+        </Layout>
     );
 }