fix: keep unconfirmed candidates in rectification
This commit is contained in:
@@ -747,7 +747,6 @@ export default function Home() {
|
||||
preview: process.env.NODE_ENV === "development" && uiPreview.current,
|
||||
onJourney: setBirthTimeJourney,
|
||||
onReady: completeGuidedBirthTime,
|
||||
onCandidateComplete: completeCandidateBirthTime,
|
||||
onEditBirthTimeDetails: editDeclaredBirthTimeDetails,
|
||||
});
|
||||
|
||||
@@ -1019,7 +1018,7 @@ export default function Home() {
|
||||
setSessions(nextSessions);
|
||||
setActiveSessionId(nextSessions[0].id);
|
||||
if ((nextProfile.birthTimeStatus === "rectifying"
|
||||
|| (nextProfile.birthTimeStatus === "candidate" && !nextProfile.time))
|
||||
|| nextProfile.birthTimeStatus === "candidate")
|
||||
&& nextProfile.rectificationCaseId) {
|
||||
try {
|
||||
const resumed = await resumeBirthTimeJourney(nextProfile.rectificationCaseId);
|
||||
@@ -1657,21 +1656,6 @@ export default function Home() {
|
||||
setOnboardingJustCompleted(true);
|
||||
}
|
||||
|
||||
function completeCandidateBirthTime(result: JourneyClientResponse, time: string) {
|
||||
const candidateProfile: Profile = {
|
||||
...profileDraft,
|
||||
time,
|
||||
birthTimeStatus: "candidate",
|
||||
rectificationCaseId: result.caseId,
|
||||
};
|
||||
setProfile(candidateProfile);
|
||||
setProfileDraft(candidateProfile);
|
||||
setBirthTimeJourney(null);
|
||||
setPresetMessageLength(0);
|
||||
setStartGreeting(createStartGreeting(candidateProfile.name));
|
||||
setOnboardingJustCompleted(true);
|
||||
}
|
||||
|
||||
async function retryBirthTimeAssessment() {
|
||||
if (!account || profileSaving) return;
|
||||
setProfileSaving(true);
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
} from "@/lib/birth-time-journey-client";
|
||||
import type { JourneyClientResponse } from "@/lib/birth-time-journey-client";
|
||||
import {
|
||||
completeGuidedBirthTimeCandidate,
|
||||
confirmGuidedBirthTimeCandidate,
|
||||
reviseBirthTimeEvidenceDraft,
|
||||
saveGuidedBirthTimeCandidate,
|
||||
@@ -37,7 +36,6 @@ type GuidedJourneyInput = {
|
||||
readonly preview: boolean;
|
||||
readonly onJourney: (journey: JourneyClientResponse) => void;
|
||||
readonly onReady: (journey: JourneyClientResponse) => void;
|
||||
readonly onCandidateComplete: (journey: JourneyClientResponse, time: string) => void;
|
||||
readonly onEditBirthTimeDetails: () => void;
|
||||
};
|
||||
|
||||
@@ -53,7 +51,6 @@ export type BirthTimeGuidedController = {
|
||||
readonly resume: () => void;
|
||||
readonly editBirthTimeDetails: () => void;
|
||||
readonly acknowledgeReady: () => void;
|
||||
readonly completeCandidate: (time: string) => void;
|
||||
readonly retryScoring: () => void;
|
||||
readonly saveCandidate: (resultId: string) => void;
|
||||
readonly confirmCandidate: (resultId: string, time: string) => void;
|
||||
@@ -70,7 +67,7 @@ function previewAction(turn: JourneyClientResponse, command: DynamicPreviewComma
|
||||
}
|
||||
|
||||
export function useBirthTimeGuidedJourney(input: GuidedJourneyInput): BirthTimeGuidedController {
|
||||
const { journey, onJourney, onReady, onCandidateComplete, onEditBirthTimeDetails, preview } = input;
|
||||
const { journey, onJourney, onReady, onEditBirthTimeDetails, preview } = input;
|
||||
const latest = useRef(journey);
|
||||
const busy = useRef(false);
|
||||
const [actionRegistry] = useState(() => createStableActionIdentityRegistry());
|
||||
@@ -185,26 +182,6 @@ export function useBirthTimeGuidedJourney(input: GuidedJourneyInput): BirthTimeG
|
||||
const acknowledgeReady = () => {
|
||||
if (journey?.nextAction.kind === "ready") onReady(journey);
|
||||
};
|
||||
const completeCandidate = (time: string) => {
|
||||
const turn = journey;
|
||||
const resultId = turn?.candidateResult?.resultId;
|
||||
const winner = turn?.candidateResult?.winningSegment;
|
||||
if (!turn || !resultId || winner?.representativeTime !== time) return;
|
||||
const release = claimMutation(busy);
|
||||
if (release === null) return;
|
||||
setPending(true);
|
||||
setError("");
|
||||
const completion = preview
|
||||
? Promise.resolve()
|
||||
: completeGuidedBirthTimeCandidate({ caseId: turn.caseId, resultId, time });
|
||||
void completion
|
||||
.then(() => onCandidateComplete(turn, time))
|
||||
.catch((caught) => setError(birthTimeUserError(caught)))
|
||||
.finally(() => {
|
||||
release();
|
||||
setPending(false);
|
||||
});
|
||||
};
|
||||
const retryScoring = () => {
|
||||
const turn = journey;
|
||||
if (preview && turn?.journeyProtocol === "dynamic-choice-v2"
|
||||
@@ -277,7 +254,6 @@ export function useBirthTimeGuidedJourney(input: GuidedJourneyInput): BirthTimeG
|
||||
resume,
|
||||
editBirthTimeDetails: onEditBirthTimeDetails,
|
||||
acknowledgeReady,
|
||||
completeCandidate,
|
||||
retryScoring,
|
||||
saveCandidate,
|
||||
confirmCandidate,
|
||||
|
||||
@@ -16,7 +16,6 @@ type DraftRevision = GuidedMutation & {
|
||||
};
|
||||
type CandidateSave = GuidedMutation & { readonly resultId: string };
|
||||
type CandidateConfirmation = CandidateSave & { readonly time: string };
|
||||
type CandidateCompletion = Pick<CandidateSave, "caseId" | "resultId"> & { readonly time: string };
|
||||
|
||||
const errorPayloadSchema = z.object({
|
||||
message: z.string().optional(),
|
||||
@@ -69,22 +68,3 @@ export function confirmGuidedBirthTimeCandidate(
|
||||
) {
|
||||
return send({ type: "confirm_guided_candidate", ...input });
|
||||
}
|
||||
|
||||
export async function completeGuidedBirthTimeCandidate(
|
||||
input: CandidateCompletion,
|
||||
) {
|
||||
const { response, payload } = await postJson({
|
||||
url: "/api/birth-time-candidate-completion",
|
||||
body: JSON.stringify(input),
|
||||
retryLostResponse: false,
|
||||
});
|
||||
if (!response.ok) {
|
||||
const parsed = errorPayloadSchema.safeParse(payload);
|
||||
throw new GuidedBirthTimeRequestError(
|
||||
response.status,
|
||||
parsed.success
|
||||
? parsed.data.message ?? parsed.data.error ?? "候选时间暂时无法保存"
|
||||
: "候选时间暂时无法保存",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ export function isBirthTimeDraftReady(draft: BirthTimeDraft) {
|
||||
|
||||
export function isBirthTimeReadyForConsultation(draft: BirthTimeDraft) {
|
||||
return Boolean(draft.time)
|
||||
&& (draft.birthTimeStatus === "candidate" || draft.birthTimeStatus === "confirmed");
|
||||
&& draft.birthTimeStatus === "confirmed";
|
||||
}
|
||||
|
||||
export function birthTimePersistenceValues(draft: BirthTimeDraft) {
|
||||
|
||||
@@ -118,6 +118,8 @@ test("ready completion is explicit and terminal low has no finish mutation", ()
|
||||
assert.doesNotMatch(hookSource, /turn\.nextAction\.kind === "ready"\) onReady/);
|
||||
assert.match(candidateSource, /acknowledgeReady/);
|
||||
assert.doesNotMatch(candidateSource, /controller\.finish/);
|
||||
assert.doesNotMatch(hookSource, /completeGuidedBirthTimeCandidate/);
|
||||
assert.doesNotMatch(hookSource, /completeCandidate:/);
|
||||
});
|
||||
|
||||
test("unconfirmed terminal candidates preserve the range without offering direct adoption", () => {
|
||||
|
||||
@@ -47,16 +47,17 @@ test("birth time intake requires only the fields selected by the source", () =>
|
||||
assert.equal(isBirthTimeDraftReady({ ...emptyDraft, birthTimeSource: "unknown" }), true);
|
||||
});
|
||||
|
||||
test("a persisted candidate working time can leave rectification onboarding", () => {
|
||||
test("an unconfirmed candidate working time remains in rectification onboarding", () => {
|
||||
const candidate = {
|
||||
...emptyDraft,
|
||||
time: "04:53",
|
||||
birthTimeStatus: "candidate",
|
||||
} satisfies BirthTimeDraft;
|
||||
|
||||
assert.equal(isBirthTimeReadyForConsultation(candidate), true);
|
||||
assert.equal(isBirthTimeReadyForConsultation(candidate), false);
|
||||
assert.equal(isBirthTimeReadyForConsultation({ ...candidate, time: "" }), false);
|
||||
assert.equal(isBirthTimeReadyForConsultation({ ...candidate, birthTimeStatus: "rectifying" }), false);
|
||||
assert.equal(isBirthTimeReadyForConsultation({ ...candidate, birthTimeStatus: "confirmed" }), true);
|
||||
});
|
||||
|
||||
test("a persisted candidate working time takes precedence over the reported range", () => {
|
||||
|
||||
Reference in New Issue
Block a user