From 362b569c8d0c935d923c1ce3354e7623391320e7 Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Thu, 25 Dec 2025 22:11:16 -0300 Subject: [PATCH] refactor(frontend): consolidate job creation into single page form - Replaced 6-step wizard (673 lines) with single-page form (290 lines) - Removed billing/payment steps for now - All fields visible with clear section headers - Save as Draft and Publish buttons --- frontend/src/app/dashboard/jobs/new/page.tsx | 772 +++++-------------- 1 file changed, 214 insertions(+), 558 deletions(-) diff --git a/frontend/src/app/dashboard/jobs/new/page.tsx b/frontend/src/app/dashboard/jobs/new/page.tsx index 446f1e1..9f44484 100644 --- a/frontend/src/app/dashboard/jobs/new/page.tsx +++ b/frontend/src/app/dashboard/jobs/new/page.tsx @@ -8,29 +8,13 @@ import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select" -import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group" -import { Badge } from "@/components/ui/badge" import { Separator } from "@/components/ui/separator" -import { ArrowLeft, ArrowRight, Check, Loader2, Building2, DollarSign, FileText, Eye, CreditCard, Receipt, MapPin, Clock, Briefcase } from "lucide-react" +import { ArrowLeft, Loader2, Building2, DollarSign, FileText, Briefcase, MapPin, Clock } from "lucide-react" import { jobsApi, adminCompaniesApi, type CreateJobPayload, type AdminCompany } from "@/lib/api" import { toast } from "sonner" -import { cn } from "@/lib/utils" - -const STEPS = [ - { id: 1, title: "Job Details", icon: FileText }, - { id: 2, title: "Salary & Type", icon: DollarSign }, - { id: 3, title: "Company", icon: Building2 }, - { id: 4, title: "Preview", icon: Eye }, - { id: 5, title: "Billing", icon: Receipt }, - { id: 6, title: "Payment", icon: CreditCard }, -] - -const JOB_POSTING_PRICE = 32.61 -const FEATURED_PRICE = 15.00 export default function NewJobPage() { const router = useRouter() - const [currentStep, setCurrentStep] = useState(1) const [isSubmitting, setIsSubmitting] = useState(false) const [companies, setCompanies] = useState([]) const [loadingCompanies, setLoadingCompanies] = useState(true) @@ -49,23 +33,8 @@ export default function NewJobPage() { workingHours: "", // Company companyId: "", - // Options - isFeatured: false, - }) - - const [billingData, setBillingData] = useState({ - type: "company" as "company" | "individual", - firstName: "", - lastName: "", - email: "", - phone: "", - companyName: "", - address: "", - addressLine2: "", - city: "", - state: "", - zip: "", - country: "BR", + // Status + status: "draft" as "draft" | "published", }) useEffect(() => { @@ -88,35 +57,20 @@ export default function NewJobPage() { setFormData(prev => ({ ...prev, [field]: value })) } - const updateBilling = (field: string, value: string) => { - setBillingData(prev => ({ ...prev, [field]: value })) + const canSubmit = () => { + return formData.title.length >= 5 && + formData.description.length >= 20 && + formData.companyId !== "" } - const selectedCompany = companies.find(c => c.id === formData.companyId) - const totalPrice = JOB_POSTING_PRICE + (formData.isFeatured ? FEATURED_PRICE : 0) - - const canProceed = () => { - switch (currentStep) { - case 1: - return formData.title.length >= 5 && formData.description.length >= 20 - case 2: - return true - case 3: - return formData.companyId !== "" - case 4: - return true // Preview is always valid - case 5: - return billingData.firstName && billingData.lastName && billingData.email && - (billingData.type === "individual" || billingData.companyName) - default: - return true + const handleSubmit = async (publishNow: boolean = false) => { + if (!canSubmit()) { + toast.error("Please fill in all required fields") + return } - } - const handlePayment = async () => { setIsSubmitting(true) try { - // First create the job as draft const payload: CreateJobPayload = { companyId: formData.companyId, title: formData.title, @@ -128,15 +82,11 @@ export default function NewJobPage() { salaryType: formData.salaryType as CreateJobPayload['salaryType'] || undefined, currency: formData.currency as CreateJobPayload['currency'] || undefined, workingHours: formData.workingHours || undefined, - status: "draft", // Will be published after payment + status: publishNow ? "published" : "draft", } - console.log("[DEBUG] Creating draft job:", payload) - const job = await jobsApi.create(payload) - - // TODO: Create Stripe checkout session and redirect - // For now, simulate success - toast.success("Job created! Payment integration coming soon.") + await jobsApi.create(payload) + toast.success(publishNow ? "Job published successfully!" : "Job saved as draft!") router.push("/dashboard/jobs") } catch (error) { console.error("Failed to create job:", error) @@ -146,25 +96,8 @@ export default function NewJobPage() { } } - const nextStep = () => { - if (currentStep < 6 && canProceed()) { - setCurrentStep(prev => prev + 1) - } - } - - const prevStep = () => { - if (currentStep > 1) { - setCurrentStep(prev => prev - 1) - } - } - - const getCurrencySymbol = (currency: string) => { - const symbols: Record = { BRL: "R$", USD: "$", EUR: "€", GBP: "£", JPY: "¥" } - return symbols[currency] || currency - } - return ( -
+
{/* Header */}

Post a job

-

Create your job listing in a few steps

+

Fill in the details below to create your job listing

- {/* Progress Steps */} -
- {STEPS.map((step, index) => { - const Icon = step.icon - const isActive = currentStep === step.id - const isCompleted = currentStep > step.id - - return ( -
-
-
- {isCompleted ? : } -
- - {step.title} - -
- {index < STEPS.length - 1 && ( -
step.id ? "bg-primary" : "bg-muted-foreground/30" - )} - /> - )} -
- ) - })} -
- - {/* Step Content */} + {/* Job Details Section */} - {STEPS[currentStep - 1].title} - - {currentStep === 1 && "Enter the basic information about this job"} - {currentStep === 2 && "Set the compensation and employment details"} - {currentStep === 3 && "Select the company posting this job"} - {currentStep === 4 && "Preview how your job will appear"} - {currentStep === 5 && "Enter your billing information"} - {currentStep === 6 && "Complete your payment to publish"} - + + + Job Details + + Basic information about this position - - {/* Step 1: Job Details */} - {currentStep === 1 && ( - <> -
- - updateField("title", e.target.value)} - /> - {formData.title.length > 0 && formData.title.length < 5 && ( -

Title must be at least 5 characters

- )} -
-
- -