Refactor UI imports and update component paths
Some checks failed
Build Frontend / build (push) Failing after 7s
Some checks failed
Build Frontend / build (push) Failing after 7s
Replaces imports from 'components/ui' with 'components/common' across the app and dashboard pages, and updates model and API imports to use new paths under 'lib'. Removes redundant authentication checks from several dashboard pages. Adds new dashboard components and utility files, and reorganizes hooks and services into the 'lib' directory for improved structure.
This commit is contained in:
@@ -4,9 +4,9 @@
|
|||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { Loader2, ArrowRight } from "lucide-react";
|
import { Loader2, ArrowRight } from "lucide-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import { useState } from "react";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Loader2, ArrowRight } from "lucide-react";
|
import { Loader2, ArrowRight } from "lucide-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { toast } from "@/hooks/use-toast";
|
import { toast } from "@/lib/hooks/use-toast";
|
||||||
|
|
||||||
// Matches LoginPage background
|
// Matches LoginPage background
|
||||||
const AuthBackground = () => (
|
const AuthBackground = () => (
|
||||||
@@ -164,3 +164,5 @@ export default function RegisterPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,11 @@
|
|||||||
import { useState, useEffect, Suspense } from "react";
|
import { useState, useEffect, Suspense } from "react";
|
||||||
import { useRouter, useSearchParams } from "next/navigation";
|
import { useRouter, useSearchParams } from "next/navigation";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
|
|
||||||
interface Vendor {
|
interface Vendor {
|
||||||
@@ -193,3 +193,5 @@ export default function ResetPasswordPage() {
|
|||||||
</Suspense>
|
</Suspense>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/common/textarea";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
|
||||||
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
|
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 { UserX, Shield, Search, Ban, Unlock, Loader2 } from "lucide-react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
|
|
||||||
interface BlockedUser {
|
interface BlockedUser {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -446,3 +446,4 @@ export default function AdminBanPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React from "react";
|
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 { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/common/textarea";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { UserPlus, Mail, Copy, Check } from "lucide-react";
|
import { UserPlus, Mail, Copy, Check } from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
@@ -206,3 +206,4 @@ export default function AdminInvitePage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
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 { Package, AlertTriangle, CheckCircle2, XCircle, DollarSign } from "lucide-react";
|
||||||
import { fetchServer } from "@/lib/api";
|
import { fetchServer } from "@/lib/api";
|
||||||
import OrdersTable from "@/components/admin/OrdersTable";
|
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';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
@@ -241,3 +241,5 @@ export default async function AdminOrdersPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
|
|
||||||
import React, { Suspense, lazy, useState, useEffect, Component, ReactNode } from "react";
|
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 Link from "next/link";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { AlertCircle, RefreshCw } from "lucide-react";
|
import { AlertCircle, RefreshCw } from "lucide-react";
|
||||||
|
|
||||||
// Error Boundary Component
|
// Error Boundary Component
|
||||||
@@ -466,3 +466,4 @@ export default function AdminPage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Server, Database, Cpu, HardDrive, Activity, Zap } from "lucide-react";
|
import { Server, Database, Cpu, HardDrive, Activity, Zap } from "lucide-react";
|
||||||
import { fetchServer } from "@/lib/api";
|
import { fetchServer } from "@/lib/api";
|
||||||
import SystemStatusCard from "@/components/admin/SystemStatusCard";
|
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';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
@@ -243,3 +243,5 @@ export default async function AdminStatusPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
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 { Search, Ban, UserCheck, Package, DollarSign, Loader2, Repeat, Users, ShoppingBag, CreditCard, UserX } from "lucide-react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
|
||||||
interface TelegramUser {
|
interface TelegramUser {
|
||||||
@@ -328,3 +328,5 @@ export default function AdminUsersPage() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
22
app/dashboard/admin/vendors/page.tsx
vendored
22
app/dashboard/admin/vendors/page.tsx
vendored
@@ -1,16 +1,16 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
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 { 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 { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from "@/components/common/dialog";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuSeparator,
|
DropdownMenuSeparator,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/common/dropdown-menu";
|
||||||
|
|
||||||
interface Vendor {
|
interface Vendor {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -571,3 +571,5 @@ export default function AdminVendorsPage() {
|
|||||||
</div >
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { SnowLoader } from "@/components/snow-loader";
|
import { SnowLoader } from "@/components/snow-loader";
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import Dashboard from "@/components/dashboard/dashboard";
|
|||||||
import AnalyticsDashboard from '@/components/analytics/AnalyticsDashboard';
|
import AnalyticsDashboard from '@/components/analytics/AnalyticsDashboard';
|
||||||
import AnalyticsDashboardSkeleton from '@/components/analytics/AnalyticsDashboardSkeleton';
|
import AnalyticsDashboardSkeleton from '@/components/analytics/AnalyticsDashboardSkeleton';
|
||||||
import StoreSelector from '@/components/analytics/StoreSelector';
|
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 { fetchServer } from '@/lib/api';
|
||||||
import { performance } from 'perf_hooks';
|
import { performance } from 'perf_hooks';
|
||||||
import { Info, GitCommit, User, Zap, BarChart3 } from 'lucide-react';
|
import { Info, GitCommit, User, Zap, BarChart3 } from 'lucide-react';
|
||||||
@@ -103,7 +103,7 @@ export default async function AnalyticsPage({
|
|||||||
|
|
||||||
// If it's a 401/403 error, redirect to login
|
// If it's a 401/403 error, redirect to login
|
||||||
if (error instanceof Error && error.message.includes('401')) {
|
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 it's a 400 error (missing storeId for staff), show store selector
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Wallet, Bitcoin, Coins, DollarSign, ArrowUpRight } from "lucide-react";
|
import { Wallet, Bitcoin, Coins, DollarSign, ArrowUpRight } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
|
|
||||||
@@ -166,3 +166,4 @@ export default function BalancePage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import { useState, useEffect, useRef } from "react";
|
import { useState, useEffect, useRef } from "react";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Plus, Pencil, Trash2, ChevronRight, ChevronDown, MoveVertical, FolderTree } from "lucide-react";
|
import { Plus, Pencil, Trash2, ChevronRight, ChevronDown, MoveVertical, FolderTree } from "lucide-react";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import {
|
import {
|
||||||
@@ -12,7 +12,7 @@ import {
|
|||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
@@ -22,10 +22,10 @@ import {
|
|||||||
AlertDialogFooter,
|
AlertDialogFooter,
|
||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/common/alert-dialog";
|
||||||
import { apiRequest } from "@/lib/api";
|
import { apiRequest } from "@/lib/api";
|
||||||
import type { Category } from "@/models/categories";
|
import type { Category } from "@/lib/models/categories";
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
|
||||||
// Drag and Drop imports
|
// Drag and Drop imports
|
||||||
@@ -495,3 +495,4 @@ export default function CategoriesPage() {
|
|||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { SnowLoader } from "@/components/snow-loader";
|
import { SnowLoader } from "@/components/snow-loader";
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Metadata } from "next";
|
import { Metadata } from "next";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { Metadata, Viewport } from "next";
|
import { Metadata, Viewport } from "next";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { useRouter } from "next/navigation";
|
|||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
import { MessageCircle, AlertCircle, RefreshCw } from "lucide-react";
|
import { MessageCircle, AlertCircle, RefreshCw } from "lucide-react";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
|
|
||||||
// Error Boundary Component
|
// Error Boundary Component
|
||||||
interface ErrorBoundaryState {
|
interface ErrorBoundaryState {
|
||||||
@@ -163,19 +163,6 @@ function ChatTableSkeleton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function ChatsPage() {
|
export default function ChatsPage() {
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const authToken = document.cookie
|
|
||||||
.split("; ")
|
|
||||||
.find((row) => row.startsWith("Authorization="))
|
|
||||||
?.split("=")[1];
|
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
}
|
|
||||||
}, [router]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dashboard>
|
<Dashboard>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { Component, ReactNode, useState, useEffect, Suspense } from "react";
|
import { Component, ReactNode, useState, useEffect, Suspense } from "react";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { AlertCircle, RefreshCw } from "lucide-react";
|
import { AlertCircle, RefreshCw } from "lucide-react";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
|
|
||||||
// Error Boundary Component
|
// Error Boundary Component
|
||||||
interface ErrorBoundaryState {
|
interface ErrorBoundaryState {
|
||||||
@@ -260,3 +260,4 @@ export default function DashboardContentWrapper({ children }: { children: ReactN
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { SnowLoader } from "@/components/snow-loader";
|
import { SnowLoader } from "@/components/snow-loader";
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Loader2 } from "lucide-react";
|
import { Loader2 } from "lucide-react";
|
||||||
import { SnowLoader } from "@/components/snow-loader";
|
import { SnowLoader } from "@/components/snow-loader";
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ import { fetchData } from '@/lib/api';
|
|||||||
import { clientFetch } from '@/lib/api';
|
import { clientFetch } from '@/lib/api';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/common/textarea";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -15,13 +15,13 @@ import {
|
|||||||
TableHead,
|
TableHead,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/common/table";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/common/card";
|
||||||
import { Clipboard, Truck, Package, ArrowRight, ChevronDown, AlertTriangle, Copy, Loader2, RefreshCw, MessageCircle } from "lucide-react";
|
import { Clipboard, Truck, Package, ArrowRight, ChevronDown, AlertTriangle, Copy, Loader2, RefreshCw, MessageCircle } from "lucide-react";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
@@ -36,9 +36,9 @@ import {
|
|||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/common/alert-dialog";
|
||||||
import Layout from "@/components/layout/layout";
|
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 OrderTimeline from "@/components/orders/order-timeline";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
|
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ import { useRouter } from "next/navigation";
|
|||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
import { Package, AlertCircle, RefreshCw } from "lucide-react";
|
import { Package, AlertCircle, RefreshCw } from "lucide-react";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
|
|
||||||
// Error Boundary Component
|
// Error Boundary Component
|
||||||
interface ErrorBoundaryState {
|
interface ErrorBoundaryState {
|
||||||
@@ -163,19 +163,6 @@ function OrderTableSkeleton() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function OrdersPage() {
|
export default function OrdersPage() {
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const authToken = document.cookie
|
|
||||||
.split("; ")
|
|
||||||
.find((row) => row.startsWith("Authorization="))
|
|
||||||
?.split("=")[1];
|
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
}
|
|
||||||
}, [router]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dashboard>
|
<Dashboard>
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import packageJson from '../../package.json';
|
|||||||
import { getGitInfo, getShortGitHash } from '@/lib/utils/git';
|
import { getGitInfo, getShortGitHash } from '@/lib/utils/git';
|
||||||
import { Suspense } from 'react';
|
import { Suspense } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { Skeleton } from '@/components/ui/skeleton';
|
import { Skeleton } from '@/components/common/skeleton';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/common/card';
|
||||||
import DashboardContentWrapper from './dashboard-content-wrapper';
|
import DashboardContentWrapper from './dashboard-content-wrapper';
|
||||||
|
|
||||||
// Loading skeleton for the dashboard content
|
// Loading skeleton for the dashboard content
|
||||||
@@ -183,3 +183,4 @@ export default async function DashboardPage() {
|
|||||||
</Dashboard>
|
</Dashboard>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
import { useState, useEffect, ChangeEvent, Suspense } from "react";
|
import { useState, useEffect, ChangeEvent, Suspense } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Product } from "@/models/products";
|
import { Product } from "@/lib/models/products";
|
||||||
import { Plus, Upload, Search, RefreshCw, Package2 } from "lucide-react";
|
import { Plus, Upload, Search, RefreshCw, Package2 } from "lucide-react";
|
||||||
import { clientFetch } from "@/lib/api";
|
import { clientFetch } from "@/lib/api";
|
||||||
import { Category } from "@/models/categories";
|
import { Category } from "@/lib/models/categories";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader } from "@/components/common/card";
|
||||||
|
|
||||||
// Lazy load heavy components with error handling
|
// Lazy load heavy components with error handling
|
||||||
const ProductTable = dynamic(() => import("@/components/tables/product-table").catch((err) => {
|
const ProductTable = dynamic(() => import("@/components/tables/product-table").catch((err) => {
|
||||||
@@ -156,16 +156,6 @@ export default function ProductsPage() {
|
|||||||
|
|
||||||
// Fetch products and categories
|
// Fetch products and categories
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const authToken = document.cookie
|
|
||||||
.split("; ")
|
|
||||||
.find((row) => row.startsWith("Authorization="))
|
|
||||||
?.split("=")[1];
|
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchDataAsync = async () => {
|
const fetchDataAsync = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -194,7 +184,7 @@ export default function ProductsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchDataAsync();
|
fetchDataAsync();
|
||||||
}, [router]);
|
}, []);
|
||||||
|
|
||||||
const handleAddTier = () => {
|
const handleAddTier = () => {
|
||||||
setProductData((prev) => ({
|
setProductData((prev) => ({
|
||||||
@@ -552,3 +542,5 @@ export default function ProductsPage() {
|
|||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import { useState, useEffect, ChangeEvent, Suspense } from "react";
|
|||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Edit, Plus, Trash, Truck } from "lucide-react";
|
import { Edit, Plus, Trash, Truck } from "lucide-react";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import {
|
import {
|
||||||
fetchShippingMethods,
|
fetchShippingMethods,
|
||||||
addShippingMethod,
|
addShippingMethod,
|
||||||
@@ -15,7 +15,7 @@ import {
|
|||||||
ShippingData
|
ShippingData
|
||||||
} from "@/lib/services/shipping-service";
|
} from "@/lib/services/shipping-service";
|
||||||
import dynamic from "next/dynamic";
|
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
|
// Lazy load components with error handling
|
||||||
const ShippingModal = dynamic(() => import("@/components/modals/shipping-modal").then(mod => ({ default: mod.ShippingModal })).catch((err) => {
|
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="))
|
.find((row) => row.startsWith("Authorization="))
|
||||||
?.split("=")[1];
|
?.split("=")[1];
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchedMethods: ShippingMethod[] = await fetchShippingMethods(
|
const fetchedMethods: ShippingMethod[] = await fetchShippingMethods(
|
||||||
authToken
|
authToken
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -3,12 +3,12 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/ui/table";
|
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from "@/components/common/table";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/common/switch";
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
@@ -16,12 +16,12 @@ import {
|
|||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
DropdownMenuLabel,
|
DropdownMenuLabel,
|
||||||
DropdownMenuSeparator
|
DropdownMenuSeparator
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/common/dropdown-menu";
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/common/popover";
|
||||||
import {
|
import {
|
||||||
AlertDialog,
|
AlertDialog,
|
||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
@@ -32,12 +32,12 @@ import {
|
|||||||
AlertDialogHeader,
|
AlertDialogHeader,
|
||||||
AlertDialogTitle,
|
AlertDialogTitle,
|
||||||
AlertDialogTrigger,
|
AlertDialogTrigger,
|
||||||
} from "@/components/ui/alert-dialog";
|
} from "@/components/common/alert-dialog";
|
||||||
import { Product } from "@/models/products";
|
import { Product } from "@/lib/models/products";
|
||||||
import { Package, RefreshCw, ChevronDown, CheckSquare, XSquare, Boxes, Download, Calendar, Search, Filter, Save, X, Edit2 } from "lucide-react";
|
import { Package, RefreshCw, ChevronDown, CheckSquare, XSquare, Boxes, Download, Calendar, Search, Filter, Save, X, Edit2 } from "lucide-react";
|
||||||
import { clientFetch } from "@/lib/api";
|
import { clientFetch } from "@/lib/api";
|
||||||
import { toast } from "sonner";
|
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 { DateRange } from "react-day-picker";
|
||||||
import { addDays, startOfDay, endOfDay, format, isSameDay } from "date-fns";
|
import { addDays, startOfDay, endOfDay, format, isSameDay } from "date-fns";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
@@ -72,16 +72,6 @@ export default function StockManagementPage() {
|
|||||||
const [isExporting, setIsExporting] = useState<boolean>(false);
|
const [isExporting, setIsExporting] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const authToken = document.cookie
|
|
||||||
.split("; ")
|
|
||||||
.find((row) => row.startsWith("Authorization="))
|
|
||||||
?.split("=")[1];
|
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchDataAsync = async () => {
|
const fetchDataAsync = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await clientFetch<Product[]>('api/products');
|
const response = await clientFetch<Product[]>('api/products');
|
||||||
@@ -105,7 +95,7 @@ export default function StockManagementPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
fetchDataAsync();
|
fetchDataAsync();
|
||||||
}, [router]);
|
}, []);
|
||||||
|
|
||||||
const handleEditStock = (productId: string) => {
|
const handleEditStock = (productId: string) => {
|
||||||
setEditingStock({
|
setEditingStock({
|
||||||
@@ -688,3 +678,4 @@ export default function StockManagementPage() {
|
|||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import React, { useEffect, useState, useCallback } from "react";
|
import React, { useEffect, useState, useCallback } from "react";
|
||||||
import { getCustomers, type CustomerStats } from "@/lib/api";
|
import { getCustomers, type CustomerStats } from "@/lib/api";
|
||||||
import { formatCurrency } from "@/utils/format";
|
import { formatCurrency } from "@/lib/utils/format";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
@@ -13,14 +13,14 @@ import {
|
|||||||
TableHead,
|
TableHead,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/common/table";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
@@ -28,8 +28,8 @@ import {
|
|||||||
DialogTitle,
|
DialogTitle,
|
||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogFooter,
|
DialogFooter,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/common/dialog";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import {
|
import {
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
@@ -47,17 +47,17 @@ import {
|
|||||||
Truck,
|
Truck,
|
||||||
CheckCircle,
|
CheckCircle,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/common/card";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
DropdownMenu,
|
DropdownMenu,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
DropdownMenuContent,
|
DropdownMenuContent,
|
||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
} from "@/components/ui/dropdown-menu";
|
} from "@/components/common/dropdown-menu";
|
||||||
|
|
||||||
export default function CustomerManagementPage() {
|
export default function CustomerManagementPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -126,16 +126,6 @@ export default function CustomerManagementPage() {
|
|||||||
fetchCustomers();
|
fetchCustomers();
|
||||||
}, [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
|
// Add filter function to filter customers when search query changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -717,3 +707,4 @@ export default function CustomerManagementPage() {
|
|||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,17 +3,17 @@
|
|||||||
import { useState, useEffect, ChangeEvent } from "react";
|
import { useState, useEffect, ChangeEvent } from "react";
|
||||||
import { useRouter } from "next/navigation";
|
import { useRouter } from "next/navigation";
|
||||||
import Layout from "@/components/layout/layout";
|
import Layout from "@/components/layout/layout";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/common/textarea";
|
||||||
import { Save, Send, Key, MessageSquare, Shield, Globe, Wallet, RefreshCw } from "lucide-react";
|
import { Save, Send, Key, MessageSquare, Shield, Globe, Wallet, RefreshCw } from "lucide-react";
|
||||||
import { apiRequest } from "@/lib/api";
|
import { apiRequest } from "@/lib/api";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import BroadcastDialog from "@/components/modals/broadcast-dialog";
|
import BroadcastDialog from "@/components/modals/broadcast-dialog";
|
||||||
import Dashboard from "@/components/dashboard/dashboard";
|
import Dashboard from "@/components/dashboard/dashboard";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/common/card";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from "framer-motion";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
@@ -21,9 +21,9 @@ import {
|
|||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/common/switch";
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/common/tooltip";
|
||||||
|
|
||||||
const SHIPPING_REGIONS = [
|
const SHIPPING_REGIONS = [
|
||||||
{ value: "UK", label: "United Kingdom", emoji: "🇬🇧" },
|
{ value: "UK", label: "United Kingdom", emoji: "🇬🇧" },
|
||||||
@@ -106,16 +106,6 @@ export default function StorefrontPage() {
|
|||||||
const [saving, setSaving] = useState<boolean>(false);
|
const [saving, setSaving] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const authToken = document.cookie
|
|
||||||
.split("; ")
|
|
||||||
.find((row) => row.startsWith("Authorization="))
|
|
||||||
?.split("=")[1];
|
|
||||||
|
|
||||||
if (!authToken) {
|
|
||||||
router.push("/login");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fetchStorefront = async () => {
|
const fetchStorefront = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
@@ -465,3 +455,5 @@ export default function StorefrontPage() {
|
|||||||
</Dashboard >
|
</Dashboard >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Metadata, Viewport } from "next";
|
import { Metadata, Viewport } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { buttonVariants } from "@/components/ui/button";
|
import { buttonVariants } from "@/components/common/button";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -38,3 +38,4 @@ export default function NotFound() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
11
app/page.tsx
11
app/page.tsx
@@ -1,10 +1,10 @@
|
|||||||
import { getPlatformStatsServer } from "@/lib/server-api";
|
import { getPlatformStatsServer } from "@/lib/api/server-api";
|
||||||
import { HomeNavbar } from "@/components/home-navbar";
|
import { HomeNavbar } from "@/components/layout/home-navbar";
|
||||||
import { Shield, LineChart, Zap, ArrowRight, Sparkles } from "lucide-react";
|
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 Link from "next/link";
|
||||||
import { AnimatedStatsSection } from "@/components/animated-stats-section";
|
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';
|
export const dynamic = 'force-dynamic';
|
||||||
|
|
||||||
@@ -109,3 +109,6 @@ export default async function Home() {
|
|||||||
return <div>Error loading page</div>;
|
return <div>Error loading page</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useKeepOnline } from "@/hooks/useKeepOnline";
|
import { useKeepOnline } from "@/lib/hooks/useKeepOnline";
|
||||||
|
|
||||||
const KeepOnline = () => {
|
const KeepOnline = () => {
|
||||||
useKeepOnline({
|
useKeepOnline({
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ import {
|
|||||||
CardDescription,
|
CardDescription,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/common/card";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import {
|
import {
|
||||||
AlertCircle,
|
AlertCircle,
|
||||||
BarChart,
|
BarChart,
|
||||||
@@ -29,8 +29,8 @@ import {
|
|||||||
Package,
|
Package,
|
||||||
Trophy,
|
Trophy,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import {
|
import {
|
||||||
BarChart as RechartsBarChart,
|
BarChart as RechartsBarChart,
|
||||||
Bar,
|
Bar,
|
||||||
@@ -43,7 +43,7 @@ import {
|
|||||||
Line,
|
Line,
|
||||||
ComposedChart,
|
ComposedChart,
|
||||||
} from "recharts";
|
} from "recharts";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP, formatNumber } from "@/lib/utils/format";
|
||||||
import { PieChart, Pie, Cell, Legend } from "recharts";
|
import { PieChart, Pie, Cell, Legend } from "recharts";
|
||||||
|
|
||||||
interface GrowthData {
|
interface GrowthData {
|
||||||
@@ -691,7 +691,7 @@ export default function AdminAnalytics() {
|
|||||||
{formatCurrency(bestMonth.revenue)}
|
{formatCurrency(bestMonth.revenue)}
|
||||||
</div>
|
</div>
|
||||||
<div className="text-sm text-muted-foreground mt-1">
|
<div className="text-sm text-muted-foreground mt-1">
|
||||||
{bestMonth.orders.toLocaleString()} orders
|
{formatNumber(bestMonth.orders)} orders
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -714,7 +714,7 @@ export default function AdminAnalytics() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.orders?.total?.toLocaleString() || "0"}
|
{formatNumber(analyticsData?.orders?.total)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
||||||
<span className="bg-muted/50 px-1.5 py-0.5 rounded">Today: {analyticsData?.orders?.totalToday || 0}</span>
|
<span className="bg-muted/50 px-1.5 py-0.5 rounded">Today: {analyticsData?.orders?.totalToday || 0}</span>
|
||||||
@@ -876,7 +876,7 @@ export default function AdminAnalytics() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.products?.total?.toLocaleString() || "0"}
|
{formatNumber(analyticsData?.products?.total)}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
<div className="flex items-center text-xs text-muted-foreground mt-1">
|
||||||
<span className="bg-muted/50 px-1.5 py-0.5 rounded">New This Week: {analyticsData?.products?.recent || 0}</span>
|
<span className="bg-muted/50 px-1.5 py-0.5 rounded">New This Week: {analyticsData?.products?.recent || 0}</span>
|
||||||
@@ -1096,27 +1096,25 @@ export default function AdminAnalytics() {
|
|||||||
<div className="bg-muted/50 p-4 rounded-lg">
|
<div className="bg-muted/50 p-4 rounded-lg">
|
||||||
<div className="text-sm font-medium mb-1">Total Vendors</div>
|
<div className="text-sm font-medium mb-1">Total Vendors</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.vendors?.total?.toLocaleString() || "0"}
|
{formatNumber(analyticsData?.vendors?.total)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-muted/50 p-4 rounded-lg">
|
<div className="bg-muted/50 p-4 rounded-lg">
|
||||||
<div className="text-sm font-medium mb-1">Active Vendors</div>
|
<div className="text-sm font-medium mb-1">Active Vendors</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.vendors?.active?.toLocaleString() || "0"}
|
{formatNumber(analyticsData?.vendors?.active)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-muted/50 p-4 rounded-lg">
|
<div className="bg-muted/50 p-4 rounded-lg">
|
||||||
<div className="text-sm font-medium mb-1">Active Stores</div>
|
<div className="text-sm font-medium mb-1">Active Stores</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.vendors?.activeStores?.toLocaleString() ||
|
{formatNumber(analyticsData?.vendors?.activeStores)}
|
||||||
"0"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-muted/50 p-4 rounded-lg">
|
<div className="bg-muted/50 p-4 rounded-lg">
|
||||||
<div className="text-sm font-medium mb-1">New This Week</div>
|
<div className="text-sm font-medium mb-1">New This Week</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{analyticsData?.vendors?.newThisWeek?.toLocaleString() ||
|
{formatNumber(analyticsData?.vendors?.newThisWeek)}
|
||||||
"0"}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1202,7 +1200,7 @@ export default function AdminAnalytics() {
|
|||||||
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
||||||
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
||||||
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Total Orders</div>
|
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Total Orders</div>
|
||||||
<div className="text-2xl font-bold">{growthData.cumulative.orders.toLocaleString()}</div>
|
<div className="text-2xl font-bold">{formatNumber(growthData.cumulative.orders)}</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="col-span-1 border-green-500/20 bg-green-500/5 backdrop-blur-sm hover:bg-green-500/10 transition-colors">
|
<Card className="col-span-1 border-green-500/20 bg-green-500/5 backdrop-blur-sm hover:bg-green-500/10 transition-colors">
|
||||||
@@ -1214,19 +1212,19 @@ export default function AdminAnalytics() {
|
|||||||
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
||||||
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
||||||
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Customers</div>
|
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Customers</div>
|
||||||
<div className="text-2xl font-bold">{growthData.cumulative.customers.toLocaleString()}</div>
|
<div className="text-2xl font-bold">{formatNumber(growthData.cumulative.customers)}</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
||||||
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
||||||
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Vendors</div>
|
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Vendors</div>
|
||||||
<div className="text-2xl font-bold">{growthData.cumulative.vendors.toLocaleString()}</div>
|
<div className="text-2xl font-bold">{formatNumber(growthData.cumulative.vendors)}</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
<Card className="col-span-1 border-border/40 bg-background/50 backdrop-blur-sm hover:bg-background/60 transition-colors">
|
||||||
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
<CardContent className="pt-4 flex flex-col items-center justify-center text-center">
|
||||||
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Products</div>
|
<div className="text-xs font-medium text-muted-foreground uppercase tracking-wider mb-1">Products</div>
|
||||||
<div className="text-2xl font-bold">{growthData.cumulative.products.toLocaleString()}</div>
|
<div className="text-2xl font-bold">{formatNumber(growthData.cumulative.products)}</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="col-span-1 border-purple-500/20 bg-purple-500/5 backdrop-blur-sm hover:bg-purple-500/10 transition-colors">
|
<Card className="col-span-1 border-purple-500/20 bg-purple-500/5 backdrop-blur-sm hover:bg-purple-500/10 transition-colors">
|
||||||
@@ -1292,7 +1290,7 @@ export default function AdminAnalytics() {
|
|||||||
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
||||||
<div className="w-2 h-2 rounded-full bg-blue-500" /> Orders
|
<div className="w-2 h-2 rounded-full bg-blue-500" /> Orders
|
||||||
</span>
|
</span>
|
||||||
<span className="font-medium">{data.orders.toLocaleString()}</span>
|
<span className="font-medium">{formatNumber(data.orders)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
||||||
@@ -1304,7 +1302,7 @@ export default function AdminAnalytics() {
|
|||||||
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
||||||
<div className="w-2 h-2 rounded-full bg-purple-500" /> Customers
|
<div className="w-2 h-2 rounded-full bg-purple-500" /> Customers
|
||||||
</span>
|
</span>
|
||||||
<span className="font-medium">{data.customers.toLocaleString()}</span>
|
<span className="font-medium">{formatNumber(data.customers)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
<span className="text-sm text-muted-foreground flex items-center gap-2">
|
||||||
@@ -1554,3 +1552,5 @@ export default function AdminAnalytics() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
|
|
||||||
export default function BanUserCard() {
|
export default function BanUserCard() {
|
||||||
const [telegramUserId, setTelegramUserId] = useState("");
|
const [telegramUserId, setTelegramUserId] = useState("");
|
||||||
@@ -70,3 +70,4 @@ export default function BanUserCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
|
|
||||||
interface Invitation {
|
interface Invitation {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -88,3 +88,4 @@ export default function InvitationsListCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Copy, Check, Ticket, Loader2, RefreshCw } from "lucide-react";
|
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() {
|
export default function InviteVendorCard() {
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
@@ -103,3 +103,5 @@ export default function InviteVendorCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,13 @@ import {
|
|||||||
DialogDescription,
|
DialogDescription,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/common/dialog";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import { Package, User, Calendar, DollarSign, MapPin, Truck, CheckCircle, XCircle, Clock, Wallet, Copy, ExternalLink } from "lucide-react";
|
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
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState, useMemo } from "react";
|
import { useState, useMemo } from "react";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
|
||||||
import { Search, Filter, Eye, ChevronLeft, ChevronRight } from "lucide-react";
|
import { Search, Filter, Eye, ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { List } from 'react-window';
|
import { List } from 'react-window';
|
||||||
import OrderDetailsModal from "./OrderDetailsModal";
|
import OrderDetailsModal from "./OrderDetailsModal";
|
||||||
@@ -366,3 +366,4 @@ export default function OrdersTable({ orders, enableModal = true }: OrdersTableP
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
|
|
||||||
interface OrderItem {
|
interface OrderItem {
|
||||||
name: string;
|
name: string;
|
||||||
@@ -99,3 +99,4 @@ export default function RecentOrdersCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
|
|
||||||
interface Status {
|
interface Status {
|
||||||
uptimeSeconds: number;
|
uptimeSeconds: number;
|
||||||
@@ -151,3 +151,5 @@ export default function SystemStatusCard() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client";
|
"use client";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import { fetchClient } from "@/lib/api-client";
|
import { fetchClient } from "@/lib/api/api-client";
|
||||||
|
|
||||||
interface Vendor {
|
interface Vendor {
|
||||||
_id: string;
|
_id: string;
|
||||||
@@ -137,3 +137,4 @@ export default function VendorsCard() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,17 +7,17 @@ import {
|
|||||||
CardDescription,
|
CardDescription,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/common/card";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import {
|
import {
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
ShoppingCart,
|
ShoppingCart,
|
||||||
@@ -32,21 +32,21 @@ import {
|
|||||||
EyeOff,
|
EyeOff,
|
||||||
Calculator,
|
Calculator,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import MetricsCard from "./MetricsCard";
|
import MetricsCard from "./MetricsCard";
|
||||||
import {
|
import {
|
||||||
getAnalyticsOverviewWithStore,
|
getAnalyticsOverviewWithStore,
|
||||||
type AnalyticsOverview,
|
type AnalyticsOverview,
|
||||||
} from "@/lib/services/analytics-service";
|
} from "@/lib/services/analytics-service";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP, formatNumber } from "@/lib/utils/format";
|
||||||
import { MetricsCardSkeleton } from "./SkeletonLoaders";
|
import { MetricsCardSkeleton } from "./SkeletonLoaders";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { DateRangePicker } from "@/components/ui/date-picker";
|
import { DateRangePicker } from "@/components/common/date-picker";
|
||||||
import { DateRange } from "react-day-picker";
|
import { DateRange } from "react-day-picker";
|
||||||
import { addDays, startOfDay, endOfDay } from "date-fns";
|
import { addDays, startOfDay, endOfDay } from "date-fns";
|
||||||
import type { DateRange as ProfitDateRange } from "@/lib/services/profit-analytics-service";
|
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";
|
import { motion } from "framer-motion";
|
||||||
|
|
||||||
const RevenueChart = dynamic(() => import("./RevenueChart"), {
|
const RevenueChart = dynamic(() => import("./RevenueChart"), {
|
||||||
@@ -170,7 +170,7 @@ export default function AnalyticsDashboard({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Total Orders",
|
title: "Total Orders",
|
||||||
value: maskValue(data.orders.total.toLocaleString()),
|
value: maskValue(formatNumber(data.orders.total)),
|
||||||
description: "All-time orders",
|
description: "All-time orders",
|
||||||
icon: ShoppingCart,
|
icon: ShoppingCart,
|
||||||
trend: data.orders.completed > 0 ? ("up" as const) : ("neutral" as const),
|
trend: data.orders.completed > 0 ? ("up" as const) : ("neutral" as const),
|
||||||
@@ -178,7 +178,7 @@ export default function AnalyticsDashboard({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Unique Customers",
|
title: "Unique Customers",
|
||||||
value: maskValue(data.customers.unique.toLocaleString()),
|
value: maskValue(formatNumber(data.customers.unique)),
|
||||||
description: "Total customers",
|
description: "Total customers",
|
||||||
icon: Users,
|
icon: Users,
|
||||||
trend: "neutral" as const,
|
trend: "neutral" as const,
|
||||||
@@ -186,7 +186,7 @@ export default function AnalyticsDashboard({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Products",
|
title: "Products",
|
||||||
value: maskValue(data.products.total.toLocaleString()),
|
value: maskValue(formatNumber(data.products.total)),
|
||||||
description: "Active products",
|
description: "Active products",
|
||||||
icon: Package,
|
icon: Package,
|
||||||
trend: "neutral" as const,
|
trend: "neutral" as const,
|
||||||
@@ -451,3 +451,5 @@ export default function AnalyticsDashboard({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/common/tabs";
|
||||||
import { MetricsCardSkeleton } from './SkeletonLoaders';
|
import { MetricsCardSkeleton } from './SkeletonLoaders';
|
||||||
import {
|
import {
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Users, Crown, UserPlus, UserCheck, Star, ChevronLeft, ChevronRight } from "lucide-react";
|
import { Users, Crown, UserPlus, UserCheck, Star, ChevronLeft, ChevronRight } from "lucide-react";
|
||||||
import { getCustomerInsightsWithStore, type CustomerInsights } from "@/lib/services/analytics-service";
|
import { getCustomerInsightsWithStore, type CustomerInsights } from "@/lib/services/analytics-service";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP } from "@/lib/utils/format";
|
||||||
import { CustomerInsightsSkeleton } from './SkeletonLoaders';
|
import { CustomerInsightsSkeleton } from './SkeletonLoaders';
|
||||||
|
|
||||||
export default function CustomerInsightsChart() {
|
export default function CustomerInsightsChart() {
|
||||||
@@ -306,3 +306,4 @@ export default function CustomerInsightsChart() {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import {
|
|||||||
CardDescription,
|
CardDescription,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/common/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { RefreshCw } from "lucide-react";
|
import { RefreshCw } from "lucide-react";
|
||||||
import {
|
import {
|
||||||
getGrowthAnalyticsWithStore,
|
getGrowthAnalyticsWithStore,
|
||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
ResponsiveContainer,
|
ResponsiveContainer,
|
||||||
Area,
|
Area,
|
||||||
} from "recharts";
|
} from "recharts";
|
||||||
|
import { formatGBP, formatNumber } from "@/lib/utils/format";
|
||||||
|
|
||||||
interface GrowthAnalyticsChartProps {
|
interface GrowthAnalyticsChartProps {
|
||||||
hideNumbers?: boolean;
|
hideNumbers?: boolean;
|
||||||
@@ -63,14 +64,6 @@ export default function GrowthAnalyticsChart({
|
|||||||
fetchGrowthData();
|
fetchGrowthData();
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatCurrency = (value: number) => {
|
|
||||||
if (hideNumbers) return "£***";
|
|
||||||
return new Intl.NumberFormat("en-GB", {
|
|
||||||
style: "currency",
|
|
||||||
currency: "GBP",
|
|
||||||
maximumFractionDigits: 0,
|
|
||||||
}).format(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
@@ -115,9 +108,7 @@ export default function GrowthAnalyticsChart({
|
|||||||
Total Orders
|
Total Orders
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{hideNumbers
|
{hideNumbers ? "***" : formatNumber(growthData.cumulative.orders)}
|
||||||
? "***"
|
|
||||||
: growthData.cumulative.orders.toLocaleString()}
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -127,7 +118,7 @@ export default function GrowthAnalyticsChart({
|
|||||||
Total Revenue
|
Total Revenue
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold text-green-600">
|
<div className="text-2xl font-bold text-green-600">
|
||||||
{formatCurrency(growthData.cumulative.revenue)}
|
{hideNumbers ? "£***" : formatGBP(growthData.cumulative.revenue)}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -137,9 +128,7 @@ export default function GrowthAnalyticsChart({
|
|||||||
Customers
|
Customers
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{hideNumbers
|
{hideNumbers ? "***" : formatNumber(growthData.cumulative.customers)}
|
||||||
? "***"
|
|
||||||
: growthData.cumulative.customers.toLocaleString()}
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -149,9 +138,7 @@ export default function GrowthAnalyticsChart({
|
|||||||
Products
|
Products
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{hideNumbers
|
{hideNumbers ? "***" : formatNumber(growthData.cumulative.products)}
|
||||||
? "***"
|
|
||||||
: growthData.cumulative.products.toLocaleString()}
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -161,7 +148,7 @@ export default function GrowthAnalyticsChart({
|
|||||||
Avg Order Value
|
Avg Order Value
|
||||||
</div>
|
</div>
|
||||||
<div className="text-2xl font-bold">
|
<div className="text-2xl font-bold">
|
||||||
{formatCurrency(growthData.cumulative.avgOrderValue)}
|
{hideNumbers ? "£***" : formatGBP(growthData.cumulative.avgOrderValue)}
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -236,16 +223,16 @@ export default function GrowthAnalyticsChart({
|
|||||||
Orders:{" "}
|
Orders:{" "}
|
||||||
{hideNumbers
|
{hideNumbers
|
||||||
? "***"
|
? "***"
|
||||||
: data.orders.toLocaleString()}
|
: formatNumber(data.orders)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-green-600">
|
<p className="text-sm text-green-600">
|
||||||
Revenue: {formatCurrency(data.revenue)}
|
Revenue: {hideNumbers ? "£***" : formatGBP(data.revenue)}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-sm text-purple-600">
|
<p className="text-sm text-purple-600">
|
||||||
Customers:{" "}
|
Customers:{" "}
|
||||||
{hideNumbers
|
{hideNumbers
|
||||||
? "***"
|
? "***"
|
||||||
: data.customers.toLocaleString()}
|
: formatNumber(data.customers)}
|
||||||
</p>
|
</p>
|
||||||
{data.newCustomers !== undefined && (
|
{data.newCustomers !== undefined && (
|
||||||
<p className="text-sm text-cyan-600">
|
<p className="text-sm text-cyan-600">
|
||||||
@@ -327,16 +314,16 @@ export default function GrowthAnalyticsChart({
|
|||||||
)}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right p-2">
|
<td className="text-right p-2">
|
||||||
{hideNumbers ? "***" : month.orders.toLocaleString()}
|
{hideNumbers ? "***" : formatNumber(month.orders)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right p-2 text-green-600">
|
<td className="text-right p-2 text-green-600">
|
||||||
{formatCurrency(month.revenue)}
|
{hideNumbers ? "£***" : formatGBP(month.revenue)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right p-2">
|
<td className="text-right p-2">
|
||||||
{hideNumbers ? "***" : month.customers.toLocaleString()}
|
{hideNumbers ? "***" : formatNumber(month.customers)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right p-2">
|
<td className="text-right p-2">
|
||||||
{formatCurrency(month.avgOrderValue)}
|
{hideNumbers ? "£***" : formatGBP(month.avgOrderValue)}
|
||||||
</td>
|
</td>
|
||||||
<td className="text-right p-2">
|
<td className="text-right p-2">
|
||||||
{hideNumbers ? "***" : (month.newCustomers ?? 0)}
|
{hideNumbers ? "***" : (month.newCustomers ?? 0)}
|
||||||
@@ -352,3 +339,5 @@ export default function GrowthAnalyticsChart({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
"use client"
|
"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 { TrendingUp, TrendingDown, Minus } from "lucide-react";
|
||||||
import { LucideIcon } from "lucide-react";
|
import { LucideIcon } from "lucide-react";
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { BarChart3, Clock, CheckCircle, XCircle, AlertCircle, AlertTriangle } from "lucide-react";
|
import { BarChart3, Clock, CheckCircle, XCircle, AlertCircle, AlertTriangle } from "lucide-react";
|
||||||
import { getOrderAnalyticsWithStore, type OrderAnalytics } from "@/lib/services/analytics-service";
|
import { getOrderAnalyticsWithStore, type OrderAnalytics } from "@/lib/services/analytics-service";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP } from "@/lib/utils/format";
|
||||||
import { ChartSkeleton } from './SkeletonLoaders';
|
import { ChartSkeleton } from './SkeletonLoaders';
|
||||||
|
|
||||||
interface OrderAnalyticsChartProps {
|
interface OrderAnalyticsChartProps {
|
||||||
@@ -202,3 +202,4 @@ export default function OrderAnalyticsChart({ timeRange }: OrderAnalyticsChartPr
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,16 @@ import {
|
|||||||
CardDescription,
|
CardDescription,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
} from "@/components/ui/card";
|
} from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
SelectItem,
|
SelectItem,
|
||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
SelectValue,
|
SelectValue,
|
||||||
} from "@/components/ui/select";
|
} from "@/components/common/select";
|
||||||
import {
|
import {
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
TrendingDown,
|
TrendingDown,
|
||||||
@@ -32,8 +32,8 @@ import {
|
|||||||
Info,
|
Info,
|
||||||
Download,
|
Download,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import CountUp from "react-countup";
|
import CountUp from "react-countup";
|
||||||
import {
|
import {
|
||||||
getPredictionsOverviewWithStore,
|
getPredictionsOverviewWithStore,
|
||||||
@@ -41,7 +41,7 @@ import {
|
|||||||
type PredictionsOverview,
|
type PredictionsOverview,
|
||||||
type StockPredictionsResponse,
|
type StockPredictionsResponse,
|
||||||
} from "@/lib/services/analytics-service";
|
} from "@/lib/services/analytics-service";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP } from "@/lib/utils/format";
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TableBody,
|
TableBody,
|
||||||
@@ -49,7 +49,7 @@ import {
|
|||||||
TableHead,
|
TableHead,
|
||||||
TableHeader,
|
TableHeader,
|
||||||
TableRow,
|
TableRow,
|
||||||
} from "@/components/ui/table";
|
} from "@/components/common/table";
|
||||||
import { format } from "date-fns";
|
import { format } from "date-fns";
|
||||||
import {
|
import {
|
||||||
AreaChart,
|
AreaChart,
|
||||||
@@ -65,9 +65,9 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/common/tooltip";
|
||||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert";
|
import { Alert, AlertDescription, AlertTitle } from "@/components/common/alert";
|
||||||
import { Slider } from "@/components/ui/slider";
|
import { Slider } from "@/components/common/slider";
|
||||||
|
|
||||||
interface PredictionsChartProps {
|
interface PredictionsChartProps {
|
||||||
timeRange?: number;
|
timeRange?: number;
|
||||||
@@ -933,3 +933,5 @@ export default function PredictionsChart({
|
|||||||
</Card >
|
</Card >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/common/table";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { Package } from "lucide-react";
|
import { Package } from "lucide-react";
|
||||||
import { getProductPerformanceWithStore, type ProductPerformance } from "@/lib/services/analytics-service";
|
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';
|
import { TableSkeleton } from './SkeletonLoaders';
|
||||||
|
|
||||||
export default function ProductPerformanceChart() {
|
export default function ProductPerformanceChart() {
|
||||||
@@ -137,7 +137,7 @@ export default function ProductPerformanceChart() {
|
|||||||
</div>
|
</div>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right font-medium">
|
<TableCell className="text-right font-medium">
|
||||||
{parseInt(product.totalSold.toFixed(0)).toLocaleString()} {product.unitType}
|
{formatNumber(parseInt(product.totalSold.toFixed(0)))} {product.unitType}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell className="text-right font-medium text-green-600">
|
<TableCell className="text-right font-medium text-green-600">
|
||||||
{formatGBP(product.totalRevenue)}
|
{formatGBP(product.totalRevenue)}
|
||||||
@@ -156,3 +156,4 @@ export default function ProductPerformanceChart() {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/common/badge";
|
||||||
import { Alert, AlertDescription } from "@/components/ui/alert";
|
import { Alert, AlertDescription } from "@/components/common/alert";
|
||||||
import {
|
import {
|
||||||
TrendingUp,
|
TrendingUp,
|
||||||
TrendingDown,
|
TrendingDown,
|
||||||
@@ -14,10 +14,10 @@ import {
|
|||||||
AlertTriangle,
|
AlertTriangle,
|
||||||
Package
|
Package
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { formatGBP } from "@/utils/format";
|
import { formatGBP } from "@/lib/utils/format";
|
||||||
import { getProfitOverview, type ProfitOverview, type DateRange } from "@/lib/services/profit-analytics-service";
|
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 {
|
interface ProfitAnalyticsChartProps {
|
||||||
timeRange?: string;
|
timeRange?: string;
|
||||||
@@ -379,3 +379,5 @@ export default function ProfitAnalyticsChart({ timeRange, dateRange, hideNumbers
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
import { TrendingUp, DollarSign } from "lucide-react";
|
import { TrendingUp, DollarSign } from "lucide-react";
|
||||||
import { getRevenueTrendsWithStore, type RevenueData } from "@/lib/services/analytics-service";
|
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 { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, AreaChart, Area } from 'recharts';
|
||||||
import { ChartSkeleton } from './SkeletonLoaders';
|
import { ChartSkeleton } from './SkeletonLoaders';
|
||||||
|
|
||||||
@@ -240,3 +240,4 @@ export default function RevenueChart({ timeRange, hideNumbers = false }: Revenue
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
import { Skeleton } from "@/components/common/skeleton";
|
||||||
|
|
||||||
// Chart skeleton for revenue trends and order analytics
|
// Chart skeleton for revenue trends and order analytics
|
||||||
export function ChartSkeleton({
|
export function ChartSkeleton({
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useRouter, useSearchParams } from 'next/navigation';
|
import { useRouter, useSearchParams } from 'next/navigation';
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/common/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/common/input";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/common/label";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/common/card";
|
||||||
import { Store, Search } from "lucide-react";
|
import { Store, Search } from "lucide-react";
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/lib/hooks/use-toast";
|
||||||
|
|
||||||
export default function StoreSelector() {
|
export default function StoreSelector() {
|
||||||
const [storeId, setStoreId] = useState('');
|
const [storeId, setStoreId] = useState('');
|
||||||
@@ -112,3 +112,4 @@ export default function StoreSelector() {
|
|||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import * as React from "react"
|
|||||||
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
import { buttonVariants } from "@/components/common/button"
|
||||||
|
|
||||||
const AlertDialog = AlertDialogPrimitive.Root
|
const AlertDialog = AlertDialogPrimitive.Root
|
||||||
|
|
||||||
@@ -139,3 +139,4 @@ export {
|
|||||||
AlertDialogAction,
|
AlertDialogAction,
|
||||||
AlertDialogCancel,
|
AlertDialogCancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react"
|
|||||||
import { DayPicker } from "react-day-picker"
|
import { DayPicker } from "react-day-picker"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
import { buttonVariants } from "@/components/common/button"
|
||||||
|
|
||||||
export type CalendarProps = React.ComponentProps<typeof DayPicker>
|
export type CalendarProps = React.ComponentProps<typeof DayPicker>
|
||||||
|
|
||||||
@@ -64,3 +64,4 @@ function Calendar({
|
|||||||
Calendar.displayName = "Calendar"
|
Calendar.displayName = "Calendar"
|
||||||
|
|
||||||
export { Calendar }
|
export { Calendar }
|
||||||
|
|
||||||
@@ -7,7 +7,7 @@ import useEmblaCarousel, {
|
|||||||
import { ArrowLeft, ArrowRight } from "lucide-react"
|
import { ArrowLeft, ArrowRight } from "lucide-react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/common/button"
|
||||||
|
|
||||||
type CarouselApi = UseEmblaCarouselType[1]
|
type CarouselApi = UseEmblaCarouselType[1]
|
||||||
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
type UseCarouselParameters = Parameters<typeof useEmblaCarousel>
|
||||||
@@ -260,3 +260,4 @@ export {
|
|||||||
CarouselPrevious,
|
CarouselPrevious,
|
||||||
CarouselNext,
|
CarouselNext,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import { Command as CommandPrimitive } from "cmdk"
|
|||||||
import { Search } from "lucide-react"
|
import { Search } from "lucide-react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
import { Dialog, DialogContent } from "@/components/common/dialog"
|
||||||
|
|
||||||
const Command = React.forwardRef<
|
const Command = React.forwardRef<
|
||||||
React.ElementRef<typeof CommandPrimitive>,
|
React.ElementRef<typeof CommandPrimitive>,
|
||||||
@@ -15,7 +15,7 @@ const Command = React.forwardRef<
|
|||||||
<CommandPrimitive
|
<CommandPrimitive
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
"flex h-full w-full flex-col overflow-hidden bg-transparent text-popover-foreground",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -26,8 +26,8 @@ Command.displayName = CommandPrimitive.displayName
|
|||||||
const CommandDialog = ({ children, ...props }: DialogProps) => {
|
const CommandDialog = ({ children, ...props }: DialogProps) => {
|
||||||
return (
|
return (
|
||||||
<Dialog {...props}>
|
<Dialog {...props}>
|
||||||
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
<DialogContent className="overflow-hidden p-0 shadow-2xl border-white/5 bg-[#0a0a0a]/80 backdrop-blur-2xl sm:max-w-[600px] [&_button[data-radix-collection-item]]:hidden [&_button[class*='absolute']]:hidden">
|
||||||
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
<Command className="[&_[cmdk-group-heading]]:px-4 [&_[cmdk-group-heading]]:font-semibold [&_[cmdk-group-heading]]:text-primary/50 [&_[cmdk-group-heading]]:text-[10px] [&_[cmdk-group-heading]]:uppercase [&_[cmdk-group-heading]]:tracking-widest [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-14 [&_[cmdk-item]]:px-3 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
||||||
{children}
|
{children}
|
||||||
</Command>
|
</Command>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
@@ -39,12 +39,12 @@ const CommandInput = React.forwardRef<
|
|||||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
React.ElementRef<typeof CommandPrimitive.Input>,
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
<div className="flex items-center border-b border-white/5 px-4 bg-white/5" cmdk-input-wrapper="">
|
||||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
<Search className="mr-3 h-5 w-5 shrink-0 text-primary opacity-70" />
|
||||||
<CommandPrimitive.Input
|
<CommandPrimitive.Input
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
"flex h-14 w-full rounded-none bg-transparent py-4 text-base outline-none placeholder:text-muted-foreground/50 disabled:cursor-not-allowed disabled:opacity-50 border-none ring-0 focus:ring-0 focus:outline-none",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -60,7 +60,7 @@ const CommandList = React.forwardRef<
|
|||||||
>(({ className, ...props }, ref) => (
|
>(({ className, ...props }, ref) => (
|
||||||
<CommandPrimitive.List
|
<CommandPrimitive.List
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden scrollbar-thin scrollbar-thumb-white/10 scrollbar-track-transparent", className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
@@ -115,7 +115,7 @@ const CommandItem = React.forwardRef<
|
|||||||
<CommandPrimitive.Item
|
<CommandPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
"relative flex cursor-default gap-2 select-none items-center rounded-lg px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-primary/20 data-[selected=true]:text-primary data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 transition-colors duration-200",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -151,3 +151,4 @@ export {
|
|||||||
CommandShortcut,
|
CommandShortcut,
|
||||||
CommandSeparator,
|
CommandSeparator,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,17 +6,17 @@ import { Calendar as CalendarIcon, ChevronLeft, ChevronRight, X } from "lucide-r
|
|||||||
import { DateRange } from "react-day-picker"
|
import { DateRange } from "react-day-picker"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles"
|
import { cn } from "@/lib/utils/styles"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/common/button"
|
||||||
import { Calendar } from "@/components/ui/calendar"
|
import { Calendar } from "@/components/common/calendar"
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover"
|
} from "@/components/common/popover"
|
||||||
import { Badge } from "@/components/ui/badge"
|
import { Badge } from "@/components/common/badge"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/common/input"
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/common/label"
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/common/select"
|
||||||
|
|
||||||
interface DatePickerProps {
|
interface DatePickerProps {
|
||||||
date?: Date
|
date?: Date
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
"use client"
|
"use client"
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/common/button"
|
||||||
import {
|
import {
|
||||||
Package,
|
Package,
|
||||||
ShoppingBag,
|
ShoppingBag,
|
||||||
@@ -136,3 +136,4 @@ export function ChatsEmptyState() {
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ import {
|
|||||||
} from "react-hook-form"
|
} from "react-hook-form"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { Label } from "@/components/ui/label"
|
import { Label } from "@/components/common/label"
|
||||||
|
|
||||||
const Form = FormProvider
|
const Form = FormProvider
|
||||||
|
|
||||||
@@ -176,3 +176,4 @@ export {
|
|||||||
FormMessage,
|
FormMessage,
|
||||||
FormField,
|
FormField,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@ import * as React from "react"
|
|||||||
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
|
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { ButtonProps, buttonVariants } from "@/components/ui/button"
|
import { ButtonProps, buttonVariants } from "@/components/common/button"
|
||||||
|
|
||||||
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
||||||
<nav
|
<nav
|
||||||
@@ -115,3 +115,4 @@ export {
|
|||||||
PaginationNext,
|
PaginationNext,
|
||||||
PaginationPrevious,
|
PaginationPrevious,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip"
|
} from "@/components/common/tooltip"
|
||||||
import { format, formatDistanceToNow, isToday, isYesterday, differenceInMinutes } from "date-fns"
|
import { format, formatDistanceToNow, isToday, isYesterday, differenceInMinutes } from "date-fns"
|
||||||
|
|
||||||
interface RelativeTimeProps {
|
interface RelativeTimeProps {
|
||||||
@@ -112,3 +112,4 @@ export function getRelativeTimeString(date: Date | string | null | undefined): s
|
|||||||
|
|
||||||
return formatDistanceToNow(d, { addSuffix: true })
|
return formatDistanceToNow(d, { addSuffix: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5,19 +5,19 @@ import { Slot } from "@radix-ui/react-slot"
|
|||||||
import { VariantProps, cva } from "class-variance-authority"
|
import { VariantProps, cva } from "class-variance-authority"
|
||||||
import { PanelLeft } from "lucide-react"
|
import { PanelLeft } from "lucide-react"
|
||||||
|
|
||||||
import { useIsMobile } from "@/hooks/use-mobile"
|
import { useIsMobile } from "@/lib/hooks/use-mobile"
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { Button } from "@/components/ui/button"
|
import { Button } from "@/components/common/button"
|
||||||
import { Input } from "@/components/ui/input"
|
import { Input } from "@/components/common/input"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/common/separator"
|
||||||
import { Sheet, SheetContent } from "@/components/ui/sheet"
|
import { Sheet, SheetContent } from "@/components/common/sheet"
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
import { Skeleton } from "@/components/common/skeleton"
|
||||||
import {
|
import {
|
||||||
Tooltip,
|
Tooltip,
|
||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip"
|
} from "@/components/common/tooltip"
|
||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar:state"
|
const SIDEBAR_COOKIE_NAME = "sidebar:state"
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
|
||||||
@@ -761,3 +761,5 @@ export {
|
|||||||
SidebarTrigger,
|
SidebarTrigger,
|
||||||
useSidebar,
|
useSidebar,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"
|
|||||||
import { type VariantProps } from "class-variance-authority"
|
import { type VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils/styles";
|
import { cn } from "@/lib/utils/styles";
|
||||||
import { toggleVariants } from "@/components/ui/toggle"
|
import { toggleVariants } from "@/components/common/toggle"
|
||||||
|
|
||||||
const ToggleGroupContext = React.createContext<
|
const ToggleGroupContext = React.createContext<
|
||||||
VariantProps<typeof toggleVariants>
|
VariantProps<typeof toggleVariants>
|
||||||
@@ -59,3 +59,4 @@ const ToggleGroupItem = React.forwardRef<
|
|||||||
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
|
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName
|
||||||
|
|
||||||
export { ToggleGroup, ToggleGroupItem }
|
export { ToggleGroup, ToggleGroupItem }
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ import * as React from "react"
|
|||||||
import type {
|
import type {
|
||||||
ToastActionElement,
|
ToastActionElement,
|
||||||
ToastProps,
|
ToastProps,
|
||||||
} from "@/components/ui/toast"
|
} from "@/components/common/toast"
|
||||||
|
|
||||||
const TOAST_LIMIT = 1
|
const TOAST_LIMIT = 1
|
||||||
const TOAST_REMOVE_DELAY = 1000000
|
const TOAST_REMOVE_DELAY = 1000000
|
||||||
@@ -192,3 +192,4 @@ function useToast() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { useToast, toast }
|
export { useToast, toast }
|
||||||
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user