Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 282ec7c7ea | |||
| 3ddd1d149b | |||
| 480f9310c6 | |||
| 4ff558d745 | |||
| 4f745c93c3 | |||
| 6373b5ea06 | |||
| 4d2b3e17b5 | |||
| 493be55972 | |||
| 3a886ec207 | |||
| 1be6979ab5 | |||
| 80ab56121a | |||
| ca6084197d | |||
| 65acbd32ab | |||
| 421a0d4dbe | |||
| d21ebfd001 | |||
| 51bcffe909 | |||
| 7a51c13052 | |||
| 7a96daee1c | |||
| 67978193ba | |||
| 9b94d81876 | |||
| 2dade11252 | |||
| 133cfea674 | |||
| 99d4f8ce22 | |||
| 405b18fb28 | |||
| 4a49487c77 | |||
| 4591aa0eca | |||
| 9346a0f432 | |||
| 2095c0060e | |||
| 8d99e049e6 | |||
| e2f8bd0110 | |||
| 89ceb71096 | |||
| 4b3707c37b | |||
| 880d6203a7 | |||
| e71c5c0f8b | |||
| 77c71a315d | |||
| 72f424682a | |||
| 0514de31b6 | |||
| 47d6d223c3 | |||
| 67c5d07b7b | |||
| 035db5c023 | |||
| d3dac0cee3 | |||
| 184c822595 | |||
| 82b0c18e52 | |||
| 61fd21c259 | |||
| 636a3a4c15 | |||
| d38cd3c458 | |||
| b8710b24a0 | |||
| cd9915cd6e | |||
| 4af8479479 | |||
| c813799e97 | |||
| 3981f7d98b | |||
| bf27ffa4ae | |||
| 4e877df3bf | |||
| d90c038218 | |||
| 99ec17545c | |||
| de4853edae | |||
| a9c024cee2 | |||
| 6a0b735d77 | |||
| 0346a28661 | |||
| 8f4c4a9a8d | |||
| 5cc569fcbe | |||
| 7a29becc6e | |||
| c522614a4f | |||
| 97524956d7 | |||
| 442db37238 | |||
| 4ba0c81193 | |||
| 61d3a35d93 | |||
| 2509960b1c | |||
| f232aa4e8f | |||
| 109159b5f8 | |||
| e1bb3ad20b | |||
| a47a53417b | |||
| 96ab94d27e | |||
| e28c7a74c3 | |||
| 46c8201b2e | |||
| ba33e12e8d | |||
| c3e170a160 | |||
| f49320b8db | |||
| d87884fca5 | |||
| 29d059a2a8 | |||
| f5dad3e157 | |||
| d1c3983b8e |
334
src/app/admin/page.tsx
Normal file
334
src/app/admin/page.tsx
Normal file
@@ -0,0 +1,334 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ name: "Search Jobs", id: "" },
|
||||||
|
{ name: "Post a Job", id: "" },
|
||||||
|
{ name: "Admin", id: "/admin" },
|
||||||
|
{ name: "Browse", id: "" },
|
||||||
|
{ name: "Contact", id: "" },
|
||||||
|
];
|
||||||
|
|
||||||
|
type TabType = "jobs" | "applications" | "users" | "analytics";
|
||||||
|
|
||||||
|
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 [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] = 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({
|
||||||
|
totalJobs: 284,
|
||||||
|
activeApplications: 156,
|
||||||
|
totalUsers: 2341,
|
||||||
|
avgTimeToHire: "18 days", monthlyGrowth: "+12.5%", conversionRate: "8.3%"});
|
||||||
|
|
||||||
|
const handleLogout = () => {
|
||||||
|
window.location.href = "/";
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ThemeProvider
|
||||||
|
defaultButtonVariant="text-stagger"
|
||||||
|
defaultTextAnimation="reveal-blur"
|
||||||
|
borderRadius="pill"
|
||||||
|
contentWidth="medium"
|
||||||
|
sizing="mediumLargeSizeLargeTitles"
|
||||||
|
background="none"
|
||||||
|
cardStyle="solid"
|
||||||
|
primaryButtonStyle="gradient"
|
||||||
|
secondaryButtonStyle="solid"
|
||||||
|
headingFontWeight="bold"
|
||||||
|
>
|
||||||
|
<div id="nav" data-section="nav">
|
||||||
|
<NavbarStyleCentered
|
||||||
|
brandName="Jobee Admin"
|
||||||
|
navItems={navItems}
|
||||||
|
button={{
|
||||||
|
text: "Logout", onClick: handleLogout,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</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>
|
||||||
|
|
||||||
|
{/* Tab Navigation */}
|
||||||
|
<div className="flex gap-4 mb-8 border-b border-slate-200">
|
||||||
|
<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"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Briefcase size={20} />
|
||||||
|
Job Management
|
||||||
|
</div>
|
||||||
|
</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"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<FileText size={20} />
|
||||||
|
Applications
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setActiveTab("users")}
|
||||||
|
className={`pb-4 px-4 font-semibold transition-colors ${
|
||||||
|
activeTab === "users"
|
||||||
|
? "text-blue-600 border-b-2 border-blue-600"
|
||||||
|
: "text-slate-600 hover:text-slate-900"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Job Management 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
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<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">Job 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">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}
|
||||||
|
</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>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</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 */}
|
||||||
|
{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">
|
||||||
|
<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">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">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}
|
||||||
|
</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>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</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>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
356
src/app/applications/page.tsx
Normal file
356
src/app/applications/page.tsx
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||||
|
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
|
||||||
|
import FooterBase from "@/components/sections/footer/FooterBase";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Briefcase, Clock, CheckCircle, AlertCircle, MapPin, DollarSign, Building2, Calendar, ArrowRight } from "lucide-react";
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ name: "Search Jobs", id: "search" },
|
||||||
|
{ name: "Post a Job", id: "post-job" },
|
||||||
|
{ name: "Admin", id: "admin-login" },
|
||||||
|
{ name: "Browse", id: "browse" },
|
||||||
|
{ name: "Contact", id: "contact" },
|
||||||
|
{ name: "Applications", id: "/applications" },
|
||||||
|
];
|
||||||
|
|
||||||
|
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 Application {
|
||||||
|
id: string;
|
||||||
|
jobTitle: string;
|
||||||
|
company: string;
|
||||||
|
location: string;
|
||||||
|
salary: string;
|
||||||
|
appliedDate: string;
|
||||||
|
status: "pending" | "reviewed" | "accepted" | "rejected";
|
||||||
|
logoSrc?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mockApplications: Application[] = [
|
||||||
|
{
|
||||||
|
id: "1", jobTitle: "Senior React Developer", company: "TechFlow Solutions", location: "Amsterdam, Netherlands", salary: "€65,000 - €80,000", appliedDate: "2025-01-15", status: "reviewed", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=TF"},
|
||||||
|
{
|
||||||
|
id: "2", jobTitle: "UX/UI Designer", company: "Creative Studios Amsterdam", location: "Amsterdam, Netherlands", salary: "€50,000 - €65,000", appliedDate: "2025-01-10", status: "accepted", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=CSA"},
|
||||||
|
{
|
||||||
|
id: "3", jobTitle: "Full Stack Developer", company: "Innovate Inc", location: "Rotterdam, Netherlands", salary: "€55,000 - €70,000", appliedDate: "2025-01-12", status: "pending", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=II"},
|
||||||
|
{
|
||||||
|
id: "4", jobTitle: "Marketing Manager", company: "Digital Growth Partners", location: "Utrecht, Netherlands", salary: "€48,000 - €60,000", appliedDate: "2025-01-08", status: "rejected", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=DGP"},
|
||||||
|
{
|
||||||
|
id: "5", jobTitle: "Data Scientist", company: "Analytics Pro", location: "The Hague, Netherlands", salary: "€60,000 - €75,000", appliedDate: "2025-01-05", status: "reviewed", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=AP"},
|
||||||
|
{
|
||||||
|
id: "6", jobTitle: "Product Manager", company: "Tech Ventures", location: "Eindhoven, Netherlands", salary: "€65,000 - €85,000", appliedDate: "2025-01-02", status: "pending", logoSrc: "https://api.dicebear.com/7.x/initials/svg?seed=TV"},
|
||||||
|
];
|
||||||
|
|
||||||
|
const getStatusColor = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "accepted":
|
||||||
|
return "bg-green-100 text-green-800";
|
||||||
|
case "rejected":
|
||||||
|
return "bg-red-100 text-red-800";
|
||||||
|
case "reviewed":
|
||||||
|
return "bg-blue-100 text-blue-800";
|
||||||
|
case "pending":
|
||||||
|
return "bg-yellow-100 text-yellow-800";
|
||||||
|
default:
|
||||||
|
return "bg-gray-100 text-gray-800";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusIcon = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "accepted":
|
||||||
|
return <CheckCircle className="w-4 h-4" />;
|
||||||
|
case "rejected":
|
||||||
|
return <AlertCircle className="w-4 h-4" />;
|
||||||
|
case "reviewed":
|
||||||
|
return <Clock className="w-4 h-4" />;
|
||||||
|
case "pending":
|
||||||
|
return <Clock className="w-4 h-4" />;
|
||||||
|
default:
|
||||||
|
return <Clock className="w-4 h-4" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStatusLabel = (status: string) => {
|
||||||
|
switch (status) {
|
||||||
|
case "accepted":
|
||||||
|
return "Accepted";
|
||||||
|
case "rejected":
|
||||||
|
return "Rejected";
|
||||||
|
case "reviewed":
|
||||||
|
return "Under Review";
|
||||||
|
case "pending":
|
||||||
|
return "Pending";
|
||||||
|
default:
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ApplicationsPage() {
|
||||||
|
const [selectedApplication, setSelectedApplication] = useState<Application | null>(null);
|
||||||
|
const [statusFilter, setStatusFilter] = useState<string>("all");
|
||||||
|
|
||||||
|
const filteredApplications = statusFilter === "all"
|
||||||
|
? mockApplications
|
||||||
|
: mockApplications.filter(app => app.status === statusFilter);
|
||||||
|
|
||||||
|
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"
|
||||||
|
navItems={navItems}
|
||||||
|
button={{
|
||||||
|
text: "Post a Job", href: "/post-job"}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<main className="min-h-screen bg-gradient-to-br from-background via-card to-background">
|
||||||
|
<div className="container mx-auto px-4 py-16">
|
||||||
|
{/* Header Section */}
|
||||||
|
<div className="mb-12">
|
||||||
|
<div className="flex items-center gap-3 mb-4">
|
||||||
|
<Briefcase className="w-8 h-8 text-primary-cta" />
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold text-foreground">My Applications</h1>
|
||||||
|
</div>
|
||||||
|
<p className="text-lg text-foreground/70 mb-8">
|
||||||
|
Track and manage all your job applications in one place. Monitor your application status and stay updated on opportunities.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Status Filter */}
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<button
|
||||||
|
onClick={() => setStatusFilter("all")}
|
||||||
|
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||||
|
statusFilter === "all"
|
||||||
|
? "bg-primary-cta text-white"
|
||||||
|
: "bg-card border border-accent/30 text-foreground hover:border-accent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
All Applications ({mockApplications.length})
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setStatusFilter("pending")}
|
||||||
|
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||||
|
statusFilter === "pending"
|
||||||
|
? "bg-yellow-500 text-white"
|
||||||
|
: "bg-card border border-accent/30 text-foreground hover:border-accent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Pending
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setStatusFilter("reviewed")}
|
||||||
|
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||||
|
statusFilter === "reviewed"
|
||||||
|
? "bg-blue-500 text-white"
|
||||||
|
: "bg-card border border-accent/30 text-foreground hover:border-accent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Under Review
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setStatusFilter("accepted")}
|
||||||
|
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||||
|
statusFilter === "accepted"
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "bg-card border border-accent/30 text-foreground hover:border-accent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Accepted
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setStatusFilter("rejected")}
|
||||||
|
className={`px-6 py-2 rounded-full font-medium transition-all ${
|
||||||
|
statusFilter === "rejected"
|
||||||
|
? "bg-red-500 text-white"
|
||||||
|
: "bg-card border border-accent/30 text-foreground hover:border-accent"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Rejected
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Applications Grid */}
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||||
|
{/* Application List */}
|
||||||
|
<div className="lg:col-span-2">
|
||||||
|
<div className="space-y-4">
|
||||||
|
{filteredApplications.length === 0 ? (
|
||||||
|
<div className="bg-card border border-accent/20 rounded-2xl p-8 text-center">
|
||||||
|
<Briefcase className="w-12 h-12 text-foreground/30 mx-auto mb-4" />
|
||||||
|
<p className="text-foreground/60">No applications found with this status.</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
filteredApplications.map((app) => (
|
||||||
|
<div
|
||||||
|
key={app.id}
|
||||||
|
onClick={() => setSelectedApplication(app)}
|
||||||
|
className={`bg-card border border-accent/20 rounded-2xl p-6 cursor-pointer transition-all hover:border-accent/50 hover:shadow-lg ${
|
||||||
|
selectedApplication?.id === app.id ? "border-primary-cta" : ""
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{/* Company Logo */}
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<div className="w-16 h-16 bg-gradient-to-br from-primary-cta/20 to-accent/20 rounded-xl flex items-center justify-center">
|
||||||
|
<Building2 className="w-8 h-8 text-primary-cta" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Application Info */}
|
||||||
|
<div className="flex-grow">
|
||||||
|
<div className="flex items-start justify-between mb-2">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-bold text-foreground">{app.jobTitle}</h3>
|
||||||
|
<p className="text-sm text-foreground/60">{app.company}</p>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
className={`px-3 py-1 rounded-full text-xs font-medium flex items-center gap-1 ${
|
||||||
|
getStatusColor(app.status)
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{getStatusIcon(app.status)}
|
||||||
|
{getStatusLabel(app.status)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-wrap gap-4 text-sm text-foreground/60 mt-3">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<MapPin className="w-4 h-4" />
|
||||||
|
{app.location}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<DollarSign className="w-4 h-4" />
|
||||||
|
{app.salary}
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<Calendar className="w-4 h-4" />
|
||||||
|
{new Date(app.appliedDate).toLocaleDateString()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Arrow Icon */}
|
||||||
|
<div className="flex-shrink-0 flex items-center">
|
||||||
|
<ArrowRight className="w-5 h-5 text-foreground/30" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Application Details Panel */}
|
||||||
|
<div className="lg:col-span-1">
|
||||||
|
{selectedApplication ? (
|
||||||
|
<div className="bg-card border border-accent/20 rounded-2xl p-6 sticky top-24">
|
||||||
|
<div className="mb-6">
|
||||||
|
<h2 className="text-2xl font-bold text-foreground mb-2">{selectedApplication.jobTitle}</h2>
|
||||||
|
<p className="text-foreground/60 mb-4">{selectedApplication.company}</p>
|
||||||
|
<span
|
||||||
|
className={`inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium ${
|
||||||
|
getStatusColor(selectedApplication.status)
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{getStatusIcon(selectedApplication.status)}
|
||||||
|
{getStatusLabel(selectedApplication.status)}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4 border-t border-accent/10 pt-6">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-semibold text-foreground/50 uppercase tracking-wide mb-2">Location</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<MapPin className="w-4 h-4 text-primary-cta" />
|
||||||
|
<p className="text-foreground">{selectedApplication.location}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-semibold text-foreground/50 uppercase tracking-wide mb-2">Salary Range</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<DollarSign className="w-4 h-4 text-primary-cta" />
|
||||||
|
<p className="text-foreground">{selectedApplication.salary}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<p className="text-xs font-semibold text-foreground/50 uppercase tracking-wide mb-2">Applied Date</p>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Calendar className="w-4 h-4 text-primary-cta" />
|
||||||
|
<p className="text-foreground">{new Date(selectedApplication.appliedDate).toLocaleDateString()}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 space-y-2">
|
||||||
|
<button className="w-full bg-primary-cta text-white py-3 rounded-lg font-medium hover:opacity-90 transition-opacity">
|
||||||
|
View Application
|
||||||
|
</button>
|
||||||
|
<button className="w-full bg-card border border-accent/30 text-foreground py-3 rounded-lg font-medium hover:border-accent transition-colors">
|
||||||
|
Contact Company
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="bg-card border border-accent/20 rounded-2xl p-6 text-center">
|
||||||
|
<Briefcase className="w-12 h-12 text-foreground/30 mx-auto mb-4" />
|
||||||
|
<p className="text-foreground/60">Select an application to view details</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<div id="footer" data-section="footer">
|
||||||
|
<FooterBase
|
||||||
|
logoText="Jobee"
|
||||||
|
copyrightText="© 2025 Jobee | Dutch Job Listing Platform"
|
||||||
|
columns={footerColumns}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarS
|
|||||||
import FeatureCardEight from "@/components/sections/feature/FeatureCardEight";
|
import FeatureCardEight from "@/components/sections/feature/FeatureCardEight";
|
||||||
import TestimonialCardTwo from "@/components/sections/testimonial/TestimonialCardTwo";
|
import TestimonialCardTwo from "@/components/sections/testimonial/TestimonialCardTwo";
|
||||||
import FooterBase from "@/components/sections/footer/FooterBase";
|
import FooterBase from "@/components/sections/footer/FooterBase";
|
||||||
import { Briefcase, Sparkles } from "lucide-react";
|
import { Sparkles } from "lucide-react";
|
||||||
|
|
||||||
export default function ApplyPage() {
|
export default function ApplyPage() {
|
||||||
const navItems = [
|
const navItems = [
|
||||||
|
|||||||
1424
src/app/layout.tsx
1424
src/app/layout.tsx
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,7 @@ import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarS
|
|||||||
import FeatureCardEight from "@/components/sections/feature/FeatureCardEight";
|
import FeatureCardEight from "@/components/sections/feature/FeatureCardEight";
|
||||||
import ContactCenter from "@/components/sections/contact/ContactCenter";
|
import ContactCenter from "@/components/sections/contact/ContactCenter";
|
||||||
import FooterBase from "@/components/sections/footer/FooterBase";
|
import FooterBase from "@/components/sections/footer/FooterBase";
|
||||||
import Link from "next/link";
|
import { Sparkles, Mail } from "lucide-react";
|
||||||
import { Briefcase, Mail, MapPin, Sparkles } from "lucide-react";
|
|
||||||
|
|
||||||
export default function PostJobPage() {
|
export default function PostJobPage() {
|
||||||
const navItems = [
|
const navItems = [
|
||||||
|
|||||||
Reference in New Issue
Block a user