Add src/app/applications/page.tsx
This commit is contained in:
298
src/app/applications/page.tsx
Normal file
298
src/app/applications/page.tsx
Normal file
@@ -0,0 +1,298 @@
|
||||
"use client";
|
||||
|
||||
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
|
||||
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
|
||||
import FooterBase from "@/components/sections/footer/FooterBase";
|
||||
import { FileText, Clock, CheckCircle, XCircle, Mail } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
|
||||
const navItems = [
|
||||
{ name: "Search Jobs", id: "search" },
|
||||
{ name: "Post a Job", id: "/post-job" },
|
||||
{ name: "Applications", id: "/applications" },
|
||||
{ name: "Browse", id: "browse" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
|
||||
const footerColumns = [
|
||||
{
|
||||
title: "Product", items: [
|
||||
{ label: "Search Jobs", href: "/search" },
|
||||
{ label: "Post a Job", href: "/post-job" },
|
||||
{ label: "My Applications", href: "/applications" },
|
||||
{ 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;
|
||||
status: "pending" | "reviewing" | "accepted" | "rejected";
|
||||
appliedDate: string;
|
||||
lastUpdate: string;
|
||||
applicantName: string;
|
||||
email: string;
|
||||
appliedPosition?: string;
|
||||
}
|
||||
|
||||
const mockApplications: Application[] = [
|
||||
{
|
||||
id: "1", jobTitle: "Senior Frontend Developer", company: "Tech Innovations BV", status: "reviewing", appliedDate: "2025-01-15", lastUpdate: "2025-01-18", applicantName: "John Doe", email: "john.doe@example.com"},
|
||||
{
|
||||
id: "2", jobTitle: "Product Manager", company: "Digital Solutions Inc", status: "pending", appliedDate: "2025-01-20", lastUpdate: "2025-01-20", applicantName: "Jane Smith", email: "jane.smith@example.com"},
|
||||
{
|
||||
id: "3", jobTitle: "UX/UI Designer", company: "Creative Studio Amsterdam", status: "accepted", appliedDate: "2025-01-10", lastUpdate: "2025-01-17", applicantName: "Alice Johnson", email: "alice.johnson@example.com"},
|
||||
{
|
||||
id: "4", jobTitle: "Data Scientist", company: "AI Labs Netherlands", status: "rejected", appliedDate: "2025-01-05", lastUpdate: "2025-01-16", applicantName: "Bob Wilson", email: "bob.wilson@example.com"},
|
||||
{
|
||||
id: "5", jobTitle: "Backend Developer", company: "Cloud Systems Ltd", status: "reviewing", appliedDate: "2025-01-12", lastUpdate: "2025-01-19", applicantName: "Charlie Brown", email: "charlie.brown@example.com"},
|
||||
];
|
||||
|
||||
export default function ApplicationsPage() {
|
||||
const [applications, setApplications] = useState<Application[]>(mockApplications);
|
||||
const [filterStatus, setFilterStatus] = useState<string>("all");
|
||||
const [selectedApp, setSelectedApp] = useState<Application | null>(null);
|
||||
|
||||
const filteredApplications =
|
||||
filterStatus === "all"
|
||||
? applications
|
||||
: applications.filter((app) => app.status === filterStatus);
|
||||
|
||||
const getStatusIcon = (status: string) => {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return <Clock className="w-5 h-5 text-yellow-600" />;
|
||||
case "reviewing":
|
||||
return <FileText className="w-5 h-5 text-blue-600" />;
|
||||
case "accepted":
|
||||
return <CheckCircle className="w-5 h-5 text-green-600" />;
|
||||
case "rejected":
|
||||
return <XCircle className="w-5 h-5 text-red-600" />;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusBadgeColor = (status: string) => {
|
||||
switch (status) {
|
||||
case "pending":
|
||||
return "bg-yellow-100 text-yellow-800";
|
||||
case "reviewing":
|
||||
return "bg-blue-100 text-blue-800";
|
||||
case "accepted":
|
||||
return "bg-green-100 text-green-800";
|
||||
case "rejected":
|
||||
return "bg-red-100 text-red-800";
|
||||
default:
|
||||
return "bg-slate-100 text-slate-800";
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusLabel = (status: string) => {
|
||||
return status.charAt(0).toUpperCase() + status.slice(1);
|
||||
};
|
||||
|
||||
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>
|
||||
|
||||
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-slate-100 pt-32 pb-20">
|
||||
<div className="max-w-6xl mx-auto px-4">
|
||||
<div className="mb-8">
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<Mail className="w-6 h-6 text-blue-600" />
|
||||
<span className="text-sm font-semibold text-blue-600 uppercase tracking-wide">
|
||||
My Applications
|
||||
</span>
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-slate-900 mb-3">
|
||||
Track Your Applications
|
||||
</h1>
|
||||
<p className="text-lg text-slate-600">
|
||||
Monitor the status of all your job applications and stay updated on each
|
||||
opportunity.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Filter Tabs */}
|
||||
<div className="mb-8 flex flex-wrap gap-3">
|
||||
{[
|
||||
{ label: "All", value: "all", count: applications.length },
|
||||
{
|
||||
label: "Pending", value: "pending", count: applications.filter((a) => a.status === "pending").length,
|
||||
},
|
||||
{
|
||||
label: "Reviewing", value: "reviewing", count: applications.filter((a) => a.status === "reviewing").length,
|
||||
},
|
||||
{
|
||||
label: "Accepted", value: "accepted", count: applications.filter((a) => a.status === "accepted").length,
|
||||
},
|
||||
{
|
||||
label: "Rejected", value: "rejected", count: applications.filter((a) => a.status === "rejected").length,
|
||||
},
|
||||
].map((filter) => (
|
||||
<button
|
||||
key={filter.value}
|
||||
onClick={() => setFilterStatus(filter.value)}
|
||||
className={`px-4 py-2 rounded-lg font-semibold transition ${
|
||||
filterStatus === filter.value
|
||||
? "bg-blue-600 text-white"
|
||||
: "bg-white text-slate-700 hover:bg-slate-100"
|
||||
}`}
|
||||
>
|
||||
{filter.label} ({filter.count})
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Applications List */}
|
||||
<div className="space-y-4">
|
||||
{filteredApplications.length === 0 ? (
|
||||
<div className="text-center py-12 bg-white rounded-lg">
|
||||
<p className="text-slate-600 text-lg">No applications found</p>
|
||||
</div>
|
||||
) : (
|
||||
filteredApplications.map((app) => (
|
||||
<div
|
||||
key={app.id}
|
||||
className="bg-white rounded-lg shadow hover:shadow-md transition p-6 cursor-pointer"
|
||||
onClick={() => setSelectedApp(app)}
|
||||
>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="flex-1">
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h3 className="text-xl font-bold text-slate-900">{app.jobTitle}</h3>
|
||||
<div
|
||||
className={`flex items-center gap-1 px-3 py-1 rounded-full text-sm font-semibold ${
|
||||
getStatusBadgeColor(app.status)
|
||||
}`}
|
||||
>
|
||||
{getStatusIcon(app.status)}
|
||||
{getStatusLabel(app.status)}
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-slate-600 mb-2">{app.company}</p>
|
||||
<div className="text-sm text-slate-500 space-y-1">
|
||||
<p>Applied: {new Date(app.appliedDate).toLocaleDateString()}</p>
|
||||
<p>Last Update: {new Date(app.lastUpdate).toLocaleDateString()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Detail Modal */}
|
||||
{selectedApp && (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4 z-50">
|
||||
<div className="bg-white rounded-lg max-w-2xl w-full max-h-96 overflow-y-auto">
|
||||
<div className="p-8">
|
||||
<div className="flex items-start justify-between mb-6">
|
||||
<div>
|
||||
<h2 className="text-2xl font-bold text-slate-900 mb-2">
|
||||
{selectedApp.jobTitle}
|
||||
</h2>
|
||||
<p className="text-slate-600 text-lg">{selectedApp.company}</p>
|
||||
</div>
|
||||
<div
|
||||
className={`flex items-center gap-2 px-4 py-2 rounded-full font-semibold ${
|
||||
getStatusBadgeColor(selectedApp.status)
|
||||
}`}
|
||||
>
|
||||
{getStatusIcon(selectedApp.status)}
|
||||
{getStatusLabel(selectedApp.status)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t pt-6 space-y-4">
|
||||
<div>
|
||||
<p className="text-sm text-slate-600">Applicant Name</p>
|
||||
<p className="text-lg font-semibold text-slate-900">{selectedApp.applicantName}</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-slate-600">Email Address</p>
|
||||
<p className="text-lg font-semibold text-slate-900">{selectedApp.email}</p>
|
||||
</div>
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<p className="text-sm text-slate-600">Applied Date</p>
|
||||
<p className="text-lg font-semibold text-slate-900">
|
||||
{new Date(selectedApp.appliedDate).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-sm text-slate-600">Last Update</p>
|
||||
<p className="text-lg font-semibold text-slate-900">
|
||||
{new Date(selectedApp.lastUpdate).toLocaleDateString()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t mt-6 pt-6">
|
||||
<div className="flex gap-3">
|
||||
<button
|
||||
onClick={() => setSelectedApp(null)}
|
||||
className="flex-1 bg-slate-200 hover:bg-slate-300 text-slate-900 font-semibold py-2 rounded-lg transition"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button className="flex-1 bg-blue-600 hover:bg-blue-700 text-white font-semibold py-2 rounded-lg transition">
|
||||
View Full Details
|
||||
</button>
|
||||
</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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user