diff --git a/app/auth/login/components/LoginForm.tsx b/app/auth/login/components/LoginForm.tsx
index 034068d..8512d8c 100644
--- a/app/auth/login/components/LoginForm.tsx
+++ b/app/auth/login/components/LoginForm.tsx
@@ -4,9 +4,9 @@
import { useState, useEffect, useRef } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
import { toast } from "sonner";
import { Loader2, ArrowRight } from "lucide-react";
import { motion } from "framer-motion";
@@ -186,4 +186,4 @@ export default function LoginForm() {
);
-}
\ No newline at end of file
+}
diff --git a/app/auth/register/page.tsx b/app/auth/register/page.tsx
index b275b97..a98aaca 100644
--- a/app/auth/register/page.tsx
+++ b/app/auth/register/page.tsx
@@ -4,12 +4,12 @@ import { useState } from "react";
import { useRouter } from "next/navigation";
import Image from "next/image";
import Link from "next/link";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
import { Loader2, ArrowRight } from "lucide-react";
import { motion } from "framer-motion";
-import { toast } from "@/hooks/use-toast";
+import { toast } from "@/lib/hooks/use-toast";
// Matches LoginPage background
const AuthBackground = () => (
@@ -164,3 +164,5 @@ export default function RegisterPage() {
);
}
+
+
diff --git a/app/auth/reset-password/page.tsx b/app/auth/reset-password/page.tsx
index 1fb5dd4..92c4b60 100644
--- a/app/auth/reset-password/page.tsx
+++ b/app/auth/reset-password/page.tsx
@@ -2,11 +2,11 @@
import { useState, useEffect, Suspense } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import Link from "next/link";
-import { fetchClient } from "@/lib/api-client";
+import { fetchClient } from "@/lib/api/api-client";
import { toast } from "sonner";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
import { Loader2 } from "lucide-react";
interface Vendor {
@@ -193,3 +193,5 @@ export default function ResetPasswordPage() {
);
}
+
+
diff --git a/app/dashboard/admin/ban/page.tsx b/app/dashboard/admin/ban/page.tsx
index 9f3f37e..098cc46 100644
--- a/app/dashboard/admin/ban/page.tsx
+++ b/app/dashboard/admin/ban/page.tsx
@@ -1,18 +1,18 @@
"use client";
import React, { useState, useEffect } from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Textarea } from "@/components/ui/textarea";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
-import { Badge } from "@/components/ui/badge";
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
-import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
+import { Textarea } from "@/components/common/textarea";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
+import { Badge } from "@/components/common/badge";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
+import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/common/alert-dialog";
import { UserX, Shield, Search, Ban, Unlock, Loader2 } from "lucide-react";
-import { fetchClient } from "@/lib/api-client";
-import { useToast } from "@/hooks/use-toast";
+import { fetchClient } from "@/lib/api/api-client";
+import { useToast } from "@/lib/hooks/use-toast";
interface BlockedUser {
_id: string;
@@ -445,4 +445,5 @@ export default function AdminBanPage() {
);
-}
\ No newline at end of file
+}
+
diff --git a/app/dashboard/admin/invite/page.tsx b/app/dashboard/admin/invite/page.tsx
index 9a1693a..d593d6e 100644
--- a/app/dashboard/admin/invite/page.tsx
+++ b/app/dashboard/admin/invite/page.tsx
@@ -1,13 +1,13 @@
"use client";
import React from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Textarea } from "@/components/ui/textarea";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
-import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
+import { Textarea } from "@/components/common/textarea";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
+import { Badge } from "@/components/common/badge";
import { UserPlus, Mail, Copy, Check } from "lucide-react";
import { useState } from "react";
import Link from "next/link";
@@ -206,3 +206,4 @@ export default function AdminInvitePage() {
);
}
+
diff --git a/app/dashboard/admin/orders/page.tsx b/app/dashboard/admin/orders/page.tsx
index 8da0c31..aa13fd2 100644
--- a/app/dashboard/admin/orders/page.tsx
+++ b/app/dashboard/admin/orders/page.tsx
@@ -1,9 +1,9 @@
import React from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
import { Package, AlertTriangle, CheckCircle2, XCircle, DollarSign } from "lucide-react";
import { fetchServer } from "@/lib/api";
import OrdersTable from "@/components/admin/OrdersTable";
-import { MotionWrapper } from "@/components/ui/motion-wrapper";
+import { MotionWrapper } from "@/components/common/motion-wrapper";
export const dynamic = 'force-dynamic';
@@ -241,3 +241,5 @@ export default async function AdminOrdersPage() {
);
}
+
+
diff --git a/app/dashboard/admin/page.tsx b/app/dashboard/admin/page.tsx
index def9a4e..0198514 100644
--- a/app/dashboard/admin/page.tsx
+++ b/app/dashboard/admin/page.tsx
@@ -2,12 +2,12 @@
export const dynamic = "force-dynamic";
import React, { Suspense, lazy, useState, useEffect, Component, ReactNode } from "react";
-import { Button } from "@/components/ui/button";
+import { Button } from "@/components/common/button";
import Link from "next/link";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
import { AlertCircle, RefreshCw } from "lucide-react";
// Error Boundary Component
@@ -466,3 +466,4 @@ export default function AdminPage() {
}
+
diff --git a/app/dashboard/admin/status/page.tsx b/app/dashboard/admin/status/page.tsx
index c9b73bf..383b6b4 100644
--- a/app/dashboard/admin/status/page.tsx
+++ b/app/dashboard/admin/status/page.tsx
@@ -1,10 +1,10 @@
import React from "react";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
import { Server, Database, Cpu, HardDrive, Activity, Zap } from "lucide-react";
import { fetchServer } from "@/lib/api";
import SystemStatusCard from "@/components/admin/SystemStatusCard";
-import { MotionWrapper } from "@/components/ui/motion-wrapper";
+import { MotionWrapper } from "@/components/common/motion-wrapper";
export const dynamic = 'force-dynamic';
@@ -243,3 +243,5 @@ export default async function AdminStatusPage() {
);
}
+
+
diff --git a/app/dashboard/admin/users/page.tsx b/app/dashboard/admin/users/page.tsx
index 30446ba..ed80df3 100644
--- a/app/dashboard/admin/users/page.tsx
+++ b/app/dashboard/admin/users/page.tsx
@@ -1,15 +1,15 @@
"use client";
import React, { useState, useEffect } from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/common/tooltip";
import { Search, Ban, UserCheck, Package, DollarSign, Loader2, Repeat, Users, ShoppingBag, CreditCard, UserX } from "lucide-react";
-import { fetchClient } from "@/lib/api-client";
-import { useToast } from "@/hooks/use-toast";
+import { fetchClient } from "@/lib/api/api-client";
+import { useToast } from "@/lib/hooks/use-toast";
import { motion, AnimatePresence } from "framer-motion";
interface TelegramUser {
@@ -328,3 +328,5 @@ export default function AdminUsersPage() {
);
}
+
+
diff --git a/app/dashboard/admin/vendors/page.tsx b/app/dashboard/admin/vendors/page.tsx
index e57d400..5a4a65b 100644
--- a/app/dashboard/admin/vendors/page.tsx
+++ b/app/dashboard/admin/vendors/page.tsx
@@ -1,16 +1,16 @@
"use client";
import React, { useState, useEffect, useCallback } from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
import { Search, MoreHorizontal, UserCheck, UserX, Mail, Loader2, Store, Shield, ShieldAlert, Clock, Calendar, Pencil, Plus } from "lucide-react";
-import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog";
-import { Label } from "@/components/ui/label";
-import { fetchClient } from "@/lib/api-client";
-import { useToast } from "@/hooks/use-toast";
+import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/common/dialog";
+import { Label } from "@/components/common/label";
+import { fetchClient } from "@/lib/api/api-client";
+import { useToast } from "@/lib/hooks/use-toast";
import { motion, AnimatePresence } from "framer-motion";
import {
DropdownMenu,
@@ -19,7 +19,7 @@ import {
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu";
+} from "@/components/common/dropdown-menu";
interface Vendor {
_id: string;
@@ -571,3 +571,5 @@ export default function AdminVendorsPage() {
);
}
+
+
diff --git a/app/dashboard/analytics/loading.tsx b/app/dashboard/analytics/loading.tsx
index c3a1483..7ba8343 100644
--- a/app/dashboard/analytics/loading.tsx
+++ b/app/dashboard/analytics/loading.tsx
@@ -1,5 +1,5 @@
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
import Layout from "@/components/layout/layout";
import { SnowLoader } from "@/components/snow-loader";
@@ -61,4 +61,4 @@ export default function AnalyticsLoading() {
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/analytics/page.tsx b/app/dashboard/analytics/page.tsx
index 45e5161..a28100f 100644
--- a/app/dashboard/analytics/page.tsx
+++ b/app/dashboard/analytics/page.tsx
@@ -5,7 +5,7 @@ import Dashboard from "@/components/dashboard/dashboard";
import AnalyticsDashboard from '@/components/analytics/AnalyticsDashboard';
import AnalyticsDashboardSkeleton from '@/components/analytics/AnalyticsDashboardSkeleton';
import StoreSelector from '@/components/analytics/StoreSelector';
-import { getAnalyticsOverviewServer } from '@/lib/server-api';
+import { getAnalyticsOverviewServer } from '@/lib/api/server-api';
import { fetchServer } from '@/lib/api';
import { performance } from 'perf_hooks';
import { Info, GitCommit, User, Zap, BarChart3 } from 'lucide-react';
@@ -34,14 +34,14 @@ export default async function AnalyticsPage({
// Await searchParams as required by Next.js 15+
const resolvedSearchParams = await searchParams;
-
+
// Check for storeId in query parameters (for staff users)
const storeId = resolvedSearchParams?.storeId;
-
+
// Check for storeId in cookies (alternative method for staff users)
const cookieStore = await cookies();
const cookieStoreId = cookieStore.get('storeId')?.value;
-
+
// Use query parameter first, then cookie, then undefined (for vendors)
const finalStoreId = storeId || cookieStoreId;
@@ -73,7 +73,7 @@ export default async function AnalyticsPage({
-
+
v{panelVersion}
@@ -100,12 +100,12 @@ export default async function AnalyticsPage({
);
} catch (error) {
console.error('Error fetching analytics data:', error);
-
+
// If it's a 401/403 error, redirect to login
if (error instanceof Error && error.message.includes('401')) {
- redirect('/login');
+ redirect('/auth/login');
}
-
+
// If it's a 400 error (missing storeId for staff), show store selector
if (error instanceof Error && error.message.includes('400')) {
return (
@@ -122,7 +122,7 @@ export default async function AnalyticsPage({
);
}
-
+
// For other errors, show a fallback
return (
@@ -142,4 +142,4 @@ export default async function AnalyticsPage({
);
}
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/balance/page.tsx b/app/dashboard/balance/page.tsx
index 7e9faf3..6b10598 100644
--- a/app/dashboard/balance/page.tsx
+++ b/app/dashboard/balance/page.tsx
@@ -2,8 +2,8 @@
import { useState } from "react";
import Dashboard from "@/components/dashboard/dashboard";
-import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
+import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/common/card";
+import { Button } from "@/components/common/button";
import { Wallet, Bitcoin, Coins, DollarSign, ArrowUpRight } from "lucide-react";
import { toast } from "sonner";
@@ -166,3 +166,4 @@ export default function BalancePage() {
);
}
+
diff --git a/app/dashboard/categories/page.tsx b/app/dashboard/categories/page.tsx
index f466c3d..3f54bd4 100644
--- a/app/dashboard/categories/page.tsx
+++ b/app/dashboard/categories/page.tsx
@@ -2,8 +2,8 @@
import { useState, useEffect, useRef } from "react";
import Layout from "@/components/layout/layout";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
import { Plus, Pencil, Trash2, ChevronRight, ChevronDown, MoveVertical, FolderTree } from "lucide-react";
import { toast } from "sonner";
import {
@@ -12,7 +12,7 @@ import {
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
+} from "@/components/common/select";
import {
AlertDialog,
AlertDialogAction,
@@ -22,10 +22,10 @@ import {
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
-} from "@/components/ui/alert-dialog";
+} from "@/components/common/alert-dialog";
import { apiRequest } from "@/lib/api";
-import type { Category } from "@/models/categories";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
+import type { Category } from "@/lib/models/categories";
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
import { motion, AnimatePresence } from "framer-motion";
// Drag and Drop imports
@@ -494,4 +494,5 @@ export default function CategoriesPage() {
);
-}
\ No newline at end of file
+}
+
diff --git a/app/dashboard/chats/[id]/loading.tsx b/app/dashboard/chats/[id]/loading.tsx
index 06a3133..8b5294d 100644
--- a/app/dashboard/chats/[id]/loading.tsx
+++ b/app/dashboard/chats/[id]/loading.tsx
@@ -1,6 +1,6 @@
import Layout from "@/components/layout/layout";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
+import { Skeleton } from "@/components/common/skeleton";
import { Loader2 } from "lucide-react";
import { SnowLoader } from "@/components/snow-loader";
diff --git a/app/dashboard/chats/[id]/page.tsx b/app/dashboard/chats/[id]/page.tsx
index 9e5bee1..00e1911 100644
--- a/app/dashboard/chats/[id]/page.tsx
+++ b/app/dashboard/chats/[id]/page.tsx
@@ -1,7 +1,7 @@
import React from "react";
import { Metadata } from "next";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Skeleton } from "@/components/common/skeleton";
import Dashboard from "@/components/dashboard/dashboard";
export const metadata: Metadata = {
diff --git a/app/dashboard/chats/new/page.tsx b/app/dashboard/chats/new/page.tsx
index 03c5723..e56fca2 100644
--- a/app/dashboard/chats/new/page.tsx
+++ b/app/dashboard/chats/new/page.tsx
@@ -1,7 +1,7 @@
import React from "react";
import { Metadata, Viewport } from "next";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Skeleton } from "@/components/common/skeleton";
import Dashboard from "@/components/dashboard/dashboard";
export const metadata: Metadata = {
@@ -42,4 +42,4 @@ export default function NewChatPage() {
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/chats/page.tsx b/app/dashboard/chats/page.tsx
index f338905..0992960 100644
--- a/app/dashboard/chats/page.tsx
+++ b/app/dashboard/chats/page.tsx
@@ -5,10 +5,10 @@ import { useRouter } from "next/navigation";
import Dashboard from "@/components/dashboard/dashboard";
import { MessageCircle, AlertCircle, RefreshCw } from "lucide-react";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { Button } from "@/components/ui/button";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
+import { Button } from "@/components/common/button";
// Error Boundary Component
interface ErrorBoundaryState {
@@ -95,7 +95,7 @@ function ChatTableSkeleton() {
{/* Subtle loading indicator */}
-
+
@@ -115,8 +115,8 @@ function ChatTableSkeleton() {
{['Customer', 'Last Message', 'Date', 'Status', 'Actions'].map((header, i) => (
-
-
+
{[...Array(6)].map((_, i) => (
-
{
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- }
- }, [router]);
-
return (
@@ -185,7 +172,7 @@ export default function ChatsPage() {
Customer Chats
-
+
}>
@@ -194,4 +181,4 @@ export default function ChatsPage() {
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/dashboard-content-wrapper.tsx b/app/dashboard/dashboard-content-wrapper.tsx
index bf0d4df..7726d3e 100644
--- a/app/dashboard/dashboard-content-wrapper.tsx
+++ b/app/dashboard/dashboard-content-wrapper.tsx
@@ -1,11 +1,11 @@
"use client";
import { Component, ReactNode, useState, useEffect, Suspense } from "react";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { Button } from "@/components/ui/button";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
+import { Button } from "@/components/common/button";
import { AlertCircle, RefreshCw } from "lucide-react";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
// Error Boundary Component
interface ErrorBoundaryState {
@@ -260,3 +260,4 @@ export default function DashboardContentWrapper({ children }: { children: ReactN
);
}
+
diff --git a/app/dashboard/loading.tsx b/app/dashboard/loading.tsx
index 6a55e5c..b1db624 100644
--- a/app/dashboard/loading.tsx
+++ b/app/dashboard/loading.tsx
@@ -1,7 +1,7 @@
"use client"
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Skeleton } from "@/components/common/skeleton";
import Layout from "@/components/layout/layout";
import { Loader2 } from "lucide-react";
import { SnowLoader } from "@/components/snow-loader";
@@ -77,4 +77,4 @@ export default function DashboardLoading() {
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/orders/[id]/loading.tsx b/app/dashboard/orders/[id]/loading.tsx
index 8fd214e..7d16b93 100644
--- a/app/dashboard/orders/[id]/loading.tsx
+++ b/app/dashboard/orders/[id]/loading.tsx
@@ -1,7 +1,7 @@
"use client"
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
+import { Skeleton } from "@/components/common/skeleton";
import Layout from "@/components/layout/layout";
import { Loader2 } from "lucide-react";
import { SnowLoader } from "@/components/snow-loader";
diff --git a/app/dashboard/orders/[id]/page.tsx b/app/dashboard/orders/[id]/page.tsx
index 2ebd044..4913e6d 100644
--- a/app/dashboard/orders/[id]/page.tsx
+++ b/app/dashboard/orders/[id]/page.tsx
@@ -4,10 +4,10 @@ import { fetchData } from '@/lib/api';
import { clientFetch } from '@/lib/api';
import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Textarea } from "@/components/ui/textarea";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
+import { Textarea } from "@/components/common/textarea";
import {
Table,
TableBody,
@@ -15,13 +15,13 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
+} from "@/components/common/table";
import {
Card,
CardContent,
CardHeader,
CardTitle,
-} from "@/components/ui/card";
+} from "@/components/common/card";
import { Clipboard, Truck, Package, ArrowRight, ChevronDown, AlertTriangle, Copy, Loader2, RefreshCw, MessageCircle } from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/navigation";
@@ -36,9 +36,9 @@ import {
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
-} from "@/components/ui/alert-dialog";
+} from "@/components/common/alert-dialog";
import Layout from "@/components/layout/layout";
-import { cacheUtils } from '@/lib/api-client';
+import { cacheUtils } from '@/lib/api/api-client';
import OrderTimeline from "@/components/orders/order-timeline";
import { motion, AnimatePresence } from "framer-motion";
diff --git a/app/dashboard/orders/page.tsx b/app/dashboard/orders/page.tsx
index e6428a3..9e5b36e 100644
--- a/app/dashboard/orders/page.tsx
+++ b/app/dashboard/orders/page.tsx
@@ -5,10 +5,10 @@ import { useRouter } from "next/navigation";
import Dashboard from "@/components/dashboard/dashboard";
import { Package, AlertCircle, RefreshCw } from "lucide-react";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { Button } from "@/components/ui/button";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
+import { Button } from "@/components/common/button";
// Error Boundary Component
interface ErrorBoundaryState {
@@ -95,7 +95,7 @@ function OrderTableSkeleton() {
{/* Subtle loading indicator */}
-
+
@@ -119,8 +119,8 @@ function OrderTableSkeleton() {
{['Order ID', 'Customer', 'Status', 'Total', 'Date', 'Actions'].map((header, i) => (
-
-
+
{/* Table rows skeleton */}
{[...Array(8)].map((_, i) => (
-
{
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- }
- }, [router]);
-
return (
@@ -194,4 +181,4 @@ export default function OrdersPage() {
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/page.tsx b/app/dashboard/page.tsx
index c71afc7..318b772 100644
--- a/app/dashboard/page.tsx
+++ b/app/dashboard/page.tsx
@@ -6,8 +6,8 @@ import packageJson from '../../package.json';
import { getGitInfo, getShortGitHash } from '@/lib/utils/git';
import { Suspense } from 'react';
import dynamic from 'next/dynamic';
-import { Skeleton } from '@/components/ui/skeleton';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
+import { Skeleton } from '@/components/common/skeleton';
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/common/card';
import DashboardContentWrapper from './dashboard-content-wrapper';
// Loading skeleton for the dashboard content
@@ -182,4 +182,5 @@ export default async function DashboardPage() {
);
-}
\ No newline at end of file
+}
+
diff --git a/app/dashboard/products/page.tsx b/app/dashboard/products/page.tsx
index f6aa4a7..5547692 100644
--- a/app/dashboard/products/page.tsx
+++ b/app/dashboard/products/page.tsx
@@ -3,16 +3,16 @@
import { useState, useEffect, ChangeEvent, Suspense } from "react";
import { useRouter } from "next/navigation";
import Layout from "@/components/layout/layout";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Product } from "@/models/products";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Product } from "@/lib/models/products";
import { Plus, Upload, Search, RefreshCw, Package2 } from "lucide-react";
import { clientFetch } from "@/lib/api";
-import { Category } from "@/models/categories";
+import { Category } from "@/lib/models/categories";
import { toast } from "sonner";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
// Lazy load heavy components with error handling
const ProductTable = dynamic(() => import("@/components/tables/product-table").catch((err) => {
@@ -156,16 +156,6 @@ export default function ProductsPage() {
// Fetch products and categories
useEffect(() => {
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- return;
- }
-
const fetchDataAsync = async () => {
try {
setLoading(true);
@@ -194,7 +184,7 @@ export default function ProductsPage() {
};
fetchDataAsync();
- }, [router]);
+ }, []);
const handleAddTier = () => {
setProductData((prev) => ({
@@ -552,3 +542,5 @@ export default function ProductsPage() {
);
}
+
+
diff --git a/app/dashboard/shipping/page.tsx b/app/dashboard/shipping/page.tsx
index 6b58cf4..f494e0a 100644
--- a/app/dashboard/shipping/page.tsx
+++ b/app/dashboard/shipping/page.tsx
@@ -4,8 +4,8 @@ import { useState, useEffect, ChangeEvent, Suspense } from "react";
import { useRouter } from "next/navigation";
import Layout from "@/components/layout/layout";
import { Edit, Plus, Trash, Truck } from "lucide-react";
-import { Button } from "@/components/ui/button";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Button } from "@/components/common/button";
+import { Skeleton } from "@/components/common/skeleton";
import {
fetchShippingMethods,
addShippingMethod,
@@ -15,7 +15,7 @@ import {
ShippingData
} from "@/lib/services/shipping-service";
import dynamic from "next/dynamic";
-import { Card, CardContent, CardHeader } from "@/components/ui/card";
+import { Card, CardContent, CardHeader } from "@/components/common/card";
// Lazy load components with error handling
const ShippingModal = dynamic(() => import("@/components/modals/shipping-modal").then(mod => ({ default: mod.ShippingModal })).catch((err) => {
@@ -142,11 +142,6 @@ export default function ShippingPage() {
.find((row) => row.startsWith("Authorization="))
?.split("=")[1];
- if (!authToken) {
- router.push("/login");
- return;
- }
-
const fetchedMethods: ShippingMethod[] = await fetchShippingMethods(
authToken
);
@@ -317,4 +312,4 @@ export default function ShippingPage() {
/>
);
-}
\ No newline at end of file
+}
diff --git a/app/dashboard/stock/page.tsx b/app/dashboard/stock/page.tsx
index 1abeb46..43cd6d3 100644
--- a/app/dashboard/stock/page.tsx
+++ b/app/dashboard/stock/page.tsx
@@ -3,12 +3,12 @@
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
import Layout from "@/components/layout/layout";
-import { Button } from "@/components/ui/button";
-import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table";
-import { Input } from "@/components/ui/input";
-import { Switch } from "@/components/ui/switch";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
+import { Button } from "@/components/common/button";
+import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/common/table";
+import { Input } from "@/components/common/input";
+import { Switch } from "@/components/common/switch";
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
import {
DropdownMenu,
DropdownMenuContent,
@@ -16,12 +16,12 @@ import {
DropdownMenuTrigger,
DropdownMenuLabel,
DropdownMenuSeparator
-} from "@/components/ui/dropdown-menu";
+} from "@/components/common/dropdown-menu";
import {
Popover,
PopoverContent,
PopoverTrigger,
-} from "@/components/ui/popover";
+} from "@/components/common/popover";
import {
AlertDialog,
AlertDialogAction,
@@ -32,12 +32,12 @@ import {
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
-} from "@/components/ui/alert-dialog";
-import { Product } from "@/models/products";
+} from "@/components/common/alert-dialog";
+import { Product } from "@/lib/models/products";
import { Package, RefreshCw, ChevronDown, CheckSquare, XSquare, Boxes, Download, Calendar, Search, Filter, Save, X, Edit2 } from "lucide-react";
import { clientFetch } from "@/lib/api";
import { toast } from "sonner";
-import { DatePicker, DateRangePicker, DateRangeDisplay, MonthPicker } from "@/components/ui/date-picker";
+import { DatePicker, DateRangePicker, DateRangeDisplay, MonthPicker } from "@/components/common/date-picker";
import { DateRange } from "react-day-picker";
import { addDays, startOfDay, endOfDay, format, isSameDay } from "date-fns";
import { motion, AnimatePresence } from "framer-motion";
@@ -72,16 +72,6 @@ export default function StockManagementPage() {
const [isExporting, setIsExporting] = useState
(false);
useEffect(() => {
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- return;
- }
-
const fetchDataAsync = async () => {
try {
const response = await clientFetch('api/products');
@@ -105,7 +95,7 @@ export default function StockManagementPage() {
};
fetchDataAsync();
- }, [router]);
+ }, []);
const handleEditStock = (productId: string) => {
setEditingStock({
@@ -687,4 +677,5 @@ export default function StockManagementPage() {
);
-}
\ No newline at end of file
+}
+
diff --git a/app/dashboard/storefront/customers/page.tsx b/app/dashboard/storefront/customers/page.tsx
index 360fed3..a37bb5c 100644
--- a/app/dashboard/storefront/customers/page.tsx
+++ b/app/dashboard/storefront/customers/page.tsx
@@ -2,7 +2,7 @@
import React, { useEffect, useState, useCallback } from "react";
import { getCustomers, type CustomerStats } from "@/lib/api";
-import { formatCurrency } from "@/utils/format";
+import { formatCurrency } from "@/lib/utils/format";
import { useRouter } from "next/navigation";
import { toast } from "sonner";
import Layout from "@/components/layout/layout";
@@ -13,14 +13,14 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
+} from "@/components/common/table";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
+} from "@/components/common/select";
import {
Dialog,
DialogContent,
@@ -28,8 +28,8 @@ import {
DialogTitle,
DialogDescription,
DialogFooter,
-} from "@/components/ui/dialog";
-import { Button } from "@/components/ui/button";
+} from "@/components/common/dialog";
+import { Button } from "@/components/common/button";
import {
ChevronLeft,
ChevronRight,
@@ -47,17 +47,17 @@ import {
Truck,
CheckCircle,
} from "lucide-react";
-import { Badge } from "@/components/ui/badge";
-import { Input } from "@/components/ui/input";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
+import { Badge } from "@/components/common/badge";
+import { Input } from "@/components/common/input";
+import { Skeleton } from "@/components/common/skeleton";
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
import { motion, AnimatePresence } from "framer-motion";
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
-} from "@/components/ui/dropdown-menu";
+} from "@/components/common/dropdown-menu";
export default function CustomerManagementPage() {
const router = useRouter();
@@ -126,16 +126,6 @@ export default function CustomerManagementPage() {
fetchCustomers();
}, [fetchCustomers]);
- useEffect(() => {
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- }
- }, [router]);
// Add filter function to filter customers when search query changes
useEffect(() => {
@@ -716,4 +706,5 @@ export default function CustomerManagementPage() {
);
-}
\ No newline at end of file
+}
+
diff --git a/app/dashboard/storefront/page.tsx b/app/dashboard/storefront/page.tsx
index 471769d..16de8bc 100644
--- a/app/dashboard/storefront/page.tsx
+++ b/app/dashboard/storefront/page.tsx
@@ -3,17 +3,17 @@
import { useState, useEffect, ChangeEvent } from "react";
import { useRouter } from "next/navigation";
import Layout from "@/components/layout/layout";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Textarea } from "@/components/ui/textarea";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Textarea } from "@/components/common/textarea";
import { Save, Send, Key, MessageSquare, Shield, Globe, Wallet, RefreshCw } from "lucide-react";
import { apiRequest } from "@/lib/api";
import { toast } from "sonner";
import BroadcastDialog from "@/components/modals/broadcast-dialog";
import Dashboard from "@/components/dashboard/dashboard";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/card";
-import { Label } from "@/components/ui/label";
-import { Badge } from "@/components/ui/badge";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/common/card";
+import { Label } from "@/components/common/label";
+import { Badge } from "@/components/common/badge";
import { motion, AnimatePresence } from "framer-motion";
import {
Select,
@@ -21,9 +21,9 @@ import {
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
-import { Switch } from "@/components/ui/switch";
-import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
+} from "@/components/common/select";
+import { Switch } from "@/components/common/switch";
+import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/common/tooltip";
const SHIPPING_REGIONS = [
{ value: "UK", label: "United Kingdom", emoji: "🇬🇧" },
@@ -106,16 +106,6 @@ export default function StorefrontPage() {
const [saving, setSaving] = useState
(false);
useEffect(() => {
- const authToken = document.cookie
- .split("; ")
- .find((row) => row.startsWith("Authorization="))
- ?.split("=")[1];
-
- if (!authToken) {
- router.push("/login");
- return;
- }
-
const fetchStorefront = async () => {
try {
setLoading(true);
@@ -465,3 +455,5 @@ export default function StorefrontPage() {
);
}
+
+
diff --git a/app/not-found.tsx b/app/not-found.tsx
index 457f036..eb2d17d 100644
--- a/app/not-found.tsx
+++ b/app/not-found.tsx
@@ -1,6 +1,6 @@
import { Metadata, Viewport } from "next";
import Link from "next/link";
-import { buttonVariants } from "@/components/ui/button";
+import { buttonVariants } from "@/components/common/button";
import { ArrowLeft } from "lucide-react";
export const metadata: Metadata = {
@@ -38,3 +38,4 @@ export default function NotFound() {
);
}
+
diff --git a/app/page.tsx b/app/page.tsx
index 733e6d8..094156f 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,10 +1,10 @@
-import { getPlatformStatsServer } from "@/lib/server-api";
-import { HomeNavbar } from "@/components/home-navbar";
+import { getPlatformStatsServer } from "@/lib/api/server-api";
+import { HomeNavbar } from "@/components/layout/home-navbar";
import { Shield, LineChart, Zap, ArrowRight, Sparkles } from "lucide-react";
-import { Button } from "@/components/ui/button";
+import { Button } from "@/components/common/button";
import Link from "next/link";
import { AnimatedStatsSection } from "@/components/animated-stats-section";
-import { MotionWrapper } from "@/components/ui/motion-wrapper";
+import { MotionWrapper } from "@/components/common/motion-wrapper";
export const dynamic = 'force-dynamic';
@@ -109,3 +109,6 @@ export default async function Home() {
return Error loading page
;
}
}
+
+
+
diff --git a/components/KeepOnline.ts b/components/KeepOnline.ts
index fe53598..0e7bc7b 100644
--- a/components/KeepOnline.ts
+++ b/components/KeepOnline.ts
@@ -1,6 +1,6 @@
"use client";
-import { useKeepOnline } from "@/hooks/useKeepOnline";
+import { useKeepOnline } from "@/lib/hooks/useKeepOnline";
const KeepOnline = () => {
useKeepOnline({
@@ -14,4 +14,4 @@ const KeepOnline = () => {
return null;
}
-export default KeepOnline;
\ No newline at end of file
+export default KeepOnline;
diff --git a/components/admin/AdminAnalytics.tsx b/components/admin/AdminAnalytics.tsx
index 36c946e..e48ba7e 100644
--- a/components/admin/AdminAnalytics.tsx
+++ b/components/admin/AdminAnalytics.tsx
@@ -7,16 +7,16 @@ import {
CardDescription,
CardHeader,
CardTitle,
-} from "@/components/ui/card";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+} from "@/components/common/card";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
-import { Button } from "@/components/ui/button";
+} from "@/components/common/select";
+import { Button } from "@/components/common/button";
import {
AlertCircle,
BarChart,
@@ -29,8 +29,8 @@ import {
Package,
Trophy,
} from "lucide-react";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { fetchClient } from "@/lib/api-client";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
+import { fetchClient } from "@/lib/api/api-client";
import {
BarChart as RechartsBarChart,
Bar,
@@ -43,7 +43,7 @@ import {
Line,
ComposedChart,
} from "recharts";
-import { formatGBP } from "@/utils/format";
+import { formatGBP, formatNumber } from "@/lib/utils/format";
import { PieChart, Pie, Cell, Legend } from "recharts";
interface GrowthData {
@@ -691,7 +691,7 @@ export default function AdminAnalytics() {
{formatCurrency(bestMonth.revenue)}
- {bestMonth.orders.toLocaleString()} orders
+ {formatNumber(bestMonth.orders)} orders
@@ -714,7 +714,7 @@ export default function AdminAnalytics() {
- {analyticsData?.orders?.total?.toLocaleString() || "0"}
+ {formatNumber(analyticsData?.orders?.total)}
Today: {analyticsData?.orders?.totalToday || 0}
@@ -876,7 +876,7 @@ export default function AdminAnalytics() {
- {analyticsData?.products?.total?.toLocaleString() || "0"}
+ {formatNumber(analyticsData?.products?.total)}
New This Week: {analyticsData?.products?.recent || 0}
@@ -1096,27 +1096,25 @@ export default function AdminAnalytics() {
Total Vendors
- {analyticsData?.vendors?.total?.toLocaleString() || "0"}
+ {formatNumber(analyticsData?.vendors?.total)}
Active Vendors
- {analyticsData?.vendors?.active?.toLocaleString() || "0"}
+ {formatNumber(analyticsData?.vendors?.active)}
Active Stores
- {analyticsData?.vendors?.activeStores?.toLocaleString() ||
- "0"}
+ {formatNumber(analyticsData?.vendors?.activeStores)}
New This Week
- {analyticsData?.vendors?.newThisWeek?.toLocaleString() ||
- "0"}
+ {formatNumber(analyticsData?.vendors?.newThisWeek)}
@@ -1202,7 +1200,7 @@ export default function AdminAnalytics() {
Total Orders
- {growthData.cumulative.orders.toLocaleString()}
+ {formatNumber(growthData.cumulative.orders)}
@@ -1214,19 +1212,19 @@ export default function AdminAnalytics() {
Customers
- {growthData.cumulative.customers.toLocaleString()}
+ {formatNumber(growthData.cumulative.customers)}
Vendors
- {growthData.cumulative.vendors.toLocaleString()}
+ {formatNumber(growthData.cumulative.vendors)}
Products
- {growthData.cumulative.products.toLocaleString()}
+ {formatNumber(growthData.cumulative.products)}
@@ -1292,7 +1290,7 @@ export default function AdminAnalytics() {
Orders
- {data.orders.toLocaleString()}
+ {formatNumber(data.orders)}
@@ -1304,7 +1302,7 @@ export default function AdminAnalytics() {
Customers
- {data.customers.toLocaleString()}
+ {formatNumber(data.customers)}
@@ -1554,3 +1552,5 @@ export default function AdminAnalytics() {
);
}
+
+
diff --git a/components/admin/BanUserCard.tsx b/components/admin/BanUserCard.tsx
index 7ff4cf4..0cf44f4 100644
--- a/components/admin/BanUserCard.tsx
+++ b/components/admin/BanUserCard.tsx
@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
-import { fetchClient } from "@/lib/api-client";
+import { fetchClient } from "@/lib/api/api-client";
export default function BanUserCard() {
const [telegramUserId, setTelegramUserId] = useState("");
@@ -70,3 +70,4 @@ export default function BanUserCard() {
}
+
diff --git a/components/admin/InvitationsListCard.tsx b/components/admin/InvitationsListCard.tsx
index 18172d3..b609d2b 100644
--- a/components/admin/InvitationsListCard.tsx
+++ b/components/admin/InvitationsListCard.tsx
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useState } from "react";
-import { fetchClient } from "@/lib/api-client";
+import { fetchClient } from "@/lib/api/api-client";
interface Invitation {
_id: string;
@@ -88,3 +88,4 @@ export default function InvitationsListCard() {
}
+
diff --git a/components/admin/InviteVendorCard.tsx b/components/admin/InviteVendorCard.tsx
index 0732f58..50204bc 100644
--- a/components/admin/InviteVendorCard.tsx
+++ b/components/admin/InviteVendorCard.tsx
@@ -1,9 +1,9 @@
import { useState } from "react";
-import { fetchClient } from "@/lib/api-client";
-import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
+import { fetchClient } from "@/lib/api/api-client";
+import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/common/card";
+import { Button } from "@/components/common/button";
import { Copy, Check, Ticket, Loader2, RefreshCw } from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
+import { useToast } from "@/lib/hooks/use-toast";
export default function InviteVendorCard() {
const [loading, setLoading] = useState(false);
@@ -103,3 +103,5 @@ export default function InviteVendorCard() {
}
+
+
diff --git a/components/admin/OrderDetailsModal.tsx b/components/admin/OrderDetailsModal.tsx
index cda7277..a6d2184 100644
--- a/components/admin/OrderDetailsModal.tsx
+++ b/components/admin/OrderDetailsModal.tsx
@@ -7,13 +7,13 @@ import {
DialogDescription,
DialogHeader,
DialogTitle,
-} from "@/components/ui/dialog";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Button } from "@/components/ui/button";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
-import { fetchClient } from "@/lib/api-client";
+} from "@/components/common/dialog";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Skeleton } from "@/components/common/skeleton";
+import { Button } from "@/components/common/button";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
+import { fetchClient } from "@/lib/api/api-client";
import { toast } from "sonner";
import { Package, User, Calendar, DollarSign, MapPin, Truck, CheckCircle, XCircle, Clock, Wallet, Copy, ExternalLink } from "lucide-react";
@@ -562,3 +562,5 @@ export default function OrderDetailsModal({ orderId, open, onOpenChange }: Order
);
}
+
+
diff --git a/components/admin/OrdersTable.tsx b/components/admin/OrdersTable.tsx
index 9cceb19..fc35ac1 100644
--- a/components/admin/OrdersTable.tsx
+++ b/components/admin/OrdersTable.tsx
@@ -1,11 +1,11 @@
"use client";
import { useState, useMemo } from "react";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
import { Search, Filter, Eye, ChevronLeft, ChevronRight } from "lucide-react";
import { List } from 'react-window';
import OrderDetailsModal from "./OrderDetailsModal";
@@ -366,3 +366,4 @@ export default function OrdersTable({ orders, enableModal = true }: OrdersTableP
);
}
+
diff --git a/components/admin/RecentOrdersCard.tsx b/components/admin/RecentOrdersCard.tsx
index 6f4c5f6..18503b1 100644
--- a/components/admin/RecentOrdersCard.tsx
+++ b/components/admin/RecentOrdersCard.tsx
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useState } from "react";
-import { fetchClient } from "@/lib/api-client";
+import { fetchClient } from "@/lib/api/api-client";
interface OrderItem {
name: string;
@@ -99,3 +99,4 @@ export default function RecentOrdersCard() {
}
+
diff --git a/components/admin/SystemStatusCard.tsx b/components/admin/SystemStatusCard.tsx
index f035127..b0badd5 100644
--- a/components/admin/SystemStatusCard.tsx
+++ b/components/admin/SystemStatusCard.tsx
@@ -1,8 +1,8 @@
"use client";
import { useEffect, useState } from "react";
-import { fetchClient } from "@/lib/api-client";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { fetchClient } from "@/lib/api/api-client";
+import { Button } from "@/components/common/button";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
interface Status {
uptimeSeconds: number;
@@ -151,3 +151,5 @@ export default function SystemStatusCard() {
}
+
+
diff --git a/components/admin/VendorsCard.tsx b/components/admin/VendorsCard.tsx
index 1034254..832f1d0 100644
--- a/components/admin/VendorsCard.tsx
+++ b/components/admin/VendorsCard.tsx
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useState } from "react";
-import { fetchClient } from "@/lib/api-client";
+import { fetchClient } from "@/lib/api/api-client";
interface Vendor {
_id: string;
@@ -137,3 +137,4 @@ export default function VendorsCard() {
);
}
+
diff --git a/components/analytics/AnalyticsDashboard.tsx b/components/analytics/AnalyticsDashboard.tsx
index 9450aa8..6b56cf5 100644
--- a/components/analytics/AnalyticsDashboard.tsx
+++ b/components/analytics/AnalyticsDashboard.tsx
@@ -7,17 +7,17 @@ import {
CardDescription,
CardHeader,
CardTitle,
-} from "@/components/ui/card";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
+} from "@/components/common/card";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
+} from "@/components/common/select";
import {
TrendingUp,
ShoppingCart,
@@ -32,21 +32,21 @@ import {
EyeOff,
Calculator,
} from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
+import { useToast } from "@/lib/hooks/use-toast";
import MetricsCard from "./MetricsCard";
import {
getAnalyticsOverviewWithStore,
type AnalyticsOverview,
} from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP, formatNumber } from "@/lib/utils/format";
import { MetricsCardSkeleton } from "./SkeletonLoaders";
import dynamic from "next/dynamic";
-import { Skeleton } from "@/components/ui/skeleton";
-import { DateRangePicker } from "@/components/ui/date-picker";
+import { Skeleton } from "@/components/common/skeleton";
+import { DateRangePicker } from "@/components/common/date-picker";
import { DateRange } from "react-day-picker";
import { addDays, startOfDay, endOfDay } from "date-fns";
import type { DateRange as ProfitDateRange } from "@/lib/services/profit-analytics-service";
-import { MotionWrapper } from "@/components/ui/motion-wrapper";
+import { MotionWrapper } from "@/components/common/motion-wrapper";
import { motion } from "framer-motion";
const RevenueChart = dynamic(() => import("./RevenueChart"), {
@@ -170,7 +170,7 @@ export default function AnalyticsDashboard({
},
{
title: "Total Orders",
- value: maskValue(data.orders.total.toLocaleString()),
+ value: maskValue(formatNumber(data.orders.total)),
description: "All-time orders",
icon: ShoppingCart,
trend: data.orders.completed > 0 ? ("up" as const) : ("neutral" as const),
@@ -178,7 +178,7 @@ export default function AnalyticsDashboard({
},
{
title: "Unique Customers",
- value: maskValue(data.customers.unique.toLocaleString()),
+ value: maskValue(formatNumber(data.customers.unique)),
description: "Total customers",
icon: Users,
trend: "neutral" as const,
@@ -186,7 +186,7 @@ export default function AnalyticsDashboard({
},
{
title: "Products",
- value: maskValue(data.products.total.toLocaleString()),
+ value: maskValue(formatNumber(data.products.total)),
description: "Active products",
icon: Package,
trend: "neutral" as const,
@@ -451,3 +451,5 @@ export default function AnalyticsDashboard({
);
}
+
+
diff --git a/components/analytics/AnalyticsDashboardSkeleton.tsx b/components/analytics/AnalyticsDashboardSkeleton.tsx
index ea4e8ad..9892af3 100644
--- a/components/analytics/AnalyticsDashboardSkeleton.tsx
+++ b/components/analytics/AnalyticsDashboardSkeleton.tsx
@@ -1,6 +1,6 @@
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Skeleton } from "@/components/ui/skeleton";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Skeleton } from "@/components/common/skeleton";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
import { MetricsCardSkeleton } from './SkeletonLoaders';
import {
TrendingUp,
@@ -201,4 +201,4 @@ export default function AnalyticsDashboardSkeleton() {
);
-}
\ No newline at end of file
+}
diff --git a/components/analytics/CustomerInsightsChart.tsx b/components/analytics/CustomerInsightsChart.tsx
index 04830b4..85d7f96 100644
--- a/components/analytics/CustomerInsightsChart.tsx
+++ b/components/analytics/CustomerInsightsChart.tsx
@@ -1,15 +1,15 @@
"use client"
import { useState, useEffect } from 'react';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
-import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
-import { useToast } from "@/hooks/use-toast";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
+import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
+import { useToast } from "@/lib/hooks/use-toast";
+import { Skeleton } from "@/components/common/skeleton";
import { Users, Crown, UserPlus, UserCheck, Star, ChevronLeft, ChevronRight } from "lucide-react";
import { getCustomerInsightsWithStore, type CustomerInsights } from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP } from "@/lib/utils/format";
import { CustomerInsightsSkeleton } from './SkeletonLoaders';
export default function CustomerInsightsChart() {
@@ -305,4 +305,5 @@ export default function CustomerInsightsChart() {
);
-}
\ No newline at end of file
+}
+
diff --git a/components/analytics/GrowthAnalyticsChart.tsx b/components/analytics/GrowthAnalyticsChart.tsx
index 52289de..251c5f4 100644
--- a/components/analytics/GrowthAnalyticsChart.tsx
+++ b/components/analytics/GrowthAnalyticsChart.tsx
@@ -7,9 +7,9 @@ import {
CardDescription,
CardHeader,
CardTitle,
-} from "@/components/ui/card";
-import { Button } from "@/components/ui/button";
-import { useToast } from "@/hooks/use-toast";
+} from "@/components/common/card";
+import { Button } from "@/components/common/button";
+import { useToast } from "@/lib/hooks/use-toast";
import { RefreshCw } from "lucide-react";
import {
getGrowthAnalyticsWithStore,
@@ -26,6 +26,7 @@ import {
ResponsiveContainer,
Area,
} from "recharts";
+import { formatGBP, formatNumber } from "@/lib/utils/format";
interface GrowthAnalyticsChartProps {
hideNumbers?: boolean;
@@ -63,14 +64,6 @@ export default function GrowthAnalyticsChart({
fetchGrowthData();
};
- const formatCurrency = (value: number) => {
- if (hideNumbers) return "£***";
- return new Intl.NumberFormat("en-GB", {
- style: "currency",
- currency: "GBP",
- maximumFractionDigits: 0,
- }).format(value);
- };
return (
@@ -115,9 +108,7 @@ export default function GrowthAnalyticsChart({
Total Orders
- {hideNumbers
- ? "***"
- : growthData.cumulative.orders.toLocaleString()}
+ {hideNumbers ? "***" : formatNumber(growthData.cumulative.orders)}
@@ -127,7 +118,7 @@ export default function GrowthAnalyticsChart({
Total Revenue
- {formatCurrency(growthData.cumulative.revenue)}
+ {hideNumbers ? "£***" : formatGBP(growthData.cumulative.revenue)}
@@ -137,9 +128,7 @@ export default function GrowthAnalyticsChart({
Customers
- {hideNumbers
- ? "***"
- : growthData.cumulative.customers.toLocaleString()}
+ {hideNumbers ? "***" : formatNumber(growthData.cumulative.customers)}
@@ -149,9 +138,7 @@ export default function GrowthAnalyticsChart({
Products
- {hideNumbers
- ? "***"
- : growthData.cumulative.products.toLocaleString()}
+ {hideNumbers ? "***" : formatNumber(growthData.cumulative.products)}
@@ -161,7 +148,7 @@ export default function GrowthAnalyticsChart({
Avg Order Value
- {formatCurrency(growthData.cumulative.avgOrderValue)}
+ {hideNumbers ? "£***" : formatGBP(growthData.cumulative.avgOrderValue)}
@@ -236,16 +223,16 @@ export default function GrowthAnalyticsChart({
Orders:{" "}
{hideNumbers
? "***"
- : data.orders.toLocaleString()}
+ : formatNumber(data.orders)}
- Revenue: {formatCurrency(data.revenue)}
+ Revenue: {hideNumbers ? "£***" : formatGBP(data.revenue)}
Customers:{" "}
{hideNumbers
? "***"
- : data.customers.toLocaleString()}
+ : formatNumber(data.customers)}
{data.newCustomers !== undefined && (
@@ -327,16 +314,16 @@ export default function GrowthAnalyticsChart({
)}
- {hideNumbers ? "***" : month.orders.toLocaleString()}
+ {hideNumbers ? "***" : formatNumber(month.orders)}
|
- {formatCurrency(month.revenue)}
+ {hideNumbers ? "£***" : formatGBP(month.revenue)}
|
- {hideNumbers ? "***" : month.customers.toLocaleString()}
+ {hideNumbers ? "***" : formatNumber(month.customers)}
|
- {formatCurrency(month.avgOrderValue)}
+ {hideNumbers ? "£***" : formatGBP(month.avgOrderValue)}
|
{hideNumbers ? "***" : (month.newCustomers ?? 0)}
@@ -352,3 +339,5 @@ export default function GrowthAnalyticsChart({
);
}
+
+
diff --git a/components/analytics/MetricsCard.tsx b/components/analytics/MetricsCard.tsx
index 450870c..4374c22 100644
--- a/components/analytics/MetricsCard.tsx
+++ b/components/analytics/MetricsCard.tsx
@@ -1,6 +1,6 @@
"use client"
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
import { TrendingUp, TrendingDown, Minus } from "lucide-react";
import { LucideIcon } from "lucide-react";
import { motion } from "framer-motion";
@@ -112,4 +112,4 @@ export default function MetricsCard({
);
-}
\ No newline at end of file
+}
diff --git a/components/analytics/OrderAnalyticsChart.tsx b/components/analytics/OrderAnalyticsChart.tsx
index fa01263..140cccb 100644
--- a/components/analytics/OrderAnalyticsChart.tsx
+++ b/components/analytics/OrderAnalyticsChart.tsx
@@ -1,13 +1,13 @@
"use client"
import { useState, useEffect } from 'react';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { useToast } from "@/hooks/use-toast";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { useToast } from "@/lib/hooks/use-toast";
+import { Skeleton } from "@/components/common/skeleton";
import { BarChart3, Clock, CheckCircle, XCircle, AlertCircle, AlertTriangle } from "lucide-react";
import { getOrderAnalyticsWithStore, type OrderAnalytics } from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP } from "@/lib/utils/format";
import { ChartSkeleton } from './SkeletonLoaders';
interface OrderAnalyticsChartProps {
@@ -201,4 +201,5 @@ export default function OrderAnalyticsChart({ timeRange }: OrderAnalyticsChartPr
);
-}
\ No newline at end of file
+}
+
diff --git a/components/analytics/PredictionsChart.tsx b/components/analytics/PredictionsChart.tsx
index 96e8954..7aa5522 100644
--- a/components/analytics/PredictionsChart.tsx
+++ b/components/analytics/PredictionsChart.tsx
@@ -7,16 +7,16 @@ import {
CardDescription,
CardHeader,
CardTitle,
-} from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
+} from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
+} from "@/components/common/select";
import {
TrendingUp,
TrendingDown,
@@ -32,8 +32,8 @@ import {
Info,
Download,
} from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
-import { Skeleton } from "@/components/ui/skeleton";
+import { useToast } from "@/lib/hooks/use-toast";
+import { Skeleton } from "@/components/common/skeleton";
import CountUp from "react-countup";
import {
getPredictionsOverviewWithStore,
@@ -41,7 +41,7 @@ import {
type PredictionsOverview,
type StockPredictionsResponse,
} from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP } from "@/lib/utils/format";
import {
Table,
TableBody,
@@ -49,7 +49,7 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
+} from "@/components/common/table";
import { format } from "date-fns";
import {
AreaChart,
@@ -65,9 +65,9 @@ import {
TooltipContent,
TooltipProvider,
TooltipTrigger,
-} from "@/components/ui/tooltip";
-import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
-import { Slider } from "@/components/ui/slider";
+} from "@/components/common/tooltip";
+import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
+import { Slider } from "@/components/common/slider";
interface PredictionsChartProps {
timeRange?: number;
@@ -933,3 +933,5 @@ export default function PredictionsChart({
);
}
+
+
diff --git a/components/analytics/ProductPerformanceChart.tsx b/components/analytics/ProductPerformanceChart.tsx
index f7858c8..9b21adc 100644
--- a/components/analytics/ProductPerformanceChart.tsx
+++ b/components/analytics/ProductPerformanceChart.tsx
@@ -1,14 +1,14 @@
"use client"
import { useState, useEffect } from 'react';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
-import { Badge } from "@/components/ui/badge";
-import { useToast } from "@/hooks/use-toast";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
+import { Badge } from "@/components/common/badge";
+import { useToast } from "@/lib/hooks/use-toast";
+import { Skeleton } from "@/components/common/skeleton";
import { Package } from "lucide-react";
import { getProductPerformanceWithStore, type ProductPerformance } from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP, formatNumber } from "@/lib/utils/format";
import { TableSkeleton } from './SkeletonLoaders';
export default function ProductPerformanceChart() {
@@ -123,10 +123,10 @@ export default function ProductPerformanceChart() {
-
- {parseInt(product.totalSold.toFixed(0)).toLocaleString()} {product.unitType}
+ {formatNumber(parseInt(product.totalSold.toFixed(0)))} {product.unitType}
{formatGBP(product.totalRevenue)}
@@ -155,4 +155,5 @@ export default function ProductPerformanceChart() {
);
-}
\ No newline at end of file
+}
+
diff --git a/components/analytics/ProfitAnalyticsChart.tsx b/components/analytics/ProfitAnalyticsChart.tsx
index e2f3978..c4d237e 100644
--- a/components/analytics/ProfitAnalyticsChart.tsx
+++ b/components/analytics/ProfitAnalyticsChart.tsx
@@ -1,9 +1,9 @@
"use client"
import { useState, useEffect } from 'react';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Badge } from "@/components/ui/badge";
-import { Alert, AlertDescription } from "@/components/ui/alert";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Badge } from "@/components/common/badge";
+import { Alert, AlertDescription } from "@/components/common/alert";
import {
TrendingUp,
TrendingDown,
@@ -14,10 +14,10 @@ import {
AlertTriangle,
Package
} from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
-import { formatGBP } from "@/utils/format";
+import { useToast } from "@/lib/hooks/use-toast";
+import { formatGBP } from "@/lib/utils/format";
import { getProfitOverview, type ProfitOverview, type DateRange } from "@/lib/services/profit-analytics-service";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Skeleton } from "@/components/common/skeleton";
interface ProfitAnalyticsChartProps {
timeRange?: string;
@@ -379,3 +379,5 @@ export default function ProfitAnalyticsChart({ timeRange, dateRange, hideNumbers
);
}
+
+
diff --git a/components/analytics/RevenueChart.tsx b/components/analytics/RevenueChart.tsx
index 7c27504..7879525 100644
--- a/components/analytics/RevenueChart.tsx
+++ b/components/analytics/RevenueChart.tsx
@@ -1,12 +1,12 @@
"use client"
import { useState, useEffect } from 'react';
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { useToast } from "@/hooks/use-toast";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { useToast } from "@/lib/hooks/use-toast";
+import { Skeleton } from "@/components/common/skeleton";
import { TrendingUp, DollarSign } from "lucide-react";
import { getRevenueTrendsWithStore, type RevenueData } from "@/lib/services/analytics-service";
-import { formatGBP } from "@/utils/format";
+import { formatGBP } from "@/lib/utils/format";
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts';
import { ChartSkeleton } from './SkeletonLoaders';
@@ -239,4 +239,5 @@ export default function RevenueChart({ timeRange, hideNumbers = false }: Revenue
);
-}
\ No newline at end of file
+}
+
diff --git a/components/analytics/SkeletonLoaders.tsx b/components/analytics/SkeletonLoaders.tsx
index 8415177..3ff81ff 100644
--- a/components/analytics/SkeletonLoaders.tsx
+++ b/components/analytics/SkeletonLoaders.tsx
@@ -1,5 +1,5 @@
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
+import { Skeleton } from "@/components/common/skeleton";
// Chart skeleton for revenue trends and order analytics
export function ChartSkeleton({
@@ -167,4 +167,4 @@ export function MetricsCardSkeleton() {
);
-}
\ No newline at end of file
+}
diff --git a/components/analytics/StoreSelector.tsx b/components/analytics/StoreSelector.tsx
index ebc9b5c..6a69926 100644
--- a/components/analytics/StoreSelector.tsx
+++ b/components/analytics/StoreSelector.tsx
@@ -2,12 +2,12 @@
import { useState, useEffect } from 'react';
import { useRouter, useSearchParams } from 'next/navigation';
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
-import { Label } from "@/components/ui/label";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
+import { Label } from "@/components/common/label";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
import { Store, Search } from "lucide-react";
-import { useToast } from "@/hooks/use-toast";
+import { useToast } from "@/lib/hooks/use-toast";
export default function StoreSelector() {
const [storeId, setStoreId] = useState('');
@@ -111,4 +111,5 @@ export default function StoreSelector() {
);
-}
\ No newline at end of file
+}
+
diff --git a/components/animated-stats-section.tsx b/components/animated-stats-section.tsx
index d84616d..8b71940 100644
--- a/components/animated-stats-section.tsx
+++ b/components/animated-stats-section.tsx
@@ -80,4 +80,4 @@ export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
);
-}
\ No newline at end of file
+}
diff --git a/components/ui/alert-dialog.tsx b/components/common/alert-dialog.tsx
similarity index 98%
rename from components/ui/alert-dialog.tsx
rename to components/common/alert-dialog.tsx
index 81f54b8..d472a6c 100644
--- a/components/ui/alert-dialog.tsx
+++ b/components/common/alert-dialog.tsx
@@ -4,7 +4,7 @@ import * as React from "react"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
import { cn } from "@/lib/utils/styles";
-import { buttonVariants } from "@/components/ui/button"
+import { buttonVariants } from "@/components/common/button"
const AlertDialog = AlertDialogPrimitive.Root
@@ -139,3 +139,4 @@ export {
AlertDialogAction,
AlertDialogCancel,
}
+
diff --git a/components/ui/alert.tsx b/components/common/alert.tsx
similarity index 100%
rename from components/ui/alert.tsx
rename to components/common/alert.tsx
diff --git a/components/ui/avatar.tsx b/components/common/avatar.tsx
similarity index 100%
rename from components/ui/avatar.tsx
rename to components/common/avatar.tsx
diff --git a/components/ui/badge.tsx b/components/common/badge.tsx
similarity index 100%
rename from components/ui/badge.tsx
rename to components/common/badge.tsx
diff --git a/components/ui/breadcrumb.tsx b/components/common/breadcrumb.tsx
similarity index 100%
rename from components/ui/breadcrumb.tsx
rename to components/common/breadcrumb.tsx
diff --git a/components/ui/button.tsx b/components/common/button.tsx
similarity index 100%
rename from components/ui/button.tsx
rename to components/common/button.tsx
diff --git a/components/ui/calendar.tsx b/components/common/calendar.tsx
similarity index 97%
rename from components/ui/calendar.tsx
rename to components/common/calendar.tsx
index 990feca..822b369 100644
--- a/components/ui/calendar.tsx
+++ b/components/common/calendar.tsx
@@ -5,7 +5,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react"
import { DayPicker } from "react-day-picker"
import { cn } from "@/lib/utils/styles";
-import { buttonVariants } from "@/components/ui/button"
+import { buttonVariants } from "@/components/common/button"
export type CalendarProps = React.ComponentProps
@@ -64,3 +64,4 @@ function Calendar({
Calendar.displayName = "Calendar"
export { Calendar }
+
diff --git a/components/ui/card.tsx b/components/common/card.tsx
similarity index 100%
rename from components/ui/card.tsx
rename to components/common/card.tsx
diff --git a/components/ui/carousel.tsx b/components/common/carousel.tsx
similarity index 99%
rename from components/ui/carousel.tsx
rename to components/common/carousel.tsx
index 3bb8c21..165fade 100644
--- a/components/ui/carousel.tsx
+++ b/components/common/carousel.tsx
@@ -7,7 +7,7 @@ import useEmblaCarousel, {
import { ArrowLeft, ArrowRight } from "lucide-react"
import { cn } from "@/lib/utils/styles";
-import { Button } from "@/components/ui/button"
+import { Button } from "@/components/common/button"
type CarouselApi = UseEmblaCarouselType[1]
type UseCarouselParameters = Parameters
@@ -260,3 +260,4 @@ export {
CarouselPrevious,
CarouselNext,
}
+
diff --git a/components/ui/chart.tsx b/components/common/chart.tsx
similarity index 100%
rename from components/ui/chart.tsx
rename to components/common/chart.tsx
diff --git a/components/ui/checkbox.tsx b/components/common/checkbox.tsx
similarity index 100%
rename from components/ui/checkbox.tsx
rename to components/common/checkbox.tsx
diff --git a/components/ui/collapsible.tsx b/components/common/collapsible.tsx
similarity index 100%
rename from components/ui/collapsible.tsx
rename to components/common/collapsible.tsx
diff --git a/components/ui/command.tsx b/components/common/command.tsx
similarity index 69%
rename from components/ui/command.tsx
rename to components/common/command.tsx
index 73d036c..3f6d92d 100644
--- a/components/ui/command.tsx
+++ b/components/common/command.tsx
@@ -6,7 +6,7 @@ import { Command as CommandPrimitive } from "cmdk"
import { Search } from "lucide-react"
import { cn } from "@/lib/utils/styles";
-import { Dialog, DialogContent } from "@/components/ui/dialog"
+import { Dialog, DialogContent } from "@/components/common/dialog"
const Command = React.forwardRef<
React.ElementRef,
@@ -15,7 +15,7 @@ const Command = React.forwardRef<
{
return (
);
};
+
+
diff --git a/components/modals/shipping-modal.tsx b/components/modals/shipping-modal.tsx
index c8af667..220753c 100644
--- a/components/modals/shipping-modal.tsx
+++ b/components/modals/shipping-modal.tsx
@@ -1,9 +1,9 @@
"use client";
import { ChangeEvent, FormEvent } from "react";
-import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
-import { Button } from "@/components/ui/button";
-import { Input } from "@/components/ui/input";
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/common/dialog";
+import { Button } from "@/components/common/button";
+import { Input } from "@/components/common/input";
import { ShippingData } from "@/lib/types";
interface ShippingModalProps {
@@ -80,3 +80,4 @@ export const ShippingModal = ({
);
};
+
diff --git a/components/notifications/OrderNotifications.tsx b/components/notifications/OrderNotifications.tsx
index 1fff6e8..d500fa6 100644
--- a/components/notifications/OrderNotifications.tsx
+++ b/components/notifications/OrderNotifications.tsx
@@ -5,14 +5,14 @@ import { clientFetch } from "@/lib/api";
import { toast } from "sonner";
import { Package, Bell } from "lucide-react";
import { useRouter } from "next/navigation";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu";
+} from "@/components/common/dropdown-menu";
interface Order {
_id: string;
@@ -234,4 +234,5 @@ export default function OrderNotifications() {
);
-}
\ No newline at end of file
+}
+
diff --git a/components/notifications/UnifiedNotifications.tsx b/components/notifications/UnifiedNotifications.tsx
index c19eb6d..66c28f1 100644
--- a/components/notifications/UnifiedNotifications.tsx
+++ b/components/notifications/UnifiedNotifications.tsx
@@ -2,8 +2,8 @@
import React, { useState } from "react";
import { useRouter } from "next/navigation";
-import { Badge } from "@/components/ui/badge";
-import { Button } from "@/components/ui/button";
+import { Badge } from "@/components/common/badge";
+import { Button } from "@/components/common/button";
import { BellRing, Package, MessageCircle } from "lucide-react";
import {
DropdownMenu,
@@ -11,8 +11,8 @@ import {
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
-} from "@/components/ui/dropdown-menu";
-import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
+} from "@/components/common/dropdown-menu";
+import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
import { useNotifications } from "@/lib/notification-context";
export default function UnifiedNotifications() {
@@ -283,4 +283,4 @@ export default function UnifiedNotifications() {
);
-}
\ No newline at end of file
+}
diff --git a/components/tables/order-table.tsx b/components/tables/order-table.tsx
index c5bde0f..baf7a42 100644
--- a/components/tables/order-table.tsx
+++ b/components/tables/order-table.tsx
@@ -11,16 +11,16 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
-import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
+} from "@/components/common/table";
+import { Button } from "@/components/common/button";
+import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
-} from "@/components/ui/select";
+} from "@/components/common/select";
import {
Eye,
Loader2,
@@ -37,10 +37,10 @@ import {
} from "lucide-react";
import Link from "next/link";
import { clientFetch } from '@/lib/api';
-import { exportOrdersToCSV } from '@/lib/api-client';
+import { exportOrdersToCSV } from '@/lib/api/api-client';
import { toast } from "sonner";
import { Download } from "lucide-react";
-import { Checkbox } from "@/components/ui/checkbox";
+import { Checkbox } from "@/components/common/checkbox";
import {
AlertDialog,
AlertDialogAction,
@@ -51,8 +51,8 @@ import {
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
-} from "@/components/ui/alert-dialog";
-import { cacheUtils } from '@/lib/api-client';
+} from "@/components/common/alert-dialog";
+import { cacheUtils } from '@/lib/api/api-client';
interface Order {
_id: string;
@@ -815,4 +815,5 @@ export default function OrderTable() {
);
-}
\ No newline at end of file
+}
+
diff --git a/components/tables/product-table.tsx b/components/tables/product-table.tsx
index 442e665..adcaebb 100644
--- a/components/tables/product-table.tsx
+++ b/components/tables/product-table.tsx
@@ -5,7 +5,7 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
+} from "@/components/common/table";
import Image from "next/image";
import {
Edit,
@@ -18,12 +18,12 @@ import {
PackageX,
Archive
} from "lucide-react";
-import { Button } from "@/components/ui/button";
+import { Button } from "@/components/common/button";
import React, { useState, useEffect } from "react";
-import { Product } from "@/models/products";
-import { Badge } from "@/components/ui/badge";
-import { Switch } from "@/components/ui/switch";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Product } from "@/lib/models/products";
+import { Badge } from "@/components/common/badge";
+import { Switch } from "@/components/common/switch";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
import { motion, AnimatePresence } from "framer-motion";
const getProductImageUrl = (product: Product) => {
@@ -329,3 +329,5 @@ const ProductTable = ({
};
export default ProductTable;
+
+
diff --git a/components/tables/shipping-table.tsx b/components/tables/shipping-table.tsx
index 6f40071..19510b0 100644
--- a/components/tables/shipping-table.tsx
+++ b/components/tables/shipping-table.tsx
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react";
-import { Skeleton } from "@/components/ui/skeleton";
+import { Skeleton } from "@/components/common/skeleton";
import {
Table,
TableBody,
@@ -7,10 +7,10 @@ import {
TableHead,
TableHeader,
TableRow,
-} from "@/components/ui/table";
-import { Button } from "@/components/ui/button";
+} from "@/components/common/table";
+import { Button } from "@/components/common/button";
import { Edit, Trash, Truck, PackageX } from "lucide-react";
-import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
+import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
import { motion, AnimatePresence } from "framer-motion";
import { ShippingMethod } from "@/lib/types";
@@ -185,3 +185,4 @@ export const ShippingTable: React.FC = ({
);
};
+
diff --git a/components/ui/accordion.tsx b/components/ui/accordion.tsx
deleted file mode 100644
index 070c70f..0000000
--- a/components/ui/accordion.tsx
+++ /dev/null
@@ -1,58 +0,0 @@
-"use client"
-
-import * as React from "react"
-import * as AccordionPrimitive from "@radix-ui/react-accordion"
-import { ChevronDown } from "lucide-react"
-
-import { cn } from "@/lib/utils/styles";
-
-const Accordion = AccordionPrimitive.Root
-
-const AccordionItem = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, ...props }, ref) => (
-
-))
-AccordionItem.displayName = "AccordionItem"
-
-const AccordionTrigger = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
- svg]:rotate-180",
- className
- )}
- {...props}
- >
- {children}
-
-
-
-))
-AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
-
-const AccordionContent = React.forwardRef<
- React.ElementRef,
- React.ComponentPropsWithoutRef
->(({ className, children, ...props }, ref) => (
-
- {children}
-
-))
-
-AccordionContent.displayName = AccordionPrimitive.Content.displayName
-
-export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
diff --git a/lib/api-client.ts b/lib/api/api-client.ts
similarity index 99%
rename from lib/api-client.ts
rename to lib/api/api-client.ts
index c7e7781..a8e2b69 100644
--- a/lib/api-client.ts
+++ b/lib/api/api-client.ts
@@ -4,7 +4,7 @@
let toast: any;
try {
// Try to import from the UI components
- toast = require("@/components/ui/use-toast").toast;
+ toast = require("@/components/common/use-toast").toast;
} catch (error) {
// Fallback toast function if not available
toast = {
@@ -512,4 +512,4 @@ export async function clientFetchWithCache(
}
return result;
-}
\ No newline at end of file
+}
diff --git a/lib/api.ts b/lib/api/index.ts
similarity index 91%
rename from lib/api.ts
rename to lib/api/index.ts
index 5ab537e..accdbab 100644
--- a/lib/api.ts
+++ b/lib/api/index.ts
@@ -33,7 +33,7 @@ export {
type Product,
type ProductsResponse,
type StockData,
-} from './services/product-service';
+} from '../services/product-service';
// Re-export shipping services
export {
@@ -46,7 +46,7 @@ export {
// Types
type ShippingOption,
type ShippingOptionsResponse,
-} from './services/shipping-service';
+} from '../services/shipping-service';
// Re-export analytics services
export {
@@ -61,15 +61,15 @@ export {
getCustomerInsightsWithStore,
getOrderAnalyticsWithStore,
getStoreIdForUser,
- formatGBP,
-
// Types
type AnalyticsOverview,
type RevenueData,
type ProductPerformance,
type CustomerInsights,
type OrderAnalytics,
-} from './services/analytics-service';
+} from '../services/analytics-service';
+
+export { formatGBP, formatNumber } from '../utils/format';
// Define the PlatformStats interface to match the expected format
export interface PlatformStats {
@@ -89,7 +89,7 @@ export interface PlatformStats {
export {
getPlatformStats,
getVendorStats,
-} from './services/stats-service';
+} from '../services/stats-service';
// Re-export server API functions
export {
@@ -111,8 +111,8 @@ export {
// Get clientFetch first so we can use it in the compatibility functions
import { clientFetch } from './api-client';
-import { getProductDetails, updateProduct } from './services/product-service';
-import { getPlatformStats } from './services/stats-service';
+import { getProductDetails, updateProduct } from '../services/product-service';
+import { getPlatformStats } from '../services/stats-service';
// Add missing functions for backward compatibility
// These are functions from the old style that we need to maintain compatibility
diff --git a/lib/server-api.ts b/lib/api/server-api.ts
similarity index 97%
rename from lib/server-api.ts
rename to lib/api/server-api.ts
index fcbd0d0..f466d5b 100644
--- a/lib/server-api.ts
+++ b/lib/api/server-api.ts
@@ -22,20 +22,20 @@ try {
*/
function getServerApiUrl(endpoint: string): string {
const apiUrl = process.env.SERVER_API_URL || 'http://localhost:3001/api';
-
+
// Validate API URL to prevent 500 errors
if (!apiUrl || apiUrl === 'undefined' || apiUrl === 'null') {
console.warn('SERVER_API_URL not properly set, using localhost fallback');
const fallbackUrl = 'http://localhost:3001/api';
const cleanEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
- return fallbackUrl.endsWith('/')
+ return fallbackUrl.endsWith('/')
? `${fallbackUrl}${cleanEndpoint}`
: `${fallbackUrl}/${cleanEndpoint}`;
}
-
+
const cleanEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint;
-
- return apiUrl.endsWith('/')
+
+ return apiUrl.endsWith('/')
? `${apiUrl}${cleanEndpoint}`
: `${apiUrl}/${cleanEndpoint}`;
}
@@ -58,18 +58,18 @@ export async function fetchServer(
"For client components, use clientFetch or fetchClient instead."
);
}
-
+
// Get auth token from cookies
const cookieStore = await cookiesModule.cookies();
const authToken = cookieStore.get('Authorization')?.value;
// Redirect to login if not authenticated
- if (!authToken) redirect('/login');
-
+ if (!authToken) redirect('/auth/login');
+
try {
// Get the complete backend URL using the utility function
const url = getServerApiUrl(endpoint);
-
+
// Make the request with proper auth headers
const res = await fetch(url, {
...options,
@@ -82,8 +82,8 @@ export async function fetchServer(
});
// Handle auth failures
- if (res.status === 401) redirect('/login');
-
+ if (res.status === 401) redirect('/auth/login');
+
// Handle other errors
if (!res.ok) {
let errorData;
@@ -92,7 +92,7 @@ export async function fetchServer(
} catch {
errorData = {};
}
-
+
// Handle new error format: { success: false, error: { message: "...", code: "..." } }
// or old format: { error: "...", message: "..." }
let errorMessage: string;
@@ -105,7 +105,7 @@ export async function fetchServer(
} else {
errorMessage = `Request failed: ${res.status} ${res.statusText}`;
}
-
+
throw new Error(errorMessage);
}
@@ -158,22 +158,22 @@ export const getCustomerDetailsServer = async (userId: string): Promise 0) {
return data;
}
-
+
console.info('Using sample stats data for demo');
return {
orders: {
@@ -296,7 +296,7 @@ export const getAnalyticsOverviewServer = async (storeId?: string): Promise => {
const params = new URLSearchParams({ period });
if (storeId) params.append('storeId', storeId);
-
+
const url = `/analytics/revenue-trends?${params.toString()}`;
return fetchServer(url);
};
@@ -314,7 +314,7 @@ export const getCustomerInsightsServer = async (storeId?: string): Promise => {
const params = new URLSearchParams({ period });
if (storeId) params.append('storeId', storeId);
-
+
const url = `/analytics/order-analytics?${params.toString()}`;
return fetchServer(url);
};
\ No newline at end of file
diff --git a/hooks/use-chromebook-keyboard.tsx b/lib/hooks/use-chromebook-keyboard.tsx
similarity index 100%
rename from hooks/use-chromebook-keyboard.tsx
rename to lib/hooks/use-chromebook-keyboard.tsx
diff --git a/hooks/use-chromebook-scroll.tsx b/lib/hooks/use-chromebook-scroll.tsx
similarity index 100%
rename from hooks/use-chromebook-scroll.tsx
rename to lib/hooks/use-chromebook-scroll.tsx
diff --git a/hooks/use-mobile.tsx b/lib/hooks/use-mobile.tsx
similarity index 100%
rename from hooks/use-mobile.tsx
rename to lib/hooks/use-mobile.tsx
diff --git a/components/ui/use-toast.ts b/lib/hooks/use-toast.ts
similarity index 99%
rename from components/ui/use-toast.ts
rename to lib/hooks/use-toast.ts
index 02e111d..714ad09 100644
--- a/components/ui/use-toast.ts
+++ b/lib/hooks/use-toast.ts
@@ -6,7 +6,7 @@ import * as React from "react"
import type {
ToastActionElement,
ToastProps,
-} from "@/components/ui/toast"
+} from "@/components/common/toast"
const TOAST_LIMIT = 1
const TOAST_REMOVE_DELAY = 1000000
diff --git a/hooks/useFilterState.ts b/lib/hooks/useFilterState.ts
similarity index 100%
rename from hooks/useFilterState.ts
rename to lib/hooks/useFilterState.ts
diff --git a/hooks/useKeepOnline.ts b/lib/hooks/useKeepOnline.ts
similarity index 100%
rename from hooks/useKeepOnline.ts
rename to lib/hooks/useKeepOnline.ts
diff --git a/hooks/useUser.ts b/lib/hooks/useUser.ts
similarity index 94%
rename from hooks/useUser.ts
rename to lib/hooks/useUser.ts
index d8ca321..9aa2785 100644
--- a/hooks/useUser.ts
+++ b/lib/hooks/useUser.ts
@@ -1,7 +1,7 @@
"use client"
import { useState, useEffect } from 'react'
-import { clientFetch } from '@/lib/api-client'
+import { clientFetch } from '@/lib/api/api-client'
interface Vendor {
_id: string;
diff --git a/hooks/useWidgetLayout.ts b/lib/hooks/useWidgetLayout.ts
similarity index 79%
rename from hooks/useWidgetLayout.ts
rename to lib/hooks/useWidgetLayout.ts
index 51be753..bffebad 100644
--- a/hooks/useWidgetLayout.ts
+++ b/lib/hooks/useWidgetLayout.ts
@@ -1,57 +1,7 @@
"use client"
import { useState, useEffect, useCallback } from "react"
-
-// Per-widget settings types
-export interface RecentActivitySettings {
- itemCount: number // 5, 10, 15
-}
-
-export interface TopProductsSettings {
- itemCount: number // 3, 5, 10
- showRevenue: boolean
-}
-
-export interface OverviewSettings {
- showChange: boolean // Show % change from previous period
-}
-
-export interface RevenueChartSettings {
- days: number // 7, 14, 30
- showComparison: boolean
-}
-
-export interface LowStockSettings {
- threshold: number // Show items with stock below this
- itemCount: number
-}
-
-export interface RecentCustomersSettings {
- itemCount: number
- showSpent: boolean
-}
-
-export interface PendingChatsSettings {
- showPreview: boolean
-}
-
-export type WidgetSettings =
- | { type: "quick-actions" }
- | { type: "overview"; settings: OverviewSettings }
- | { type: "recent-activity"; settings: RecentActivitySettings }
- | { type: "top-products"; settings: TopProductsSettings }
- | { type: "revenue-chart"; settings: RevenueChartSettings }
- | { type: "low-stock"; settings: LowStockSettings }
- | { type: "recent-customers"; settings: RecentCustomersSettings }
- | { type: "pending-chats"; settings: PendingChatsSettings }
-
-export interface WidgetConfig {
- id: string
- title: string
- visible: boolean
- order: number
- settings?: Record
-}
+import type { WidgetConfig, WidgetSettings } from "@/lib/types/dashboard"
const DEFAULT_WIDGETS: WidgetConfig[] = [
{ id: "quick-actions", title: "Quick Actions", visible: true, order: 0 },
diff --git a/models/categories.ts b/lib/models/categories.ts
similarity index 100%
rename from models/categories.ts
rename to lib/models/categories.ts
diff --git a/models/products.ts b/lib/models/products.ts
similarity index 100%
rename from models/products.ts
rename to lib/models/products.ts
diff --git a/lib/notification-context.tsx b/lib/notification-context.tsx
index 0a500fe..3ab209e 100644
--- a/lib/notification-context.tsx
+++ b/lib/notification-context.tsx
@@ -4,7 +4,7 @@ import React, { createContext, useContext, useState, useEffect, useRef, ReactNod
import { clientFetch } from "@/lib/api";
import { toast } from "sonner";
import { getCookie } from "@/lib/api";
-import { cacheUtils } from '@/lib/api-client';
+import { cacheUtils } from '@/lib/api/api-client';
import { Package } from "lucide-react";
interface Order {
@@ -343,4 +343,4 @@ export function useNotifications() {
throw new Error('useNotifications must be used within a NotificationProvider');
}
return context;
-}
\ No newline at end of file
+}
diff --git a/lib/services/analytics-service.ts b/lib/services/analytics-service.ts
index d59c507..f74d926 100644
--- a/lib/services/analytics-service.ts
+++ b/lib/services/analytics-service.ts
@@ -1,6 +1,7 @@
"use client";
-import { clientFetch } from "../api-client";
+import { clientFetch } from '@/lib/api/api-client';
+import { formatGBP } from '@/lib/utils/format';
// Analytics Types
export interface AnalyticsOverview {
@@ -293,15 +294,6 @@ export const getGrowthAnalyticsWithStore =
return getGrowthAnalytics(storeId);
};
-export function formatGBP(value: number) {
- return value.toLocaleString("en-GB", {
- style: "currency",
- currency: "GBP",
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
-}
-
// Prediction Types
export interface SalesPrediction {
predicted: number | null;
diff --git a/services/customerService.ts b/lib/services/customerService.ts
similarity index 100%
rename from services/customerService.ts
rename to lib/services/customerService.ts
diff --git a/lib/services/index.ts b/lib/services/index.ts
index da3dbb0..b4117f5 100644
--- a/lib/services/index.ts
+++ b/lib/services/index.ts
@@ -1,5 +1,3 @@
-// Re-export all service functionality
-export * from './product-service';
-export * from './shipping-service';
-export * from './stats-service';
-export * from '../api-client';
\ No newline at end of file
+// Re-export all services from the lib directory
+// This provides backward compatibility
+export * from '../lib/api';
\ No newline at end of file
diff --git a/lib/services/product-service.ts b/lib/services/product-service.ts
index 21db135..5cfe057 100644
--- a/lib/services/product-service.ts
+++ b/lib/services/product-service.ts
@@ -1,4 +1,4 @@
-import { clientFetch } from '../api-client';
+import { clientFetch } from '@/lib/api/api-client';
// Product data types
export interface Product {
diff --git a/lib/services/shipping-service.ts b/lib/services/shipping-service.ts
index 092c3e6..6d59975 100644
--- a/lib/services/shipping-service.ts
+++ b/lib/services/shipping-service.ts
@@ -1,4 +1,4 @@
-import { clientFetch } from '../api-client';
+import { clientFetch } from '@/lib/api/api-client';
/**
* Shipping service - Handles shipping options
diff --git a/lib/services/stats-service.ts b/lib/services/stats-service.ts
index 110cafd..b594630 100644
--- a/lib/services/stats-service.ts
+++ b/lib/services/stats-service.ts
@@ -1,4 +1,4 @@
-import { clientFetch } from '../api-client';
+import { clientFetch } from '@/lib/api/api-client';
// Stats data types
export interface PlatformStats {
diff --git a/lib/types/dashboard.ts b/lib/types/dashboard.ts
new file mode 100644
index 0000000..c9e0e09
--- /dev/null
+++ b/lib/types/dashboard.ts
@@ -0,0 +1,61 @@
+export interface RecentActivitySettings {
+ itemCount: number // 5, 10, 15
+}
+
+export interface TopProductsSettings {
+ itemCount: number // 3, 5, 10
+ showRevenue: boolean
+}
+
+export interface OverviewSettings {
+ showChange: boolean // Show % change from previous period
+}
+
+export interface RevenueChartSettings {
+ days: number // 7, 14, 30
+ showComparison: boolean
+}
+
+export interface LowStockSettings {
+ threshold: number // Show items with stock below this
+ itemCount: number
+}
+
+export interface RecentCustomersSettings {
+ itemCount: number
+ showSpent: boolean
+}
+
+export interface PendingChatsSettings {
+ showPreview: boolean
+}
+
+export type WidgetSettings =
+ | { type: "quick-actions" }
+ | { type: "overview"; settings: OverviewSettings }
+ | { type: "recent-activity"; settings: RecentActivitySettings }
+ | { type: "top-products"; settings: TopProductsSettings }
+ | { type: "revenue-chart"; settings: RevenueChartSettings }
+ | { type: "low-stock"; settings: LowStockSettings }
+ | { type: "recent-customers"; settings: RecentCustomersSettings }
+ | { type: "pending-chats"; settings: PendingChatsSettings }
+
+export interface WidgetConfig {
+ id: string
+ title: string
+ visible: boolean
+ order: number
+ colSpan?: number
+ settings?: Record
+}
+
+export interface TopProduct {
+ id: string;
+ name: string;
+ price: number | number[];
+ image: string;
+ count: number;
+ revenue: number;
+ unitType?: string;
+ currentStock?: number;
+}
diff --git a/lib/utils/format.ts b/lib/utils/format.ts
new file mode 100644
index 0000000..3ebb021
--- /dev/null
+++ b/lib/utils/format.ts
@@ -0,0 +1,28 @@
+export const formatCurrency = (amount: number | undefined | null): string => {
+ if (amount === undefined || amount === null || isNaN(Number(amount))) {
+ return '£0.00';
+ }
+ return new Intl.NumberFormat('en-GB', {
+ style: 'currency',
+ currency: 'GBP'
+ }).format(Number(amount));
+};
+
+export function formatGBP(value: number | undefined | null) {
+ if (value === undefined || value === null || isNaN(Number(value))) {
+ return '£0.00';
+ }
+ return Number(value).toLocaleString('en-GB', {
+ style: 'currency',
+ currency: 'GBP',
+ minimumFractionDigits: 2,
+ maximumFractionDigits: 2,
+ });
+}
+
+export function formatNumber(value: number | undefined | null, options: Intl.NumberFormatOptions = {}) {
+ if (value === undefined || value === null || isNaN(Number(value))) {
+ return '0';
+ }
+ return Number(value).toLocaleString('en-GB', options);
+}
\ No newline at end of file
diff --git a/middleware.ts b/middleware.ts
new file mode 100644
index 0000000..77e3cff
--- /dev/null
+++ b/middleware.ts
@@ -0,0 +1,25 @@
+import { NextResponse } from 'next/server';
+import type { NextRequest } from 'next/server';
+
+export function middleware(request: NextRequest) {
+ const { pathname } = request.nextUrl;
+
+ // Protect dashboard routes
+ if (pathname.startsWith('/dashboard')) {
+ const authToken = request.cookies.get('Authorization')?.value;
+
+ if (!authToken) {
+ // Redirect to login if no token is found
+ const loginUrl = new URL('/auth/login', request.url);
+ loginUrl.searchParams.set('redirectUrl', pathname);
+ return NextResponse.redirect(loginUrl);
+ }
+ }
+
+ return NextResponse.next();
+}
+
+// See "Matching Paths" below to learn more
+export const config = {
+ matcher: ['/dashboard/:path*'],
+};
diff --git a/public/git-info.json b/public/git-info.json
index be281d7..c6ce719 100644
--- a/public/git-info.json
+++ b/public/git-info.json
@@ -1,4 +1,4 @@
{
- "commitHash": "a6b7286",
- "buildTime": "2026-01-12T10:20:09.966Z"
+ "commitHash": "a6e6cd0",
+ "buildTime": "2026-01-13T04:57:00.870Z"
}
\ No newline at end of file
diff --git a/services/index.ts b/services/index.ts
deleted file mode 100644
index b4117f5..0000000
--- a/services/index.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-// Re-export all services from the lib directory
-// This provides backward compatibility
-export * from '../lib/api';
\ No newline at end of file
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 439b464..f7d21f2 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -8,8 +8,6 @@ const config: Config = {
"./app/**/*.{js,ts,jsx,tsx,mdx}",
"./src/**/*.{ts,tsx}",
"./lib/**/*.{js,ts,jsx,tsx,mdx}",
- "./hooks/**/*.{js,ts,jsx,tsx,mdx}",
- "./utils/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
container: {
@@ -46,11 +44,11 @@ const config: Config = {
'50%': { opacity: '1', transform: 'scale(1) rotate(180deg)' }
},
glow: {
- '0%, 100%': {
- boxShadow: '0 0 5px hsl(0 84% 50%), 0 0 10px hsl(0 84% 50%), 0 0 15px hsl(0 84% 50%)'
+ '0%, 100%': {
+ boxShadow: '0 0 5px hsl(0 84% 50%), 0 0 10px hsl(0 84% 50%), 0 0 15px hsl(0 84% 50%)'
},
- '50%': {
- boxShadow: '0 0 10px hsl(142 76% 36%), 0 0 20px hsl(142 76% 36%), 0 0 30px hsl(142 76% 36%)'
+ '50%': {
+ boxShadow: '0 0 10px hsl(142 76% 36%), 0 0 20px hsl(142 76% 36%), 0 0 30px hsl(142 76% 36%)'
}
}
},
diff --git a/utils/format.ts b/utils/format.ts
deleted file mode 100644
index 62d055f..0000000
--- a/utils/format.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-export const formatCurrency = (amount: number): string => {
- return new Intl.NumberFormat('en-GB', {
- style: 'currency',
- currency: 'GBP'
- }).format(amount);
-};
-
-export function formatGBP(value: number) {
- return value.toLocaleString('en-GB', {
- style: 'currency',
- currency: 'GBP',
- minimumFractionDigits: 2,
- maximumFractionDigits: 2,
- });
-}
\ No newline at end of file
|