'use client'; import { useState } from 'react'; import { Plus, Trash2, Save } from 'lucide-react'; import { Badge, Button } from '@nextcraft/ui'; import type { Job, Seniority } from '@nextcraft/types'; import { formatSalaryK, relativeTime, seniorityLabel } from '../../lib/format'; /* -------------------------------------------------------------------------- */ /* Mock posting list (status + applicant count derived from the Job) */ /* -------------------------------------------------------------------------- */ type PostingStatus = 'active' | 'draft' | 'expired'; interface PostingRow { job: Job; status: PostingStatus; applicants: number; } interface ApplicantRow { name: string; appliedAt: string; stage: 'Screening' | 'Interview' | 'Offer'; matchScore: number; } /* Deterministically derive a posting status per job id. */ function deriveStatus(job: Job, idx: number): PostingStatus { if (idx < 8) return 'active'; if (idx < 11) return 'draft'; return 'expired'; } function deriveApplicants(job: Job, idx: number): number { return 4 + ((job.matchScore + idx * 7) % 18); } function deriveApplicantList(job: Job): ApplicantRow[] { const names = [ 'Maya Okonkwo', 'Devon Park', 'Priya Iyer', 'Tomás Vega', 'Liam Chen', 'Yuki Tanaka', 'Sofia Marchetti', ]; const stages: ApplicantRow['stage'][] = ['Screening', 'Interview', 'Offer']; const count = 5 + (job.matchScore % 2); const rows: ApplicantRow[] = []; for (let i = 0; i < count; i++) { const stage = stages[i % stages.length]; rows.push({ name: names[(job.matchScore + i) % names.length], appliedAt: new Date(Date.UTC(2026, 7, 28 - i * 2)).toISOString(), stage, matchScore: 78 + ((job.matchScore + i * 3) % 18), }); } return rows; } /* -------------------------------------------------------------------------- */ /* Status badge */ /* -------------------------------------------------------------------------- */ function StatusBadge({ status }: { status: PostingStatus }) { if (status === 'active') return Active; if (status === 'draft') return Draft; return Expired; } function StageBadge({ stage }: { stage: ApplicantRow['stage'] }) { if (stage === 'Offer') return Offer; if (stage === 'Interview') return Interview; return Screening; } /* -------------------------------------------------------------------------- */ /* Component */ /* -------------------------------------------------------------------------- */ export interface PostingManagerProps { jobs: Job[]; } export function PostingManager({ jobs }: PostingManagerProps) { const postings: PostingRow[] = jobs.map((job, idx) => ({ job, status: deriveStatus(job, idx), applicants: deriveApplicants(job, idx), })); const [selectedId, setSelectedId] = useState(postings[0]?.job.id ?? ''); const selected = postings.find((p) => p.job.id === selectedId) ?? null; return (
{/* Left panel — posting list */}

Postings

{postings.map((p) => { const active = p.job.id === selectedId; return ( ); })}
{/* Right panel — detail */}
{selected ? ( ) : (
Select a posting to view details
)}
); } function PostingDetail({ posting }: { posting: PostingRow }) { const { job, applicants } = posting; const applicantList = deriveApplicantList(job); const seniorityOptions: Seniority[] = ['entry', 'mid', 'senior', 'staff', 'principal']; const inputClass = 'h-10 w-full rounded-md border border-slate-300 bg-white px-3 text-sm text-slate-900 focus:border-primary-500 focus:ring-2 focus:ring-primary-500/30 focus:outline-none dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100'; return (
{/* Posting form */}

Edit Posting