Add src/app/admin/page.tsx
This commit is contained in:
311
src/app/admin/page.tsx
Normal file
311
src/app/admin/page.tsx
Normal file
@@ -0,0 +1,311 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleApple from "@/components/navbar/NavbarStyleApple/NavbarStyleApple";
|
||||
import FooterBaseReveal from "@/components/sections/footer/FooterBaseReveal";
|
||||
import { BarChart3, TrendingUp, DollarSign, Eye, Plus, Edit2, Trash2, Search } from "lucide-react";
|
||||
|
||||
export default function AdminPage() {
|
||||
const navItems = [
|
||||
{ name: "Home", id: "/" },
|
||||
{ name: "How It Works", id: "#how-it-works" },
|
||||
{ name: "Top Products", id: "#products" },
|
||||
{ name: "Admin", id: "/admin" },
|
||||
{ name: "Contact", id: "#contact" },
|
||||
];
|
||||
|
||||
const [campaigns, setCampaigns] = useState([
|
||||
{
|
||||
id: 1,
|
||||
name: "Wireless Earbuds Campaign", status: "active", impressions: 45230,
|
||||
clicks: 1240,
|
||||
conversions: 89,
|
||||
revenue: 4450,
|
||||
ctr: 2.74,
|
||||
conversionRate: 7.18,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Power Bank Q1 Push", status: "active", impressions: 32100,
|
||||
clicks: 890,
|
||||
conversions: 52,
|
||||
revenue: 2340,
|
||||
ctr: 2.77,
|
||||
conversionRate: 5.84,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "LED Lamp Bundle", status: "paused", impressions: 28900,
|
||||
clicks: 720,
|
||||
conversions: 41,
|
||||
revenue: 1845,
|
||||
ctr: 2.49,
|
||||
conversionRate: 5.69,
|
||||
},
|
||||
]);
|
||||
|
||||
const totalMetrics = {
|
||||
totalImpressions: campaigns.reduce((sum, c) => sum + c.impressions, 0),
|
||||
totalClicks: campaigns.reduce((sum, c) => sum + c.clicks, 0),
|
||||
totalConversions: campaigns.reduce((sum, c) => sum + c.conversions, 0),
|
||||
totalRevenue: campaigns.reduce((sum, c) => sum + c.revenue, 0),
|
||||
overallCTR: 2.67,
|
||||
overallConversionRate: 6.24,
|
||||
};
|
||||
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const [selectedCampaign, setSelectedCampaign] = useState<typeof campaigns[0] | null>(null);
|
||||
|
||||
const filteredCampaigns = campaigns.filter((campaign) =>
|
||||
campaign.name.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-stagger"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="rounded"
|
||||
contentWidth="mediumLarge"
|
||||
sizing="mediumSizeLargeTitles"
|
||||
background="circleGradient"
|
||||
cardStyle="glass-depth"
|
||||
primaryButtonStyle="shadow"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="semibold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleApple brandName="ProductHuntr" navItems={navItems} />
|
||||
</div>
|
||||
|
||||
<div className="min-h-screen bg-background py-20 px-4">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
{/* Header */}
|
||||
<div className="mb-12">
|
||||
<h1 className="text-5xl font-bold text-foreground mb-4">Ad Management Dashboard</h1>
|
||||
<p className="text-lg text-foreground/70">Manage campaigns, track performance, and monitor revenue generation</p>
|
||||
</div>
|
||||
|
||||
{/* KPI Cards */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-12">
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-foreground/70 text-sm font-medium">Total Revenue</h3>
|
||||
<DollarSign className="w-5 h-5 text-primary-cta" />
|
||||
</div>
|
||||
<p className="text-4xl font-bold text-foreground">${totalMetrics.totalRevenue.toLocaleString()}</p>
|
||||
<p className="text-sm text-foreground/50 mt-2">From {campaigns.length} active campaigns</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-foreground/70 text-sm font-medium">Total Conversions</h3>
|
||||
<TrendingUp className="w-5 h-5 text-primary-cta" />
|
||||
</div>
|
||||
<p className="text-4xl font-bold text-foreground">{totalMetrics.totalConversions}</p>
|
||||
<p className="text-sm text-foreground/50 mt-2">Conversion rate: {totalMetrics.overallConversionRate}%</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-foreground/70 text-sm font-medium">Total Impressions</h3>
|
||||
<Eye className="w-5 h-5 text-primary-cta" />
|
||||
</div>
|
||||
<p className="text-4xl font-bold text-foreground">{(totalMetrics.totalImpressions / 1000).toFixed(1)}K</p>
|
||||
<p className="text-sm text-foreground/50 mt-2">CTR: {totalMetrics.overallCTR}%</p>
|
||||
</div>
|
||||
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h3 className="text-foreground/70 text-sm font-medium">Total Clicks</h3>
|
||||
<BarChart3 className="w-5 h-5 text-primary-cta" />
|
||||
</div>
|
||||
<p className="text-4xl font-bold text-foreground">{totalMetrics.totalClicks.toLocaleString()}</p>
|
||||
<p className="text-sm text-foreground/50 mt-2">From impressions</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Campaign Management */}
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-8">
|
||||
<div className="flex flex-col md:flex-row justify-between items-start md:items-center gap-6 mb-8">
|
||||
<h2 className="text-3xl font-bold text-foreground">Campaign Manager</h2>
|
||||
<div className="flex gap-4 w-full md:w-auto">
|
||||
<div className="relative flex-1 md:flex-none md:w-64">
|
||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 w-4 h-4 text-foreground/40" />
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search campaigns..."
|
||||
value={searchTerm}
|
||||
onChange={(e) => setSearchTerm(e.target.value)}
|
||||
className="w-full pl-10 pr-4 py-2 bg-background border border-accent/20 rounded-lg text-foreground placeholder-foreground/40 focus:outline-none focus:border-primary-cta"
|
||||
/>
|
||||
</div>
|
||||
<button className="px-6 py-2 bg-primary-cta text-background rounded-lg font-medium hover:opacity-90 transition-opacity flex items-center gap-2 whitespace-nowrap">
|
||||
<Plus className="w-4 h-4" />
|
||||
New Campaign
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Campaign Table */}
|
||||
<div className="overflow-x-auto">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-accent/20">
|
||||
<th className="text-left py-4 px-4 text-foreground/70 font-semibold">Campaign Name</th>
|
||||
<th className="text-left py-4 px-4 text-foreground/70 font-semibold">Status</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">Impressions</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">Clicks</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">CTR</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">Conversions</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">Revenue</th>
|
||||
<th className="text-right py-4 px-4 text-foreground/70 font-semibold">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{filteredCampaigns.map((campaign) => (
|
||||
<tr key={campaign.id} className="border-b border-accent/10 hover:bg-background/50 transition-colors">
|
||||
<td className="py-4 px-4 text-foreground font-medium">{campaign.name}</td>
|
||||
<td className="py-4 px-4">
|
||||
<span
|
||||
className={`px-3 py-1 rounded-full text-xs font-semibold ${
|
||||
campaign.status === "active"
|
||||
? "bg-green-500/20 text-green-400"
|
||||
: "bg-yellow-500/20 text-yellow-400"
|
||||
}`}
|
||||
>
|
||||
{campaign.status.charAt(0).toUpperCase() + campaign.status.slice(1)}
|
||||
</span>
|
||||
</td>
|
||||
<td className="py-4 px-4 text-right text-foreground">{campaign.impressions.toLocaleString()}</td>
|
||||
<td className="py-4 px-4 text-right text-foreground">{campaign.clicks.toLocaleString()}</td>
|
||||
<td className="py-4 px-4 text-right text-foreground">{campaign.ctr}%</td>
|
||||
<td className="py-4 px-4 text-right text-foreground">{campaign.conversions}</td>
|
||||
<td className="py-4 px-4 text-right font-bold text-primary-cta">${campaign.revenue.toLocaleString()}</td>
|
||||
<td className="py-4 px-4 text-right">
|
||||
<div className="flex justify-end gap-2">
|
||||
<button
|
||||
onClick={() => setSelectedCampaign(campaign)}
|
||||
className="p-2 hover:bg-background rounded transition-colors"
|
||||
title="View Details"
|
||||
>
|
||||
<Eye className="w-4 h-4 text-foreground/60" />
|
||||
</button>
|
||||
<button className="p-2 hover:bg-background rounded transition-colors" title="Edit">
|
||||
<Edit2 className="w-4 h-4 text-foreground/60" />
|
||||
</button>
|
||||
<button className="p-2 hover:bg-background rounded transition-colors" title="Delete">
|
||||
<Trash2 className="w-4 h-4 text-foreground/60" />
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Campaign Details Modal */}
|
||||
{selectedCampaign && (
|
||||
<div className="fixed inset-0 bg-background/80 backdrop-blur-sm flex items-center justify-center z-50 p-4">
|
||||
<div className="bg-card border border-accent/20 rounded-lg p-8 max-w-2xl w-full">
|
||||
<div className="flex justify-between items-start mb-6">
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold text-foreground">{selectedCampaign.name}</h3>
|
||||
<span
|
||||
className={`inline-block mt-2 px-3 py-1 rounded-full text-xs font-semibold ${
|
||||
selectedCampaign.status === "active"
|
||||
? "bg-green-500/20 text-green-400"
|
||||
: "bg-yellow-500/20 text-yellow-400"
|
||||
}`}
|
||||
>
|
||||
{selectedCampaign.status.charAt(0).toUpperCase() + selectedCampaign.status.slice(1)}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setSelectedCampaign(null)}
|
||||
className="text-foreground/60 hover:text-foreground transition-colors text-2xl"
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-6 mb-8">
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">Impressions</p>
|
||||
<p className="text-3xl font-bold text-foreground">{selectedCampaign.impressions.toLocaleString()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">Clicks</p>
|
||||
<p className="text-3xl font-bold text-foreground">{selectedCampaign.clicks.toLocaleString()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">Conversions</p>
|
||||
<p className="text-3xl font-bold text-foreground">{selectedCampaign.conversions}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">Revenue</p>
|
||||
<p className="text-3xl font-bold text-primary-cta">${selectedCampaign.revenue.toLocaleString()}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">CTR</p>
|
||||
<p className="text-3xl font-bold text-foreground">{selectedCampaign.ctr}%</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-foreground/70 text-sm mb-1">Conversion Rate</p>
|
||||
<p className="text-3xl font-bold text-foreground">{selectedCampaign.conversionRate}%</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-4 justify-end">
|
||||
<button
|
||||
onClick={() => setSelectedCampaign(null)}
|
||||
className="px-6 py-2 bg-background border border-accent/20 text-foreground rounded-lg font-medium hover:bg-background/80 transition-colors"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button className="px-6 py-2 bg-primary-cta text-background rounded-lg font-medium hover:opacity-90 transition-opacity">
|
||||
Edit Campaign
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBaseReveal
|
||||
columns={[
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "How It Works", href: "#how-it-works" },
|
||||
{ label: "Top Products", href: "#products" },
|
||||
{ label: "Admin", href: "/admin" },
|
||||
{ label: "Dashboard", href: "#" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Company", items: [
|
||||
{ label: "About Us", href: "/" },
|
||||
{ label: "Blog", href: "#" },
|
||||
{ label: "Careers", href: "#" },
|
||||
{ label: "Contact", href: "#contact" },
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Legal", items: [
|
||||
{ label: "Privacy Policy", href: "#" },
|
||||
{ label: "Terms of Service", href: "#" },
|
||||
{ label: "Cookie Policy", href: "#" },
|
||||
{ label: "Affiliate Disclosure", href: "#" },
|
||||
],
|
||||
},
|
||||
]}
|
||||
copyrightText="© 2025 ProductHuntr. All rights reserved. | Affiliate Partnerships: Amazon | Walmart | eBay | Alibaba"
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user