Răsfoiți Sursa

feat(ui): add dark mode support and modern styling across all pages

- Implement gradient backgrounds and dark mode color schemes
- Add responsive container layouts with consistent spacing
- Update typography with dark mode text colors
- Enhance card components with dark mode variants
- Add dark mode support for tables, buttons, and form elements
- Update CSS variables for comprehensive dark mode styling
- Apply consistent styling to API docs, files, imports, and layout pages
vidane 6 luni în urmă
părinte
comite
f4ccc390d4
5 a modificat fișierele cu 196 adăugiri și 192 ștergeri
  1. 13 12
      app/api-docs/page.tsx
  2. 12 12
      app/files/page.tsx
  3. 41 54
      app/globals.css
  4. 104 93
      app/imports/page.tsx
  5. 26 21
      app/layout-configurations/page.tsx

+ 13 - 12
app/api-docs/page.tsx

@@ -44,23 +44,24 @@ const openApiSpec = {
 
 export default function ApiDocs() {
   return (
-    <div className="min-h-screen bg-gray-50">
-      <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
-        <div className="bg-white shadow rounded-lg">
+    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
+      <div className="container mx-auto px-4 py-8">
+        <div className="mb-8">
+          <h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">
+            Vtorio API Documentation
+          </h1>
+          <p className="text-gray-600 dark:text-gray-300">
+            Interactive API documentation for file upload and management endpoints.
+          </p>
+        </div>
+        <div className="bg-white dark:bg-gray-800 shadow rounded-lg border dark:border-gray-700">
           <div className="px-4 py-5 sm:p-6">
-            <div className="mb-4">
-              <h1 className="text-2xl font-bold text-gray-900">
-                Vtorio API Documentation
-              </h1>
-              <p className="text-gray-600 mt-2">
-                Interactive API documentation for file upload and management endpoints.
-              </p>
-            </div>
             <ApiReferenceReact
               configuration={{
                 content: openApiSpec,
                 theme: 'default',
-                layout: 'modern'
+                layout: 'modern',
+                darkMode: true,
               }}
             />
           </div>

+ 12 - 12
app/files/page.tsx

@@ -2,21 +2,21 @@ import { FilesTable } from "../components/filesTable";
 
 export default function FilesPage() {
   return (
-    <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
-      <main className="flex flex-col gap-8 row-start-2 items-center sm:items-start">
-        
-        <h1 className="text-3xl font-bold text-center sm:text-left">
-          File Management
-        </h1>
-        
-        <p className="text-sm text-center sm:text-left max-w-[600px]">
-          Upload and manage your media files here. Use the upload button in the table header to add new files.
-        </p>
+    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
+      <div className="container mx-auto px-4 py-8">
+        <div className="mb-8">
+          <h1 className="text-3xl font-bold text-gray-900 dark:text-white mb-2">
+            File Management
+          </h1>
+          <p className="text-gray-600 dark:text-gray-300">
+            Upload and manage your media files here. Use the upload button in the table header to add new files.
+          </p>
+        </div>
 
-        <div className="w-full max-w-6xl">
+        <div className="w-full">
           <FilesTable />
         </div>
-      </main>
+      </div>
     </div>
   );
 }

+ 41 - 54
app/globals.css

@@ -2,120 +2,107 @@
 @tailwind components;
 @tailwind utilities;
 
-
-
 @layer base {
   :root {
-
     --background: 0 0% 100%;
-
     --foreground: 222.2 84% 4.9%;
-
     --card: 0 0% 100%;
-
     --card-foreground: 222.2 84% 4.9%;
-
     --popover: 0 0% 100%;
-
     --popover-foreground: 222.2 84% 4.9%;
-
     --primary: 222.2 47.4% 11.2%;
-
     --primary-foreground: 210 40% 98%;
-
     --secondary: 210 40% 96.1%;
-
     --secondary-foreground: 222.2 47.4% 11.2%;
-
     --muted: 210 40% 96.1%;
-
     --muted-foreground: 215.4 16.3% 46.9%;
-
     --accent: 210 40% 96.1%;
-
     --accent-foreground: 222.2 47.4% 11.2%;
-
     --destructive: 0 84.2% 60.2%;
-
     --destructive-foreground: 210 40% 98%;
-
     --border: 214.3 31.8% 91.4%;
-
     --input: 214.3 31.8% 91.4%;
-
     --ring: 222.2 84% 4.9%;
-
     --chart-1: 12 76% 61%;
-
     --chart-2: 173 58% 39%;
-
     --chart-3: 197 37% 24%;
-
     --chart-4: 43 74% 66%;
-
     --chart-5: 27 87% 67%;
-
     --radius: 0.5rem
   }
-  .dark {
 
+  .dark {
     --background: 222.2 84% 4.9%;
-
     --foreground: 210 40% 98%;
-
     --card: 222.2 84% 4.9%;
-
     --card-foreground: 210 40% 98%;
-
     --popover: 222.2 84% 4.9%;
-
     --popover-foreground: 210 40% 98%;
-
     --primary: 210 40% 98%;
-
     --primary-foreground: 222.2 47.4% 11.2%;
-
     --secondary: 217.2 32.6% 17.5%;
-
     --secondary-foreground: 210 40% 98%;
-
     --muted: 217.2 32.6% 17.5%;
-
     --muted-foreground: 215 20.2% 65.1%;
-
     --accent: 217.2 32.6% 17.5%;
-
     --accent-foreground: 210 40% 98%;
-
     --destructive: 0 62.8% 30.6%;
-
     --destructive-foreground: 210 40% 98%;
-
     --border: 217.2 32.6% 17.5%;
-
     --input: 217.2 32.6% 17.5%;
-
     --ring: 212.7 26.8% 83.9%;
-
     --chart-1: 220 70% 50%;
-
     --chart-2: 160 60% 45%;
-
     --chart-3: 30 80% 55%;
-
     --chart-4: 280 65% 60%;
-
-    --chart-5: 340 75% 55%
+    --chart-5: 340 75% 55%;
   }
 }
 
-
-
 @layer base {
   * {
     @apply border-border;
   }
+
   body {
     @apply bg-background text-foreground;
   }
 }
+
+/* Custom dark mode styles to match dashboard */
+.dark {
+  @apply bg-gradient-to-br from-gray-900 to-gray-800;
+}
+
+/* Ensure consistent dark mode backgrounds */
+.dark .bg-white {
+  @apply bg-gray-800;
+}
+
+.dark .bg-gray-50 {
+  @apply bg-gray-900;
+}
+
+.dark .bg-gray-100 {
+  @apply bg-gray-800;
+}
+
+.dark .border-gray-200 {
+  @apply border-gray-700;
+}
+
+.dark .text-gray-900 {
+  @apply text-white;
+}
+
+.dark .text-gray-700 {
+  @apply text-gray-300;
+}
+
+.dark .text-gray-600 {
+  @apply text-gray-400;
+}
+
+.dark .text-gray-500 {
+  @apply text-gray-400;
+}

+ 104 - 93
app/imports/page.tsx

@@ -123,109 +123,120 @@ export default function ImportsPage() {
 
   if (loading) {
     return (
-      <div className="container mx-auto py-8">
-        <div className="flex justify-center">
-          <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
+      <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
+        <div className="container mx-auto px-4 py-8">
+          <div className="flex justify-center">
+            <div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary"></div>
+          </div>
         </div>
       </div>
     );
   }
 
   return (
-    <div className="container mx-auto py-8">
-      <div className="flex justify-between items-center mb-6">
-        <div>
-          <h1 className="text-3xl font-bold">Import Management</h1>
-          <p className="text-muted-foreground">Manage your data imports and configurations</p>
+    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
+      <div className="container mx-auto px-4 py-8">
+        <div className="flex justify-between items-center mb-8">
+          <div>
+            <h1 className="text-3xl font-bold text-gray-900 dark:text-white">
+              Import Management
+            </h1>
+            <p className="text-gray-600 dark:text-gray-300">
+              Manage your data imports and configurations
+            </p>
+          </div>
+          <Button onClick={() => setCreateDialogOpen(true)}>
+            <Plus className="mr-2 h-4 w-4" />
+            Create Import
+          </Button>
         </div>
-        <Button onClick={() => setCreateDialogOpen(true)}>
-          <Plus className="mr-2 h-4 w-4" />
-          Create Import
-        </Button>
-      </div>
 
-      {imports.length === 0 ? (
-        <Card>
-          <CardContent className="flex flex-col items-center justify-center py-12">
-            <FileText className="h-12 w-12 text-muted-foreground mb-4" />
-            <h3 className="text-lg font-semibold mb-2">No imports yet</h3>
-            <p className="text-muted-foreground mb-4">
-              Get started by creating your first import
-            </p>
-            <Button onClick={() => setCreateDialogOpen(true)}>
-              <Plus className="mr-2 h-4 w-4" />
-              Create Import
-            </Button>
-          </CardContent>
-        </Card>
-      ) : (
-        <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
-          {imports.map((importRecord) => (
-            <Card key={importRecord.id} className="hover:shadow-lg transition-shadow">
-              <CardHeader>
-                <div className="flex justify-between items-start">
-                  <div>
-                    <CardTitle className="text-lg">{importRecord.name}</CardTitle>
-                    <CardDescription>
-                      Layout: {importRecord.layout.name}
-                    </CardDescription>
+        {imports.length === 0 ? (
+          <Card className="dark:bg-gray-800 dark:border-gray-700">
+            <CardContent className="flex flex-col items-center justify-center py-12">
+              <FileText className="h-12 w-12 text-muted-foreground mb-4" />
+              <h3 className="text-lg font-semibold mb-2 text-gray-900 dark:text-white">No imports yet</h3>
+              <p className="text-muted-foreground mb-4 dark:text-gray-300">
+                Get started by creating your first import
+              </p>
+              <Button onClick={() => setCreateDialogOpen(true)}>
+                <Plus className="mr-2 h-4 w-4" />
+                Create Import
+              </Button>
+            </CardContent>
+          </Card>
+        ) : (
+          <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
+            {imports.map((importRecord) => (
+              <Card key={importRecord.id} className="hover:shadow-lg transition-shadow dark:bg-gray-800 dark:border-gray-700">
+                <CardHeader>
+                  <div className="flex justify-between items-start">
+                    <div>
+                      <CardTitle className="text-lg text-gray-900 dark:text-white">{importRecord.name}</CardTitle>
+                      <CardDescription className="dark:text-gray-300">
+                        Layout: {importRecord.layout.name}
+                      </CardDescription>
+                    </div>
+                    <Badge variant="outline" className="dark:border-gray-600 dark:text-gray-300">
+                      <Calendar className="mr-1 h-3 w-3" />
+                      {format(new Date(importRecord.importDate), 'MMM d, yyyy')}
+                    </Badge>
                   </div>
-                  <Badge variant="outline">
-                    <Calendar className="mr-1 h-3 w-3" />
-                    {format(new Date(importRecord.importDate), 'MMM d, yyyy')}
-                  </Badge>
-                </div>
-              </CardHeader>
-              <CardContent>
-                <div className="flex justify-between items-center">
-                  <div className="flex gap-2">
-                    <Button
-                      variant="ghost"
-                      size="sm"
-                      onClick={() => handleViewImport(importRecord)}
-                    >
-                      <FileText className="h-4 w-4" />
-                    </Button>
-                    <Button
-                      variant="ghost"
-                      size="sm"
-                      onClick={() => handleEditImport(importRecord)}
-                    >
-                      <Edit className="h-4 w-4" />
-                    </Button>
-                    <Button
-                      variant="ghost"
-                      size="sm"
-                      onClick={() => handleDeleteImport(importRecord.id)}
-                    >
-                      <Trash2 className="h-4 w-4" />
-                    </Button>
+                </CardHeader>
+                <CardContent>
+                  <div className="flex justify-between items-center">
+                    <div className="flex gap-2">
+                      <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => handleViewImport(importRecord)}
+                        className="dark:hover:bg-gray-700"
+                      >
+                        <FileText className="h-4 w-4" />
+                      </Button>
+                      <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => handleEditImport(importRecord)}
+                        className="dark:hover:bg-gray-700"
+                      >
+                        <Edit className="h-4 w-4" />
+                      </Button>
+                      <Button
+                        variant="ghost"
+                        size="sm"
+                        onClick={() => handleDeleteImport(importRecord.id)}
+                        className="dark:hover:bg-gray-700"
+                      >
+                        <Trash2 className="h-4 w-4" />
+                      </Button>
+                    </div>
                   </div>
-                </div>
-              </CardContent>
-            </Card>
-          ))}
-        </div>
-      )}
-
-      <CreateImportDialog
-        open={createDialogOpen}
-        onOpenChange={setCreateDialogOpen}
-        onSuccess={loadImports}
-      />
-
-      <EditImportDialog
-        open={editDialogOpen}
-        onOpenChange={setEditDialogOpen}
-        importRecord={selectedImport}
-        onSuccess={loadImports}
-      />
-
-      <ImportDetailDialog
-        open={detailDialogOpen}
-        onOpenChange={setDetailDialogOpen}
-        importId={selectedImport?.id || 0}
-      />
+                </CardContent>
+              </Card>
+            ))}
+          </div>
+        )}
+
+        <CreateImportDialog
+          open={createDialogOpen}
+          onOpenChange={setCreateDialogOpen}
+          onSuccess={loadImports}
+        />
+
+        <EditImportDialog
+          open={editDialogOpen}
+          onOpenChange={setEditDialogOpen}
+          importRecord={selectedImport}
+          onSuccess={loadImports}
+        />
+
+        <ImportDetailDialog
+          open={detailDialogOpen}
+          onOpenChange={setDetailDialogOpen}
+          importId={selectedImport?.id || 0}
+        />
+      </div>
     </div>
   );
 }

+ 26 - 21
app/layout-configurations/page.tsx

@@ -6,6 +6,7 @@ import { CreateLayoutConfigurationDialog } from "@/app/components/layout-configu
 import { Skeleton } from "@/components/ui/skeleton";
 import { Button } from "@/components/ui/button";
 import { RefreshCw } from "lucide-react";
+import { Card } from "@/components/ui/card";
 
 export default function LayoutConfigurationsPage() {
   const [refreshKey, setRefreshKey] = useState(0);
@@ -15,27 +16,31 @@ export default function LayoutConfigurationsPage() {
   }, []);
 
   return (
-    <div className="container mx-auto py-8 px-4">
-      <div className="flex justify-between items-center mb-6">
-        <h1 className="text-3xl font-bold">Layout Configurations</h1>
-        <div className="flex gap-2">
-          <Button
-            variant="outline"
-            size="sm"
-            onClick={handleRefresh}
-            className="flex items-center gap-2"
-          >
-            <RefreshCw className="h-4 w-4" />
-            Refresh
-          </Button>
-          <CreateLayoutConfigurationDialog />
+    <div className="min-h-screen bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800">
+      <div className="container mx-auto py-8 px-4">
+        <div className="flex justify-between items-center mb-8">
+          <h1 className="text-3xl font-bold text-gray-900 dark:text-white">
+            Layout Configurations
+          </h1>
+          <div className="flex gap-2">
+            <Button
+              variant="outline"
+              size="sm"
+              onClick={handleRefresh}
+              className="flex items-center gap-2 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700"
+            >
+              <RefreshCw className="h-4 w-4" />
+              Refresh
+            </Button>
+            <CreateLayoutConfigurationDialog />
+          </div>
         </div>
-      </div>
-      
-      <div className="bg-white rounded-lg shadow">
-        <Suspense fallback={<LayoutConfigurationsSkeleton />}>
-          <LayoutConfigurationsTable key={refreshKey} />
-        </Suspense>
+
+        <Card className="dark:bg-gray-800 dark:border-gray-700">
+          <Suspense fallback={<LayoutConfigurationsSkeleton />}>
+            <LayoutConfigurationsTable key={refreshKey} />
+          </Suspense>
+        </Card>
       </div>
     </div>
   );
@@ -46,7 +51,7 @@ function LayoutConfigurationsSkeleton() {
     <div className="p-4 space-y-4">
       {[...Array(5)].map((_, i) => (
         <div key={i} className="flex items-center space-x-4">
-          <Skeleton className="h-12 w-full" />
+          <Skeleton className="h-12 w-full dark:bg-gray-700" />
         </div>
       ))}
     </div>