feat(ai): AI Workspace panel on every job application
Phase 5 frontend. A new "AI Workspace" tab in the job details dialog hosts the five suggestion modules (Job Analysis, Career Match, Cover Letter with tone, Interview Prep, Application Review) with a generate flow, a dependency-free markdown renderer for results, and a history sidebar (reuse / compare / copy / delete). Everything is suggestion-only — copy to keep; nothing auto-applies. - aiWorkspace.ts (types + API), components/AiWorkspacePanel.tsx, components/Markdown.tsx (no HTML injection surface — renders React nodes) - mounted as the last tab in JobDetailsDialog (index-safe, no reindexing) - 3 tests (generate flow, cover-letter mode, markdown); tsc + build clean Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import { emptyTailoredCvDraft, joinLines, normalizeTailoredCvDraft, splitLines }
|
||||
|
||||
import Correspondence from "./Correspondence";
|
||||
import Attachments from "./Attachments";
|
||||
import AiWorkspacePanel from "./AiWorkspacePanel";
|
||||
import JobFlowBar from "./JobFlowBar";
|
||||
import GradientButton from "./GradientButton";
|
||||
import { useI18n } from "../i18n/I18nProvider";
|
||||
@@ -697,6 +698,7 @@ export default function JobDetailsDialog({ open, jobId, onClose, initialTab = 0,
|
||||
<Tab label={t("jobDetailsTabInterviewPrep")} />
|
||||
<Tab label={t("jobTableReadiness")} />
|
||||
{isAdmin ? <Tab label={t("jobDetailsTabHistory")} /> : null}
|
||||
<Tab label="AI Workspace" />
|
||||
</Tabs>
|
||||
|
||||
{attachmentPicker}
|
||||
@@ -1270,6 +1272,8 @@ export default function JobDetailsDialog({ open, jobId, onClose, initialTab = 0,
|
||||
{history.length === 0 ? <Typography sx={{ color: "text.secondary" }}>{t("jobDetailsNoHistory")}</Typography> : history.map((entry) => <PaperRow key={entry.id} type={entry.type} oldValue={entry.oldValue} newValue={entry.newValue} at={entry.at} note={entry.note} />)}
|
||||
</Box>
|
||||
)}
|
||||
{/* AI Workspace is the last tab: index depends on whether the admin History tab is present. */}
|
||||
{tab === (isAdmin ? 10 : 9) && jobId && <AiWorkspacePanel jobId={jobId} />}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user