Refactor UI imports and update component paths
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:
g
2026-01-13 05:02:13 +00:00
parent a6e6cd0757
commit fe01f31538
173 changed files with 1512 additions and 867 deletions

View File

@@ -0,0 +1,226 @@
"use client"
import { useState, useEffect } from "react"
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetDescription
} from "@/components/common/sheet"
import { clientFetch } from "@/lib/api"
import { Badge } from "@/components/common/badge"
import { Separator } from "@/components/common/separator"
import { ScrollArea } from "@/components/common/scroll-area"
import { Package, Truck, CreditCard, Calendar, User, MapPin, ExternalLink } from "lucide-react"
import { RelativeTime } from "@/components/common/relative-time"
import { formatGBP } from "@/lib/utils/format"
import Link from "next/link"
import { Button } from "@/components/common/button"
import { Skeleton } from "@/components/common/skeleton"
interface OrderPeekProps {
orderId: string | null
open: boolean
onOpenChange: (open: boolean) => void
}
export function OrderPeek({ orderId, open, onOpenChange }: OrderPeekProps) {
const [order, setOrder] = useState<any>(null)
const [loading, setLoading] = useState(false)
useEffect(() => {
if (open && orderId) {
fetchOrderDetails()
} else if (!open) {
// Don't clear order immediately to avoid flicker during closing
// setOrder(null)
}
}, [open, orderId])
const fetchOrderDetails = async () => {
setLoading(true)
try {
const data = await clientFetch(`/orders/${orderId}`)
setOrder(data.order)
} catch (error) {
console.error("Failed to fetch order details for peek:", error)
} finally {
setLoading(false)
}
}
const getStatusStyle = (status: string) => {
switch (status) {
case 'paid': return 'bg-emerald-500/10 text-emerald-500 border-emerald-500/20';
case 'shipped': return 'bg-blue-500/10 text-blue-500 border-blue-500/20';
case 'completed': return 'bg-green-500/10 text-green-500 border-green-500/20';
case 'cancelled': return 'bg-red-500/10 text-red-500 border-red-500/20';
case 'unpaid': return 'bg-yellow-500/10 text-yellow-500 border-yellow-500/20';
default: return 'bg-gray-500/10 text-gray-500 border-gray-500/20';
}
}
return (
<Sheet open={open} onOpenChange={onOpenChange}>
<SheetContent className="sm:max-w-md border-white/5 bg-[#0a0a0a]/80 backdrop-blur-2xl p-0 overflow-hidden flex flex-col shadow-2xl shadow-black/50">
<SheetHeader className="p-6 border-b border-white/5 bg-white/5">
<div className="flex items-center justify-between mb-2">
<SheetTitle className="text-xl font-bold flex items-center gap-2">
<Package className="h-5 w-5 text-primary" />
Order Details
</SheetTitle>
{order && (
<Link href={`/dashboard/orders/${order._id}`} onClick={() => onOpenChange(false)}>
<Button variant="ghost" size="sm" className="h-8 gap-1.5 text-xs text-muted-foreground hover:text-primary">
Open Full <ExternalLink className="h-3 w-3" />
</Button>
</Link>
)}
</div>
<SheetDescription asChild>
<div className="flex items-center gap-2 text-white font-mono bg-white/5 px-2.5 py-1 rounded-lg border border-white/10 w-fit mt-1">
{loading ? <Skeleton className="h-4 w-32" /> : order ? `Order #${order.orderId}` : "Loading..."}
</div>
</SheetDescription>
</SheetHeader>
<ScrollArea className="flex-1">
{loading ? (
<div className="p-6 space-y-6">
<div className="space-y-3">
<Skeleton className="h-4 w-24" />
<Skeleton className="h-8 w-full" />
</div>
<Separator className="bg-white/5" />
<div className="space-y-4">
{[1, 2, 3].map(i => <Skeleton key={i} className="h-12 w-full" />)}
</div>
</div>
) : order ? (
<div className="p-6 space-y-8">
{/* Summary Stats */}
<div className="grid grid-cols-2 gap-4">
<div className="p-4 rounded-2xl bg-white/5 border border-white/5 space-y-1">
<span className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Status</span>
<div className="flex pt-1">
<Badge variant="outline" className={`${getStatusStyle(order.status)} border-none px-0 text-3xl font-black capitalize tracking-tight`}>
{order.status}
</Badge>
</div>
</div>
<div className="p-4 rounded-2xl bg-white/5 border border-white/5 space-y-1">
<span className="text-[10px] font-bold uppercase tracking-wider text-muted-foreground">Total Value</span>
<div className="text-lg font-bold text-primary tabular-nums">
{formatGBP(order.totalPrice)}
</div>
</div>
</div>
{/* Customer Info */}
<div className="space-y-4">
<h3 className="text-sm font-bold flex items-center gap-2 text-muted-foreground uppercase tracking-widest">
<User className="h-4 w-4" /> Customer Information
</h3>
<div className="p-4 rounded-2xl bg-white/5 border border-white/5 space-y-3">
<div className="flex justify-between items-start text-sm">
<span className="text-muted-foreground pt-1">Customer</span>
<div className="flex flex-col items-end bg-white/5 p-3 rounded-xl border border-white/5 min-w-[160px]">
<span className="font-black text-white text-base">
{order.telegramUsername ? `@${order.telegramUsername}` : "Anonymous"}
</span>
<span className="text-[10px] text-muted-foreground font-mono uppercase tracking-tighter mt-1 opacity-60">
ID: {order.telegramBuyerId?.slice(0, 16) || "N/A"}
</span>
</div>
</div>
<div className="flex justify-between items-center text-sm">
<span className="text-muted-foreground">Order Date</span>
<span className="text-white">
{order.orderDate ? <RelativeTime date={order.orderDate} /> : "N/A"}
</span>
</div>
</div>
</div>
{/* Order Items */}
<div className="space-y-4">
<h3 className="text-sm font-bold flex items-center gap-2 text-muted-foreground uppercase tracking-widest">
<Package className="h-4 w-4" /> Order Items
</h3>
<div className="space-y-2">
{order.products?.map((item: any, idx: number) => (
<div key={idx} className="flex items-center justify-between p-3 rounded-xl bg-white/5 border border-white/5 hover:bg-white/10 transition-colors">
<div className="flex flex-col">
<span className="text-sm font-medium text-white truncate max-w-[200px]">
{item.name || `Item ${idx + 1}`}
</span>
<span className="text-xs text-muted-foreground">Qty: {item.quantity}</span>
</div>
<span className="text-sm font-bold tabular-nums">{formatGBP(item.totalItemPrice)}</span>
</div>
))}
{order.shippingMethod && (
<div className="flex items-center justify-between p-3 rounded-xl bg-primary/5 border border-primary/10">
<div className="flex flex-col">
<span className="text-sm font-medium text-primary">Shipping: {order.shippingMethod.type}</span>
<span className="text-xs text-primary/60 italic">Standard Delivery</span>
</div>
<span className="text-sm font-bold text-primary tabular-nums">{formatGBP(order.shippingMethod.price)}</span>
</div>
)}
</div>
</div>
{/* Shipping Address Peek */}
<div className="space-y-4">
<h3 className="text-sm font-bold flex items-center gap-2 text-muted-foreground uppercase tracking-widest">
<MapPin className="h-4 w-4" /> Delivery Address
</h3>
<div className="p-4 rounded-2xl bg-[#050505] border border-white/10 overflow-hidden shadow-inner">
<p className="text-xs text-muted-foreground leading-relaxed break-all font-mono opacity-70 selection:bg-primary/30">
{order.pgpAddress || "No address provided or encrypted."}
</p>
</div>
</div>
{/* Timeline Indicator */}
<div className="space-y-4">
<h3 className="text-sm font-bold flex items-center gap-2 text-muted-foreground uppercase tracking-widest">
<Calendar className="h-4 w-4" /> Next Milestone
</h3>
<div className="p-4 rounded-2xl bg-amber-500/5 border border-amber-500/20">
<div className="flex items-center gap-3">
<div className="p-2 rounded-full bg-amber-500/20 text-amber-500">
<Truck className="h-4 w-4" />
</div>
<div>
<p className="text-sm font-bold text-amber-500">Pending Shipment</p>
<p className="text-xs text-amber-500/60">Awaiting vendor processing and label creation.</p>
</div>
</div>
</div>
</div>
</div>
) : (
<div className="p-12 text-center text-muted-foreground">
Failed to load order data.
</div>
)}
</ScrollArea>
{order && (
<div className="p-6 border-t border-white/5 bg-white/5 mt-auto">
<Link href={`/dashboard/orders/${order._id}`} className="w-full" onClick={() => onOpenChange(false)}>
<Button className="w-full font-bold h-12 shadow-xl shadow-primary/10">
Full Order Management
</Button>
</Link>
</div>
)}
</SheetContent>
</Sheet>
)
}