Update src/app/post-job/page.tsx

This commit is contained in:
2026-03-08 22:12:39 +00:00
parent ba33e12e8d
commit 46c8201b2e

View File

@@ -1,48 +1,130 @@
"use client";
import { useState } from "react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from "@/components/navbar/NavbarStyleCentered/NavbarStyleCentered";
import FeatureCardEight from "@/components/sections/feature/FeatureCardEight";
import ContactCenter from "@/components/sections/contact/ContactCenter";
import FooterBase from "@/components/sections/footer/FooterBase";
import Link from "next/link";
import { Briefcase, Mail, MapPin, Sparkles } from "lucide-react";
import Input from "@/components/form/Input";
import { Upload, CheckCircle, X } 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" },
];
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 FormData {
jobTitle: string;
companyName: string;
location: string;
jobType: string;
salary: string;
description: string;
requirements: string;
benefits: string;
contactEmail: string;
}
interface FormErrors {
[key: string]: string;
}
export default function PostJobPage() {
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" },
];
const [formData, setFormData] = useState<FormData>({
jobTitle: "", companyName: "", location: "", jobType: "Full-time", salary: "", description: "", requirements: "", benefits: "", contactEmail: ""});
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: "#" },
],
},
];
const [errors, setErrors] = useState<FormErrors>({});
const [submitted, setSubmitted] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const validateForm = (): boolean => {
const newErrors: FormErrors = {};
if (!formData.jobTitle.trim()) {
newErrors.jobTitle = "Job title is required";
}
if (!formData.companyName.trim()) {
newErrors.companyName = "Company name is required";
}
if (!formData.location.trim()) {
newErrors.location = "Location is required";
}
if (!formData.salary.trim()) {
newErrors.salary = "Salary range is required";
}
if (!formData.description.trim() || formData.description.trim().length < 20) {
newErrors.description = "Job description must be at least 20 characters";
}
if (!formData.requirements.trim() || formData.requirements.trim().length < 20) {
newErrors.requirements = "Requirements must be at least 20 characters";
}
if (!formData.contactEmail.trim()) {
newErrors.contactEmail = "Contact email is required";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.contactEmail)) {
newErrors.contactEmail = "Please enter a valid email address";
}
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleInputChange = (field: keyof FormData, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
if (errors[field]) {
setErrors((prev) => {
const newErrors = { ...prev };
delete newErrors[field];
return newErrors;
});
}
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!validateForm()) return;
setIsLoading(true);
try {
await new Promise((resolve) => setTimeout(resolve, 2000));
setSubmitted(true);
setFormData({
jobTitle: "", companyName: "", location: "", jobType: "Full-time", salary: "", description: "", requirements: "", benefits: "", contactEmail: ""});
setTimeout(() => setSubmitted(false), 5000);
} catch (error) {
console.error("Submission error:", error);
} finally {
setIsLoading(false);
}
};
return (
<ThemeProvider
@@ -59,65 +141,230 @@ export default function PostJobPage() {
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
navItems={navItems}
button={{ text: "Post a Job", href: "/post-job" }}
brandName="Jobee"
navItems={navItems}
button={{
text: "Post a Job", href: "/post-job"}}
/>
</div>
<div id="features" data-section="features">
<FeatureCardEight
features={[
{
id: 1,
title: "Create a Job Posting", description:
"Fill in job details, requirements, and salary information. Our intuitive form guides you through every step to create a compelling job listing.", imageSrc:
"http://img.b2bpic.net/free-vector/professional-recruitment-plan-diversity-general-infographic-template_23-2148947635.jpg?_wi=4", imageAlt: "Job posting creation interface"},
{
id: 2,
title: "Reach Qualified Candidates", description:
"Your job posting is automatically distributed across our network of active job seekers across all 12 Dutch provinces.", imageSrc:
"http://img.b2bpic.net/free-photo/homepage-concept-with-search-bar_23-2150040187.jpg?_wi=5", imageAlt: "Candidate reach visualization"},
{
id: 3,
title: "Review Applications", description:
"Manage all incoming applications in one centralized dashboard. Review resumes, cover letters, and candidate profiles easily.", imageSrc:
"http://img.b2bpic.net/free-photo/personal-information-form-identity-concept_53876-137622.jpg?_wi=4", imageAlt: "Application review dashboard"},
]}
title="Post a Job in Three Easy Steps"
description="Reach thousands of qualified job seekers across the Netherlands and build your dream team."
tag="Simple Process"
tagIcon={Sparkles}
tagAnimation="slide-up"
textboxLayout="default"
useInvertedBackground={false}
buttons={[{ text: "Start Posting", href: "/post-job" }]}
buttonAnimation="slide-up"
/>
</div>
<div className="min-h-screen bg-background py-16 md:py-24">
<div className="mx-auto w-full max-w-2xl px-4 md:px-8">
{/* Header */}
<div className="mb-12 text-center">
<h1 className="mb-4 text-4xl md:text-5xl font-bold text-foreground">
Post a Job
</h1>
<p className="text-lg text-foreground/75">
Reach thousands of qualified job seekers across the Netherlands
</p>
</div>
<div id="contact" data-section="contact">
<ContactCenter
tag="Newsletter"
title="Get Notified About Top Talent"
description="Subscribe to receive alerts when qualified candidates match your job requirements. Stay ahead of the competition and hire the best talent."
tagIcon={Mail}
tagAnimation="slide-up"
background={{ variant: "animated-grid" }}
useInvertedBackground={false}
inputPlaceholder="Enter your company email"
buttonText="Subscribe"
termsText="We respect your privacy. Unsubscribe anytime from our notifications."
/>
{/* Success Message */}
{submitted && (
<div className="mb-8 flex items-center gap-3 rounded-lg bg-green-50 p-4 text-green-700 border border-green-200">
<CheckCircle size={20} />
<div>
<p className="font-semibold">Job posted successfully!</p>
<p className="text-sm">Your job listing will be live shortly.</p>
</div>
<button
onClick={() => setSubmitted(false)}
className="ml-auto p-1 hover:bg-green-100 rounded"
>
<X size={16} />
</button>
</div>
)}
{/* Form */}
<form
onSubmit={handleSubmit}
className="rounded-xl bg-card p-8 md:p-12 border border-accent/20 shadow-lg"
>
{/* Job Title */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Job Title *
</label>
<Input
value={formData.jobTitle}
onChange={(value) => handleInputChange("jobTitle", value)}
placeholder="e.g., Senior Software Engineer"
required
/>
{errors.jobTitle && (
<p className="mt-1 text-sm text-red-600">{errors.jobTitle}</p>
)}
</div>
{/* Company Name */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Company Name *
</label>
<Input
value={formData.companyName}
onChange={(value) => handleInputChange("companyName", value)}
placeholder="Your company name"
required
/>
{errors.companyName && (
<p className="mt-1 text-sm text-red-600">{errors.companyName}</p>
)}
</div>
{/* Location */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Location *
</label>
<Input
value={formData.location}
onChange={(value) => handleInputChange("location", value)}
placeholder="e.g., Amsterdam, Netherlands"
required
/>
{errors.location && (
<p className="mt-1 text-sm text-red-600">{errors.location}</p>
)}
</div>
{/* Job Type and Salary */}
<div className="mb-6 grid gap-6 md:grid-cols-2">
<div>
<label className="block mb-2 text-sm font-semibold text-foreground">
Job Type *
</label>
<select
value={formData.jobType}
onChange={(e) => handleInputChange("jobType", e.target.value)}
className="w-full rounded-lg bg-secondary-button px-4 py-2.5 text-foreground placeholder-foreground/75 border border-accent/20 focus:outline-none focus:ring-2 focus:ring-primary-cta"
>
<option>Full-time</option>
<option>Part-time</option>
<option>Contract</option>
<option>Temporary</option>
<option>Internship</option>
</select>
</div>
<div>
<label className="block mb-2 text-sm font-semibold text-foreground">
Salary Range *
</label>
<Input
value={formData.salary}
onChange={(value) => handleInputChange("salary", value)}
placeholder="e.g., €50,000 - €80,000"
required
/>
{errors.salary && (
<p className="mt-1 text-sm text-red-600">{errors.salary}</p>
)}
</div>
</div>
{/* Job Description */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Job Description *
</label>
<textarea
value={formData.description}
onChange={(e) => handleInputChange("description", e.target.value)}
placeholder="Describe the role, responsibilities, and key details..."
rows={6}
className="w-full rounded-lg bg-secondary-button px-4 py-2.5 text-foreground placeholder-foreground/75 border border-accent/20 focus:outline-none focus:ring-2 focus:ring-primary-cta resize-none"
required
/>
{errors.description && (
<p className="mt-1 text-sm text-red-600">{errors.description}</p>
)}
</div>
{/* Requirements */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Requirements *
</label>
<textarea
value={formData.requirements}
onChange={(e) => handleInputChange("requirements", e.target.value)}
placeholder="List the key requirements and qualifications (e.g., skills, experience, education)..."
rows={5}
className="w-full rounded-lg bg-secondary-button px-4 py-2.5 text-foreground placeholder-foreground/75 border border-accent/20 focus:outline-none focus:ring-2 focus:ring-primary-cta resize-none"
required
/>
{errors.requirements && (
<p className="mt-1 text-sm text-red-600">{errors.requirements}</p>
)}
</div>
{/* Benefits */}
<div className="mb-6">
<label className="block mb-2 text-sm font-semibold text-foreground">
Benefits (Optional)
</label>
<textarea
value={formData.benefits}
onChange={(e) => handleInputChange("benefits", e.target.value)}
placeholder="Highlight benefits such as remote work, flexible hours, health insurance, training, etc."
rows={4}
className="w-full rounded-lg bg-secondary-button px-4 py-2.5 text-foreground placeholder-foreground/75 border border-accent/20 focus:outline-none focus:ring-2 focus:ring-primary-cta resize-none"
/>
</div>
{/* Contact Email */}
<div className="mb-8">
<label className="block mb-2 text-sm font-semibold text-foreground">
Contact Email *
</label>
<Input
value={formData.contactEmail}
onChange={(value) => handleInputChange("contactEmail", value)}
type="email"
placeholder="your-email@company.com"
required
/>
{errors.contactEmail && (
<p className="mt-1 text-sm text-red-600">{errors.contactEmail}</p>
)}
</div>
{/* Submit Button */}
<button
type="submit"
disabled={isLoading}
className="w-full rounded-lg bg-primary-cta px-6 py-3 font-semibold text-white hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition-opacity flex items-center justify-center gap-2"
>
{isLoading ? (
<>
<div className="h-5 w-5 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
Posting...
</>
) : (
<>
<Upload size={18} />
Post Job
</>
)}
</button>
{/* Form Info */}
<p className="mt-4 text-center text-sm text-foreground/60">
* Required fields. Your job will be reviewed before going live.
</p>
</form>
</div>
</div>
<div id="footer" data-section="footer">
<FooterBase
columns={footerColumns}
logoText="Jobee"
copyrightText="© 2025 Jobee | Dutch Job Listing Platform"
columns={footerColumns}
/>
</div>
</ThemeProvider>
);
}
}