fix(ui): preserve application drafts and recovery states
This commit is contained in:
@@ -82,7 +82,9 @@ export function ApplicationWorkspace({
|
||||
const secondaryId = useId();
|
||||
const panelRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const [overview, setOverview] = useState<WorkspaceOverview | null>(null);
|
||||
const [loadedOverview, setOverview] = useState<WorkspaceOverview | null>(null);
|
||||
const overview = loadedOverview?.id === jobId ? loadedOverview : null;
|
||||
const overviewRequest = useRef(0);
|
||||
const [error, setError] = useState<ViewResourceError | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [editOpen, setEditOpen] = useState(false);
|
||||
@@ -123,6 +125,7 @@ export function ApplicationWorkspace({
|
||||
}, [blocker, confirm, t]);
|
||||
|
||||
const load = useCallback(async () => {
|
||||
const request = ++overviewRequest.current;
|
||||
if (!Number.isInteger(jobId) || jobId <= 0) {
|
||||
setOverview(null);
|
||||
setError({ kind: "error", message: t("workspaceInvalidLink"), retryable: false });
|
||||
@@ -132,17 +135,20 @@ export function ApplicationWorkspace({
|
||||
try {
|
||||
setError(null);
|
||||
setLoading(true);
|
||||
setOverview(await applicationWorkspaceApi.overview(jobId));
|
||||
const next = await applicationWorkspaceApi.overview(jobId);
|
||||
if (request === overviewRequest.current) setOverview(next);
|
||||
} catch (err) {
|
||||
if (request !== overviewRequest.current) return;
|
||||
const status = (err as { response?: { status?: number } })?.response?.status;
|
||||
setError({ kind: "error", message: getApiErrorMessage(err, t("workspaceLoadFailed")), retryable: !status || status >= 500, status });
|
||||
} finally {
|
||||
setLoading(false);
|
||||
if (request === overviewRequest.current) setLoading(false);
|
||||
}
|
||||
}, [jobId, t]);
|
||||
|
||||
useEffect(() => {
|
||||
load();
|
||||
void load();
|
||||
return () => { overviewRequest.current += 1; };
|
||||
}, [load]);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -253,16 +259,17 @@ export function ApplicationWorkspace({
|
||||
{subsections.map((sub) => <Tab key={sub.key} value={sub.key} id={`${secondaryId}-${sub.key}`} aria-controls={`${secondaryId}-panel`} label={sub.label} />)}
|
||||
</Tabs>
|
||||
<Box role="tabpanel" id={`${secondaryId}-panel`} aria-labelledby={`${secondaryId}-${subsection}`} tabIndex={0} sx={{ display: "grid", gap: 2, minWidth: 0 }}>
|
||||
{section === "application" && subsection === "cv" && jobId > 0 && <ApplicationCvSection jobId={jobId} includePackages={false} />}
|
||||
{section === "application" && subsection === "letter" && jobId > 0 && <ApplicationCoverLetterSection jobId={jobId} onDirtyChange={setCoverLetterDirty} />}
|
||||
{section === "application" && subsection === "answers" && jobId > 0 && <ApplicationPackageDraftsSection
|
||||
{section === "application" && subsection === "cv" && jobId > 0 && <ApplicationCvSection key={jobId} jobId={jobId} includePackages={false} />}
|
||||
{section === "application" && subsection === "letter" && jobId > 0 && <ApplicationCoverLetterSection key={jobId} jobId={jobId} onDirtyChange={setCoverLetterDirty} />}
|
||||
{section === "application" && subsection === "answers" && overview && jobId > 0 && <ApplicationPackageDraftsSection
|
||||
key={jobId}
|
||||
jobId={jobId}
|
||||
initialApplicationAnswer={overview?.applicationAnswerDraft ?? ""}
|
||||
initialRecruiterMessage={overview?.recruiterMessageDraft ?? ""}
|
||||
onSaved={load}
|
||||
onDirtyChange={setPackageDraftsDirty}
|
||||
/>}
|
||||
{section === "application" && subsection === "submission" && jobId > 0 && <SubmittedPackagesSection jobId={jobId} />}
|
||||
{section === "application" && subsection === "submission" && jobId > 0 && <SubmittedPackagesSection key={jobId} jobId={jobId} />}
|
||||
{section === "timeline" && subsection === "activity" && jobId > 0 && <ApplicationTimeline jobId={jobId} />}
|
||||
{section === "timeline" && subsection === "correspondence" && jobId > 0 && <PageSection surface title={t("workspaceCommunication")} level="h3"><Correspondence jobId={jobId} jobContext={{ companyName: overview?.company, jobTitle: overview?.jobTitle }} /></PageSection>}
|
||||
</Box>
|
||||
@@ -272,7 +279,7 @@ export function ApplicationWorkspace({
|
||||
<Button onClick={() => go("application", "cv")}>{t("workspaceCv")}</Button>
|
||||
<Button onClick={() => go("application", "letter")}>{t("workspaceCoverLetter")}</Button>
|
||||
</>}><Attachments jobId={jobId} /></PageSection>
|
||||
<SubmittedPackagesSection jobId={jobId} allowCapture={false} />
|
||||
<SubmittedPackagesSection key={jobId} jobId={jobId} allowCapture={false} />
|
||||
</>}
|
||||
{section === "tasks" && jobId > 0 && <>
|
||||
<PageSection surface title={t("workspaceNotes")} actions={<Button startIcon={<EditOutlinedIcon />} onClick={() => setEditOpen(true)}>{t("workspaceEdit")}</Button>}>
|
||||
|
||||
Reference in New Issue
Block a user