Update UI styles and dashboard product display
All checks were successful
Build Frontend / build (push) Successful in 1m10s

Refined color scheme in AnimatedStatsSection to use indigo instead of pink, and improved gradient backgrounds. In dashboard/content.tsx, updated TopProduct price to support arrays and display revenue per product. UnifiedNotifications received minor style and layout adjustments for better consistency and usability.
This commit is contained in:
g
2026-01-12 08:03:19 +00:00
parent 3ffb64cf9a
commit 7ddcd7afb6
4 changed files with 45 additions and 46 deletions

View File

@@ -13,7 +13,7 @@ export default async function Home() {
const stats = await getPlatformStatsServer(); const stats = await getPlatformStatsServer();
return ( return (
<div className="flex flex-col min-h-screen bg-black text-white"> <div className="relative flex flex-col min-h-screen bg-black text-white">
<div className="absolute inset-0 bg-gradient-to-br from-indigo-500/10 via-purple-500/5 to-transparent pointer-events-none scale-100" /> <div className="absolute inset-0 bg-gradient-to-br from-indigo-500/10 via-purple-500/5 to-transparent pointer-events-none scale-100" />
<HomeNavbar /> <HomeNavbar />

View File

@@ -20,12 +20,12 @@ export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
return ( return (
<div className="mx-auto grid max-w-5xl grid-cols-1 gap-6 md:grid-cols-3"> <div className="mx-auto grid max-w-5xl grid-cols-1 gap-6 md:grid-cols-3">
<div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6"> <div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6">
<div className="absolute inset-0 bg-[#D53F8C]/5 opacity-0 group-hover:opacity-100 transition-opacity" /> <div className="absolute inset-0 bg-indigo-500/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative flex flex-col items-center"> <div className="relative flex flex-col items-center">
<Package className="h-6 w-6 text-[#D53F8C]" /> <Package className="h-6 w-6 text-indigo-500" />
<div className="mt-4 text-3xl font-bold text-white"> <div className="mt-4 text-3xl font-bold text-white">
<AnimatedCounter <AnimatedCounter
value={stats.orders.completed} value={stats.orders.completed}
duration={2000} duration={2000}
suffix="+" suffix="+"
/> />
@@ -38,14 +38,14 @@ export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
</p> </p>
</div> </div>
</div> </div>
<div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6"> <div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6">
<div className="absolute inset-0 bg-[#D53F8C]/5 opacity-0 group-hover:opacity-100 transition-opacity" /> <div className="absolute inset-0 bg-indigo-500/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative flex flex-col items-center"> <div className="relative flex flex-col items-center">
<Users className="h-6 w-6 text-[#D53F8C]" /> <Users className="h-6 w-6 text-indigo-500" />
<div className="mt-4 text-3xl font-bold text-white"> <div className="mt-4 text-3xl font-bold text-white">
<AnimatedCounter <AnimatedCounter
value={stats.vendors.total} value={stats.vendors.total}
duration={2000} duration={2000}
suffix="+" suffix="+"
/> />
@@ -58,14 +58,14 @@ export function AnimatedStatsSection({ stats }: AnimatedStatsProps) {
</p> </p>
</div> </div>
</div> </div>
<div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6"> <div className="group relative overflow-hidden flex flex-col items-center text-center rounded-xl bg-gradient-to-b from-zinc-900/50 to-black border border-[#1C1C1C] p-6">
<div className="absolute inset-0 bg-[#D53F8C]/5 opacity-0 group-hover:opacity-100 transition-opacity" /> <div className="absolute inset-0 bg-indigo-500/5 opacity-0 group-hover:opacity-100 transition-opacity" />
<div className="relative flex flex-col items-center"> <div className="relative flex flex-col items-center">
<CreditCard className="h-6 w-6 text-[#D53F8C]" /> <CreditCard className="h-6 w-6 text-indigo-500" />
<div className="mt-4 text-3xl font-bold text-white"> <div className="mt-4 text-3xl font-bold text-white">
<AnimatedCounter <AnimatedCounter
value={stats.transactions.volume} value={stats.transactions.volume}
duration={2500} duration={2500}
formatter={formatCurrency} formatter={formatCurrency}
/> />

View File

@@ -25,7 +25,7 @@ interface ContentProps {
interface TopProduct { interface TopProduct {
id: string; id: string;
name: string; name: string;
price: number; price: number | number[];
image: string; image: string;
count: number; count: number;
revenue: number; revenue: number;
@@ -73,7 +73,7 @@ export default function Content({ username, orderStats }: ContentProps) {
<h1 className="text-4xl font-bold tracking-tight text-foreground"> <h1 className="text-4xl font-bold tracking-tight text-foreground">
{greeting}, <span className="text-primary">{username}</span>! {greeting}, <span className="text-primary">{username}</span>!
</h1> </h1>
<p className="text-muted-foreground mt-2 max-w-2xl text-lg"> <p className="text-muted-foreground mt-2 text-lg">
"{randomQuote.text}" <span className="font-medium">{randomQuote.author}</span> "{randomQuote.text}" <span className="font-medium">{randomQuote.author}</span>
</p> </p>
</div> </div>
@@ -181,14 +181,13 @@ export default function Content({ username, orderStats }: ContentProps) {
<div className="flex-grow min-w-0"> <div className="flex-grow min-w-0">
<h4 className="font-semibold text-lg truncate group-hover:text-primary transition-colors">{product.name}</h4> <h4 className="font-semibold text-lg truncate group-hover:text-primary transition-colors">{product.name}</h4>
<div className="flex items-center gap-3 mt-0.5"> <div className="flex items-center gap-3 mt-0.5">
<span className="text-sm text-muted-foreground font-medium">£{(Number(product.price) || 0).toFixed(2)}</span> <span className="text-sm text-muted-foreground font-medium">£{(Number(Array.isArray(product.price) ? product.price[0] : product.price) || 0).toFixed(2)}</span>
<span className="h-1 w-1 rounded-full bg-muted-foreground/30" />
<span className="text-xs text-muted-foreground">ID: {product.id.slice(-6)}</span>
</div> </div>
</div> </div>
<div className="text-right"> <div className="text-right">
<div className="text-xl font-bold">{product.count}</div> <div className="text-xl font-bold">{product.count}</div>
<div className="text-xs text-muted-foreground font-medium uppercase tracking-tighter">Units Sold</div> <div className="text-xs text-muted-foreground font-medium uppercase tracking-tighter mb-1">Units Sold</div>
<div className="text-sm font-semibold text-primary">£{product.revenue.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}</div>
</div> </div>
</motion.div> </motion.div>
))} ))}

View File

@@ -18,7 +18,7 @@ import { useNotifications } from "@/lib/notification-context";
export default function UnifiedNotifications() { export default function UnifiedNotifications() {
const router = useRouter(); const router = useRouter();
const [activeTab, setActiveTab] = useState<string>("all"); const [activeTab, setActiveTab] = useState<string>("all");
// Get notification state from context // Get notification state from context
const { const {
unreadCounts, unreadCounts,
@@ -33,11 +33,11 @@ export default function UnifiedNotifications() {
const handleChatClick = (chatId: string) => { const handleChatClick = (chatId: string) => {
router.push(`/dashboard/chats/${chatId}`); router.push(`/dashboard/chats/${chatId}`);
}; };
const handleOrderClick = (orderId: string) => { const handleOrderClick = (orderId: string) => {
router.push(`/dashboard/orders/${orderId}`); router.push(`/dashboard/orders/${orderId}`);
}; };
// Format the price as currency // Format the price as currency
const formatPrice = (price: number) => { const formatPrice = (price: number) => {
return `£${price.toFixed(2)}`; return `£${price.toFixed(2)}`;
@@ -49,8 +49,8 @@ export default function UnifiedNotifications() {
<Button variant="ghost" size="icon" className="relative" disabled={loading}> <Button variant="ghost" size="icon" className="relative" disabled={loading}>
<BellRing className="h-5 w-5" /> <BellRing className="h-5 w-5" />
{totalNotifications > 0 && ( {totalNotifications > 0 && (
<Badge <Badge
variant="destructive" variant="destructive"
className="absolute -top-1 -right-1 px-1.5 py-0.5 text-xs" className="absolute -top-1 -right-1 px-1.5 py-0.5 text-xs"
> >
{totalNotifications} {totalNotifications}
@@ -58,12 +58,12 @@ export default function UnifiedNotifications() {
)} )}
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-80"> <DropdownMenuContent align="end" className="w-80" collisionPadding={10}>
<div className="p-2 border-b"> <div className="p-2 border-b">
<Tabs defaultValue="all" value={activeTab} onValueChange={setActiveTab}> <Tabs defaultValue="all" value={activeTab} onValueChange={setActiveTab}>
<TabsList className="grid w-full grid-cols-3"> <TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="all" className="text-xs"> <TabsTrigger value="all" className="text-xs">
All All
{totalNotifications > 0 && ( {totalNotifications > 0 && (
<Badge variant="secondary" className="ml-1"> <Badge variant="secondary" className="ml-1">
{totalNotifications} {totalNotifications}
@@ -87,7 +87,7 @@ export default function UnifiedNotifications() {
)} )}
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>
<TabsContent value="all" className="m-0"> <TabsContent value="all" className="m-0">
{totalNotifications === 0 ? ( {totalNotifications === 0 ? (
<div className="p-4 flex items-center justify-center"> <div className="p-4 flex items-center justify-center">
@@ -102,7 +102,7 @@ export default function UnifiedNotifications() {
Unread Messages Unread Messages
</div> </div>
{Object.entries(unreadCounts.chatCounts).slice(0, 3).map(([chatId, count]) => ( {Object.entries(unreadCounts.chatCounts).slice(0, 3).map(([chatId, count]) => (
<DropdownMenuItem <DropdownMenuItem
key={`chat-${chatId}`} key={`chat-${chatId}`}
className="p-3 cursor-pointer" className="p-3 cursor-pointer"
onClick={() => handleChatClick(chatId)} onClick={() => handleChatClick(chatId)}
@@ -130,15 +130,15 @@ export default function UnifiedNotifications() {
)} )}
</> </>
)} )}
{/* Orders Section */} {/* Orders Section */}
{newOrders.length > 0 && ( {newOrders.length > 0 && (
<> <>
<div className="px-3 py-2 text-xs font-medium bg-muted/50 flex justify-between items-center"> <div className="px-3 py-2 text-xs font-medium bg-muted/50 flex justify-between items-center">
<span>New Paid Orders</span> <span>New Paid Orders</span>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
clearOrderNotifications(); clearOrderNotifications();
@@ -149,7 +149,7 @@ export default function UnifiedNotifications() {
</Button> </Button>
</div> </div>
{newOrders.slice(0, 3).map((order) => ( {newOrders.slice(0, 3).map((order) => (
<DropdownMenuItem <DropdownMenuItem
key={`order-${order._id}`} key={`order-${order._id}`}
className="p-3 cursor-pointer" className="p-3 cursor-pointer"
onClick={() => handleOrderClick(order._id)} onClick={() => handleOrderClick(order._id)}
@@ -178,7 +178,7 @@ export default function UnifiedNotifications() {
</div> </div>
)} )}
</TabsContent> </TabsContent>
<TabsContent value="messages" className="m-0"> <TabsContent value="messages" className="m-0">
{unreadCounts.totalUnread === 0 ? ( {unreadCounts.totalUnread === 0 ? (
<div className="p-4 flex items-center justify-center"> <div className="p-4 flex items-center justify-center">
@@ -188,7 +188,7 @@ export default function UnifiedNotifications() {
<> <>
<div className="max-h-96 overflow-y-auto"> <div className="max-h-96 overflow-y-auto">
{Object.entries(unreadCounts.chatCounts).map(([chatId, count]) => ( {Object.entries(unreadCounts.chatCounts).map(([chatId, count]) => (
<DropdownMenuItem <DropdownMenuItem
key={`chat-tab-${chatId}`} key={`chat-tab-${chatId}`}
className="p-3 cursor-pointer" className="p-3 cursor-pointer"
onClick={() => handleChatClick(chatId)} onClick={() => handleChatClick(chatId)}
@@ -211,8 +211,8 @@ export default function UnifiedNotifications() {
))} ))}
</div> </div>
<div className="p-2 border-t"> <div className="p-2 border-t">
<Button <Button
variant="outline" variant="outline"
className="w-full" className="w-full"
onClick={() => router.push('/dashboard/chats')} onClick={() => router.push('/dashboard/chats')}
> >
@@ -222,7 +222,7 @@ export default function UnifiedNotifications() {
</> </>
)} )}
</TabsContent> </TabsContent>
<TabsContent value="orders" className="m-0"> <TabsContent value="orders" className="m-0">
{newOrders.length === 0 ? ( {newOrders.length === 0 ? (
<div className="p-4 flex items-center justify-center"> <div className="p-4 flex items-center justify-center">
@@ -232,9 +232,9 @@ export default function UnifiedNotifications() {
<> <>
<div className="px-3 py-2 text-xs font-medium bg-muted/50 flex justify-between items-center"> <div className="px-3 py-2 text-xs font-medium bg-muted/50 flex justify-between items-center">
<span>New Paid Orders</span> <span>New Paid Orders</span>
<Button <Button
variant="ghost" variant="ghost"
size="sm" size="sm"
onClick={(e) => { onClick={(e) => {
e.stopPropagation(); e.stopPropagation();
clearOrderNotifications(); clearOrderNotifications();
@@ -246,7 +246,7 @@ export default function UnifiedNotifications() {
</div> </div>
<div className="max-h-96 overflow-y-auto"> <div className="max-h-96 overflow-y-auto">
{newOrders.map((order) => ( {newOrders.map((order) => (
<DropdownMenuItem <DropdownMenuItem
key={`order-tab-${order._id}`} key={`order-tab-${order._id}`}
className="p-3 cursor-pointer" className="p-3 cursor-pointer"
onClick={() => handleOrderClick(order._id)} onClick={() => handleOrderClick(order._id)}
@@ -267,8 +267,8 @@ export default function UnifiedNotifications() {
))} ))}
</div> </div>
<div className="p-2 border-t"> <div className="p-2 border-t">
<Button <Button
variant="outline" variant="outline"
className="w-full" className="w-full"
onClick={() => router.push('/dashboard/orders')} onClick={() => router.push('/dashboard/orders')}
> >