This commit is contained in:
g
2025-12-15 18:09:38 +00:00
parent 0176f89cb7
commit f697181d00
89 changed files with 177 additions and 134 deletions

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useKeepOnline } from "@/hooks/useKeepOnline"; import { useKeepOnline } from "@/hooks/useKeepOnline";
@@ -14,4 +14,4 @@ const KeepOnline = () => {
return null; return null;
} }
export default KeepOnline; export default KeepOnline;

View File

@@ -1,4 +1,4 @@
"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/ui/card";
@@ -739,4 +739,4 @@ export default function AdminAnalytics() {
</Tabs> </Tabs>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { fetchClient } from "@/lib/api-client"; import { fetchClient } from "@/lib/api-client";

View File

@@ -1,4 +1,4 @@
"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-client";
@@ -62,7 +62,7 @@ export default function InvitationsListCard() {
Code: <span className="font-mono px-1.5 py-0.5 rounded bg-muted">{inv.code}</span> Code: <span className="font-mono px-1.5 py-0.5 rounded bg-muted">{inv.code}</span>
</div> </div>
<div className="text-xs text-muted-foreground"> <div className="text-xs text-muted-foreground">
Created: {new Date(inv.createdAt).toLocaleString()} Expires: {new Date(inv.expiresAt).toLocaleString()} Created: {new Date(inv.createdAt).toLocaleString()} · Expires: {new Date(inv.expiresAt).toLocaleString()}
</div> </div>
</div> </div>
<div className="flex items-center gap-2 shrink-0"> <div className="flex items-center gap-2 shrink-0">

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { fetchClient } from "@/lib/api-client"; import { fetchClient } from "@/lib/api-client";

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";

View File

@@ -1,4 +1,4 @@
"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-client";
@@ -81,7 +81,7 @@ export default function RecentOrdersCard() {
</div> </div>
</div> </div>
<div className="mt-1 text-xs text-muted-foreground"> <div className="mt-1 text-xs text-muted-foreground">
User: {o.userId} Total: £{Number(o.total).toFixed(2)} User: {o.userId} · Total: £{Number(o.total).toFixed(2)}
</div> </div>
{o.items && o.items.length > 0 && ( {o.items && o.items.length > 0 && (
<ul className="mt-2 text-xs list-disc pl-4 text-muted-foreground"> <ul className="mt-2 text-xs list-disc pl-4 text-muted-foreground">

View File

@@ -1,4 +1,4 @@
"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-client";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";

View File

@@ -1,4 +1,4 @@
"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-client";
@@ -63,7 +63,7 @@ export default function VendorsCard() {
<div className="font-medium">{vendor.username}</div> <div className="font-medium">{vendor.username}</div>
<div className="text-xs text-muted-foreground"> <div className="text-xs text-muted-foreground">
Created: {new Date(vendor.createdAt).toLocaleDateString()} Created: {new Date(vendor.createdAt).toLocaleDateString()}
{vendor.lastLogin && ` Last login: ${new Date(vendor.lastLogin).toLocaleDateString()}`} {vendor.lastLogin && ` · Last login: ${new Date(vendor.lastLogin).toLocaleDateString()}`}
</div> </div>
</div> </div>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
@@ -68,4 +68,4 @@ export function AnimatedCounter({
: `${prefix}${displayValue.toLocaleString()}${suffix}`; : `${prefix}${displayValue.toLocaleString()}${suffix}`;
return <span>{formattedValue}</span>; return <span>{formattedValue}</span>;
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { Package, Users, CreditCard } from "lucide-react"; import { Package, Users, CreditCard } from "lucide-react";
import { AnimatedCounter } from "./animated-counter"; import { AnimatedCounter } from "./animated-counter";
@@ -80,4 +80,4 @@ export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
</div> </div>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useEffect } from "react" import { useEffect } from "react"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
import { isDecember } from "@/lib/utils/christmas" import { isDecember } from "@/lib/utils/christmas"
@@ -39,30 +39,30 @@ export function ChristmasDecorations() {
animationDuration: `${flake.duration}s`, animationDuration: `${flake.duration}s`,
}} }}
> >
ÔØä
</div> </div>
))} ))}
{/* Twinkling stars in corners */} {/* Twinkling stars in corners */}
<div className="absolute top-4 left-4 text-yellow-300 animate-twinkle text-lg"> <div className="absolute top-4 left-4 text-yellow-300 animate-twinkle text-lg">
Ô£¿
</div> </div>
<div className="absolute top-4 right-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '0.5s' }}> <div className="absolute top-4 right-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '0.5s' }}>
Ô£¿
</div> </div>
<div className="absolute bottom-4 left-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '1s' }}> <div className="absolute bottom-4 left-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '1s' }}>
Ô£¿
</div> </div>
<div className="absolute bottom-4 right-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '1.5s' }}> <div className="absolute bottom-4 right-4 text-yellow-300 animate-twinkle text-lg" style={{ animationDelay: '1.5s' }}>
Ô£¿
</div> </div>
{/* Christmas tree emoji decorations */} {/* Christmas tree emoji decorations */}
<div className="absolute top-8 left-1/4 text-green-500/40 animate-sparkle text-xl" style={{ animationDelay: '2s' }}> <div className="absolute top-8 left-1/4 text-green-500/40 animate-sparkle text-xl" style={{ animationDelay: '2s' }}>
­ƒÄä 🎄
</div> </div>
<div className="absolute top-8 right-1/4 text-green-500/40 animate-sparkle text-xl" style={{ animationDelay: '3s' }}> <div className="absolute top-8 right-1/4 text-green-500/40 animate-sparkle text-xl" style={{ animationDelay: '3s' }}>
­ƒÄä 🎄
</div> </div>
</div> </div>
) )

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import React, { useState, useEffect, useCallback, useRef } from "react"; import React, { useState, useEffect, useCallback, useRef } from "react";
import { Package, ShoppingBag, Info, ExternalLink, Loader2, AlertTriangle } from "lucide-react"; import { Package, ShoppingBag, Info, ExternalLink, Loader2, AlertTriangle } from "lucide-react";
@@ -237,7 +237,7 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps)
<div className="p-3 border-b"> <div className="p-3 border-b">
<h4 className="font-medium text-sm">Customer Orders</h4> <h4 className="font-medium text-sm">Customer Orders</h4>
<p className="text-xs text-muted-foreground"> <p className="text-xs text-muted-foreground">
{orders.length} {orders.length === 1 ? 'order' : 'orders'} ÔÇó Total: {formatPrice( {orders.length} {orders.length === 1 ? 'order' : 'orders'} Total: {formatPrice(
orders.reduce((sum, order) => sum + order.totalPrice, 0) orders.reduce((sum, order) => sum + order.totalPrice, 0)
)} )}
</p> </p>
@@ -279,11 +279,11 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps)
<div className="flex justify-between items-center text-xs text-muted-foreground pl-5"> <div className="flex justify-between items-center text-xs text-muted-foreground pl-5">
<div className="flex gap-1"> <div className="flex gap-1">
<span>{order.products.length} {order.products.length === 1 ? 'product' : 'products'}</span> <span>{order.products.length} {order.products.length === 1 ? 'product' : 'products'}</span>
<span></span> <span>·</span>
<span>{formatPrice(order.totalPrice)}</span> <span>{formatPrice(order.totalPrice)}</span>
{isOrderUnderpaid(order) && ( {isOrderUnderpaid(order) && (
<> <>
<span></span> <span>·</span>
<span className="text-red-500">Underpaid</span> <span className="text-red-500">Underpaid</span>
</> </>
)} )}
@@ -299,4 +299,4 @@ export default function BuyerOrderInfo({ buyerId, chatId }: BuyerOrderInfoProps)
</Tooltip> </Tooltip>
</TooltipProvider> </TooltipProvider>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import React, { useState, useEffect, useRef } from "react"; import React, { useState, useEffect, useRef } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
@@ -832,4 +832,4 @@ export default function ChatDetail({ chatId }: { chatId: string }) {
/> />
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import React, { useState, useEffect, useRef, useCallback } from 'react'; import React, { useState, useEffect, useRef, useCallback } from 'react';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
@@ -420,4 +420,4 @@ export default function ChatTable() {
)} )}
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { useRouter, useSearchParams } from "next/navigation"; import { useRouter, useSearchParams } from "next/navigation";
@@ -350,4 +350,4 @@ export default function NewChatForm() {
</CardContent> </CardContent>
</Card> </Card>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import OrderStats from "./order-stats" import OrderStats from "./order-stats"
@@ -75,7 +75,7 @@ export default function Content({ username, orderStats }: ContentProps) {
{greeting}, {username}! {greeting}, {username}!
</h1> </h1>
<p className="text-muted-foreground mt-1 italic text-sm"> <p className="text-muted-foreground mt-1 italic text-sm">
"{randomQuote.text}" ÔÇö <span className="font-medium">{randomQuote.author}</span> "{randomQuote.text}" <span className="font-medium">{randomQuote.author}</span>
</p> </p>
</div> </div>

View File

@@ -1,4 +1,4 @@
import type React from "react" import type React from "react"
import Layout from "../layout/layout" import Layout from "../layout/layout"
export default function Dashboard({ children }: { children: React.ReactNode }) { export default function Dashboard({ children }: { children: React.ReactNode }) {

View File

@@ -1,4 +1,4 @@
import type { LucideIcon } from "lucide-react" import type { LucideIcon } from "lucide-react"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
interface OrderStatsProps { interface OrderStatsProps {

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { Skeleton } from "@/components/ui/skeleton"; import { Skeleton } from "@/components/ui/skeleton";
import { Card } from "@/components/ui/card"; import { Card } from "@/components/ui/card";
@@ -113,4 +113,4 @@ export default function PageLoading({
</Card> </Card>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { z } from 'zod'; import { z } from 'zod';
@@ -464,4 +464,4 @@ export default function EditPromotionForm({ promotion, onSuccess, onCancel }: Ed
</form> </form>
</Form> </Form>
); );
} }

View File

@@ -1,4 +1,4 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { z } from 'zod'; import { z } from 'zod';
@@ -459,4 +459,4 @@ export default function NewPromotionForm({ onSuccess, onCancel }: NewPromotionFo
</form> </form>
</Form> </Form>
); );
} }

View File

@@ -1,4 +1,4 @@
'use client'; 'use client';
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { Check, ChevronDown, X, Search } from 'lucide-react'; import { Check, ChevronDown, X, Search } from 'lucide-react';
@@ -248,4 +248,4 @@ export default function ProductSelector({
)} )}
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { import {
@@ -222,7 +222,7 @@ export default function PromotionDetailsModal({
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium">Current Usage</span> <span className="text-sm font-medium">Current Usage</span>
<span className="text-sm text-muted-foreground"> <span className="text-sm text-muted-foreground">
{promotion.usageCount} / {promotion.maxUsage || 'Ôê×'} {promotion.usageCount} / {promotion.maxUsage || ''}
</span> </span>
</div> </div>
<div className="w-full bg-gray-200 rounded-full h-2"> <div className="w-full bg-gray-200 rounded-full h-2">
@@ -382,4 +382,4 @@ export default function PromotionDetailsModal({
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );
} }

View File

@@ -1,4 +1,4 @@
'use client'; 'use client';
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Plus, Tag, RefreshCw, Trash, Edit, Check, X, Eye } from 'lucide-react'; import { Plus, Tag, RefreshCw, Trash, Edit, Check, X, Eye } from 'lucide-react';
@@ -184,7 +184,7 @@ export default function PromotionsList() {
: 'None'} : 'None'}
</TableCell> </TableCell>
<TableCell> <TableCell>
{promotion.usageCount} / {promotion.maxUsage || 'Ôê×'} {promotion.usageCount} / {promotion.maxUsage || ''}
</TableCell> </TableCell>
<TableCell>{formatDate(promotion.endDate)}</TableCell> <TableCell>{formatDate(promotion.endDate)}</TableCell>
<TableCell> <TableCell>
@@ -306,4 +306,4 @@ export default function PromotionsList() {
/> />
</> </>
); );
} }

View File

@@ -1,4 +1,4 @@
import { import {
Table, Table,
TableBody, TableBody,
TableCell, TableCell,
@@ -59,4 +59,4 @@ export default function PromotionsPageSkeleton() {
</Card> </Card>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import Link from "next/link"; import Link from "next/link";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -89,4 +89,4 @@ export function HomeNavbar() {
)} )}
</header> </header>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import KeepOnline from "@/components/KeepOnline"; import KeepOnline from "@/components/KeepOnline";
@@ -14,4 +14,4 @@ const KeepOnlineWrapper = () => {
return <KeepOnline />; return <KeepOnline />;
}; };
export default KeepOnlineWrapper; export default KeepOnlineWrapper;

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useState, useEffect } from "react" import { useState, useEffect } from "react"
import { useTheme } from "next-themes" import { useTheme } from "next-themes"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import Link from "next/link" import Link from "next/link"
import { usePathname } from "next/navigation" import { usePathname } from "next/navigation"
@@ -65,4 +65,4 @@ export const NavItem: React.FC<NavItemProps> = ({ href, icon: Icon, children, on
{children} {children}
</Link> </Link>
) )
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useState } from "react" import { useState } from "react"
import Link from "next/link" import Link from "next/link"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { ThemeProvider as NextThemesProvider } from "next-themes" import { ThemeProvider as NextThemesProvider } from "next-themes"
import type { ThemeProviderProps } from "next-themes" import type { ThemeProviderProps } from "next-themes"

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState, useRef } from "react"; import { useState, useRef } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -350,4 +350,4 @@ __italic text__
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );
} }

View File

@@ -1,4 +1,4 @@
import { Dialog, DialogContent } from "@/components/ui/dialog"; import { Dialog, DialogContent } from "@/components/ui/dialog";
import { ChevronLeft, ChevronRight, X } from "lucide-react"; import { ChevronLeft, ChevronRight, X } from "lucide-react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { useEffect } from "react"; import { useEffect } from "react";
@@ -96,4 +96,4 @@ export function ImageViewerModal({ isOpen, onClose, imageUrl, onNavigate }: Imag
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState } from "react"; import { useState } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
@@ -65,7 +65,7 @@ export default function ImportProductsModal({ open, setOpen, onImportComplete }:
const [name] = productInfo.split("\n"); const [name] = productInfo.split("\n");
if (!name) continue; if (!name) continue;
const [category, subcategory] = productInfo.split("\n")[1].split("ÔÇó")[0].split("->") const [category, subcategory] = productInfo.split("\n")[1].split("")[0].split("->")
.map(item => item.trim()); .map(item => item.trim());
if (!category || !subcategory) continue; if (!category || !subcategory) continue;
@@ -193,4 +193,4 @@ export default function ImportProductsModal({ open, setOpen, onImportComplete }:
</DialogContent> </DialogContent>
</Dialog> </Dialog>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
@@ -320,7 +320,7 @@ const ProductBasicInfo: React.FC<{
</div> </div>
<div className="bg-background rounded-lg border border-border p-4"> <div className="bg-background rounded-lg border border-border p-4">
<h3 className="text-sm font-medium mb-4">­ƒÆ Cost & Profit Tracking</h3> <h3 className="text-sm font-medium mb-4">💰 Cost & Profit Tracking</h3>
<p className="text-xs text-muted-foreground mb-4"> <p className="text-xs text-muted-foreground mb-4">
Track your costs to automatically calculate profit margins and markup percentages. Track your costs to automatically calculate profit margins and markup percentages.
</p> </p>
@@ -474,4 +474,4 @@ const UnitTypeSelect: React.FC<{
</Button> </Button>
</div> </div>
</div> </div>
); );

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -127,4 +127,4 @@ export default function ProductSelector({ selectedProducts, onSelectionChange }:
)} )}
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog";

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { ChangeEvent, FormEvent } from "react"; import { ChangeEvent, FormEvent } from "react";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
@@ -9,7 +9,7 @@ import { ShippingData } from "@/lib/types";
interface ShippingModalProps { interface ShippingModalProps {
open: boolean; open: boolean;
onClose: () => void; onClose: () => void;
onSave: (shippingData: ShippingData) => void; //  Allow passing shippingData onSave: (shippingData: ShippingData) => void; // Allow passing shippingData
shippingData: ShippingData; shippingData: ShippingData;
setShippingData: React.Dispatch<React.SetStateAction<ShippingData>>; setShippingData: React.Dispatch<React.SetStateAction<ShippingData>>;
editing: boolean; editing: boolean;

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
import { isDecember } from "@/lib/utils/christmas" import { isDecember } from "@/lib/utils/christmas"
@@ -45,7 +45,7 @@ export function SnowLoader({ className = "", count = 20 }: SnowLoaderProps) {
fontSize: `${flake.size}rem`, fontSize: `${flake.size}rem`,
}} }}
> >
ÔØä
</div> </div>
))} ))}
</div> </div>

View File

@@ -34,7 +34,9 @@ import {
} from "lucide-react"; } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import { clientFetch } from '@/lib/api'; import { clientFetch } from '@/lib/api';
import { exportOrdersToCSV } from '@/lib/api-client';
import { toast } from "sonner"; import { toast } from "sonner";
import { Download } from "lucide-react";
import { Checkbox } from "@/components/ui/checkbox"; import { Checkbox } from "@/components/ui/checkbox";
import { import {
AlertDialog, AlertDialog,
@@ -140,6 +142,7 @@ export default function OrderTable() {
const [itemsPerPage, setItemsPerPage] = useState<number>(20); const [itemsPerPage, setItemsPerPage] = useState<number>(20);
const pageSizeOptions = [5, 10, 15, 20, 25, 50, 75, 100]; const pageSizeOptions = [5, 10, 15, 20, 25, 50, 75, 100];
const [refreshTrigger, setRefreshTrigger] = useState(0); const [refreshTrigger, setRefreshTrigger] = useState(0);
const [exporting, setExporting] = useState(false);
// Add order refresh subscription // Add order refresh subscription
useEffect(() => { useEffect(() => {
@@ -351,6 +354,25 @@ export default function OrderTable() {
toast.success("Orders refreshed"); toast.success("Orders refreshed");
}; };
// Handle CSV export
const handleExportCSV = async () => {
if (statusFilter === "all") {
toast.error("Please select a specific status to export");
return;
}
try {
setExporting(true);
await exportOrdersToCSV(statusFilter);
toast.success(`Orders exported successfully!`);
} catch (error) {
console.error("Error exporting orders:", error);
toast.error("Failed to export orders");
} finally {
setExporting(false);
}
};
// Add periodic refresh for underpaid orders // Add periodic refresh for underpaid orders
useEffect(() => { useEffect(() => {
// Check if we have any underpaid orders // Check if we have any underpaid orders
@@ -384,6 +406,27 @@ export default function OrderTable() {
onChange={(value) => handleItemsPerPageChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)} onChange={(value) => handleItemsPerPageChange({ target: { value } } as React.ChangeEvent<HTMLSelectElement>)}
options={pageSizeOptions} options={pageSizeOptions}
/> />
{statusFilter !== "all" && (
<Button
onClick={handleExportCSV}
disabled={exporting}
variant="outline"
size="sm"
>
{exporting ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Exporting...
</>
) : (
<>
<Download className="mr-2 h-4 w-4" />
Export CSV
</>
)}
</Button>
)}
</div> </div>
<div className="flex items-center gap-2 self-end lg:self-auto"> <div className="flex items-center gap-2 self-end lg:self-auto">

View File

@@ -1,4 +1,4 @@
"use client"; "use client";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
@@ -27,4 +27,4 @@ export function ThemeSwitcher() {
)} )}
</Button> </Button>
); );
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { Moon, Sun } from "lucide-react" import { Moon, Sun } from "lucide-react"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as AccordionPrimitive from "@radix-ui/react-accordion" import * as AccordionPrimitive from "@radix-ui/react-accordion"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as AvatarPrimitive from "@radix-ui/react-avatar" import * as AvatarPrimitive from "@radix-ui/react-avatar"

View File

@@ -1,4 +1,4 @@
import * as React from "react"; import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority"; import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";
@@ -35,4 +35,4 @@ function Badge({ className, variant, ...props }: BadgeProps) {
); );
} }
export { Badge, badgeVariants }; export { Badge, badgeVariants };

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { ChevronRight, MoreHorizontal } from "lucide-react" import { ChevronRight, MoreHorizontal } from "lucide-react"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority" import { cva, type VariantProps } from "class-variance-authority"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { ChevronLeft, ChevronRight } from "lucide-react" import { ChevronLeft, ChevronRight } from "lucide-react"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils/general" import { cn } from "@/lib/utils/general"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import useEmblaCarousel, { import useEmblaCarousel, {

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as RechartsPrimitive from "recharts" import * as RechartsPrimitive from "recharts"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as CheckboxPrimitive from "@radix-ui/react-checkbox" import * as CheckboxPrimitive from "@radix-ui/react-checkbox"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { type DialogProps } from "@radix-ui/react-dialog" import { type DialogProps } from "@radix-ui/react-dialog"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { format, addDays, startOfDay, endOfDay, isSameDay, isWithinInterval, getMonth, getYear, setMonth, setYear } from "date-fns" import { format, addDays, startOfDay, endOfDay, isSameDay, isWithinInterval, getMonth, getYear, setMonth, setYear } from "date-fns"
@@ -410,4 +410,4 @@ export function DateRangeDisplay({ dateRange }: { dateRange?: DateRange }) {
</span> </span>
</div> </div>
) )
} }

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as DialogPrimitive from "@radix-ui/react-dialog" import * as DialogPrimitive from "@radix-ui/react-dialog"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { Drawer as DrawerPrimitive } from "vaul" import { Drawer as DrawerPrimitive } from "vaul"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label" import * as LabelPrimitive from "@radix-ui/react-label"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as MenubarPrimitive from "@radix-ui/react-menubar" import * as MenubarPrimitive from "@radix-ui/react-menubar"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu" import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
import { cva } from "class-variance-authority" import { cva } from "class-variance-authority"
import { ChevronDown } from "lucide-react" import { ChevronDown } from "lucide-react"

View File

@@ -1,4 +1,4 @@
import * as React from "react" 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";

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as PopoverPrimitive from "@radix-ui/react-popover" import * as PopoverPrimitive from "@radix-ui/react-popover"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as ProgressPrimitive from "@radix-ui/react-progress" import * as ProgressPrimitive from "@radix-ui/react-progress"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import { GripVertical } from "lucide-react" import { GripVertical } from "lucide-react"
import * as ResizablePrimitive from "react-resizable-panels" import * as ResizablePrimitive from "react-resizable-panels"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as SelectPrimitive from "@radix-ui/react-select" import * as SelectPrimitive from "@radix-ui/react-select"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as SeparatorPrimitive from "@radix-ui/react-separator" import * as SeparatorPrimitive from "@radix-ui/react-separator"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog" import * as SheetPrimitive from "@radix-ui/react-dialog"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import { Slot } from "@radix-ui/react-slot" import { Slot } from "@radix-ui/react-slot"

View File

@@ -1,4 +1,4 @@
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";
function Skeleton({ function Skeleton({
className, className,

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as SliderPrimitive from "@radix-ui/react-slider" import * as SliderPrimitive from "@radix-ui/react-slider"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as SwitchPrimitives from "@radix-ui/react-switch" import * as SwitchPrimitives from "@radix-ui/react-switch"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as TabsPrimitive from "@radix-ui/react-tabs" import * as TabsPrimitive from "@radix-ui/react-tabs"

View File

@@ -1,4 +1,4 @@
import * as React from "react" import * as React from "react"
import { cn } from "@/lib/utils/styles"; import { cn } from "@/lib/utils/styles";

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as ToastPrimitives from "@radix-ui/react-toast" import * as ToastPrimitives from "@radix-ui/react-toast"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as TogglePrimitive from "@radix-ui/react-toggle" import * as TogglePrimitive from "@radix-ui/react-toggle"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
import * as React from "react" import * as React from "react"
import * as TooltipPrimitive from "@radix-ui/react-tooltip" import * as TooltipPrimitive from "@radix-ui/react-tooltip"

View File

@@ -1,4 +1,4 @@
"use client" "use client"
// Inspired by react-hot-toast library // Inspired by react-hot-toast library
import * as React from "react" import * as React from "react"