Update src/app/admin/page.tsx

This commit is contained in:
2026-03-08 22:37:12 +00:00
parent c696694318
commit f69459c79e

View File

@@ -1,48 +1,108 @@
"use client";
import { useState } from "react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
import { useState } from "react";
import { BarChart3, Users, Briefcase, FileText, TrendingUp, LogOut } from "lucide-react";
import FooterBase from "@/components/sections/footer/FooterBase";
import { Users, Briefcase, BarChart3, ChevronDown, Plus, Trash2, Edit2 } from "lucide-react";
const navItems = [
{ name: "Search Jobs", id: "" },
{ name: "Post a Job", id: "" },
{ name: "Admin", id: "/admin" },
{ name: "Browse", id: "" },
{ name: "Contact", id: "" },
{ name: "Dashboard", id: "/admin" },
{ name: "Jobs", id: "/admin" },
{ name: "Users", id: "/admin" },
{ name: "Analytics", id: "/admin" },
{ name: "Home", id: "/" },
];
type TabType = "jobs" | "applications" | "users" | "analytics";
const footerColumns = [
{
title: "Product", items: [
{ label: "Search Jobs", href: "/search" },
{ label: "Post a Job", href: "/post-job" },
{ label: "Browse by Province", href: "#provinces" },
{ label: "For Employers", href: "#" },
],
},
{
title: "Company", items: [
{ label: "About Jobee", href: "#about" },
{ label: "Careers", href: "#" },
{ label: "Contact Us", href: "#contact" },
{ label: "Blog", href: "#" },
],
},
{
title: "Resources", items: [
{ label: "Privacy Policy", href: "#" },
{ label: "Terms of Service", href: "#" },
{ label: "FAQ", href: "#" },
{ label: "Support", href: "#" },
],
},
];
interface Job {
id: string;
title: string;
company: string;
location: string;
status: "active" | "closed";
applications: number;
postedDate: string;
}
interface User {
id: string;
name: string;
email: string;
role: "job_seeker" | "employer";
joinDate: string;
status: "active" | "inactive";
}
interface AnalyticsData {
totalJobs: number;
totalUsers: number;
activeApplications: number;
successfulPlacements: number;
}
export default function AdminDashboard() {
const [activeTab, setActiveTab] = useState<TabType>("jobs");
const [jobs] = useState([
{ id: 1, title: "Senior Developer", company: "Tech Corp", status: "Active", applications: 12, posted: "2 days ago" },
{ id: 2, title: "Product Manager", company: "Startup Inc", status: "Active", applications: 8, posted: "5 days ago" },
{ id: 3, title: "Designer", company: "Creative Agency", status: "Inactive", applications: 5, posted: "10 days ago" },
const [activeTab, setActiveTab] = useState<"dashboard" | "jobs" | "users">("dashboard");
const [jobs, setJobs] = useState<Job[]>([
{
id: "1", title: "Senior React Developer", company: "TechCorp", location: "Amsterdam", status: "active", applications: 24,
postedDate: "2025-01-10"},
{
id: "2", title: "UX Designer", company: "DesignStudio", location: "Rotterdam", status: "active", applications: 18,
postedDate: "2025-01-08"},
{
id: "3", title: "Backend Engineer", company: "DataSystems", location: "Utrecht", status: "closed", applications: 42,
postedDate: "2024-12-20"},
]);
const [applications] = useState([
{ id: 1, candidate: "John Smith", position: "Senior Developer", status: "Under Review", appliedDate: "2025-01-20" },
{ id: 2, candidate: "Sarah Johnson", position: "Product Manager", status: "Interview", appliedDate: "2025-01-19" },
{ id: 3, candidate: "Mike Davis", position: "Senior Developer", status: "Rejected", appliedDate: "2025-01-18" },
const [users, setUsers] = useState<User[]>([
{
id: "1", name: "Alice Johnson", email: "alice@example.com", role: "job_seeker", joinDate: "2024-11-15", status: "active"},
{
id: "2", name: "Bob Smith", email: "bob@example.com", role: "employer", joinDate: "2024-10-20", status: "active"},
{
id: "3", name: "Carol White", email: "carol@example.com", role: "job_seeker", joinDate: "2024-09-05", status: "inactive"},
]);
const [users] = useState([
{ id: 1, name: "Alice Chen", email: "alice@example.com", role: "Job Seeker", joined: "2025-01-10", status: "Active" },
{ id: 2, name: "Bob Wilson", email: "bob@example.com", role: "Employer", joined: "2025-01-05", status: "Active" },
{ id: 3, name: "Carol White", email: "carol@example.com", role: "Job Seeker", joined: "2024-12-20", status: "Inactive" },
]);
const [analytics] = useState<AnalyticsData>({
totalJobs: 156,
totalUsers: 3245,
activeApplications: 892,
successfulPlacements: 142,
});
const [analytics] = useState({
totalJobs: 284,
activeApplications: 156,
totalUsers: 2341,
avgTimeToHire: "18 days", monthlyGrowth: "+12.5%", conversionRate: "8.3%"});
const handleDeleteJob = (id: string) => {
setJobs(jobs.filter((job) => job.id !== id));
};
const handleLogout = () => {
window.location.href = "/";
const handleDeleteUser = (id: string) => {
setUsers(users.filter((user) => user.id !== id));
};
return (
@@ -50,12 +110,12 @@ export default function AdminDashboard() {
defaultButtonVariant="text-stagger"
defaultTextAnimation="reveal-blur"
borderRadius="pill"
contentWidth="medium"
contentWidth="smallMedium"
sizing="mediumLargeSizeLargeTitles"
background="none"
cardStyle="solid"
primaryButtonStyle="gradient"
secondaryButtonStyle="solid"
background="circleGradient"
cardStyle="gradient-radial"
primaryButtonStyle="double-inset"
secondaryButtonStyle="glass"
headingFontWeight="bold"
>
<div id="nav" data-section="nav">
@@ -63,111 +123,148 @@ export default function AdminDashboard() {
brandName="Jobee Admin"
navItems={navItems}
button={{
text: "Logout", onClick: handleLogout,
text: "Logout", onClick: () => console.log("Logout"),
}}
/>
</div>
<div className="min-h-screen bg-slate-50 pt-24 pb-12">
<div className="mx-auto max-w-7xl px-4">
<h1 className="text-4xl font-bold text-slate-900 mb-8">Admin Dashboard</h1>
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-slate-100 py-16 px-4">
<div className="max-w-7xl mx-auto">
{/* Header */}
<div className="mb-12">
<h1 className="text-4xl font-bold text-slate-900 mb-2">Admin Dashboard</h1>
<p className="text-slate-600">Manage jobs, users, and view analytics</p>
</div>
{/* Tab Navigation */}
<div className="flex gap-4 mb-8 border-b border-slate-200">
<div className="flex gap-4 mb-8">
<button
onClick={() => setActiveTab("jobs")}
className={`pb-4 px-4 font-semibold transition-colors ${
activeTab === "jobs"
? "text-blue-600 border-b-2 border-blue-600"
: "text-slate-600 hover:text-slate-900"
onClick={() => setActiveTab("dashboard")}
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === "dashboard"
? "bg-blue-600 text-white shadow-lg"
: "bg-white text-slate-700 hover:bg-slate-100"
}`}
>
<div className="flex items-center gap-2">
<Briefcase size={20} />
Job Management
</div>
<BarChart3 className="inline mr-2" size={20} />
Dashboard
</button>
<button
onClick={() => setActiveTab("applications")}
className={`pb-4 px-4 font-semibold transition-colors ${
activeTab === "applications"
? "text-blue-600 border-b-2 border-blue-600"
: "text-slate-600 hover:text-slate-900"
onClick={() => setActiveTab("jobs")}
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === "jobs"
? "bg-blue-600 text-white shadow-lg"
: "bg-white text-slate-700 hover:bg-slate-100"
}`}
>
<div className="flex items-center gap-2">
<FileText size={20} />
Applications
</div>
<Briefcase className="inline mr-2" size={20} />
Jobs ({jobs.length})
</button>
<button
onClick={() => setActiveTab("users")}
className={`pb-4 px-4 font-semibold transition-colors ${
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === "users"
? "text-blue-600 border-b-2 border-blue-600"
: "text-slate-600 hover:text-slate-900"
? "bg-blue-600 text-white shadow-lg"
: "bg-white text-slate-700 hover:bg-slate-100"
}`}
>
<div className="flex items-center gap-2">
<Users size={20} />
User Management
</div>
</button>
<button
onClick={() => setActiveTab("analytics")}
className={`pb-4 px-4 font-semibold transition-colors ${
activeTab === "analytics"
? "text-blue-600 border-b-2 border-blue-600"
: "text-slate-600 hover:text-slate-900"
}`}
>
<div className="flex items-center gap-2">
<BarChart3 size={20} />
Analytics
</div>
<Users className="inline mr-2" size={20} />
Users ({users.length})
</button>
</div>
{/* Job Management Tab */}
{/* Dashboard Tab */}
{activeTab === "dashboard" && (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="bg-white rounded-lg p-6 shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Total Jobs</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.totalJobs}</p>
</div>
<Briefcase className="text-blue-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg p-6 shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Total Users</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.totalUsers}</p>
</div>
<Users className="text-green-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg p-6 shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Active Applications</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.activeApplications}</p>
</div>
<ChevronDown className="text-purple-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg p-6 shadow-md">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Successful Placements</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.successfulPlacements}</p>
</div>
<BarChart3 className="text-orange-600" size={40} />
</div>
</div>
</div>
)}
{/* Jobs Tab */}
{activeTab === "jobs" && (
<div className="space-y-4">
<div className="flex justify-between items-center mb-6">
<h2 className="text-2xl font-bold text-slate-900">Job Listings</h2>
<button className="px-6 py-2 bg-blue-600 text-white rounded-lg font-semibold hover:bg-blue-700 transition">
+ New Job
<div className="bg-white rounded-lg shadow-md overflow-hidden">
<div className="p-6 border-b border-slate-200 flex justify-between items-center">
<h2 className="text-2xl font-bold text-slate-900">Job Management</h2>
<button className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-all">
<Plus size={20} />
Add Job
</button>
</div>
<div className="bg-white rounded-lg shadow overflow-hidden">
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-slate-100 border-b border-slate-200">
<thead className="bg-slate-50 border-b border-slate-200">
<tr>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Job Title</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Title</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Company</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Location</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Status</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Applications</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Posted</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Actions</th>
</tr>
</thead>
<tbody>
{jobs.map((job) => (
<tr key={job.id} className="border-b border-slate-200 hover:bg-slate-50">
<td className="px-6 py-4 text-sm text-slate-900 font-medium">{job.title}</td>
<td className="px-6 py-4 text-sm text-slate-600">{job.company}</td>
<td className="px-6 py-4 text-sm">
<span className={`px-3 py-1 rounded-full text-xs font-semibold ${
job.status === "Active"
? "bg-green-100 text-green-700"
: "bg-gray-100 text-gray-700"
}`}>
{job.status}
<tr key={job.id} className="border-b border-slate-200 hover:bg-slate-50 transition-colors">
<td className="px-6 py-4 text-slate-900 font-medium">{job.title}</td>
<td className="px-6 py-4 text-slate-600">{job.company}</td>
<td className="px-6 py-4 text-slate-600">{job.location}</td>
<td className="px-6 py-4">
<span
className={`px-3 py-1 rounded-full text-sm font-medium ${
job.status === "active"
? "bg-green-100 text-green-800"
: "bg-red-100 text-red-800"
}`}
>
{job.status.charAt(0).toUpperCase() + job.status.slice(1)}
</span>
</td>
<td className="px-6 py-4 text-sm text-slate-600">{job.applications}</td>
<td className="px-6 py-4 text-sm text-slate-600">{job.posted}</td>
<td className="px-6 py-4 text-sm space-x-2">
<button className="px-3 py-1 text-blue-600 hover:bg-blue-50 rounded transition">Edit</button>
<button className="px-3 py-1 text-red-600 hover:bg-red-50 rounded transition">Delete</button>
<td className="px-6 py-4 text-slate-600">{job.applications}</td>
<td className="px-6 py-4 flex gap-2">
<button className="p-2 text-blue-600 hover:bg-blue-50 rounded transition-colors">
<Edit2 size={18} />
</button>
<button
onClick={() => handleDeleteJob(job.id)}
className="p-2 text-red-600 hover:bg-red-50 rounded transition-colors"
>
<Trash2 size={18} />
</button>
</td>
</tr>
))}
@@ -177,85 +274,58 @@ export default function AdminDashboard() {
</div>
)}
{/* Applications Management Tab */}
{activeTab === "applications" && (
<div className="space-y-4">
<h2 className="text-2xl font-bold text-slate-900 mb-6">Application Management</h2>
<div className="bg-white rounded-lg shadow overflow-hidden">
<table className="w-full">
<thead className="bg-slate-100 border-b border-slate-200">
<tr>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Candidate</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Position</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Status</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Applied Date</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Actions</th>
</tr>
</thead>
<tbody>
{applications.map((app) => (
<tr key={app.id} className="border-b border-slate-200 hover:bg-slate-50">
<td className="px-6 py-4 text-sm text-slate-900 font-medium">{app.candidate}</td>
<td className="px-6 py-4 text-sm text-slate-600">{app.position}</td>
<td className="px-6 py-4 text-sm">
<span className={`px-3 py-1 rounded-full text-xs font-semibold ${
app.status === "Interview"
? "bg-blue-100 text-blue-700"
: app.status === "Under Review"
? "bg-yellow-100 text-yellow-700"
: "bg-red-100 text-red-700"
}`}>
{app.status}
</span>
</td>
<td className="px-6 py-4 text-sm text-slate-600">{app.appliedDate}</td>
<td className="px-6 py-4 text-sm space-x-2">
<button className="px-3 py-1 text-blue-600 hover:bg-blue-50 rounded transition">View</button>
<button className="px-3 py-1 text-green-600 hover:bg-green-50 rounded transition">Approve</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)}
{/* User Management Tab */}
{/* Users Tab */}
{activeTab === "users" && (
<div className="space-y-4">
<h2 className="text-2xl font-bold text-slate-900 mb-6">User Management</h2>
<div className="bg-white rounded-lg shadow overflow-hidden">
<div className="bg-white rounded-lg shadow-md overflow-hidden">
<div className="p-6 border-b border-slate-200 flex justify-between items-center">
<h2 className="text-2xl font-bold text-slate-900">User Management</h2>
<button className="flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-all">
<Plus size={20} />
Add User
</button>
</div>
<div className="overflow-x-auto">
<table className="w-full">
<thead className="bg-slate-100 border-b border-slate-200">
<thead className="bg-slate-50 border-b border-slate-200">
<tr>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Name</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Email</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Role</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Joined</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Join Date</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Status</th>
<th className="px-6 py-3 text-left text-sm font-semibold text-slate-900">Actions</th>
</tr>
</thead>
<tbody>
{users.map((user) => (
<tr key={user.id} className="border-b border-slate-200 hover:bg-slate-50">
<td className="px-6 py-4 text-sm text-slate-900 font-medium">{user.name}</td>
<td className="px-6 py-4 text-sm text-slate-600">{user.email}</td>
<td className="px-6 py-4 text-sm text-slate-600">{user.role}</td>
<td className="px-6 py-4 text-sm text-slate-600">{user.joined}</td>
<td className="px-6 py-4 text-sm">
<span className={`px-3 py-1 rounded-full text-xs font-semibold ${
user.status === "Active"
? "bg-green-100 text-green-700"
: "bg-gray-100 text-gray-700"
}`}>
{user.status}
<tr key={user.id} className="border-b border-slate-200 hover:bg-slate-50 transition-colors">
<td className="px-6 py-4 text-slate-900 font-medium">{user.name}</td>
<td className="px-6 py-4 text-slate-600">{user.email}</td>
<td className="px-6 py-4 text-slate-600">
<span className="capitalize">{user.role.replace("_", " ")}</span>
</td>
<td className="px-6 py-4 text-slate-600">{user.joinDate}</td>
<td className="px-6 py-4">
<span
className={`px-3 py-1 rounded-full text-sm font-medium ${
user.status === "active"
? "bg-green-100 text-green-800"
: "bg-gray-100 text-gray-800"
}`}
>
{user.status.charAt(0).toUpperCase() + user.status.slice(1)}
</span>
</td>
<td className="px-6 py-4 text-sm space-x-2">
<button className="px-3 py-1 text-blue-600 hover:bg-blue-50 rounded transition">Edit</button>
<button className="px-3 py-1 text-red-600 hover:bg-red-50 rounded transition">Disable</button>
<td className="px-6 py-4 flex gap-2">
<button className="p-2 text-blue-600 hover:bg-blue-50 rounded transition-colors">
<Edit2 size={18} />
</button>
<button
onClick={() => handleDeleteUser(user.id)}
className="p-2 text-red-600 hover:bg-red-50 rounded transition-colors"
>
<Trash2 size={18} />
</button>
</td>
</tr>
))}
@@ -264,71 +334,16 @@ export default function AdminDashboard() {
</div>
</div>
)}
{/* Analytics Tab */}
{activeTab === "analytics" && (
<div className="space-y-6">
<h2 className="text-2xl font-bold text-slate-900 mb-6">Analytics Overview</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-blue-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Total Jobs</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.totalJobs}</p>
</div>
<Briefcase className="text-blue-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-green-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Active Applications</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.activeApplications}</p>
</div>
<FileText className="text-green-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-purple-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Total Users</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.totalUsers}</p>
</div>
<Users className="text-purple-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-yellow-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Avg Time to Hire</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.avgTimeToHire}</p>
</div>
<TrendingUp className="text-yellow-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-red-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Monthly Growth</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.monthlyGrowth}</p>
</div>
<BarChart3 className="text-red-600" size={40} />
</div>
</div>
<div className="bg-white rounded-lg shadow p-6 border-l-4 border-indigo-600">
<div className="flex items-center justify-between">
<div>
<p className="text-slate-600 text-sm font-medium">Conversion Rate</p>
<p className="text-3xl font-bold text-slate-900 mt-2">{analytics.conversionRate}</p>
</div>
<BarChart3 className="text-indigo-600" size={40} />
</div>
</div>
</div>
</div>
)}
</div>
</div>
<div id="footer" data-section="footer">
<FooterBase
logoText="Jobee"
copyrightText="© 2025 Jobee | Dutch Job Listing Platform"
columns={footerColumns}
/>
</div>
</ThemeProvider>
);
}