Add src/app/admin/page.tsx
This commit is contained in:
349
src/app/admin/page.tsx
Normal file
349
src/app/admin/page.tsx
Normal file
@@ -0,0 +1,349 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
|
||||
import FooterBase from "@/components/sections/footer/FooterBase";
|
||||
import { Users, Briefcase, BarChart3, ChevronDown, Plus, Trash2, Edit2 } from "lucide-react";
|
||||
|
||||
const navItems = [
|
||||
{ name: "Dashboard", id: "/admin" },
|
||||
{ name: "Jobs", id: "/admin" },
|
||||
{ name: "Users", id: "/admin" },
|
||||
{ name: "Analytics", id: "/admin" },
|
||||
{ name: "Home", id: "/" },
|
||||
];
|
||||
|
||||
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<"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 [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 [analytics] = useState<AnalyticsData>({
|
||||
totalJobs: 156,
|
||||
totalUsers: 3245,
|
||||
activeApplications: 892,
|
||||
successfulPlacements: 142,
|
||||
});
|
||||
|
||||
const handleDeleteJob = (id: string) => {
|
||||
setJobs(jobs.filter((job) => job.id !== id));
|
||||
};
|
||||
|
||||
const handleDeleteUser = (id: string) => {
|
||||
setUsers(users.filter((user) => user.id !== id));
|
||||
};
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="text-stagger"
|
||||
defaultTextAnimation="reveal-blur"
|
||||
borderRadius="pill"
|
||||
contentWidth="smallMedium"
|
||||
sizing="mediumLargeSizeLargeTitles"
|
||||
background="circleGradient"
|
||||
cardStyle="gradient-radial"
|
||||
primaryButtonStyle="double-inset"
|
||||
secondaryButtonStyle="glass"
|
||||
headingFontWeight="bold"
|
||||
>
|
||||
<div id="nav" data-section="nav">
|
||||
<NavbarStyleCentered
|
||||
brandName="Jobee Admin"
|
||||
navItems={navItems}
|
||||
button={{
|
||||
text: "Logout", onClick: () => console.log("Logout"),
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
<button
|
||||
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"
|
||||
}`}
|
||||
>
|
||||
<BarChart3 className="inline mr-2" size={20} />
|
||||
Dashboard
|
||||
</button>
|
||||
<button
|
||||
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"
|
||||
}`}
|
||||
>
|
||||
<Briefcase className="inline mr-2" size={20} />
|
||||
Jobs ({jobs.length})
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("users")}
|
||||
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
|
||||
activeTab === "users"
|
||||
? "bg-blue-600 text-white shadow-lg"
|
||||
: "bg-white text-slate-700 hover:bg-slate-100"
|
||||
}`}
|
||||
>
|
||||
<Users className="inline mr-2" size={20} />
|
||||
Users ({users.length})
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* 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="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="overflow-x-auto">
|
||||
<table className="w-full">
|
||||
<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">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">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{jobs.map((job) => (
|
||||
<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-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>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Users Tab */}
|
||||
{activeTab === "users" && (
|
||||
<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-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">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 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 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>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="footer" data-section="footer">
|
||||
<FooterBase
|
||||
logoText="Jobee"
|
||||
copyrightText="© 2025 Jobee | Dutch Job Listing Platform"
|
||||
columns={footerColumns}
|
||||
/>
|
||||
</div>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user