fix(rd21): retain draft revisions and qualify conflict recovery
This commit is contained in:
@@ -38,7 +38,7 @@ type AssetError = ViewResourceError & { messageKey: TranslationKey; retry?: () =
|
||||
function assetError(error: unknown, messageKey: TranslationKey, retryable = false): AssetError {
|
||||
const status = (error as { response?: { status?: number } })?.response?.status;
|
||||
const unauthorized = status === 401 || status === 403;
|
||||
return { kind: unauthorized ? "unauthorized" : "error", message: getApiErrorMessage(error, ""), messageKey, retryable: retryable && !unauthorized, status };
|
||||
return { kind: unauthorized ? "unauthorized" : "error", message: status === 409 ? "" : getApiErrorMessage(error, ""), messageKey: status === 409 ? "revisionConflict" : messageKey, retryable: retryable && !unauthorized, status };
|
||||
}
|
||||
|
||||
function useAsset<T>(load: () => Promise<T>, deps: React.DependencyList) {
|
||||
@@ -538,7 +538,7 @@ export function ApplicationCoverLetterSection({ jobId, onDirtyChange }: { jobId:
|
||||
contentRef.current?.focus();
|
||||
setBusy(true);
|
||||
try {
|
||||
const next = await applicationAssetsApi.saveCoverLetter(jobId, value, source, aiAction);
|
||||
const next = await applicationAssetsApi.saveCoverLetter(jobId, value, data.revision, source, aiAction);
|
||||
if (!isCurrent()) return;
|
||||
setData(next);
|
||||
setDraft(null);
|
||||
@@ -568,7 +568,7 @@ export function ApplicationCoverLetterSection({ jobId, onDirtyChange }: { jobId:
|
||||
if (!isCurrent()) return;
|
||||
contentRef.current?.focus();
|
||||
setBusy(true);
|
||||
const next = await applicationAssetsApi.restoreCoverLetter(jobId, version);
|
||||
const next = await applicationAssetsApi.restoreCoverLetter(jobId, version, data.revision);
|
||||
if (!isCurrent()) return;
|
||||
setData(next);
|
||||
setDraft(null);
|
||||
@@ -832,18 +832,21 @@ export function ApplicationPackageDraftsSection({
|
||||
jobId,
|
||||
initialApplicationAnswer,
|
||||
initialRecruiterMessage,
|
||||
initialRevision,
|
||||
onSaved,
|
||||
onDirtyChange,
|
||||
}: {
|
||||
jobId: number;
|
||||
initialApplicationAnswer: string;
|
||||
initialRecruiterMessage: string;
|
||||
initialRevision: number;
|
||||
onSaved?: () => void;
|
||||
onDirtyChange?: (dirty: boolean) => void;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const initial = { applicationAnswer: initialApplicationAnswer, recruiterMessage: initialRecruiterMessage };
|
||||
const [saved, setSaved] = useState<PackageDrafts>(initial);
|
||||
const [revision, setRevision] = useState(initialRevision);
|
||||
const [draft, setDraft] = useState<PackageDrafts | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState<AssetError | null>(null);
|
||||
@@ -853,10 +856,10 @@ export function ApplicationPackageDraftsSection({
|
||||
useEffect(() => { active.current = true; return () => { active.current = false; }; }, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (draft === null) setSaved(initial);
|
||||
if (draft === null) { setSaved(initial); setRevision(initialRevision); }
|
||||
// `draft` is deliberately excluded: a parent refresh must never overwrite in-progress edits.
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [jobId, initialApplicationAnswer, initialRecruiterMessage]);
|
||||
}, [jobId, initialApplicationAnswer, initialRecruiterMessage, initialRevision]);
|
||||
|
||||
const value = draft ?? saved;
|
||||
const dirty = draft !== null && (
|
||||
@@ -876,8 +879,9 @@ export function ApplicationPackageDraftsSection({
|
||||
contentRef.current?.focus();
|
||||
setBusy(true);
|
||||
try {
|
||||
await applicationAssetsApi.saveApplicationDrafts(jobId, value.applicationAnswer, value.recruiterMessage);
|
||||
const nextRevision = await applicationAssetsApi.saveApplicationDrafts(jobId, value.applicationAnswer, value.recruiterMessage, revision);
|
||||
if (!active.current) return;
|
||||
setRevision(nextRevision);
|
||||
setSaved(value);
|
||||
setDraft(null);
|
||||
setError(null);
|
||||
|
||||
Reference in New Issue
Block a user