feat: complete release readiness work
- consolidate API ownership and remove dead vendor code - add Stripe billing, learning paths, and public CV hardening - add migration, recovery, security, audit, and browser gates
This commit is contained in:
@@ -27,21 +27,20 @@ import {
|
||||
} from "../components/ApplicationAssets";
|
||||
import { ApplicationInterviewPrep } from "../components/InterviewPrep";
|
||||
import {
|
||||
WORKSPACE_SECTIONS, WorkspaceOverview, WorkspaceSectionKey, applicationWorkspaceApi,
|
||||
WORKSPACE_SECTIONS, WorkspaceOverview, WorkspaceSectionKey, applicationWorkspaceApi, workspaceSection,
|
||||
} from "../applicationWorkspace";
|
||||
|
||||
// Phase 5 Milestone 1 — the dedicated Application Workspace.
|
||||
//
|
||||
// This is a surface, not a new data store: the overview is one aggregate read, and each section
|
||||
// reuses the component that already owns that domain (Attachments, Correspondence, AiWorkspacePanel).
|
||||
// Sections belonging to later milestones say so rather than pretending to work.
|
||||
// docs/architecture/application-workspace.md.
|
||||
export default function ApplicationWorkspacePage() {
|
||||
const { id } = useParams();
|
||||
const jobId = Number(id);
|
||||
const navigate = useNavigate();
|
||||
const [params, setParams] = useSearchParams();
|
||||
const section = (params.get("section") as WorkspaceSectionKey) || "overview";
|
||||
const section = workspaceSection(params.get("section"));
|
||||
|
||||
const [overview, setOverview] = useState<WorkspaceOverview | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -87,8 +86,7 @@ export default function ApplicationWorkspacePage() {
|
||||
<ListItemButton key={s.key} selected={section === s.key} onClick={() => go(s.key)} sx={{ borderRadius: 2 }}>
|
||||
<ListItemText
|
||||
primary={s.label}
|
||||
secondary={s.milestone ? `Milestone ${s.milestone}` : undefined}
|
||||
slotProps={{ primary: { fontSize: 14, fontWeight: section === s.key ? 700 : 500 }, secondary: { fontSize: 11 } }}
|
||||
slotProps={{ primary: { fontSize: 14, fontWeight: section === s.key ? 700 : 500 } }}
|
||||
/>
|
||||
</ListItemButton>
|
||||
))}
|
||||
@@ -126,14 +124,10 @@ export default function ApplicationWorkspacePage() {
|
||||
<Paper sx={{ p: 2, borderRadius: 3 }}><AiWorkspacePanel jobId={jobId} /></Paper>
|
||||
</>
|
||||
)}
|
||||
{["portfolio", "notes"].includes(section) && (
|
||||
<ComingInMilestone section={section} />
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function WorkspaceHeader({ overview }: { overview: WorkspaceOverview | null }) {
|
||||
if (!overview) return <Paper sx={{ p: 2.5, borderRadius: 3 }}><Skeleton width="45%" height={34} /><Skeleton width="30%" /></Paper>;
|
||||
return (
|
||||
@@ -265,15 +259,3 @@ function JobDetailsSection({ overview }: { overview: WorkspaceOverview | null })
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
function ComingInMilestone({ section }: { section: string }) {
|
||||
const m = WORKSPACE_SECTIONS.find((s) => s.key === section);
|
||||
return (
|
||||
<Paper sx={{ p: 3, borderRadius: 3, textAlign: "center" }}>
|
||||
<Typography sx={{ fontWeight: 700 }}>{m?.label}</Typography>
|
||||
<Typography color="text.secondary">
|
||||
Arriving in Phase 5 milestone {m?.milestone}. Existing tools for this remain available in the application dialog.
|
||||
</Typography>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user