Browse Source

init byom-web

lblt 5 tháng trước cách đây
mục cha
commit
0415d43f7a

+ 60 - 0
Dockerfile

@@ -0,0 +1,60 @@
+# syntax=docker.io/docker/dockerfile:1
+
+FROM node:18-alpine AS base
+
+# Install dependencies only when needed
+FROM base AS deps
+RUN apk add --no-cache libc6-compat
+WORKDIR /app
+
+
+# Install dependencies based on the preferred package manager
+COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* .npmrc* ./
+RUN \
+  if [ -f yarn.lock ]; then yarn --frozen-lockfile; \
+  elif [ -f package-lock.json ]; then npm ci; \
+  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
+  else echo "Lockfile not found." && exit 1; \
+  fi
+
+# Rebuild the source code only when needed
+FROM base AS builder
+WORKDIR /app
+COPY --from=deps /app/node_modules ./node_modules
+COPY . .
+
+# Disable telemetry during the build
+ENV NEXT_TELEMETRY_DISABLED 1
+
+# Build Next.js
+RUN \
+  if [ -f yarn.lock ]; then NEXT_TELEMETRY_DISABLED=1 yarn run build; \
+  elif [ -f package-lock.json ]; then NEXT_TELEMETRY_DISABLED=1 npm run build; \
+  elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && NEXT_TELEMETRY_DISABLED=1 pnpm run build; \
+  else echo "Lockfile not found." && exit 1; \
+  fi
+
+# Verify the standalone directory exists
+RUN ls -la .next/standalone || (echo "Standalone directory not found" && exit 1)
+
+# Production image, copy all the files and run next
+FROM base AS runner
+WORKDIR /app
+
+ENV NODE_ENV production
+ENV NEXT_TELEMETRY_DISABLED 1
+
+RUN addgroup --system --gid 1001 nodejs
+RUN adduser --system --uid 1001 nextjs
+
+# Copy necessary files
+COPY --from=builder /app/public ./public
+COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
+COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
+
+USER nextjs
+
+ENV PORT=3000
+ENV HOSTNAME="0.0.0.0"
+
+CMD ["node", "server.js"]

+ 83 - 21
README.md

@@ -1,36 +1,98 @@
-This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
 
-## Getting Started
+## 🐳 Docker Deployment
 
-First, run the development server:
+### Prerequisites
+- Docker and Docker Compose installed
+- Domain name (for production)
+- SSL certificates (optional)
 
+### Configuration Files
+
+#### docker-compose.yml
+
+```yaml
+services:
+  byom-web:
+    container_name: byom-web
+    build:
+      context: /path/to/byom-web
+      dockerfile: Dockerfile
+    environment:
+      - NEXT_PUBLIC_API_URL=${API_URL:-http://localhost:3001}
+      - NODE_ENV=production
+    labels:
+      - "traefik.enable=true"
+      - "traefik.http.routers.web.rule=Host(`${DOMAIN:-localhost}`)"
+      - "traefik.http.services.web.loadbalancer.server.port=3000"
+      # HTTPS redirect
+      - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https"
+      - "traefik.http.routers.web.middlewares=https-redirect"
+      # Secure router
+      - "traefik.http.routers.web-secure.rule=Host(`${DOMAIN:-localhost}`)"
+      - "traefik.http.routers.web-secure.entrypoints=websecure"
+      - "traefik.http.routers.web-secure.tls=true"
+    networks:
+      - traefik-public
+    restart: unless-stopped
+
+networks:
+  traefik-public:
+    external: true
+```
+
+### Quick Start
+1. Create network for Traefik:
+```bash
+docker network create traefik-public
+```
+
+2. Configure environment variables:
 ```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
-# or
-bun dev
+# Copy example env file
+cp .env.example .env
+
+# Edit with your settings
+nano .env
 ```
 
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+3. Deploy the stack:
+```bash
+docker compose up -d
+```
 
-You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+### Environment Variables
+```env
+# Domain configuration
+DOMAIN=your-domain.com        # Your domain name
+API_URL=https://api.domain.com # Backend API URL
 
-This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
+# Optional SSL config
+SSL_EMAIL=your@email.com      # For Let's Encrypt notifications
+```
 
-## Learn More
+### Accessing the Application
+- Web UI: `https://your-domain.com`
+- Traefik Dashboard: `http://localhost:8080` (development only)
 
-To learn more about Next.js, take a look at the following resources:
+### Common Commands
+```bash
+# View logs
+docker compose logs -f
 
-- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
-- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+# Restart services
+docker compose restart
 
-You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
+# Stop stack
+docker compose down
 
-## Deploy on Vercel
+# Update images and restart
+docker compose pull
+docker compose up -d
+```
 
-The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+### Production Considerations
+- Enable SSL in Traefik configuration
+- Disable Traefik dashboard
+- Use proper secrets management
+- Set up monitoring
 
-Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.

+ 21 - 0
components.json

@@ -0,0 +1,21 @@
+{
+  "$schema": "https://ui.shadcn.com/schema.json",
+  "style": "default",
+  "rsc": true,
+  "tsx": true,
+  "tailwind": {
+    "config": "tailwind.config.ts",
+    "css": "src/app/globals.css",
+    "baseColor": "neutral",
+    "cssVariables": true,
+    "prefix": ""
+  },
+  "aliases": {
+    "components": "@/components",
+    "utils": "@/lib/utils",
+    "ui": "@/components/ui",
+    "lib": "@/lib",
+    "hooks": "@/hooks"
+  },
+  "iconLibrary": "lucide"
+}

+ 5 - 0
environment.d.ts

@@ -0,0 +1,5 @@
+declare namespace NodeJS {
+    export interface ProcessEnv {
+      readonly NEXT_PUBLIC_API_CORE_URL: string;
+    }
+  }

+ 9 - 0
next.config.ts

@@ -1,7 +1,16 @@
 import type { NextConfig } from "next";
 
 const nextConfig: NextConfig = {
+  output: 'standalone',
+  experimental: {
+    //outputFileTracingRoot: undefined, // Helps with Docker builds
+  },
+  env: {
+    NEXT_PUBLIC_API_CORE_URL: process.env.NEXT_PUBLIC_API_CORE_URL,
+  },
   /* config options here */
 };
 
+
+
 export default nextConfig;

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 798 - 37
package-lock.json


+ 13 - 5
package.json

@@ -9,19 +9,27 @@
     "lint": "next lint"
   },
   "dependencies": {
+    "@radix-ui/react-dropdown-menu": "^2.1.4",
+    "@radix-ui/react-slot": "^1.1.1",
+    "class-variance-authority": "^0.7.1",
+    "clsx": "^2.1.1",
+    "lucide-react": "^0.469.0",
+    "next": "15.1.3",
     "react": "^19.0.0",
     "react-dom": "^19.0.0",
-    "next": "15.1.3"
+    "recharts": "^2.15.0",
+    "tailwind-merge": "^2.6.0",
+    "tailwindcss-animate": "^1.0.7"
   },
   "devDependencies": {
-    "typescript": "^5",
+    "@eslint/eslintrc": "^3",
     "@types/node": "^20",
     "@types/react": "^19",
     "@types/react-dom": "^19",
-    "postcss": "^8",
-    "tailwindcss": "^3.4.1",
     "eslint": "^9",
     "eslint-config-next": "15.1.3",
-    "@eslint/eslintrc": "^3"
+    "postcss": "^8",
+    "tailwindcss": "^3.4.1",
+    "typescript": "^5"
   }
 }

BIN
src/app/assets/byom.png


+ 204 - 0
src/app/dashboard/ads/page.tsx

@@ -0,0 +1,204 @@
+// src/app/dashboard/ads/page.tsx
+'use client'
+import { useState } from 'react'
+import { 
+  Megaphone,
+  Instagram,
+  Image as ImageIcon,
+  Type,
+  Video,
+  Clock,
+  Edit2,
+  Trash2,
+  TrendingUp,
+  TrendingDown 
+} from 'lucide-react'
+import { useTheme } from '@/contexts/themecontext'
+
+// Mock scheduled posts
+const scheduledPosts = [
+  {
+    id: 1,
+    content: "Discover our new collection...",
+    type: "image",
+    platform: "instagram",
+    scheduledFor: "2024-12-30T10:00:00",
+    status: "scheduled",
+    imageUrl: "https://picsum.photos/400/400",
+    analytics: {
+      reach: 1200,
+      engagement: 320,
+      clicks: 45
+    }
+  },
+  {
+    id: 2,
+    content: "Behind the scenes look...",
+    type: "video",
+    platform: "tiktok",
+    scheduledFor: "2024-12-31T15:30:00",
+    status: "draft",
+    imageUrl: "https://picsum.photos/400/401",
+    analytics: {
+      reach: 2500,
+      engagement: 850,
+      clicks: 120
+    }
+  }
+]
+
+export default function AdsPage() {
+  const [activeTab, setActiveTab] = useState('create')
+  const { theme } = useTheme()
+
+  return (
+    <div className="p-6">
+      {/* Header */}
+      <div className="mb-8">
+        <h1 className={`text-4xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2 flex items-center`}>
+          <Megaphone className="w-8 h-8 mr-3 text-orange-500" />
+          Content Manager
+        </h1>
+        <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>Create, schedule, and track your social media content</p>
+      </div>
+
+      {/* Main Navigation */}
+      <div className={`flex space-x-1 ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} p-1 rounded-lg mb-8 max-w-md shadow-lg`}>
+        {['create', 'scheduled', 'analytics'].map((tab) => (
+          <button
+            key={tab}
+            onClick={() => setActiveTab(tab)}
+            className={`flex-1 px-4 py-2 rounded-md text-sm font-medium transition-colors ${
+              activeTab === tab 
+                ? 'bg-orange-500 text-white' 
+                : `${theme === 'dark' ? 'text-gray-400 hover:text-white hover:bg-gray-700' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100'}`
+            }`}
+          >
+            {tab.charAt(0).toUpperCase() + tab.slice(1)}
+          </button>
+        ))}
+      </div>
+
+      {/* Create Content Section */}
+      {activeTab === 'create' && (
+        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
+          {/* Quick Create Options */}
+          <button className={`p-6 ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg hover:ring-2 hover:ring-orange-500/50 transition-all group shadow-lg`}>
+            <ImageIcon className="w-8 h-8 mb-4 text-orange-500" />
+            <h3 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>Image Post</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-sm`}>Create image-based posts with AI assistance</p>
+          </button>
+
+          <button className={`p-6 ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg hover:ring-2 hover:ring-orange-500/50 transition-all group shadow-lg`}>
+            <Video className="w-8 h-8 mb-4 text-orange-500" />
+            <h3 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>Video Post</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-sm`}>Create and edit video content</p>
+          </button>
+
+          <button className={`p-6 ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg hover:ring-2 hover:ring-orange-500/50 transition-all group shadow-lg`}>
+            <Type className="w-8 h-8 mb-4 text-orange-500" />
+            <h3 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>Text Post</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-sm`}>Generate engaging captions and text content</p>
+          </button>
+        </div>
+      )}
+
+      {/* Scheduled Content Section */}
+      {activeTab === 'scheduled' && (
+        <div className="space-y-6">
+          {/* Calendar View Toggle */}
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 mb-6 shadow-lg`}>
+            <div className="flex items-center justify-between mb-4">
+              <h2 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>Content Calendar</h2>
+              <button className="px-4 py-2 bg-orange-500 text-white rounded-md hover:bg-orange-600 transition-colors">
+                Schedule New Post
+              </button>
+            </div>
+            {/* Calendar would go here */}
+          </div>
+
+          {/* Scheduled Posts List */}
+          <div className="space-y-4">
+            {scheduledPosts.map((post) => (
+              <div key={post.id} className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-4 shadow-lg`}>
+                <div className="flex items-start gap-4">
+                  {/* Post Preview */}
+                  <div className={`w-24 h-24 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-lg overflow-hidden flex-shrink-0`}>
+                    <img 
+                      src={post.imageUrl} 
+                      alt="Post preview" 
+                      className="w-full h-full object-cover"
+                    />
+                  </div>
+
+                  {/* Post Details */}
+                  <div className="flex-1">
+                    <div className="flex items-center justify-between mb-2">
+                      <div className="flex items-center gap-2">
+                        <Instagram className="w-4 h-4 text-pink-500" />
+                        <span className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>{post.platform}</span>
+                        <span className={`px-2 py-0.5 rounded-full text-xs ${
+                          post.status === 'scheduled' 
+                            ? 'bg-green-500/10 text-green-500' 
+                            : 'bg-yellow-500/10 text-yellow-500'
+                        }`}>
+                          {post.status}
+                        </span>
+                      </div>
+                      <div className="flex items-center gap-2">
+                        <button className={`p-1 ${theme === 'dark' ? 'hover:bg-gray-700' : 'hover:bg-gray-100'} rounded`}>
+                          <Edit2 className={`w-4 h-4 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+                        </button>
+                        <button className={`p-1 ${theme === 'dark' ? 'hover:bg-gray-700' : 'hover:bg-gray-100'} rounded`}>
+                          <Trash2 className={`w-4 h-4 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+                        </button>
+                      </div>
+                    </div>
+                    <p className={`${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>{post.content}</p>
+                    <div className={`flex items-center text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+                      <Clock className="w-4 h-4 mr-1" />
+                      Scheduled for {new Date(post.scheduledFor).toLocaleString()}
+                    </div>
+                  </div>
+                </div>
+              </div>
+            ))}
+          </div>
+        </div>
+      )}
+
+      {/* Analytics Section */}
+      {activeTab === 'analytics' && (
+        <div>
+          {/* Overview Cards */}
+          <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
+            {[
+              { title: 'Total Reach', value: '24.5K', change: '+12.3%', trending: 'up' },
+              { title: 'Engagement Rate', value: '3.8%', change: '+2.1%', trending: 'up' },
+              { title: 'Click-through Rate', value: '2.4%', change: '-0.8%', trending: 'down' }
+            ].map((stat, index) => (
+              <div key={index} className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 shadow-lg`}>
+                <h3 className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mb-2 text-sm`}>{stat.title}</h3>
+                <div className={`text-2xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>{stat.value}</div>
+                <div className={`text-sm flex items-center mt-2 ${
+                  stat.trending === 'up' ? 'text-green-500' : 'text-red-500'
+                }`}>
+                  {stat.trending === 'up' ? <TrendingUp className="w-4 h-4 mr-1" /> : <TrendingDown className="w-4 h-4 mr-1" />}
+                  {stat.change}
+                </div>
+              </div>
+            ))}
+          </div>
+
+          {/* Performance Chart */}
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 shadow-lg`}>
+            <h2 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-4`}>Performance Over Time</h2>
+            <div className="h-64">
+              {/* Chart would go here */}
+            </div>
+          </div>
+        </div>
+      )}
+    </div>
+  )
+}

+ 88 - 0
src/app/dashboard/components/workspaceselector.tsx

@@ -0,0 +1,88 @@
+// Inside your dashboard layout, add state for dropdown
+import { useState } from 'react'
+import { ChevronDown, PlusCircle } from 'lucide-react'
+
+// Mock data for workspaces
+const workspaces = [
+  { id: 1, name: "My Workspace", initial: "M", color: "bg-blue-500" },
+  { id: 2, name: "Design Team", initial: "D", color: "bg-purple-500" },
+  { id: 3, name: "Marketing", initial: "M", color: "bg-emerald-500" },
+]
+
+// Component for workspace selection
+export function WorkspaceSelector() {
+  const [isOpen, setIsOpen] = useState(false)
+  const [selectedWorkspace, setSelectedWorkspace] = useState(workspaces[0])
+
+  return (
+    <div className="relative">
+      {/* Trigger Button */}
+      <button
+        onClick={() => setIsOpen(!isOpen)}
+        className="w-full p-4 flex items-center space-x-2 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-lg transition-colors"
+      >
+        <div className={`${selectedWorkspace.color} w-8 h-8 rounded flex items-center justify-center text-white font-bold`}>
+          {selectedWorkspace.initial}
+        </div>
+        <div className="flex-1">
+          <h1 className="text-gray-900 dark:text-white font-medium text-left">
+            {selectedWorkspace.name}
+          </h1>
+        </div>
+        <ChevronDown className={`w-4 h-4 text-gray-500 transition-transform duration-200 ${isOpen ? 'transform rotate-180' : ''}`} />
+      </button>
+
+      {/* Dropdown Menu */}
+      {isOpen && (
+        <>
+          {/* Backdrop for closing dropdown */}
+          <div 
+            className="fixed inset-0 z-10"
+            onClick={() => setIsOpen(false)}
+          />
+
+          <div className="absolute top-full left-0 w-full mt-2 py-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 z-20">
+            <div className="px-3 py-2 text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
+              Your Workspaces
+            </div>
+            
+            <div className="mt-2">
+              {workspaces.map((workspace) => (
+                <button
+                  key={workspace.id}
+                  onClick={() => {
+                    setSelectedWorkspace(workspace)
+                    setIsOpen(false)
+                  }}
+                  className={`w-full px-3 py-2 flex items-center space-x-2 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors
+                    ${selectedWorkspace.id === workspace.id ? 'bg-gray-50 dark:bg-gray-700' : ''}`}
+                >
+                  <div className={`${workspace.color} w-6 h-6 rounded flex items-center justify-center text-white font-medium text-sm`}>
+                    {workspace.initial}
+                  </div>
+                  <span className="text-gray-900 dark:text-white text-sm">
+                    {workspace.name}
+                  </span>
+                </button>
+              ))}
+            </div>
+
+            <div className="h-px bg-gray-200 dark:bg-gray-700 my-2" />
+            
+            <button
+              onClick={() => {
+                // Handle new workspace creation
+                console.log('Create new workspace')
+                setIsOpen(false)
+              }}
+              className="w-full px-3 py-2 flex items-center space-x-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors"
+            >
+              <PlusCircle className="w-4 h-4" />
+              <span className="text-sm">Create New Workspace</span>
+            </button>
+          </div>
+        </>
+      )}
+    </div>
+  )
+}

+ 180 - 0
src/app/dashboard/design/page.tsx

@@ -0,0 +1,180 @@
+// src/app/dashboard/design/page.tsx
+'use client'
+import { useState } from 'react'
+import { 
+  Palette, 
+  Sparkles, 
+  Clock, 
+  Search,
+  Filter,
+  Download,
+  Share2,
+  PlusCircle
+} from 'lucide-react'
+import { useTheme } from '@/contexts/themecontext'
+
+// Mock data for previously generated images
+const recentDesigns = [
+  {
+    id: 1,
+    prompt: "Minimalist social media post for coffee shop",
+    date: "2 hours ago",
+    imageUrl: "https://picsum.photos/200/300",
+    tags: ["social media", "minimalist"]
+  },
+  {
+    id: 2,
+    prompt: "Instagram story with modern typography",
+    date: "5 hours ago",
+    imageUrl: "https://picsum.photos/250/300",
+    tags: ["instagram", "typography"]
+  },
+  // Add more mock designs
+]
+
+export default function DesignPage() {
+  const [prompt, setPrompt] = useState("")
+  const [isGenerating, setIsGenerating] = useState(false)
+  const { theme } = useTheme()
+
+  const handleGenerate = () => {
+    setIsGenerating(true)
+    // Mock generation process
+    setTimeout(() => {
+      setIsGenerating(false)
+    }, 2000)
+  }
+
+  return (
+    <div className="p-6">
+      {/* Header */}
+      <div className="mb-8">
+        <h1 className={`text-4xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2 flex items-center`}>
+          <Palette className="w-8 h-8 mr-3 text-purple-500" />
+          Design
+        </h1>
+        <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>Generate and manage your AI-powered designs</p>
+      </div>
+
+      {/* Generation Section */}
+      <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 mb-8 shadow-lg`}>
+        <div className="max-w-3xl mx-auto">
+          <h2 className={`text-xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-4`}>Create New Design</h2>
+          
+          {/* Prompt Input */}
+          <div className="mb-6">
+            <div className="relative">
+              <input
+                type="text"
+                placeholder="Describe your design idea..."
+                value={prompt}
+                onChange={(e) => setPrompt(e.target.value)}
+                className={`w-full ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-lg pl-4 pr-36 py-3 ${theme === 'dark' ? 'text-white' : 'text-gray-900'} ${theme === 'dark' ? 'placeholder-gray-400' : 'placeholder-gray-500'} focus:ring-2 focus:ring-purple-500`}
+              />
+              <button
+                onClick={handleGenerate}
+                disabled={isGenerating || !prompt}
+                className="absolute right-2 top-1/2 -translate-y-1/2 bg-purple-500 hover:bg-purple-600 disabled:bg-gray-600 text-white px-4 py-1.5 rounded-md flex items-center transition-colors"
+              >
+                <Sparkles className="w-4 h-4 mr-2" />
+                {isGenerating ? 'Generating...' : 'Generate'}
+              </button>
+            </div>
+            
+            {/* Quick Suggestions */}
+            <div className="flex gap-2 mt-3">
+              {['Social Media Post', 'Story Template', 'Advertisement'].map((suggestion) => (
+                <button 
+                  key={suggestion}
+                  className={`px-3 py-1.5 ${theme === 'dark' ? 'bg-gray-700 hover:bg-gray-600' : 'bg-gray-100 hover:bg-gray-200'} rounded-full text-sm ${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'} transition-colors`}
+                >
+                  {suggestion}
+                </button>
+              ))}
+            </div>
+          </div>
+        </div>
+      </div>
+
+      {/* Recent Designs */}
+      <div>
+        <div className="flex items-center justify-between mb-6">
+          <h2 className={`text-xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} flex items-center`}>
+            <Clock className="w-5 h-5 mr-2" />
+            Recent Designs
+          </h2>
+          
+          <div className="flex items-center gap-4">
+            {/* Search */}
+            <div className="relative">
+              <Search className={`w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+              <input
+                type="text"
+                placeholder="Search designs..."
+                className={`${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-md pl-9 pr-4 py-2 text-sm ${theme === 'dark' ? 'text-white' : 'text-gray-900'} ${theme === 'dark' ? 'placeholder-gray-400' : 'placeholder-gray-500'} focus:ring-2 focus:ring-purple-500`}
+              />
+            </div>
+            
+            {/* Filter */}
+            <button className={`${theme === 'dark' ? 'bg-gray-700 hover:bg-gray-600' : 'bg-gray-100 hover:bg-gray-200'} p-2 rounded-md transition-colors`}>
+              <Filter className={`w-4 h-4 ${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'}`} />
+            </button>
+          </div>
+        </div>
+
+        {/* Design Grid */}
+        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
+          {/* New Design Card */}
+          <button className={`aspect-video ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg border-2 border-dashed ${theme === 'dark' ? 'border-gray-700' : 'border-gray-200'} hover:border-purple-500 flex items-center justify-center group transition-colors shadow-lg`}>
+            <div className="text-center">
+              <PlusCircle className="w-8 h-8 mb-2 text-gray-500 group-hover:text-purple-500 mx-auto transition-colors" />
+              <span className="text-gray-500 group-hover:text-purple-500 transition-colors">Create New Design</span>
+            </div>
+          </button>
+
+          {/* Recent Designs */}
+          {recentDesigns.map((design) => (
+            <div key={design.id} className={`group relative ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg overflow-hidden shadow-lg`}>
+              {/* Image */}
+              <img
+                src={design.imageUrl}
+                alt={design.prompt}
+                className="w-full aspect-video object-cover"
+              />
+              
+              {/* Overlay */}
+              <div className="absolute inset-0 bg-gradient-to-t from-black/60 via-black/0 to-black/0 opacity-0 group-hover:opacity-100 transition-opacity">
+                <div className="absolute bottom-0 left-0 right-0 p-4">
+                  <p className="text-white text-sm mb-2">{design.prompt}</p>
+                  <div className="flex items-center justify-between">
+                    <span className="text-gray-300 text-xs">{design.date}</span>
+                    <div className="flex gap-2">
+                      <button className={`p-1.5 ${theme === 'dark' ? 'bg-gray-800/80 hover:bg-gray-700' : 'bg-white/80 hover:bg-gray-100'} rounded-md transition-colors`}>
+                        <Download className={`w-4 h-4 ${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'}`} />
+                      </button>
+                      <button className={`p-1.5 ${theme === 'dark' ? 'bg-gray-800/80 hover:bg-gray-700' : 'bg-white/80 hover:bg-gray-100'} rounded-md transition-colors`}>
+                        <Share2 className={`w-4 h-4 ${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'}`} />
+                      </button>
+                    </div>
+                  </div>
+                </div>
+              </div>
+
+              {/* Tags */}
+              <div className="absolute top-2 left-2 flex gap-2">
+                {design.tags.map((tag, index) => (
+                  <span 
+                    key={index}
+                    className="px-2 py-1 bg-black/50 rounded-full text-white text-xs"
+                  >
+                    {tag}
+                  </span>
+                ))}
+              </div>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}

+ 349 - 0
src/app/dashboard/layout.tsx

@@ -0,0 +1,349 @@
+// src/app/dashboard/layout.tsx
+'use client'
+
+import Onboarding from '@/components/profiles/addProfile'; 
+import InviteCollaborators from '@/components/shared/inviteCollaborators';
+import { useEffect, useState, ReactNode, useCallback } from 'react';
+import { useRouter } from 'next/navigation';
+import { Plus } from 'lucide-react';
+import { userMe, getProfilesByWorkspace, type Profile } from '@/lib/api/core';
+import { Workspace } from '@/types/auth';
+
+import Link from 'next/link'
+import { 
+  TrendingUp,
+  Palette,
+  Megaphone,
+  Sparkles,
+  ChevronDown,
+  PlusCircle,
+  Lightbulb,
+  Sun,
+  Moon,
+  Home,
+  LogOut,
+  User
+} from 'lucide-react'
+import { useTheme } from '@/contexts/themecontext'
+
+interface DashboardLayoutProps {
+  children: ReactNode
+}
+
+// Helper function to get workspace initial
+const getInitial = (name: string | undefined) => {
+  if (!name) return '?';
+  return name.charAt(0).toUpperCase();
+};
+
+// Workspace selector component
+const WorkspaceSelector = ({ workspaces, onWorkspaceChange }: { workspaces: Workspace[], onWorkspaceChange: (workspace: Workspace) => void }) => {
+  const [selectedWorkspace, setSelectedWorkspace] = useState(workspaces[0]);
+  const [isOpen, setIsOpen] = useState(false);
+  const initial = getInitial(selectedWorkspace?.name);
+  const router = useRouter();
+
+  useEffect(() => {
+    if (selectedWorkspace) {
+      localStorage.setItem('selectedWorkspaceId', selectedWorkspace.id.toString());
+      onWorkspaceChange(selectedWorkspace);
+    }
+  }, [selectedWorkspace, onWorkspaceChange]);
+
+  return (
+    <div className="p-4 border-b border-gray-200 dark:border-gray-800 relative">
+      <button 
+        onClick={() => setIsOpen(!isOpen)}
+        className="w-full flex items-center justify-between px-2 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white hover:bg-gray-100 dark:hover:bg-gray-800 rounded-md"
+      >
+        <div className="flex items-center">
+          <div className="w-8 h-8 rounded-md bg-blue-500 text-white flex items-center justify-center mr-3">
+            {initial}
+          </div>
+          <span>{selectedWorkspace?.name || 'Workspace'}</span>
+        </div>
+        <ChevronDown className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
+      </button>
+
+      {isOpen && (
+        <>
+          <div 
+            className="fixed inset-0 z-10" 
+            onClick={() => setIsOpen(false)}
+          />
+          <div className="absolute left-0 right-0 mt-2 mx-4 py-2 bg-white dark:bg-gray-800 rounded-lg shadow-lg z-20 border border-gray-200 dark:border-gray-700">
+            {workspaces.map((workspace) => (
+              <button
+                key={workspace.id}
+                onClick={() => {
+                  setSelectedWorkspace(workspace);
+                  setIsOpen(false);
+                }}
+                className={`w-full px-3 py-2 flex items-center space-x-2 hover:bg-gray-100 dark:hover:bg-gray-700 ${
+                  selectedWorkspace?.id === workspace.id ? 'bg-gray-50 dark:bg-gray-700' : ''
+                }`}
+              >
+                <div className="w-6 h-6 rounded bg-blue-500 text-white flex items-center justify-center">
+                  {getInitial(workspace.name)}
+                </div>
+                <span className="text-gray-900 dark:text-white">{workspace.name}</span>
+              </button>
+            ))}
+            <div className="border-t border-gray-200 dark:border-gray-700 mt-2 pt-2">
+              <button
+                onClick={() => router.push('/setup')}
+                className="w-full px-3 py-2 flex items-center space-x-2 text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700"
+              >
+                <PlusCircle className="w-4 h-4" />
+                <span>Create New Workspace</span>
+              </button>
+            </div>
+          </div>
+        </>
+      )}
+    </div>
+  );
+};
+
+export default function DashboardLayout({ children }: DashboardLayoutProps) {
+  const { theme, toggleTheme } = useTheme()
+  const [showOnboarding, setShowOnboarding] = useState(false);
+  const [showInviteModal, setShowInviteModal] = useState(false);
+  const [showUserDropdown, setShowUserDropdown] = useState(false);
+  const [workspaces, setWorkspaces] = useState<Workspace[]>([]);
+  const [profiles, setProfiles] = useState<Profile[]>([]);
+  const [isLoading, setIsLoading] = useState(true);
+  const router = useRouter();
+
+  const handleOnboardingComplete = () => {
+    setShowOnboarding(false);
+    // Refresh profiles after creating a new one
+    const workspaceId = localStorage.getItem('selectedWorkspaceId');
+    if (workspaceId) {
+      getProfilesByWorkspace(workspaceId).then(setProfiles);
+    }
+  };
+
+  const handleLogout = () => {
+    localStorage.clear();
+    router.push('/login');
+  };
+
+  const handleWorkspaceChange = useCallback(async (workspace: Workspace) => {
+    try {
+      const profiles = await getProfilesByWorkspace(workspace.id.toString());
+      setProfiles(profiles);
+    } catch (error) {
+      console.error('Failed to fetch profiles', error);
+      setProfiles([]);
+    }
+  }, []);
+
+  useEffect(() => {
+    const fetchWorkspaces = async () => {
+      try {
+        const response = await userMe();
+        setWorkspaces(response.workspaces);
+        
+        // Fetch profiles for the first workspace
+        if (response.workspaces.length > 0) {
+          await handleWorkspaceChange(response.workspaces[0]);
+        }
+      }
+      catch (error) {
+        console.error('Failed to fetch workspaces', error);
+        setWorkspaces([]);
+      }
+      finally {
+        setIsLoading(false);
+      }
+    };
+
+    fetchWorkspaces();
+  }, [handleWorkspaceChange]);
+
+  if (isLoading) {
+    return (
+      <div className="flex justify-center items-center min-h-screen bg-gray-900">
+        <div className="w-5 h-5 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
+      </div>
+    );
+  }
+
+  if (workspaces.length === 0) {
+    return (
+      <div className={`flex flex-col items-center justify-center min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} px-4 relative`}>
+        <button
+          onClick={toggleTheme}
+          className={`absolute top-4 right-4 p-2 rounded-lg ${
+            theme === 'dark' 
+              ? 'bg-gray-800 hover:bg-gray-700' 
+              : 'bg-white hover:bg-gray-100'
+          } transition-colors shadow-lg`}
+          aria-label="Toggle theme"
+        >
+          {theme === 'dark' ? (
+            <Sun className="w-5 h-5 text-yellow-500" />
+          ) : (
+            <Moon className="w-5 h-5 text-gray-600" />
+          )}
+        </button>
+
+        <div className="text-center max-w-md">
+          <h2 className={`text-2xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-3`}>
+            Bienvenue sur votre tableau de bord
+          </h2>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mb-8`}>
+            Vous n&apos;avez pas encore d&apos;espaces de travail. Créez votre premier espace de travail pour commencer.
+          </p>
+          <button
+            onClick={() => router.push('/setup')}
+            className={`inline-flex items-center justify-center rounded-md ${
+              theme === 'dark' ? 'bg-blue-600 hover:bg-blue-500' : 'bg-blue-500 hover:bg-blue-400'
+            } px-4 py-2 text-sm font-semibold text-white shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500`}
+          >
+            <Plus className="w-5 h-5 mr-2" />
+            Créer un espace de travail
+          </button>
+        </div>
+      </div>
+    );
+  }
+
+  return (
+    <div className="flex h-screen bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-300">
+      {showOnboarding && <Onboarding onComplete={handleOnboardingComplete} />}
+      <aside className="w-64 border-r border-gray-200 dark:border-gray-800">
+        <div className="h-full flex flex-col">
+          <WorkspaceSelector workspaces={workspaces} onWorkspaceChange={handleWorkspaceChange} />
+
+          <nav className="flex-1 p-4 space-y-1">
+            <Link href="/dashboard" 
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <Home className="w-4 h-4 mr-3" />
+              Accueil
+            </Link>
+            <Link href="/dashboard/trends" 
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <TrendingUp className="w-4 h-4 mr-3" />
+              Tendances
+            </Link>
+            <Link href="/dashboard/suggestions"
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <Lightbulb className="w-4 h-4 mr-3" />
+              Suggestions
+            </Link>
+            <Link href="/dashboard/design"
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <Palette className="w-4 h-4 mr-3" />
+              Design
+            </Link>
+            <Link href="/dashboard/ads"
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <Megaphone className="w-4 h-4 mr-3" />
+              Publicités
+            </Link>
+            <Link href="/dashboard/showcase"
+              className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800">
+              <Sparkles className="w-4 h-4 mr-3" />
+              Vitrine
+            </Link>
+
+            {/* Profiles Section */}
+            <div className="mt-8">
+              <div className="px-2 flex items-center justify-between mb-2">
+                <h2 className="text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wider">
+                  Profils
+                </h2>
+                <button
+                  onClick={() => setShowOnboarding(true)}
+                  className="p-1 hover:bg-gray-100 dark:hover:bg-gray-800 rounded-md"
+                >
+                  <PlusCircle className="w-4 h-4 text-gray-500 dark:text-gray-400" />
+                </button>
+              </div>
+              <div className="mt-2 space-y-1">
+                {profiles.length > 0 ? (
+                  profiles.map((profile) => (
+                    <Link
+                      key={profile.id}
+                      href={`/dashboard/profile/${profile.name.toLowerCase()}`}
+                      className="flex items-center px-2 py-2 rounded text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
+                    >
+                      <User className="w-4 h-4 mr-3 text-blue-500" />
+                      @{profile.name}
+                    </Link>
+                  ))
+                ) : (
+                  <div className="px-2 py-2 text-sm text-gray-500 dark:text-gray-400">
+                    Aucun profil
+                  </div>
+                )}
+              </div>
+            </div>
+          </nav>
+        </div>
+      </aside>
+
+      <div className="flex-1 flex flex-col">
+        <header className="h-16 border-b border-gray-200 dark:border-gray-800">
+          <div className="h-full px-4 flex items-center justify-between">
+            <div className="flex items-center space-x-4 ml-auto">
+              <button 
+                onClick={() => setShowInviteModal(true)}
+                className="text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
+                Inviter des collaborateurs
+              </button>
+              <button
+                onClick={toggleTheme}
+                className="p-2 rounded-md bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-white hover:bg-gray-200 dark:hover:bg-gray-700 transition-colors"
+                aria-label="Toggle theme"
+              >
+                {theme === 'dark' ? (
+                  <Sun className="w-4 h-4" />
+                ) : (
+                  <Moon className="w-4 h-4" />
+                )}
+              </button>
+              <div className="relative">
+                <button
+                  onClick={() => setShowUserDropdown(!showUserDropdown)}
+                  className="w-8 h-8 bg-gray-200 dark:bg-gray-700 rounded-full flex items-center justify-center text-gray-900 dark:text-white hover:ring-2 hover:ring-gray-300 dark:hover:ring-gray-600 transition-all"
+                >
+                  U
+                </button>
+                
+                {showUserDropdown && (
+                  <>
+                    <div 
+                      className="fixed inset-0 z-10" 
+                      onClick={() => setShowUserDropdown(false)}
+                    />
+                    
+                    <div className={`absolute right-0 mt-2 w-48 py-2 ${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg shadow-lg border ${theme === 'dark' ? 'border-gray-700' : 'border-gray-200'} z-20`}>
+                      <button
+                        onClick={handleLogout}
+                        className="w-full px-4 py-2 text-left flex items-center space-x-2 text-red-500 hover:bg-gray-100 dark:hover:bg-gray-700"
+                      >
+                        <LogOut className="w-4 h-4" />
+                        <span>Se déconnecter</span>
+                      </button>
+                    </div>
+                  </>
+                )}
+              </div>
+            </div>
+          </div>
+        </header>
+
+        <main className="flex-1 overflow-y-auto">
+          {children}
+        </main>
+
+        {showInviteModal && (
+          <InviteCollaborators onClose={() => setShowInviteModal(false)} />
+        )}
+      </div>
+    </div>
+  );
+}

+ 157 - 0
src/app/dashboard/page.tsx

@@ -0,0 +1,157 @@
+// src/app/dashboard/page.tsx
+'use client'
+
+import { Plus, Twitter, InstagramIcon, Facebook, Linkedin } from 'lucide-react';
+import { useState, useEffect } from 'react';
+import AddProfile from '@/components/profiles/addProfile';
+import { useTheme } from '@/contexts/themecontext';
+import { getProfilesByWorkspace, type Profile } from '@/lib/api/core';
+
+export default function DashboardPage() {
+  const [showOnboarding, setShowOnboarding] = useState(false);
+  const [profiles, setProfiles] = useState<Profile[]>([]);
+  const [isLoading, setIsLoading] = useState(true);
+  const { theme } = useTheme();
+
+  useEffect(() => {
+    const fetchProfiles = async () => {
+      try {
+        const workspaceId = localStorage.getItem('selectedWorkspaceId');
+        if (!workspaceId) return;
+        
+        const fetchedProfiles = await getProfilesByWorkspace(workspaceId);
+        setProfiles(fetchedProfiles);
+      } catch (error) {
+        console.error('Failed to fetch profiles:', error);
+      } finally {
+        setIsLoading(false);
+      }
+    };
+
+    fetchProfiles();
+  }, []);
+
+  const handleNewProfileClick = () => {
+    setShowOnboarding(true);
+  };
+
+  const handleOnboardingComplete = () => {
+    setShowOnboarding(false);
+    // Refresh profiles after creating a new one
+    const workspaceId = localStorage.getItem('selectedWorkspaceId');
+    if (workspaceId) {
+      getProfilesByWorkspace(workspaceId).then(setProfiles);
+    }
+  };
+
+  if (isLoading) {
+    return (
+      <div className="flex justify-center items-center h-full">
+        <div className="w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" />
+      </div>
+    );
+  }
+
+  return (
+    <div className="p-4">
+      {showOnboarding && <AddProfile onComplete={handleOnboardingComplete} />}
+
+      <div className="flex items-center justify-between mb-6">
+        <h1 className={`text-2xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
+          Tous les profils
+        </h1>
+      </div>
+
+      {profiles.length === 0 ? (
+        <div className={`text-center py-12 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+          <p className="text-lg mb-4">Aucun profil</p>
+          <button
+            onClick={handleNewProfileClick}
+            className={`inline-flex items-center px-4 py-2 rounded-md ${
+              theme === 'dark' ? 'bg-gray-800 hover:bg-gray-700' : 'bg-gray-100 hover:bg-gray-200'
+            } transition-colors`}
+          >
+            <Plus className="w-5 h-5 mr-2" />
+            Créer un profil
+          </button>
+        </div>
+      ) : (
+        <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
+          {profiles.map((profile) => (
+            <ProfileCard 
+              key={profile.id} 
+              profile={profile} 
+              theme={theme} 
+            />
+          ))}
+          <NewProfileCard onClick={handleNewProfileClick} theme={theme} />
+        </div>
+      )}
+    </div>
+  );
+}
+
+function ProfileCard({ profile, theme }: { profile: Profile, theme: 'dark' | 'light' }) {
+  const socialIcons = {
+    twitter: <Twitter className="w-4 h-4 text-blue-400" />,
+    instagram: <InstagramIcon className="w-4 h-4 text-pink-500" />,
+    facebook: <Facebook className="w-4 h-4 text-blue-600" />,
+    linkedin: <Linkedin className="w-4 h-4 text-blue-700" />
+  };
+
+  const getProfileIcon = () => {
+    if (profile.socials && profile.socials.length > 0) {
+      const firstSocial = profile.socials[0];
+      return socialIcons[firstSocial.type as keyof typeof socialIcons] || '👤';
+    }
+    return '👤';
+  };
+
+  return (
+    <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-4 hover:ring-2 hover:ring-blue-500/50 transition-all cursor-pointer shadow-lg`}>
+      <div className="flex items-center space-x-4">
+        <div className={`w-12 h-12 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-full flex items-center justify-center text-2xl`}>
+          {getProfileIcon()}
+        </div>
+        <div>
+          <h3 className={`font-medium ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
+            {profile.name}
+          </h3>
+          <p className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+            @{profile.name.toLowerCase()}
+          </p>
+        </div>
+      </div>
+
+      <div className="mt-4">
+        <div className="flex flex-wrap gap-2">
+          {profile.socials?.map((social) => (
+            <div 
+              key={social.id}
+              className={`flex items-center px-2 py-1 rounded ${
+                theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'
+              }`}
+            >
+              {socialIcons[social.type as keyof typeof socialIcons]}
+              <span className="ml-1 text-sm">{social.identifier}</span>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  );
+}
+
+function NewProfileCard({ onClick, theme }: { onClick: () => void, theme: 'dark' | 'light' }) {
+  return (
+    <div
+      className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg aspect-video p-4 flex flex-col justify-center items-center hover:ring-2 hover:ring-blue-500/50 transition-all cursor-pointer shadow-lg`}
+      onClick={onClick}
+    >
+      <div className={`w-12 h-12 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-full flex items-center justify-center`}>
+        <Plus className={`w-6 h-6 ${theme === 'dark' ? 'text-gray-500' : 'text-gray-400'}`} />
+      </div>
+      <p className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mt-2`}>Ajouter un nouveau profil</p>
+    </div>
+  );
+}

+ 171 - 0
src/app/dashboard/showcase/page.tsx

@@ -0,0 +1,171 @@
+// src/app/dashboard/showcase/page.tsx
+'use client'
+import { 
+    Sparkles, 
+    ShoppingBag, 
+    Globe, 
+    Share2,
+    ArrowRight
+  } from 'lucide-react'
+import { useTheme } from '@/contexts/themecontext'
+  
+  const integrations = [
+    {
+      id: 1,
+      name: "Shopify",
+      description: "Connect your Shopify store to automate product promotion and track sales from social posts",
+      icon: "https://img.icons8.com/color/512/shopify.png", // Replace with actual Shopify icon
+      features: [
+        "Automatic product sync",
+        "Sales tracking",
+        "Inventory management",
+        "Direct checkout"
+      ],
+      status: "Popular",
+      category: "E-commerce"
+    },
+    {
+      id: 2,
+      name: "WooCommerce",
+      description: "Integrate with WordPress-based stores to streamline your social media marketing",
+      icon: "https://uxwing.com/wp-content/themes/uxwing/download/brands-and-social-media/woocommerce-icon.png", // Replace with actual WooCommerce icon
+      features: [
+        "WordPress integration",
+        "Product catalog sync",
+        "Order tracking",
+        "Custom fields support"
+      ],
+      status: "New",
+      category: "E-commerce"
+    },
+    {
+      id: 3,
+      name: "Meta Business",
+      description: "Connect with Facebook and Instagram shops for seamless social selling",
+      icon: "https://cdn-icons-png.flaticon.com/512/6033/6033716.png", // Replace with actual Meta icon
+      features: [
+        "Facebook Shop integration",
+        "Instagram Shopping",
+        "Automated tagging",
+        "Cross-platform insights"
+      ],
+      status: "Popular",
+      category: "Social Commerce"
+    },
+    {
+      id: 4,
+      name: "Square",
+      description: "Connect your Square POS system to track in-store and online sales",
+      icon: "https://icons.veryicon.com/png/o/object/material-design-icons-1/square-inc.png", // Replace with actual Square icon
+      features: [
+        "POS integration",
+        "Payment processing",
+        "Unified inventory",
+        "Sales analytics"
+      ],
+      status: "New",
+      category: "Payments"
+    }
+  ]
+  
+  export default function ShowcasePage() {
+    const { theme } = useTheme()
+  
+    return (
+      <div className="p-6">
+        {/* Header */}
+        <div className="mb-8">
+          <h1 className={`text-4xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2 flex items-center`}>
+            <Sparkles className="w-8 h-8 mr-3 text-yellow-500" />
+            Integrations
+          </h1>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>Connect your store and expand your reach</p>
+        </div>
+  
+        {/* Quick Stats */}
+        <div className="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 shadow-lg`}>
+            <ShoppingBag className="w-8 h-8 text-blue-500 mb-4" />
+            <h3 className={`${theme === 'dark' ? 'text-white' : 'text-gray-900'} text-lg font-semibold mb-1`}>E-commerce</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>Connect your online store</p>
+          </div>
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 shadow-lg`}>
+            <Globe className="w-8 h-8 text-purple-500 mb-4" />
+            <h3 className={`${theme === 'dark' ? 'text-white' : 'text-gray-900'} text-lg font-semibold mb-1`}>Multi-platform</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>Sell across channels</p>
+          </div>
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 shadow-lg`}>
+            <Share2 className="w-8 h-8 text-green-500 mb-4" />
+            <h3 className={`${theme === 'dark' ? 'text-white' : 'text-gray-900'} text-lg font-semibold mb-1`}>Analytics</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>Track performance</p>
+          </div>
+        </div>
+  
+        {/* Integrations Grid */}
+        <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
+          {integrations.map((integration) => (
+            <div key={integration.id} className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 hover:ring-2 hover:ring-blue-500/50 transition-all shadow-lg`}>
+              {/* Header */}
+              <div className="flex items-start justify-between mb-4">
+                <div className="flex items-center">
+                  <div className={`w-12 h-12 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-lg mr-4 overflow-hidden`}>
+                    <img 
+                      src={integration.icon} 
+                      alt={integration.name} 
+                      className="w-full h-full object-cover"
+                    />
+                  </div>
+                  <div>
+                    <div className="flex items-center">
+                      <h3 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>{integration.name}</h3>
+                      {integration.status && (
+                        <span className={`ml-2 px-2 py-0.5 rounded-full text-xs ${
+                          integration.status === 'Popular' 
+                            ? 'bg-green-500/10 text-green-500' 
+                            : 'bg-blue-500/10 text-blue-400'
+                        }`}>
+                          {integration.status}
+                        </span>
+                      )}
+                    </div>
+                    <span className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>{integration.category}</span>
+                  </div>
+                </div>
+              </div>
+  
+              {/* Description */}
+              <p className={`${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'} mb-4`}>{integration.description}</p>
+  
+              {/* Features */}
+              <div className="mb-6">
+                <h4 className={`text-sm font-semibold ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'} mb-2`}>Key Features</h4>
+                <ul className="grid grid-cols-2 gap-2">
+                  {integration.features.map((feature, index) => (
+                    <li key={index} className={`flex items-center text-sm ${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'}`}>
+                      <div className="w-1.5 h-1.5 rounded-full bg-blue-500 mr-2"></div>
+                      {feature}
+                    </li>
+                  ))}
+                </ul>
+              </div>
+  
+              {/* Action Button */}
+              <button className={`w-full ${theme === 'dark' ? 'bg-gray-700 hover:bg-gray-600' : 'bg-gray-100 hover:bg-gray-200'} text-${theme === 'dark' ? 'white' : 'gray-900'} rounded-lg px-4 py-2 flex items-center justify-center space-x-2 transition-colors`}>
+                <span>Learn More</span>
+                <ArrowRight className="w-4 h-4" />
+              </button>
+            </div>
+          ))}
+        </div>
+  
+        {/* Coming Soon Section */}
+        <div className={`mt-8 bg-gradient-to-r ${theme === 'dark' ? 'from-blue-500/10 to-purple-500/10' : 'from-blue-100 to-purple-100'} rounded-lg p-6`}>
+          <h2 className={`text-lg font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>More Integrations Coming Soon</h2>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>We are constantly adding new integrations. Request the ones you need!</p>
+          <button className="mt-4 bg-blue-500 hover:bg-blue-600 text-white px-4 py-2 rounded-lg transition-colors">
+            Request Integration
+          </button>
+        </div>
+      </div>
+    )
+  }

+ 132 - 0
src/app/dashboard/suggestions/page.tsx

@@ -0,0 +1,132 @@
+// src/app/dashboard/suggestions/page.tsx
+'use client'
+import { 
+  Lightbulb,
+  TrendingUp,
+  DollarSign,
+  Target,
+  ArrowRight,
+  ShoppingBag,
+  ArrowUpRight
+} from 'lucide-react'
+import Link from 'next/link'
+import { useTheme } from '@/contexts/themecontext'
+
+const suggestions = [
+  {
+    id: 1,
+    type: 'Tool',
+    title: 'Video Editing Suite',
+    description: 'Professional video editing tool optimized for social media',
+    trendLink: 'Rising demand in vertical video content',
+    roi: 'Expected ROI: 3.2x',
+    price: '$49/month',
+    category: 'Content Creation',
+    designGuide: true
+  },
+  {
+    id: 2,
+    type: 'Service',
+    title: 'Social Media Strategy',
+    description: 'Personalized content calendar & hashtag research',
+    trendLink: 'Engagement optimization trending up',
+    roi: 'Expected ROI: 2.8x',
+    price: '$299/month',
+    category: 'Marketing',
+    designGuide: true
+  },
+  {
+    id: 3,
+    type: 'Tool',
+    title: 'AI Caption Generator',
+    description: 'Create engaging captions using AI technology',
+    trendLink: 'AI tools adoption growing',
+    roi: 'Expected ROI: 4.1x',
+    price: '$29/month',
+    category: 'AI Tools',
+    designGuide: false
+  }
+]
+
+export default function SuggestionsPage() {
+  const { theme } = useTheme()
+
+  return (
+    <div className="p-6">
+      {/* Header */}
+      <div className="mb-8">
+        <h1 className={`text-4xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2 flex items-center`}>
+          <Lightbulb className="w-8 h-8 mr-3 text-yellow-500" />
+          Suggestions
+        </h1>
+        <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>Discover tools and services to grow your presence</p>
+      </div>
+
+      {/* Suggestions Grid */}
+      <div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
+        {suggestions.map((item) => (
+          <div key={item.id} className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 hover:ring-2 hover:ring-blue-500/50 transition-all shadow-lg`}>
+            {/* Header */}
+            <div className="flex items-start justify-between mb-4">
+              <span className="px-2 py-1 bg-blue-500/10 text-blue-400 rounded text-sm">
+                {item.type}
+              </span>
+              <span className={`text-xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>{item.price}</span>
+            </div>
+
+            {/* Content */}
+            <h3 className={`text-xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-2`}>{item.title}</h3>
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mb-4`}>{item.description}</p>
+
+            {/* Links */}
+            <div className="space-y-3 mb-6">
+              <Link 
+                href="/dashboard/trends" 
+                className="flex items-center text-sm text-blue-400 hover:text-blue-300"
+              >
+                <TrendingUp className="w-4 h-4 mr-2" />
+                <span>{item.trendLink}</span>
+                <ArrowUpRight className="w-4 h-4 ml-2" />
+              </Link>
+
+              {item.designGuide && (
+                <Link 
+                  href="/dashboard/design" 
+                  className="flex items-center text-sm text-purple-400 hover:text-purple-300"
+                >
+                  <Target className="w-4 h-4 mr-2" />
+                  <span>View design guide</span>
+                  <ArrowUpRight className="w-4 h-4 ml-2" />
+                </Link>
+              )}
+
+              <div className="flex items-center text-sm">
+                <DollarSign className="w-4 h-4 mr-2 text-yellow-500" />
+                <span className={`${theme === 'dark' ? 'text-gray-300' : 'text-gray-600'}`}>{item.roi}</span>
+              </div>
+            </div>
+
+            {/* Action Button */}
+            <button className="w-full bg-blue-500 hover:bg-blue-600 text-white rounded-lg px-4 py-2 flex items-center justify-center space-x-2 transition-colors">
+              <ShoppingBag className="w-4 h-4" />
+              <span>Learn More</span>
+            </button>
+          </div>
+        ))}
+      </div>
+
+      {/* Quick Actions */}
+      <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mt-8">
+        {['Compare Solutions', 'Schedule Demo', 'Custom Solution'].map((action) => (
+          <button 
+            key={action}
+            className={`${theme === 'dark' ? 'bg-gray-800 hover:bg-gray-700' : 'bg-white hover:bg-gray-50'} rounded-lg p-4 flex items-center justify-between transition-colors shadow-lg`}
+          >
+            <span className={theme === 'dark' ? 'text-white' : 'text-gray-900'}>{action}</span>
+            <ArrowRight className={`w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+          </button>
+        ))}
+      </div>
+    </div>
+  )
+}

+ 233 - 0
src/app/dashboard/trends/page.tsx

@@ -0,0 +1,233 @@
+// src/app/dashboard/trends/page.tsx
+'use client'
+import { 
+  Instagram, 
+  TrendingUp, 
+  Users, 
+  Activity,
+} from 'lucide-react'
+import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts'
+import { useTheme } from '@/contexts/themecontext'
+
+// Mock data remains the same
+const audienceGrowthData = [
+  { date: 'Jan', instagram: 15000, tiktok: 25000 },
+  { date: 'Feb', instagram: 17000, tiktok: 32000 },
+  { date: 'Mar', instagram: 19000, tiktok: 38000 },
+  { date: 'Apr', instagram: 22000, tiktok: 45000 },
+  { date: 'May', instagram: 24000, tiktok: 52000 },
+  { date: 'Jun', instagram: 28000, tiktok: 58000 },
+]
+
+const engagementData = [
+  { time: '12am', instagram: 1.2, tiktok: 2.5 },
+  { time: '4am', instagram: 0.8, tiktok: 1.8 },
+  { time: '8am', instagram: 2.8, tiktok: 3.9 },
+  { time: '12pm', instagram: 3.9, tiktok: 4.8 },
+  { time: '4pm', instagram: 3.5, tiktok: 5.2 },
+  { time: '8pm', instagram: 2.9, tiktok: 4.1 },
+]
+
+const trendingHashtags = [
+  { tag: '#design', posts: '2.1M', growth: '+12%' },
+  { tag: '#ui', posts: '1.8M', growth: '+8%' },
+  { tag: '#webdesign', posts: '1.6M', growth: '+15%' },
+  { tag: '#minimal', posts: '1.2M', growth: '+5%' },
+]
+
+export default function TrendsPage() {  
+  const { theme } = useTheme()
+const isDark = theme === 'dark'
+
+// Define theme-dependent colors
+const colors = {
+  gridStroke: isDark ? '#374151' : '#E5E7EB',
+  axisStroke: isDark ? '#9CA3AF' : '#6B7280',
+  tooltipBg: isDark ? '#1F2937' : '#ffffff',
+  tooltipBorder: isDark ? 'none' : '1px solid #E5E7EB',
+  tooltipText: isDark ? '#ffffff' : '#111827',
+}
+  return (
+    <div className="p-6">
+      {/* Header */}
+      <div className="mb-8">
+        <h1 className="text-4xl font-bold dark:text-white  mb-2 flex items-center">Tendances des réseaux sociaux</h1>
+        <p className="text-gray-400 text-lg dark:text-gray-400">Suivez les performances de vos réseaux sociaux et les insights de votre audience</p>
+      </div>
+
+      {/* Platform Stats */}
+      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
+        {/* Instagram Stats */}
+        <div className="bg-white dark:bg-gradient-to-r from-purple-500/10 to-pink-500/10 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-4">
+            <Instagram className="w-6 h-6 text-pink-500" />
+            <span className="text-green-500 flex items-center text-sm">
+              <TrendingUp className="w-4 h-4 mr-1" /> 12%
+            </span>
+          </div>
+          <h3 className="text-2xl font-bold text-gray-900  mb-1">24.8k</h3>
+          <p className="text-gray-600 dark:text-gray-400 text-sm">Abonnés Instagram</p>
+        </div>
+
+        {/* TikTok Stats */}
+        <div className="bg-white dark:bg-gradient-to-r from-blue-500/10 to-cyan-500/10 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-4">
+            <svg className="w-6 h-6 text-cyan-500" viewBox="0 0 24 24" fill="currentColor">
+              <path d="M19.59 6.69a4.83 4.83 0 01-3.77-4.25V2h-3.45v13.67a2.89 2.89 0 01-5.2 1.74 2.89 2.89 0 012.31-4.64 2.93 2.93 0 01.88.13V9.4a6.84 6.84 0 00-1-.05A6.33 6.33 0 005 20.1a6.34 6.34 0 0011-4.31v-7a8.16 8.16 0 004.65 1.48V6.69z"/>
+            </svg>
+            <span className="text-green-500 flex items-center text-sm">
+              <TrendingUp className="w-4 h-4 mr-1" /> 28%
+            </span>
+          </div>
+          <h3 className="text-2xl font-bold text-gray-900  mb-1">58.2k</h3>
+          <p className="text-gray-600 dark:text-gray-400 text-sm">Abonnés TikTok</p>
+        </div>
+
+        {/* Engagement Rate */}
+        <div className="bg-white dark:bg-gradient-to-r from-green-500/10 to-emerald-500/10 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-4">
+            <Activity className="w-6 h-6 text-emerald-500" />
+            <span className="text-green-500 flex items-center text-sm">
+              <TrendingUp className="w-4 h-4 mr-1" /> 5%
+            </span>
+          </div>
+          <h3 className="text-2xl font-bold text-gray-900  mb-1">4.2%</h3>
+          <p className="text-gray-600 dark:text-gray-400 text-sm">Taux d&apos;engagement moyen</p>
+        </div>
+
+        {/* Audience Reach */}
+        <div className="bg-white dark:bg-gradient-to-r from-orange-500/10 to-amber-500/10 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-4">
+            <Users className="w-6 h-6 text-amber-500" />
+            <span className="text-green-500 flex items-center text-sm">
+              <TrendingUp className="w-4 h-4 mr-1" /> 15%
+            </span>
+          </div>
+          <h3 className="text-2xl font-bold text-gray-900  mb-1">1.2M</h3>
+          <p className="text-gray-600 dark:text-gray-400 text-sm">Portée totale</p>
+        </div>
+      </div>
+
+      {/* Charts Section */}
+      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
+        {/* Audience Growth Chart */}
+        <div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-6">
+            <h2 className="text-xl font-bold text-gray-900 dark:text-white">Croissance de l&apos;audience</h2>
+            <select className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white text-sm rounded-md px-3 py-2 border-0 focus:ring-2 focus:ring-blue-500">
+              <option>6 derniers mois</option>
+              <option>L&apos;année dernière</option>
+            </select>
+          </div>
+          <div className="h-64">
+            <ResponsiveContainer width="100%" height="100%">
+              <AreaChart data={audienceGrowthData}>
+                <CartesianGrid strokeDasharray="3 3" stroke={colors.gridStroke} />
+                <XAxis dataKey="date" stroke={colors.axisStroke} />
+                <YAxis stroke={colors.axisStroke} />
+                <Tooltip 
+                  contentStyle={{ 
+                    backgroundColor: colors.tooltipBg,
+                    border: colors.tooltipBorder,
+                    borderRadius: '0.5rem',
+                    color: colors.tooltipText
+                  }}
+                />
+                <Area 
+                  type="monotone" 
+                  dataKey="instagram" 
+                  stroke="#E1306C"
+                  fill="#E1306C"
+                  fillOpacity={0.1}
+                />
+                <Area 
+                  type="monotone" 
+                  dataKey="tiktok" 
+                  stroke="#69C9D0"
+                  fill="#69C9D0"
+                  fillOpacity={0.1}
+                />
+              </AreaChart>
+            </ResponsiveContainer>
+          </div>
+        </div>
+
+        {/* Engagement Times Chart */}
+        <div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+          <div className="flex items-center justify-between mb-6">
+            <h2 className="text-xl font-bold text-gray-900 dark:text-white">Meilleurs moments d&apos;engagement</h2>
+            <select className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white text-sm rounded-md px-3 py-2 border-0 focus:ring-2 focus:ring-blue-500">
+              <option>Aujourd&apos;hui</option>
+              <option>Cette semaine</option>
+            </select>
+          </div>
+          <div className="h-64">
+            <ResponsiveContainer width="100%" height="100%">
+              <LineChart data={engagementData}>
+                <CartesianGrid strokeDasharray="3 3" stroke={colors.gridStroke} />
+                <XAxis dataKey="time" stroke={colors.axisStroke} />
+                <YAxis stroke={colors.axisStroke} />
+                <Tooltip 
+                  contentStyle={{ 
+                    backgroundColor: colors.tooltipBg,
+                    border: colors.tooltipBorder,
+                    borderRadius: '0.5rem',
+                    color: colors.tooltipText
+                  }}
+                />
+                <Line 
+                  type="monotone" 
+                  dataKey="instagram" 
+                  stroke="#E1306C" 
+                  strokeWidth={2}
+                  dot={{ fill: '#E1306C' }}
+                />
+                <Line 
+                  type="monotone" 
+                  dataKey="tiktok" 
+                  stroke="#69C9D0" 
+                  strokeWidth={2}
+                  dot={{ fill: '#69C9D0' }}
+                />
+              </LineChart>
+            </ResponsiveContainer>
+          </div>
+        </div>
+      </div>
+
+
+      {/* Trending Hashtags */}
+      <div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-transparent shadow-sm">
+        <div className="flex items-center justify-between mb-6">
+          <h2 className="text-xl font-bold text-gray-900 dark:text-white">Hashtags tendance</h2>
+          <select className="bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-white text-sm rounded-md px-3 py-2 border-0 focus:ring-2 focus:ring-blue-500">
+            <option>Global</option>
+            <option>Votre niche</option>
+          </select>
+        </div>
+
+        <div className="space-y-4">
+          {trendingHashtags.map((item) => (
+            <div key={item.tag} className="flex items-center justify-between p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 rounded-lg transition-colors">
+              <div className="flex items-center space-x-4">
+                <div className="text-lg font-medium text-blue-500 dark:text-blue-400">
+                  {item.tag}
+                </div>
+              </div>
+              <div className="flex items-center space-x-6">
+                <div className="text-right">
+                  <div className="text-gray-900 dark:text-white font-medium mb-1">{item.posts}</div>
+                  <span className="text-sm text-gray-600 dark:text-gray-400">Total des publications</span>
+                </div>
+                <div className="text-right">
+                  <div className="text-green-500 font-medium">{item.growth}</div>
+                  <span className="text-sm text-gray-600 dark:text-gray-400">Croissance</span>
+                </div>
+              </div>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}

BIN
src/app/favicon.ico


+ 15 - 0
src/app/globals.css

@@ -19,3 +19,18 @@ body {
   background: var(--background);
   font-family: Arial, Helvetica, sans-serif;
 }
+
+/* Custom scrollbar styles */
+::-webkit-scrollbar {
+  width: 12px;
+}
+
+::-webkit-scrollbar-track {
+  background: #111827;
+}
+
+::-webkit-scrollbar-thumb {
+  background-color: var(--foreground);
+  border-radius: 10px;
+  border: 3px solid var(--background);
+}

+ 168 - 0
src/app/invite/page.tsx

@@ -0,0 +1,168 @@
+'use client';
+
+import { Suspense } from 'react'
+import { useEffect, useState } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import { ArrowRight, Moon, Sun } from 'lucide-react';
+import { validateInviteToken } from '@/lib/api/core'
+import Image from 'next/image'
+import byom from '@/app/assets/byom.png'
+import { useTheme } from '@/contexts/themecontext'
+
+function InvitContent() {
+  const router = useRouter();
+  const searchParams = useSearchParams();
+  const token = searchParams.get('token');
+  const { theme, toggleTheme } = useTheme();
+  const [isLoading, setIsLoading] = useState(true);
+  const [error, setError] = useState<string | null>(null);
+  const [isValid, setIsValid] = useState(false);
+  const [email, setEmail] = useState<string>('');
+
+  useEffect(() => {
+    const validateToken = async () => {
+      if (!token) {
+        setError('Aucun jeton d\'invitation fourni');
+        setIsLoading(false);
+        return;
+      }
+
+      try {
+        const response = await validateInviteToken(token);
+        setIsValid(true);
+        if (response.email) {
+          setEmail(response.email);
+        }
+      } catch (error) {
+        setError(error instanceof Error ? error.message : 'Échec de la validation de l\'invitation');
+      } finally {
+        setIsLoading(false);
+      }
+    };
+
+    validateToken();
+  }, [token]);
+
+  const handleContinueToRegister = () => {
+    router.push(`/register/member?token=${token}&email=${email}`);
+  };
+
+  const handleDecline = () => {
+    router.push('/');
+  };
+
+  if (isLoading) {
+    return (
+      <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col items-center justify-center relative p-4 transition-colors duration-300`}>
+        <div className={`w-full max-w-md ${theme === 'dark' ? 'bg-gray-800/50 backdrop-blur-xl' : 'bg-white/80 backdrop-blur-xl'} rounded-2xl shadow-2xl p-8 transition-all duration-300`}>
+          <div className="flex justify-center">
+            <div className="w-8 h-8 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
+          </div>
+        </div>
+      </div>
+    );
+  }
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col items-center justify-center relative p-4 transition-colors duration-300`}>
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-3 rounded-xl ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      <div className={`w-full max-w-md ${theme === 'dark' ? 'bg-gray-800/50 backdrop-blur-xl' : 'bg-white/80 backdrop-blur-xl'} rounded-2xl shadow-2xl p-8 transition-all duration-300`}>
+        <div className="flex justify-center mb-8 transform hover:scale-105 transition-transform duration-300">
+          <Image 
+            src={byom} 
+            alt="BYOM" 
+            width={200} 
+            className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300 drop-shadow-lg`}
+          />
+        </div>
+        
+        <div className="text-center mb-8">
+          <h1 className={`text-3xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-3 tracking-tight`}>
+            Invitation à l&apos;espace de travail
+          </h1>
+          {email && (
+            <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>
+              pour <span className={theme === 'dark' ? 'text-white' : 'text-gray-900'}>{email}</span>
+            </p>
+          )}
+        </div>
+
+        <div className="space-y-6">
+          {error ? (
+            <div className="space-y-4">
+              <div className={`p-4 rounded-xl ${theme === 'dark' ? 'bg-red-900/50 text-red-300' : 'bg-red-100 text-red-600'} backdrop-blur-xl`}>
+                {error}
+              </div>
+              <button 
+                className="w-full flex items-center justify-center px-4 py-3 rounded-xl bg-blue-500 text-white font-medium hover:bg-blue-600 hover:shadow-lg hover:-translate-y-0.5 transition-all duration-300"
+                onClick={() => router.push('/')}
+              >
+                Retour à l&apos;accueil
+              </button>
+            </div>
+          ) : isValid ? (
+            <div className="space-y-6">
+              <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-base`}>
+                Vous devez créer un compte pour rejoindre cet espace de travail. Cliquez sur continuer pour configurer votre compte.
+              </p>
+              <div className="flex gap-3">
+                <button
+                  className="flex-1 flex items-center justify-center px-4 py-3 rounded-xl bg-blue-500 text-white font-medium hover:bg-blue-600 hover:shadow-lg hover:-translate-y-0.5 transition-all duration-300 disabled:opacity-70 disabled:cursor-not-allowed disabled:hover:translate-y-0"
+                  onClick={handleContinueToRegister}
+                  disabled={isLoading}
+                >
+                  {isLoading ? (
+                    <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
+                  ) : (
+                    <>
+                      <span>Continuer</span>
+                      <ArrowRight className="w-5 h-5 ml-2 transform group-hover:translate-x-1 transition-transform duration-300" />
+                    </>
+                  )}
+                </button>
+                <button
+                  className={`flex-1 px-4 py-3 rounded-xl font-medium transition-all duration-300 disabled:opacity-70 disabled:cursor-not-allowed ${
+                    theme === 'dark'
+                      ? 'bg-gray-700 text-white hover:bg-gray-600'
+                      : 'bg-gray-200 text-gray-900 hover:bg-gray-300'
+                  }`}
+                  onClick={handleDecline}
+                  disabled={isLoading}
+                >
+                  Refuser
+                </button>
+              </div>
+            </div>
+          ) : (
+            <div className={`p-4 rounded-xl ${theme === 'dark' ? 'bg-yellow-900/50 text-yellow-300' : 'bg-yellow-100 text-yellow-600'} backdrop-blur-xl`}>
+              Ce lien d&apos;invitation semble invalide ou a expiré.
+            </div>
+          )}
+        </div>
+      </div>
+    </div>
+  );
+}
+
+export default function InvitePage() {
+  return (
+    <Suspense fallback={<div>Loading...</div>}>
+      <InvitContent />
+    </Suspense>
+  )
+}

+ 12 - 14
src/app/layout.tsx

@@ -1,5 +1,6 @@
-import type { Metadata } from "next";
+// src/app/layout.tsx
 import { Geist, Geist_Mono } from "next/font/google";
+import { ThemeProvider } from "@/contexts/themecontext";
 import "./globals.css";
 
 const geistSans = Geist({
@@ -12,23 +13,20 @@ const geistMono = Geist_Mono({
   subsets: ["latin"],
 });
 
-export const metadata: Metadata = {
-  title: "Create Next App",
-  description: "Generated by create next app",
-};
-
 export default function RootLayout({
   children,
-}: Readonly<{
+}: {
   children: React.ReactNode;
-}>) {
+}) {
   return (
-    <html lang="en">
-      <body
-        className={`${geistSans.variable} ${geistMono.variable} antialiased`}
-      >
-        {children}
+    <html lang="en" suppressHydrationWarning>
+      <head>
+        <title>BYOM - Dashboard</title>
+        <link rel="icon" href="/favicon.ico" sizes="any" />
+      </head>
+      <body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
+        <ThemeProvider>{children}</ThemeProvider>
       </body>
     </html>
   );
-}
+}

+ 217 - 0
src/app/login/page.tsx

@@ -0,0 +1,217 @@
+'use client';
+
+import { Suspense } from 'react'
+import { useState } from 'react';
+import { useRouter, useSearchParams } from 'next/navigation';
+import { Eye, EyeOff, ArrowRight, Sun, Moon, Mail, Lock } from 'lucide-react';
+import Image from 'next/image';
+import byom from '@/app/assets/byom.png';
+import { useTheme } from '@/contexts/themecontext';
+import Link from 'next/link';
+import { login } from '@/lib/api/core';
+
+function LoginContent() {
+  const router = useRouter();
+  const searchParams = useSearchParams();
+  const { theme, toggleTheme } = useTheme();
+  const [showPassword, setShowPassword] = useState(false);
+  const [formData, setFormData] = useState({
+    email: searchParams.get('email') || '',
+    password: ''
+  });
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<string | null>(null);
+
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    setFormData(prev => ({
+      ...prev,
+      [e.target.name]: e.target.value
+    }));
+  };
+
+  const handleLogin = async (e: React.FormEvent) => {
+    e.preventDefault();
+    setError(null);
+    setIsLoading(true);
+
+    try {
+      const token = await login(formData);
+
+      if (!token || !token.token) {
+        throw new Error('Token is missing from response');
+      }
+      
+      localStorage.removeItem('token');
+      localStorage.setItem('token', token.token);
+      router.push('/dashboard');
+    } catch (err) {
+      setError(err instanceof Error ? err.message : 'Login failed');
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col items-center justify-center relative p-4 transition-colors duration-300`}>
+      {/* Theme Toggle */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-3 rounded-xl ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      <div className={`w-full max-w-md ${theme === 'dark' ? 'bg-gray-800/50 backdrop-blur-xl' : 'bg-white/80 backdrop-blur-xl'} rounded-2xl shadow-2xl p-8 transition-all duration-300`}>
+        {/* Logo */}
+        <div className="flex justify-center mb-8 transform hover:scale-105 transition-transform duration-300">
+          <Image 
+            src={byom} 
+            alt="BYOM" 
+            width={200} 
+            className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300 drop-shadow-lg`}
+          />
+        </div>
+
+        {/* Welcome Text */}
+        <div className="text-center mb-8">
+          <h1 className={`text-3xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-3 tracking-tight`}>
+            Bienvenue
+          </h1>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>
+            Connectez-vous pour accéder à votre espace
+          </p>
+        </div>
+
+        {/* Login Form */}
+        <form onSubmit={handleLogin} className="space-y-6">
+          {error && (
+            <div className={`p-4 rounded-xl ${theme === 'dark' ? 'bg-red-900/50 text-red-300' : 'bg-red-100 text-red-600'} backdrop-blur-xl`}>
+              {error}
+            </div>
+          )}
+
+          <div className="space-y-4">
+            <div>
+              <label htmlFor="email" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+                Adresse email
+              </label>
+              <div className="relative">
+                <Mail className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+                <input
+                  id="email"
+                  name="email"
+                  type="email"
+                  value={formData.email}
+                  onChange={handleChange}
+                  className={`w-full pl-11 pr-4 py-3 rounded-xl ${
+                    theme === 'dark' 
+                      ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                      : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+                  } border-none focus:ring-2 transition-all duration-300`}
+                  placeholder="vous@exemple.com"
+                  required
+                />
+              </div>
+            </div>
+
+            <div>
+              <label htmlFor="password" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+                Mot de passe
+              </label>
+              <div className="relative">
+                <Lock className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+                <input
+                  id="password"
+                  name="password"
+                  type={showPassword ? 'text' : 'password'}
+                  value={formData.password}
+                  onChange={handleChange}
+                  className={`w-full pl-11 pr-11 py-3 rounded-xl ${
+                    theme === 'dark' 
+                      ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                      : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+                  } border-none focus:ring-2 transition-all duration-300`}
+                  placeholder="••••••••"
+                  required
+                />
+                <button
+                  type="button"
+                  onClick={() => setShowPassword(!showPassword)}
+                  className={`absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-lg ${
+                    theme === 'dark' ? 'text-gray-400 hover:text-gray-300 hover:bg-gray-600/50' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200/50'
+                  } transition-all duration-300`}
+                >
+                  {showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
+                </button>
+              </div>
+            </div>
+          </div>
+
+          <div className="flex items-center justify-between pt-2">
+            <div className="flex items-center">
+              <input
+                id="remember"
+                type="checkbox"
+                className="h-4 w-4 rounded-md border-gray-300 text-blue-500 focus:ring-blue-500 transition-colors duration-300"
+              />
+              <label htmlFor="remember" className={`ml-2 block text-sm ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}`}>
+                Se souvenir de moi
+              </label>
+            </div>
+            <Link
+              href="/forgot-password"
+              className="text-sm font-medium text-blue-500 hover:text-blue-400 transition-colors duration-300"
+            >
+              Mot de passe oublié ?
+            </Link>
+          </div>
+
+          <button
+            type="submit"
+            disabled={isLoading}
+            className={`w-full flex items-center justify-center px-4 py-3 rounded-xl bg-blue-500 text-white font-medium 
+              ${isLoading ? 'opacity-70 cursor-not-allowed' : 'hover:bg-blue-600 hover:shadow-lg hover:-translate-y-0.5'} 
+              transition-all duration-300 mt-6`}
+          >
+            {isLoading ? (
+              <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
+            ) : (
+              <>
+                <span>Se connecter</span>
+                <ArrowRight className="w-5 h-5 ml-2 transform group-hover:translate-x-1 transition-transform duration-300" />
+              </>
+            )}
+          </button>
+        </form>
+
+        {/* Register Link */}
+        <p className={`mt-8 text-center text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+          Pas encore de compte ?{' '}
+          <Link
+            href="/register"
+            className="font-medium text-blue-500 hover:text-blue-400 transition-colors duration-300 hover:underline"
+          >
+            Créer un compte
+          </Link>
+        </p>
+      </div>
+    </div>
+  );
+}
+
+export default function LoginPage() {
+  return (
+    <Suspense fallback={<div>Loading...</div>}>
+      <LoginContent />
+    </Suspense>
+  )
+}

+ 78 - 0
src/app/not-found.tsx

@@ -0,0 +1,78 @@
+// src/app/not-found.tsx
+'use client'
+
+import { useRouter } from 'next/navigation'
+import { Home, ArrowLeft, Search } from 'lucide-react'
+
+export default function NotFound() {
+  const router = useRouter()
+  
+  return (
+    <div className="min-h-screen bg-white dark:bg-gray-900 flex flex-col items-center justify-center px-6">
+      {/* 404 Heading with Gradient */}
+      <div className="relative">
+        <h1 className="text-[150px] font-bold text-transparent bg-clip-text bg-gradient-to-r from-blue-600 to-purple-600 leading-none select-none">
+          404
+        </h1>
+        <div className="absolute -bottom-2 left-0 right-0 h-2 bg-gradient-to-r from-blue-600/20 to-purple-600/20 blur-sm" />
+      </div>
+
+      {/* Error Message */}
+      <h2 className="mt-8 text-3xl font-bold text-gray-900 dark:text-white text-center">
+        Page not found
+      </h2>
+      <p className="mt-4 text-gray-600 dark:text-gray-400 text-center max-w-md">
+        Sorry, we couldn ot find the page you are looking for. It might have been moved or does not exist.
+      </p>
+
+      {/* Action Buttons */}
+      <div className="mt-12 flex flex-col sm:flex-row gap-4">
+        <button
+          onClick={() => router.back()}
+          className="inline-flex items-center justify-center px-6 py-3 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors duration-200"
+        >
+          <ArrowLeft className="w-5 h-5 mr-2" />
+          Go back
+        </button>
+
+        <button
+          onClick={() => router.push('/dashboard')}
+          className="inline-flex items-center justify-center px-6 py-3 bg-blue-600 rounded-lg text-white hover:bg-blue-700 transition-colors duration-200"
+        >
+          <Home className="w-5 h-5 mr-2" />
+          Back to Dashboard
+        </button>
+      </div>
+
+      {/* Search Suggestion */}
+      <div className="mt-12 w-full max-w-md">
+        <div className="relative">
+          <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-5 h-5 text-gray-400" />
+          <input
+            type="text"
+            placeholder="Search for pages..."
+            className="w-full pl-10 pr-4 py-3 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
+          />
+        </div>
+      </div>
+
+      {/* Quick Links */}
+      <div className="mt-12">
+        <h3 className="text-gray-600 dark:text-gray-400 text-sm font-medium mb-4 text-center">
+          Quick Links
+        </h3>
+        <div className="flex flex-wrap justify-center gap-4">
+          {['Trends', 'Suggestions', 'Design', 'Ads', 'Showcase'].map((link) => (
+            <button
+              key={link}
+              onClick={() => router.push(`/dashboard/${link.toLowerCase()}`)}
+              className="px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white bg-gray-50 dark:bg-gray-800/50 rounded-full transition-colors duration-200 hover:bg-gray-100 dark:hover:bg-gray-700/50"
+            >
+              {link}
+            </button>
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}

+ 44 - 96
src/app/page.tsx

@@ -1,101 +1,49 @@
-import Image from "next/image";
+// src/app/page.tsx
+'use client'
 
-export default function Home() {
-  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">
-        <Image
-          className="dark:invert"
-          src="/next.svg"
-          alt="Next.js logo"
-          width={180}
-          height={38}
-          priority
-        />
-        <ol className="list-inside list-decimal text-sm text-center sm:text-left font-[family-name:var(--font-geist-mono)]">
-          <li className="mb-2">
-            Get started by editing{" "}
-            <code className="bg-black/[.05] dark:bg-white/[.06] px-1 py-0.5 rounded font-semibold">
-              src/app/page.tsx
-            </code>
-            .
-          </li>
-          <li>Save and see your changes instantly.</li>
-        </ol>
+import {Moon, Sun } from 'lucide-react'
+import Image from 'next/image'
+import byom from '@/app/assets/byom.png'
+import { useTheme } from '@/contexts/themecontext'
+
+export default function HomePage() {
+
+  const { theme, toggleTheme } = useTheme();
 
-        <div className="flex gap-4 items-center flex-col sm:flex-row">
-          <a
-            className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-foreground text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
-            href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            <Image
-              className="dark:invert"
-              src="/vercel.svg"
-              alt="Vercel logomark"
-              width={20}
-              height={20}
+
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col justify-center relative`}>
+      {/* Theme Toggle Button */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-2 rounded-lg ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-colors shadow-lg`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+            
+      <div className="sm:mx-auto sm:w-full sm:max-w-md px-4">
+        {/* Logo */}
+        <div className="flex justify-center mb-8">
+          <div className="rounded-lg flex items-center justify-center">
+            <Image 
+              src={byom} 
+              alt="BYOM" 
+              width={300}
+              className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300`}
             />
-            Deploy now
-          </a>
-          <a
-            className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
-            href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-            target="_blank"
-            rel="noopener noreferrer"
-          >
-            Read our docs
-          </a>
+          </div>
         </div>
-      </main>
-      <footer className="row-start-3 flex gap-6 flex-wrap items-center justify-center">
-        <a
-          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
-          href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          <Image
-            aria-hidden
-            src="/file.svg"
-            alt="File icon"
-            width={16}
-            height={16}
-          />
-          Learn
-        </a>
-        <a
-          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
-          href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          <Image
-            aria-hidden
-            src="/window.svg"
-            alt="Window icon"
-            width={16}
-            height={16}
-          />
-          Examples
-        </a>
-        <a
-          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
-          href="https://nextjs.org?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
-          target="_blank"
-          rel="noopener noreferrer"
-        >
-          <Image
-            aria-hidden
-            src="/globe.svg"
-            alt="Globe icon"
-            width={16}
-            height={16}
-          />
-          Go to nextjs.org →
-        </a>
-      </footer>
+      </div>
     </div>
-  );
-}
+  )
+}

+ 113 - 0
src/app/page_fancy.tsx

@@ -0,0 +1,113 @@
+// src/app/page.tsx
+'use client'
+
+import { useRouter } from 'next/navigation'
+import { ArrowRight, Github, Twitter, Moon, Sun } from 'lucide-react'
+import Image from 'next/image'
+import byom from '@/app/assets/byom.png'
+import { useTheme } from '@/contexts/themecontext'
+
+export default function HomePage() {
+  const router = useRouter()
+  const { theme, toggleTheme } = useTheme();
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col relative`}>
+      {/* Theme Toggle Button */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-2 rounded-lg ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-colors shadow-lg`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      {/* Navigation */}
+      <nav className="p-4">
+        <div className="max-w-7xl mx-auto flex justify-between items-center">
+          <div className="w-32">
+            <Image 
+              src={byom} 
+              alt="BYOM" 
+              width={100}
+              className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300`}
+            />
+          </div>
+          <div className="flex gap-4">
+            <button 
+              onClick={() => router.push('/login')}
+              className={`px-4 py-2 rounded-lg ${
+                theme === 'dark' 
+                  ? 'text-gray-300 hover:text-white' 
+                  : 'text-gray-700 hover:text-gray-900'
+              } transition-colors`}
+            >
+              Se connecter
+            </button>
+            <button 
+              onClick={() => router.push('/register')}
+              className="px-4 py-2 rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors"
+            >
+              S&apos;inscrire
+            </button>
+          </div>
+        </div>
+      </nav>
+
+      {/* Hero Section */}
+      <main className="flex-1 flex flex-col items-center justify-center px-4 text-center">
+        <h1 className={`text-5xl font-bold mb-6 ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
+          Gérez vos réseaux sociaux <br />
+          <span className="text-blue-500">en toute simplicité</span>
+        </h1>
+        <p className={`text-xl mb-8 max-w-2xl ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+          Planifiez, analysez et optimisez votre présence sur les réseaux sociaux avec notre plateforme tout-en-un.
+        </p>
+        <div className="flex gap-4">
+          <button 
+            onClick={() => router.push('/register')}
+            className="px-6 py-3 rounded-lg bg-blue-500 text-white hover:bg-blue-600 transition-colors flex items-center gap-2"
+          >
+            Commencer gratuitement
+            <ArrowRight className="w-4 h-4" />
+          </button>
+          <button 
+            onClick={() => router.push('/demo')}
+            className={`px-6 py-3 rounded-lg ${
+              theme === 'dark' 
+                ? 'bg-gray-800 text-gray-300 hover:bg-gray-700' 
+                : 'bg-white text-gray-700 hover:bg-gray-100'
+            } transition-colors`}
+          >
+            Voir la démo
+          </button>
+        </div>
+      </main>
+
+      {/* Footer */}
+      <footer className={`p-8 ${theme === 'dark' ? 'border-t border-gray-800' : 'border-t border-gray-200'}`}>
+        <div className="max-w-7xl mx-auto flex justify-between items-center">
+          <p className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+            © 2024 BYOM. Tous droits réservés.
+          </p>
+          <div className="flex gap-4">
+            <a href="#" className={`${theme === 'dark' ? 'text-gray-400 hover:text-white' : 'text-gray-600 hover:text-gray-900'} transition-colors`}>
+              <Github className="w-5 h-5" />
+            </a>
+            <a href="#" className={`${theme === 'dark' ? 'text-gray-400 hover:text-white' : 'text-gray-600 hover:text-gray-900'} transition-colors`}>
+              <Twitter className="w-5 h-5" />
+            </a>
+          </div>
+        </div>
+      </footer>
+    </div>
+  )
+}

+ 76 - 0
src/app/register/member/page.tsx

@@ -0,0 +1,76 @@
+'use client'
+
+import { Suspense } from 'react'
+import { useSearchParams } from 'next/navigation'
+import RegistrationForm from '@/components/forms/registrationForm'
+import Image from 'next/image'
+import byom from '@/app/assets/byom.png'
+import { useTheme } from '@/contexts/themecontext'
+import { Moon, Sun } from 'lucide-react'
+
+function MemberRegistrationContent() {
+  const searchParams = useSearchParams()
+  const { theme, toggleTheme } = useTheme()
+
+  
+  const token = searchParams.get('token') || ''
+  const email = searchParams.get('email')
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col items-center justify-center relative p-4 transition-colors duration-300`}>
+      {/* Theme Toggle */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-3 rounded-xl ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      <div className={`w-full max-w-md ${theme === 'dark' ? 'bg-gray-800/50 backdrop-blur-xl' : 'bg-white/80 backdrop-blur-xl'} rounded-2xl shadow-2xl p-8 transition-all duration-300`}>
+        {/* Logo */}
+        <div className="flex justify-center mb-8 transform hover:scale-105 transition-transform duration-300">
+          <Image 
+            src={byom} 
+            alt="BYOM" 
+            width={200} 
+            className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300 drop-shadow-lg`}
+          />
+        </div>
+
+        {/* Welcome Text */}
+        <div className="text-center mb-8">
+          <h1 className={`text-3xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-3 tracking-tight`}>
+            Complétez votre inscription
+          </h1>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>
+            Configurez votre compte pour rejoindre l&apos;espace de travail
+          </p>
+        </div>
+
+        {/* Registration Form */}
+        <RegistrationForm 
+        type="member" 
+        token={token}
+        email={email || undefined}
+      />
+      </div>
+    </div>
+  );
+}
+
+export default function MemberRegistrationPage() {
+  return (
+    <Suspense fallback={<div>Loading...</div>}>
+      <MemberRegistrationContent />
+    </Suspense>
+  )
+}

+ 57 - 0
src/app/register/page.tsx

@@ -0,0 +1,57 @@
+'use client'
+
+import RegistrationForm from '@/components/forms/registrationForm'
+import Image from 'next/image'
+import byom from '@/app/assets/byom.png'
+import { useTheme } from '@/contexts/themecontext'
+import { Moon, Sun } from 'lucide-react'
+
+export default function OwnerRegistrationPage() {
+  const { theme, toggleTheme } = useTheme();
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col items-center justify-center relative p-4 transition-colors duration-300`}>
+      {/* Theme Toggle */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-3 rounded-xl ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-all duration-300 shadow-lg hover:shadow-xl transform hover:scale-105`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      <div className={`w-full max-w-md ${theme === 'dark' ? 'bg-gray-800/50 backdrop-blur-xl' : 'bg-white/80 backdrop-blur-xl'} rounded-2xl shadow-2xl p-8 transition-all duration-300`}>
+        {/* Logo */}
+        <div className="flex justify-center mb-8 transform hover:scale-105 transition-transform duration-300">
+          <Image 
+            src={byom} 
+            alt="BYOM" 
+            width={200} 
+            className={`${theme === 'dark' ? '' : 'invert'} transition-all duration-300 drop-shadow-lg`}
+          />
+        </div>
+
+        {/* Welcome Text */}
+        <div className="text-center mb-8">
+          <h1 className={`text-3xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-3 tracking-tight`}>
+            Créez votre compte
+          </h1>
+          <p className={`${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} text-lg`}>
+            Configurez votre espace de travail et commencez
+          </p>
+        </div>
+
+        {/* Registration Form */}
+        <RegistrationForm type="owner" />
+      </div>
+    </div>
+  );
+}

+ 132 - 0
src/app/setup/page.tsx

@@ -0,0 +1,132 @@
+'use client';
+
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { Moon, Sun } from 'lucide-react';
+import { useTheme } from '@/contexts/themecontext';
+import { createWorkspace, applyUserToWorkspace } from '@/lib/api/core';
+
+interface SetupData {
+  name: string;
+}
+
+export default function SetupPage() {
+  const router = useRouter();
+  const { theme, toggleTheme } = useTheme();
+  const [currentStep] = useState(1);
+  const [data, setData] = useState<SetupData>({
+    name: '',
+  });
+  const [isLoading, setIsLoading] = useState(false);
+  const [, setError] = useState<string | null>(null);
+
+  const handleSubmit = async () => {
+    setIsLoading(true);
+    setError(null);
+
+    try {
+      const workspace = await createWorkspace(data);
+
+      console.log('Workspace:', workspace);
+
+      const userData = {
+        workspace_id: workspace.id, 
+        role: 'owner'
+      }
+
+      await applyUserToWorkspace(userData);
+
+
+      router.push('/dashboard');
+    } catch (err) {
+      setError(err instanceof Error ? err.message : 'La configuration a échoué');
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  return (
+    <div className={`min-h-screen ${theme === 'dark' ? 'bg-gray-900' : 'bg-gray-50'} flex flex-col justify-center py-12 px-4 sm:px-6 lg:px-8 relative`}>
+      {/* Theme Toggle Button */}
+      <button
+        onClick={toggleTheme}
+        className={`absolute top-4 right-4 p-2 rounded-lg ${
+          theme === 'dark' 
+            ? 'bg-gray-800 hover:bg-gray-700' 
+            : 'bg-white hover:bg-gray-100'
+        } transition-colors shadow-lg`}
+        aria-label="Toggle theme"
+      >
+        {theme === 'dark' ? (
+          <Sun className="w-5 h-5 text-yellow-500" />
+        ) : (
+          <Moon className="w-5 h-5 text-gray-600" />
+        )}
+      </button>
+
+      <div className="sm:mx-auto sm:w-full sm:max-w-2xl">
+        {/* Progress Steps */}
+        <div className="flex justify-center mb-8">
+          <div className="flex items-center space-x-4">
+            <div className={`w-8 h-8 rounded-full flex items-center justify-center text-white ${
+              currentStep >= 1 ? 'bg-blue-500' : theme === 'dark' ? 'bg-gray-700' : 'bg-gray-300'
+            }`}>
+              1
+            </div>
+            <div className={`w-16 h-1 ${currentStep >= 2 ? 'bg-blue-500' : theme === 'dark' ? 'bg-gray-700' : 'bg-gray-300'}`} />
+            <div className={`w-8 h-8 rounded-full flex items-center justify-center text-white ${
+              currentStep >= 2 ? 'bg-blue-500' : theme === 'dark' ? 'bg-gray-700' : 'bg-gray-300'
+            }`}>
+              2
+            </div>
+          </div>
+        </div>
+
+        {/* Step 1: Workspace Name */}
+        {currentStep === 1 && (
+          <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} py-8 px-4 shadow sm:rounded-lg sm:px-10`}>
+            <h2 className={`text-2xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-6`}>
+              Nommez votre espace de travail
+            </h2>
+            <div className="space-y-6">
+              <div>
+                <label htmlFor="workspace-name" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-200' : 'text-gray-700'}`}>
+                  Nom de l&apos;espace de travail
+                </label>
+                <div className="mt-1">
+                  <input
+                    type="text"
+                    id="workspace-name"
+                    value={data.name}
+                    onChange={(e) => setData(prev => ({ ...prev, name: e.target.value }))}
+                    className={`block w-full appearance-none rounded-md border-0 ${
+                      theme === 'dark'
+                        ? 'bg-gray-700 text-white placeholder-gray-400'
+                        : 'bg-gray-50 text-gray-900 placeholder-gray-500'
+                    } px-3 py-2 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500 sm:text-sm`}
+                    placeholder="Entrez le nom de l'espace de travail"
+                    required
+                  />
+                </div>
+              </div>
+
+              <div className="flex justify-end">
+                <button
+                  onClick={handleSubmit}
+                  disabled={!data.name.trim() || isLoading}
+                  className="flex items-center justify-center rounded-md bg-blue-500 px-4 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-400 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 disabled:opacity-50 disabled:cursor-not-allowed"
+                >
+                  {isLoading ? (
+                    <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
+                  ) : (
+                    'Terminer la configuration'
+                  )}
+                </button>
+              </div>
+            </div>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+}

+ 238 - 0
src/components/forms/registrationForm.tsx

@@ -0,0 +1,238 @@
+'use client';
+
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { Eye, EyeOff, Mail, Lock, User, Phone, ArrowRight } from 'lucide-react';
+import { createWorkspaceOwner, createInvitedUser } from '@/lib/api/core';
+import { useTheme } from '@/contexts/themecontext';
+import Link from 'next/link';
+
+interface RegistrationFormProps {
+  type: 'owner' | 'member';
+  token?: string;
+  email?: string;
+}
+
+export default function RegistrationForm({ type, token, email }: RegistrationFormProps) {
+  const router = useRouter();
+  const { theme } = useTheme();
+  const [showPassword, setShowPassword] = useState(false);
+  const [formData, setFormData] = useState({
+    email: email || '',
+    password: '',
+    confirmPassword: '',
+    name: '',
+    phone_number: '',
+  });
+  const [isLoading, setIsLoading] = useState(false);
+  const [error, setError] = useState<string | null>(null);
+
+  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
+    setFormData(prev => ({
+      ...prev,
+      [e.target.name]: e.target.value
+    }));
+  };
+
+  const handleSubmit = async (e: React.FormEvent) => {
+    e.preventDefault();
+    setError(null);
+
+    if (formData.password !== formData.confirmPassword) {
+      setError("Les mots de passe ne correspondent pas");
+      return;
+    }
+
+    setIsLoading(true);
+
+    try {
+      if (type === 'owner') {
+        await createWorkspaceOwner(formData);
+        router.push('/login');
+      }
+
+      if (type === 'member') {
+        if (!token) {
+          throw new Error('Le jeton est requis pour l\'inscription des membres');
+        }
+        const response = await createInvitedUser({ ...formData, token });
+        router.push(`/login?workspace_id=${response.workspace_id}&email=${response.user.email}`);
+      }
+    } catch (err) {
+      setError(err instanceof Error ? err.message : 'Échec de l\'inscription');
+    } finally {
+      setIsLoading(false);
+    }
+  };
+
+  return (
+    <form onSubmit={handleSubmit} className="space-y-6">
+      {error && (
+        <div className={`p-4 rounded-xl ${theme === 'dark' ? 'bg-red-900/50 text-red-300' : 'bg-red-100 text-red-600'} backdrop-blur-xl`}>
+          {error}
+        </div>
+      )}
+
+      <div className="space-y-4">
+        {/* Name Field */}
+        <div>
+          <label htmlFor="name" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+            Nom complet
+          </label>
+          <div className="relative">
+            <User className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+            <input
+              id="name"
+              name="name"
+              type="text"
+              required
+              value={formData.name}
+              onChange={handleChange}
+              className={`w-full pl-11 pr-4 py-3 rounded-xl ${
+                theme === 'dark' 
+                  ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                  : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+              } border-none focus:ring-2 transition-all duration-300`}
+              placeholder="Entrez votre nom complet"
+            />
+          </div>
+        </div>
+
+        {/* Email Field */}
+        <div>
+          <label htmlFor="email" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+            Adresse email
+          </label>
+          <div className="relative">
+            <Mail className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+            <input
+              id="email"
+              name="email"
+              type="email"
+              autoComplete="email"
+              required
+              value={formData.email}
+              onChange={handleChange}
+              disabled={type === 'member' && !!email}
+              className={`w-full pl-11 pr-4 py-3 rounded-xl ${
+                theme === 'dark' 
+                  ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                  : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+              } border-none focus:ring-2 transition-all duration-300 disabled:opacity-50`}
+              placeholder="vous@exemple.com"
+            />
+          </div>
+        </div>
+
+        {/* Password Field */}
+        <div>
+          <label htmlFor="password" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+            Mot de passe
+          </label>
+          <div className="relative">
+            <Lock className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+            <input
+              id="password"
+              name="password"
+              type={showPassword ? 'text' : 'password'}
+              required
+              value={formData.password}
+              onChange={handleChange}
+              className={`w-full pl-11 pr-11 py-3 rounded-xl ${
+                theme === 'dark' 
+                  ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                  : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+              } border-none focus:ring-2 transition-all duration-300`}
+              placeholder="Créez un mot de passe"
+            />
+            <button
+              type="button"
+              onClick={() => setShowPassword(!showPassword)}
+              className={`absolute right-3 top-1/2 -translate-y-1/2 p-1 rounded-lg ${
+                theme === 'dark' ? 'text-gray-400 hover:text-gray-300 hover:bg-gray-600/50' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200/50'
+              } transition-all duration-300`}
+            >
+              {showPassword ? <EyeOff className="w-5 h-5" /> : <Eye className="w-5 h-5" />}
+            </button>
+          </div>
+        </div>
+
+        {/* Confirm Password Field */}
+        <div>
+          <label htmlFor="confirmPassword" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+            Confirmez le mot de passe
+          </label>
+          <div className="relative">
+            <Lock className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+            <input
+              id="confirmPassword"
+              name="confirmPassword"
+              type="password"
+              required
+              value={formData.confirmPassword}
+              onChange={handleChange}
+              className={`w-full pl-11 pr-4 py-3 rounded-xl ${
+                theme === 'dark' 
+                  ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                  : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+              } border-none focus:ring-2 transition-all duration-300`}
+              placeholder="Confirmez votre mot de passe"
+            />
+          </div>
+        </div>
+
+        {/* Phone Number Field */}
+        <div>
+          <label htmlFor="phone_number" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+            Numéro de téléphone
+          </label>
+          <div className="relative">
+            <Phone className={`absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-500'}`} />
+            <input
+              id="phone_number"
+              name="phone_number"
+              type="tel"
+              value={formData.phone_number}
+              onChange={handleChange}
+              className={`w-full pl-11 pr-4 py-3 rounded-xl ${
+                theme === 'dark' 
+                  ? 'bg-gray-700/50 text-white placeholder-gray-400 focus:ring-blue-500' 
+                  : 'bg-gray-50/50 text-gray-900 placeholder-gray-500 focus:ring-blue-500'
+              } border-none focus:ring-2 transition-all duration-300`}
+              placeholder="Entrez votre numéro de téléphone"
+            />
+          </div>
+        </div>
+      </div>
+
+      <button
+        type="submit"
+        disabled={isLoading}
+        className={`w-full flex items-center justify-center px-4 py-3 rounded-xl bg-blue-500 text-white font-medium 
+          ${isLoading ? 'opacity-70 cursor-not-allowed' : 'hover:bg-blue-600 hover:shadow-lg hover:-translate-y-0.5'} 
+          transition-all duration-300 mt-6`}
+      >
+        {isLoading ? (
+          <div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin" />
+        ) : (
+          <>
+            <span>Créer un compte</span>
+            <ArrowRight className="w-5 h-5 ml-2 transform group-hover:translate-x-1 transition-transform duration-300" />
+          </>
+        )}
+      </button>
+
+      {type === 'owner' && (
+        <p className={`mt-8 text-center text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
+          Vous avez déjà un compte ?{' '}
+          <Link
+            href="/login"
+            className="font-medium text-blue-500 hover:text-blue-400 transition-colors duration-300 hover:underline"
+          >
+            Se connecter
+          </Link>
+        </p>
+      )}
+    </form>
+  );
+}

+ 198 - 0
src/components/profiles/addProfile.tsx

@@ -0,0 +1,198 @@
+// src/components/Onboarding.tsx
+'use client'
+import { useState } from 'react';
+import { X, ArrowRight, Twitter, InstagramIcon, Facebook, Linkedin } from 'lucide-react';
+import { createProfile } from '@/lib/api/core';
+import { useTheme } from '@/contexts/themecontext';
+
+interface AddProfileProps {
+  onComplete: () => void;
+}
+
+interface SocialInput {
+  type: string;
+  identifier: string;
+}
+
+export default function AddProfile({ onComplete }: AddProfileProps) {
+  const { theme } = useTheme();
+  const [step, setStep] = useState(1);
+  const [profileName, setProfileName] = useState('');
+  const [socials, setSocials] = useState<SocialInput[]>([]);
+  const [error, setError] = useState('');
+
+  const handleAddSocial = (type: string) => {
+    setSocials([...socials, { type, identifier: '' }]);
+  };
+
+  const handleUpdateSocial = (index: number, identifier: string) => {
+    const newSocials = [...socials];
+    newSocials[index].identifier = identifier;
+    setSocials(newSocials);
+  };
+
+  const handleRemoveSocial = (index: number) => {
+    setSocials(socials.filter((_, i) => i !== index));
+  };
+
+  const handleSubmit = async () => {
+    try {
+      setError('');
+      const workspaceId = localStorage.getItem('selectedWorkspaceId');
+      if (!workspaceId) {
+        setError('No workspace selected');
+        return;
+      }
+
+      if (!profileName.trim()) {
+        setError('Profile name is required');
+        return;
+      }
+
+      // Filter out socials with empty identifiers
+      const validSocials = socials.filter(s => s.identifier.trim() !== '');
+
+      await createProfile({
+        name: profileName.trim(),
+        workspace_id: workspaceId,
+        socials: validSocials
+      });
+
+      onComplete();
+    } catch (error) {
+      console.error('Failed to create profile:', error);
+      setError('Failed to create profile. Please try again.');
+    }
+  };
+
+  return (
+    <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
+      <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg shadow-xl max-w-md w-full p-6 relative`}>
+        <button
+          onClick={onComplete}
+          className={`absolute top-4 right-4 p-1 rounded-full ${
+            theme === 'dark' ? 'hover:bg-gray-700' : 'hover:bg-gray-100'
+          }`}
+        >
+          <X className="w-5 h-5" />
+        </button>
+
+        <div className="mb-8">
+          <h2 className={`text-xl font-semibold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
+            {step === 1 ? 'Ajouter un profil' : 'Ajouter des réseaux sociaux'}
+          </h2>
+          <div className="flex mt-4">
+            <div className={`h-1 flex-1 rounded ${step === 1 ? 'bg-blue-500' : 'bg-gray-300'}`} />
+            <div className={`h-1 flex-1 rounded ml-2 ${step === 2 ? 'bg-blue-500' : 'bg-gray-300'}`} />
+          </div>
+        </div>
+
+        {error && (
+          <div className="mb-4 p-3 bg-red-100 text-red-700 rounded-md">
+            {error}
+          </div>
+        )}
+
+        {step === 1 ? (
+          <div>
+            <div className="mb-6">
+              <label className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'} mb-2`}>
+                Nom du profil
+              </label>
+              <input
+                type="text"
+                value={profileName}
+                onChange={(e) => setProfileName(e.target.value)}
+                className={`w-full px-3 py-2 rounded-md border ${
+                  theme === 'dark' 
+                    ? 'bg-gray-700 border-gray-600 text-white' 
+                    : 'bg-white border-gray-300 text-gray-900'
+                } focus:ring-2 focus:ring-blue-500 focus:border-transparent`}
+                placeholder="Entrez le nom du profil"
+              />
+            </div>
+            <button
+              onClick={() => setStep(2)}
+              disabled={!profileName.trim()}
+              className={`w-full flex items-center justify-center px-4 py-2 rounded-md ${
+                profileName.trim() 
+                  ? 'bg-blue-500 hover:bg-blue-600 text-white' 
+                  : 'bg-gray-300 text-gray-500 cursor-not-allowed'
+              }`}
+            >
+              Suivant
+              <ArrowRight className="w-4 h-4 ml-2" />
+            </button>
+          </div>
+        ) : (
+          <div>
+            <div className="space-y-4 mb-6">
+              {socials.map((social, index) => (
+                <div key={index} className="flex items-center space-x-2">
+                  <input
+                    type="text"
+                    value={social.identifier}
+                    onChange={(e) => handleUpdateSocial(index, e.target.value)}
+                    className={`flex-1 px-3 py-2 rounded-md border ${
+                      theme === 'dark' 
+                        ? 'bg-gray-700 border-gray-600 text-white' 
+                        : 'bg-white border-gray-300 text-gray-900'
+                    } focus:ring-2 focus:ring-blue-500 focus:border-transparent`}
+                    placeholder={`Entrez l'identifiant ${social.type}`}
+                  />
+                  <button
+                    onClick={() => handleRemoveSocial(index)}
+                    className="p-2 text-red-500 hover:bg-red-100 rounded-md"
+                  >
+                    <X className="w-4 h-4" />
+                  </button>
+                </div>
+              ))}
+
+              <div className="flex flex-wrap gap-2">
+                {['twitter', 'instagram', 'facebook', 'linkedin'].filter(
+                  type => !socials.some(s => s.type === type)
+                ).map((type) => (
+                  <button
+                    key={type}
+                    onClick={() => handleAddSocial(type)}
+                    className={`flex items-center px-3 py-2 rounded-md ${
+                      theme === 'dark' 
+                        ? 'bg-gray-700 hover:bg-gray-600' 
+                        : 'bg-gray-100 hover:bg-gray-200'
+                    }`}
+                  >
+                    {type === 'twitter' && <Twitter className="w-4 h-4 mr-2" />}
+                    {type === 'instagram' && <InstagramIcon className="w-4 h-4 mr-2" />}
+                    {type === 'facebook' && <Facebook className="w-4 h-4 mr-2" />}
+                    {type === 'linkedin' && <Linkedin className="w-4 h-4 mr-2" />}
+                    Ajouter {type.charAt(0).toUpperCase() + type.slice(1)}
+                  </button>
+                ))}
+              </div>
+            </div>
+
+            <div className="flex space-x-3">
+              <button
+                onClick={() => setStep(1)}
+                className={`flex-1 px-4 py-2 rounded-md ${
+                  theme === 'dark' 
+                    ? 'bg-gray-700 hover:bg-gray-600' 
+                    : 'bg-gray-100 hover:bg-gray-200'
+                }`}
+              >
+                Retour
+              </button>
+              <button
+                onClick={handleSubmit}
+                className="flex-1 px-4 py-2 rounded-md bg-blue-500 hover:bg-blue-600 text-white"
+              >
+                Créer le profil
+              </button>
+            </div>
+          </div>
+        )}
+      </div>
+    </div>
+  );
+}

+ 128 - 0
src/components/shared/inviteCollaborators.tsx

@@ -0,0 +1,128 @@
+// src/components/InviteCollaborators.tsx
+'use client'
+
+import { useState } from 'react';
+import { UserPlus, ChevronDown, X } from 'lucide-react';
+import { inviteUser } from '@/lib/api/core';
+import { useTheme } from '@/contexts/themecontext';
+
+export default function InviteCollaborators({ onClose }: { onClose: () => void }) {
+  const [email, setEmail] = useState('');
+  const [role, setRole] = useState('Éditeur');
+  const [isOpen, setIsOpen] = useState(false);
+  const { theme } = useTheme();
+
+  const roles = ['Admin', 'Éditeur', 'Spectateur'];
+
+  const handleInvite = async () => {
+    // Send invitation logic (e.g., API call)
+    console.log(`Inviting ${email} as ${role}`);
+
+    // retrieve workspaceId from context or local storage
+    try {
+      //get workspaceId from context or local storage
+      const workspaceId = localStorage.getItem('selectedWorkspaceId') || '';
+      const data = { email, role, workspace_id: workspaceId };
+      await inviteUser(data);
+    } catch (err) {
+      console.error('Failed to send invitation, error:', err);
+    } finally {
+      setEmail(''); // Clear input after sending
+      onClose();
+    }
+  };
+
+  return (
+    <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-6 max-w-md w-full shadow-lg relative`}>
+      {/* Close Button */}
+      <button
+        onClick={onClose}
+        className={`absolute top-4 right-4 p-2 rounded-lg ${
+          theme === 'dark' 
+            ? 'hover:bg-gray-700 text-gray-400 hover:text-gray-300' 
+            : 'hover:bg-gray-100 text-gray-600 hover:text-gray-700'
+        } transition-colors`}
+        aria-label="Close"
+      >
+        <X className="w-5 h-5" />
+      </button>
+
+      <h2 className={`text-xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'} mb-4`}>
+        Inviter des Collaborateurs
+      </h2>
+      
+      {/* Email Input */}
+      <div className="mb-4">
+        <label htmlFor="email" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mb-1`}>
+          Adresse Email
+        </label>
+        <input
+          type="email"
+          id="email"
+          placeholder="Entrez l'email du collaborateur"
+          value={email}
+          onChange={(e) => setEmail(e.target.value)}
+          className={`w-full ${
+            theme === 'dark' 
+              ? 'bg-gray-700 text-white placeholder-gray-400' 
+              : 'bg-gray-50 text-gray-900 placeholder-gray-500'
+          } rounded-lg px-4 py-2 focus:ring-2 focus:ring-blue-500`}
+        />
+      </div>
+
+      {/* Role Dropdown */}
+      <div className="mb-6">
+        <label htmlFor="role" className={`block text-sm font-medium ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mb-1`}>
+          Rôle
+        </label>
+        <div className="relative">
+          <button
+            onClick={() => setIsOpen(!isOpen)}
+            className={`w-full ${
+              theme === 'dark' 
+                ? 'bg-gray-700 text-white' 
+                : 'bg-gray-50 text-gray-900'
+            } rounded-lg px-4 py-2 flex items-center justify-between`}
+          >
+            <span>{role}</span>
+            <ChevronDown className="w-4 h-4" />
+          </button>
+          {isOpen && (
+            <div className={`absolute mt-2 w-full ${
+              theme === 'dark' 
+                ? 'bg-gray-700' 
+                : 'bg-white'
+            } rounded-lg shadow-lg z-10`}>
+              {roles.map((r) => (
+                <button
+                  key={r}
+                  onClick={() => {
+                    setRole(r);
+                    setIsOpen(false);
+                  }}
+                  className={`w-full px-4 py-2 text-left ${
+                    theme === 'dark'
+                      ? 'text-white hover:bg-gray-600'
+                      : 'text-gray-900 hover:bg-gray-50'
+                  }`}
+                >
+                  {r}
+                </button>
+              ))}
+            </div>
+          )}
+        </div>
+      </div>
+
+      {/* Invite Button */}
+      <button
+        onClick={handleInvite}
+        disabled={!email}
+        className="w-full bg-blue-500 text-white px-4 py-2 rounded-lg flex items-center justify-center space-x-2 hover:bg-blue-600 disabled:bg-gray-600 disabled:cursor-not-allowed transition-colors"
+      >
+        <UserPlus className="w-4 h-4" />
+        <span>Envoyer l&apos;Invitation</span>
+      </button>
+    </div>
+  );
+}

+ 23 - 0
src/components/shared/themeToggle.tsx

@@ -0,0 +1,23 @@
+// src/components/ThemeToggle.tsx
+'use client'
+
+import { Sun, Moon } from 'lucide-react'
+import { useTheme } from '@/contexts/themecontext'
+
+export function ThemeToggle() {
+  const { theme, toggleTheme } = useTheme()
+
+  return (
+    <button
+      onClick={toggleTheme}
+      className="p-2 rounded-lg bg-gray-800 dark:bg-gray-100 text-gray-100 dark:text-gray-800 hover:bg-gray-700 dark:hover:bg-gray-200 transition-colors"
+      aria-label="Toggle theme"
+    >
+      {theme === 'dark' ? (
+        <Sun className="w-5 h-5" />
+      ) : (
+        <Moon className="w-5 h-5" />
+      )}
+    </button>
+  )
+}

+ 7 - 0
src/config/index.ts

@@ -0,0 +1,7 @@
+
+export const config = {
+  apiCoreUrl: process.env.NEXT_PUBLIC_API_CORE_URL
+};
+
+// Add this console.log for debugging
+console.log('Config loaded with API URL:', process.env.NEXT_PUBLIC_API_CORE_URL);

+ 47 - 0
src/contexts/themecontext.tsx

@@ -0,0 +1,47 @@
+// src/contexts/ThemeContext.tsx
+'use client'
+
+import { createContext, useContext, useEffect, useState } from 'react'
+
+type Theme = 'dark' | 'light'
+
+interface ThemeContextType {
+  theme: Theme
+  toggleTheme: () => void
+}
+
+const ThemeContext = createContext<ThemeContextType | undefined>(undefined)
+
+export function ThemeProvider({ children }: { children: React.ReactNode }) {
+  const [theme, setTheme] = useState<Theme>('light')
+
+  useEffect(() => {
+    // Only check local storage, default to light
+    const storedTheme = localStorage.getItem('theme') as Theme
+    const initialTheme = storedTheme || 'light'
+    
+    setTheme(initialTheme)
+    document.documentElement.classList.toggle('dark', initialTheme === 'dark')
+  }, [])
+
+  const toggleTheme = () => {
+    const newTheme = theme === 'dark' ? 'light' : 'dark'
+    setTheme(newTheme)
+    localStorage.setItem('theme', newTheme)
+    document.documentElement.classList.toggle('dark', newTheme === 'dark')
+  }
+
+  return (
+    <ThemeContext.Provider value={{ theme, toggleTheme }}>
+      {children}
+    </ThemeContext.Provider>
+  )
+}
+
+export function useTheme() {
+  const context = useContext(ThemeContext)
+  if (!context) {
+    throw new Error('useTheme must be used within ThemeProvider')
+  }
+  return context
+}

+ 0 - 0
src/lib/api/auth.ts


+ 229 - 0
src/lib/api/core.ts

@@ -0,0 +1,229 @@
+import { RegisterOwner, User, InviteData, InviteToken, InvitedUser, UserMe } from '@/types/auth';
+import { config } from '@/config';
+
+
+const API_BASE_URL = `${config.apiCoreUrl}`
+
+// Helper function to handle API errors
+const handleApiError = (error: unknown, customMessage: string): never => {
+  console.error(`${customMessage}:`, error);
+  if (error instanceof Response) {
+    throw new Error(`${customMessage} (Status: ${error.status})`);
+  }
+  throw new Error(customMessage);
+};
+
+// Helper function to make authenticated requests
+const authenticatedRequest = async (endpoint: string, options: RequestInit = {}): Promise<Response> => {
+  const token = localStorage.getItem('token');
+  if (!token) {
+    throw new Error('No authentication token found');
+  }
+
+  const response = await fetch(`${API_BASE_URL}${endpoint}`, {
+    ...options,
+    headers: {
+      ...options.headers,
+      'Authorization': `Bearer ${token}`,
+      'Content-Type': 'application/json',
+    },
+  });
+
+  if (!response.ok) {
+    throw response;
+  }
+
+  return response;
+};
+
+export async function createWorkspaceOwner(data: RegisterOwner): Promise<User> {
+  try {
+    const response = await fetch(`${API_BASE_URL}/workspaces/owner`, {
+      method: 'PUT',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(data),
+    });
+
+    if (!response.ok) {
+      throw response;
+    }
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to create workspace owner');
+  }
+}
+
+export async function createWorkspace(data: { name: string }): Promise<{ id: string }> {
+  try {
+    const response = await authenticatedRequest('/workspaces', {
+      method: 'POST',
+      body: JSON.stringify(data),
+    });
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to create workspace');
+  }
+}
+
+export async function applyUserToWorkspace(data: { workspace_id: string; role: string }): Promise<void> {
+  try {
+    await authenticatedRequest('/users/workspaces', {
+      method: 'POST',
+      body: JSON.stringify(data),
+    });
+  } catch (error) {
+    return handleApiError(error, 'Failed to apply user to workspace');
+  }
+}
+
+export async function createInvitedUser(data: RegisterOwner & { token: string }): Promise<InvitedUser> {
+  try {
+    const body = {
+      email: data.email,
+      name: data.name,
+      password: data.password,
+      phone_number: data.phone_number,
+      token: data.token
+    };
+
+    const response = await fetch(`${API_BASE_URL}/workspaces/invite`, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(body),
+    });
+
+    if (!response.ok) {
+      throw response;
+    }
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to accept invitation');
+  }
+}
+
+export async function inviteUser(data: InviteData): Promise<{ token: string }> {
+  try {
+    const response = await authenticatedRequest('/users/invite', {
+      method: 'POST',
+      body: JSON.stringify(data),
+    });
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to invite user');
+  }
+}
+
+export async function validateInviteToken(token: string): Promise<InviteToken> {
+  try {
+    const response = await fetch(`${API_BASE_URL}/workspaces/invite/validate?token=${token}`, {
+      method: 'GET',
+      headers: { 'Content-Type': 'application/json' },
+    });
+
+    if (!response.ok) {
+      throw response;
+    }
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to validate invite token');
+  }
+}
+
+export async function login(data: { email: string; password: string }): Promise<{ token: string }> {
+
+  const loginUrl = `${API_BASE_URL}/auth/login`;
+  console.log(`Attempting login at: ${loginUrl}`);
+
+  try {
+    const response = await fetch(loginUrl, {
+      method: 'POST',
+      headers: { 'Content-Type': 'application/json' },
+      body: JSON.stringify(data),
+    });
+
+    if (!response.ok) {
+      throw response;
+    }
+
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to login');
+  }
+}
+
+export async function userMe(): Promise<UserMe> {
+  try {
+    const response = await authenticatedRequest('/users/me');
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to fetch user data');
+  }
+}
+
+export interface Profile {
+  id: string;
+  name: string;
+  workspace_id: string;
+  created_at: string;
+  socials?: Social[];
+}
+
+export interface Social {
+  id: string;
+  type: string;
+  identifier: string;
+  profile_id: string;
+  last_sync: string;
+}
+
+export async function getProfilesByWorkspace(workspaceId: string): Promise<Profile[]> {
+  try {
+    const response = await authenticatedRequest(`/profiles/workspaces?workspaceID=${workspaceId}`);
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to fetch profiles');
+  }
+}
+
+export async function createProfile(data: { 
+  name: string; 
+  workspace_id: string;
+  socials?: { type: string; identifier: string; }[];
+}): Promise<Profile> {
+  try {
+    const response = await authenticatedRequest('/profiles', {
+      method: 'POST',
+      body: JSON.stringify(data),
+    });
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to create profile');
+  }
+}
+
+export async function updateProfile(profileId: string, data: { name: string }): Promise<Profile> {
+  try {
+    const response = await authenticatedRequest(`/profiles/${profileId}`, {
+      method: 'PUT',
+      body: JSON.stringify(data),
+    });
+    return response.json();
+  } catch (error) {
+    return handleApiError(error, 'Failed to update profile');
+  }
+}
+
+export async function deleteProfile(profileId: string): Promise<void> {
+  try {
+    await authenticatedRequest(`/profiles/${profileId}`, {
+      method: 'DELETE',
+    });
+  } catch (error) {
+    return handleApiError(error, 'Failed to delete profile');
+  }
+}

+ 0 - 0
src/lib/api/profiles.ts


+ 0 - 0
src/lib/api/workspaces.ts


+ 6 - 0
src/lib/utils.ts

@@ -0,0 +1,6 @@
+import { clsx, type ClassValue } from "clsx"
+import { twMerge } from "tailwind-merge"
+
+export function cn(...inputs: ClassValue[]) {
+  return twMerge(clsx(inputs))
+}

+ 53 - 0
src/types/auth.ts

@@ -0,0 +1,53 @@
+export interface User {
+    id: string;
+    email: string;
+    name: string;
+    phone_number: string;
+    role: string;
+    status: string;
+}
+
+export interface InvitedUser {
+    user: User;
+    workspace_id: string;
+}
+  
+export interface RegisterOwner {
+    email: string;
+    name: string;
+    password: string;
+    phone_number: string;
+}
+
+export interface RegisterInvitedUser {
+    email: string;
+    name: string;
+    password: string;
+    phone_number: string;
+    token: string;
+    
+}
+
+export interface InviteData {
+    email: string;
+    role: string;
+    workspace_id: string;
+}
+
+export interface InviteToken {
+    valid: boolean;
+    workspace_id: string;
+    email: string;
+    error: string;
+}
+
+export interface UserMe {
+    user: User;
+    workspaces: Workspace[];
+}
+
+export interface Workspace {
+    id: string;
+    name: string;
+}
+    

+ 11 - 3
tailwind.config.ts

@@ -1,3 +1,4 @@
+// tailwind.config.ts
 import type { Config } from "tailwindcss";
 
 export default {
@@ -6,13 +7,20 @@ export default {
     "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
     "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
   ],
+  darkMode: 'class', // Enable class-based dark mode
   theme: {
     extend: {
       colors: {
-        background: "var(--background)",
-        foreground: "var(--foreground)",
+        background: {
+          DEFAULT: '#ffffff',
+          dark: '#111827',
+        },
+        foreground: {
+          DEFAULT: '#111827',
+          dark: '#ffffff',
+        },
       },
     },
   },
   plugins: [],
-} satisfies Config;
+} satisfies Config;

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác