From aa3567d8a8ca2cedd5800273d7ca76f3fb31a5f6 Mon Sep 17 00:00:00 2001 From: cesnimda Date: Wed, 15 Jul 2026 10:39:13 +0200 Subject: [PATCH] feat(applications): guide job creation in steps --- job-tracker-ui/src/components/AddJobModal.tsx | 93 ++++++++++++++----- 1 file changed, 68 insertions(+), 25 deletions(-) diff --git a/job-tracker-ui/src/components/AddJobModal.tsx b/job-tracker-ui/src/components/AddJobModal.tsx index 977530a..d37e9ec 100644 --- a/job-tracker-ui/src/components/AddJobModal.tsx +++ b/job-tracker-ui/src/components/AddJobModal.tsx @@ -18,6 +18,9 @@ import { ListItem, ListItemText, MenuItem, + Step, + StepLabel, + Stepper, TextField, Typography, } from "@mui/material"; @@ -103,6 +106,7 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr const { t, language } = useI18n(); const [saving, setSaving] = useState(false); + const [activeStep, setActiveStep] = useState(0); const [importing, setImporting] = useState(false); const [duplicateCheck, setDuplicateCheck] = useState(null); @@ -154,6 +158,7 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr }, [open, initialUrl]); const resetForm = () => { + setActiveStep(0); setCompany(null); setCompanyInput(""); setNewCompanyLocation(""); @@ -163,6 +168,10 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr setStatus("Applied"); setLocation(""); setSalary(""); + setSalaryMin(""); + setSalaryMax(""); + setSalaryCurrency(""); + setSalaryPeriod(""); setJobUrl(""); setDeadline(""); setDescription(""); @@ -272,6 +281,7 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr setDeadline(r.deadline ? r.deadline.slice(0, 10) : ""); toast(t("addJobModalImported"), "success"); + setActiveStep(1); } catch (e: any) { toast(e?.message || t("addJobModalImportFailed"), "error"); } finally { @@ -355,6 +365,8 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr }; const canSave = normalizedCompanyName.length > 0 && jobTitle.trim().length > 0; + const steps = ["Add job", "Review details", "CV", "Cover letter", "Portfolio", "Additional files"]; + const optionalStep = activeStep >= 2 && activeStep <= 5; const setFilesForBucket = (bucket: AttachmentBucketKey, files: FileList | null) => { setAttachments((prev) => ({ @@ -400,6 +412,30 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr + + {steps.map((label) => {label})} + + + Step {activeStep + 1} of {steps.length}: {steps[activeStep]} + + + {activeStep === 0 ? + + Start with the job advert + + Paste a job URL and Jobbjakt will try to fill the details. You can continue with manual entry whenever extraction is unavailable. + + + setJobUrl(e.target.value)} fullWidth sx={FIELD_SX} /> + + + + + : null} + + {activeStep === 1 ? <> {t("addJobModalCompanySection")} @@ -466,11 +502,6 @@ export default function AddJobModal({ open, onClose, onCreated, initialUrl }: Pr setJobUrl(e.target.value)} sx={{ ...FIELD_SX, gridColumn: "1 / -1" }} /> - - - setNotes(e.target.value)} helperText={`${notes.length} characters`} sx={{ gridColumn: "1 / -1" }} /> - - {t("addJobModalDocuments")} - - {uploadField("resume", t("addJobModalResume"), t("addJobModalResumeHelp"))} - {uploadField("coverLetter", t("addJobModalCoverLetter"), t("addJobModalCoverLetterHelp"))} - {uploadField("portfolio", t("addJobModalPortfolio"), t("addJobModalPortfolioHelp"))} - {uploadField("other", t("addJobModalOtherFiles"), t("addJobModalOtherFilesHelp"))} - - - - - - - + : null} + + {activeStep >= 2 ? + + {steps[activeStep]} + + {activeStep === 2 ? "Use your master CV later in Career Workspace, or attach the version prepared for this application now." : null} + {activeStep === 3 ? "Attach a drafted cover letter now, or add/generate one from the application workspace later." : null} + {activeStep === 4 ? "Add supporting portfolio material now, or select lightweight profile-linked projects later." : null} + {activeStep === 5 ? "Certificates, references, and other supporting documents are optional." : null} + + + {activeStep === 2 ? uploadField("resume", t("addJobModalResume"), t("addJobModalResumeHelp")) : null} + {activeStep === 3 ? uploadField("coverLetter", t("addJobModalCoverLetter"), t("addJobModalCoverLetterHelp")) : null} + {activeStep === 4 ? uploadField("portfolio", t("addJobModalPortfolio"), t("addJobModalPortfolioHelp")) : null} + {activeStep === 5 ? uploadField("other", t("addJobModalOtherFiles"), t("addJobModalOtherFilesHelp")) : null} + + + + + : null} - - + {activeStep > 0 ? : null} + {activeStep < steps.length - 1 ? : <> + + + }