feat(jobs): embed route-backed workspace
This commit is contained in:
@@ -36,11 +36,29 @@ import {
|
||||
// reuses the component that already owns that domain (Attachments, Correspondence, AiWorkspacePanel).
|
||||
// docs/architecture/application-workspace.md.
|
||||
export default function ApplicationWorkspacePage() {
|
||||
return <ApplicationWorkspace />;
|
||||
}
|
||||
|
||||
type ApplicationWorkspaceProps = {
|
||||
jobIdOverride?: number;
|
||||
sectionOverride?: WorkspaceSectionKey;
|
||||
onSectionChange?: (section: WorkspaceSectionKey) => void;
|
||||
onClose?: () => void;
|
||||
fullPageHref?: string;
|
||||
};
|
||||
|
||||
export function ApplicationWorkspace({
|
||||
jobIdOverride,
|
||||
sectionOverride,
|
||||
onSectionChange,
|
||||
onClose,
|
||||
fullPageHref,
|
||||
}: ApplicationWorkspaceProps) {
|
||||
const { id } = useParams();
|
||||
const jobId = Number(id);
|
||||
const jobId = jobIdOverride ?? Number(id);
|
||||
const navigate = useNavigate();
|
||||
const [params, setParams] = useSearchParams();
|
||||
const section = workspaceSection(params.get("section"));
|
||||
const section = sectionOverride ?? workspaceSection(params.get("section"));
|
||||
|
||||
const [overview, setOverview] = useState<WorkspaceOverview | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -57,12 +75,16 @@ export default function ApplicationWorkspacePage() {
|
||||
load();
|
||||
}, [load]);
|
||||
|
||||
const go = (next: WorkspaceSectionKey) => setParams({ section: next }, { replace: true });
|
||||
const go = (next: WorkspaceSectionKey) => {
|
||||
if (onSectionChange) onSectionChange(next);
|
||||
else setParams({ section: next }, { replace: true });
|
||||
};
|
||||
const close = onClose ?? (() => navigate("/jobs"));
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<Box sx={{ p: 3 }}>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={() => navigate("/jobs")}>Back to applications</Button>
|
||||
<Button startIcon={<ArrowBackIcon />} onClick={close}>Back to applications</Button>
|
||||
<Alert severity="error" sx={{ mt: 2 }}>{error}</Alert>
|
||||
</Box>
|
||||
);
|
||||
@@ -73,13 +95,28 @@ export default function ApplicationWorkspacePage() {
|
||||
<Paper sx={{ p: 1, borderRadius: 3, position: { md: "sticky" }, top: 12 }}>
|
||||
<Stack direction="row" alignItems="center" spacing={0.5} sx={{ px: 1, py: 0.5 }}>
|
||||
<Tooltip title="Back to applications">
|
||||
<IconButton size="small" aria-label="Back to applications" onClick={() => navigate("/jobs")}>
|
||||
<IconButton size="small" aria-label="Back to applications" onClick={close}>
|
||||
<ArrowBackIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Typography variant="caption" sx={{ fontWeight: 800, letterSpacing: ".08em", textTransform: "uppercase", color: "text.secondary" }}>
|
||||
Workspace
|
||||
</Typography>
|
||||
{fullPageHref ? (
|
||||
<Tooltip title="Open full-page workspace">
|
||||
<IconButton
|
||||
component="a"
|
||||
href={fullPageHref}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
size="small"
|
||||
aria-label="Open full-page workspace"
|
||||
sx={{ ml: "auto" }}
|
||||
>
|
||||
<OpenInNewIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</Stack>
|
||||
<List dense component="nav" aria-label="Workspace sections">
|
||||
{WORKSPACE_SECTIONS.map((s) => (
|
||||
|
||||
Reference in New Issue
Block a user