fix(people): 本人 can edit their own birth data in 星盘档案 (S1, BUG-1081)
The owner had no edit entry anywhere once /people replaced the settings chart pane. 本人 now gets 编辑 with the same form; the save goes through PATCH /api/account via a shared lib/self-profile-save.ts that the home onboarding also uses. The dead saveProfile is removed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
adbb205440
commit
8415fdca72
@@ -7,14 +7,9 @@ import {
|
||||
type BeamAvatarPatch,
|
||||
} from "@/lib/beam-avatar";
|
||||
import {
|
||||
applyPersistedBirthTime,
|
||||
birthTimePersistenceValues,
|
||||
isBirthTimeDraftReady,
|
||||
} from "@/lib/birth-time-intake-model";
|
||||
import {
|
||||
birthTimeConsultationOptionsCopy,
|
||||
createBirthTimeConsultationConsentState,
|
||||
type BirthTimeConsultationConsentState,
|
||||
type LatestAccountRequestGuard,
|
||||
} from "@/lib/birth-time-consultation-consent";
|
||||
import { readChartBirthFingerprint } from "@/lib/chart-birth-truth";
|
||||
@@ -30,13 +25,12 @@ import {
|
||||
pinChartSnapshotIdentity,
|
||||
} from "@/lib/secondary-page-data";
|
||||
import {
|
||||
birthProfileDeclarationChanged,
|
||||
missingProfileStep,
|
||||
readProfile,
|
||||
selectedBirthPlace,
|
||||
} from "@/lib/home-profile";
|
||||
import { resolveAyanamsa } from "@/lib/ayanamsa";
|
||||
import { withSavedGender, type ProfileGender } from "@/lib/profile-gender";
|
||||
import { saveSelfProfile } from "@/lib/self-profile-save";
|
||||
import { createStartGreeting } from "@/lib/starter-greeting";
|
||||
import { clearHomeWarmSnapshot } from "@/lib/home-warm-snapshot";
|
||||
import {
|
||||
@@ -68,7 +62,6 @@ export type ProfileOnboardingParams = {
|
||||
setAccountMenuOpen: Dispatch<SetStateAction<boolean>>;
|
||||
setActiveAccountDialog: Dispatch<SetStateAction<AccountDialog | null>>;
|
||||
setBirthTimeAssessmentPhase: Dispatch<SetStateAction<BirthTimeAssessmentPhase | null>>;
|
||||
setBirthTimeConsultationConsent: Dispatch<SetStateAction<BirthTimeConsultationConsentState>>;
|
||||
setBirthTimeError: Dispatch<SetStateAction<string>>;
|
||||
setBirthTimeJourney: Dispatch<SetStateAction<JourneyClientResponse | null>>;
|
||||
setBillingPane: Dispatch<SetStateAction<OpenAccountDialogOptions>>;
|
||||
@@ -76,7 +69,6 @@ export type ProfileOnboardingParams = {
|
||||
setOnboardingJustCompleted: Dispatch<SetStateAction<boolean>>;
|
||||
setOnboardingStep: Dispatch<SetStateAction<OnboardingStep>>;
|
||||
setPresetMessageLength: Dispatch<SetStateAction<number>>;
|
||||
setRectificationError: Dispatch<SetStateAction<string>>;
|
||||
setSigningOut: Dispatch<SetStateAction<boolean>>;
|
||||
setStartGreeting: Dispatch<SetStateAction<string>>;
|
||||
signingOut: boolean;
|
||||
@@ -99,7 +91,6 @@ export function useProfileOnboarding(params: ProfileOnboardingParams) {
|
||||
setAccountMenuOpen,
|
||||
setActiveAccountDialog,
|
||||
setBirthTimeAssessmentPhase,
|
||||
setBirthTimeConsultationConsent,
|
||||
setBirthTimeError,
|
||||
setBirthTimeJourney,
|
||||
setBillingPane,
|
||||
@@ -107,7 +98,6 @@ export function useProfileOnboarding(params: ProfileOnboardingParams) {
|
||||
setOnboardingJustCompleted,
|
||||
setOnboardingStep,
|
||||
setPresetMessageLength,
|
||||
setRectificationError,
|
||||
setSigningOut,
|
||||
setStartGreeting,
|
||||
signingOut,
|
||||
@@ -227,42 +217,9 @@ export function useProfileOnboarding(params: ProfileOnboardingParams) {
|
||||
async function persistProfile(nextProfile: Profile): Promise<Profile> {
|
||||
if (!account) throw new Error("账户尚未加载完成");
|
||||
if (process.env.NODE_ENV === "development" && uiPreview.current) return nextProfile;
|
||||
const birthPlace = selectedBirthPlace(nextProfile);
|
||||
const response = await fetch("/api/account", {
|
||||
method: "PATCH",
|
||||
credentials: "same-origin",
|
||||
headers: { "content-type": "application/json" },
|
||||
body: JSON.stringify({
|
||||
name: nextProfile.name.trim() || null,
|
||||
birth_date: nextProfile.date || null,
|
||||
...birthTimePersistenceValues(nextProfile),
|
||||
country_code: nextProfile.countryCode,
|
||||
province_code: nextProfile.provinceCode || null,
|
||||
city_code: nextProfile.cityCode || null,
|
||||
district_code: nextProfile.districtCode || null,
|
||||
birth_place_label: nextProfile.birthPlaceLabel || null,
|
||||
birth_place_type: nextProfile.birthPlaceType || null,
|
||||
birth_place_provider: nextProfile.birthPlaceProvider || null,
|
||||
birth_place_provider_id: nextProfile.birthPlaceProviderId || null,
|
||||
latitude: birthPlace?.lat ?? null,
|
||||
longitude: birthPlace?.lon ?? null,
|
||||
timezone_id: nextProfile.timezoneId || null,
|
||||
timezone_offset: birthPlace?.tz ?? null,
|
||||
timezone_source: nextProfile.timezoneSource || null,
|
||||
ayanamsa: resolveAyanamsa(nextProfile),
|
||||
}),
|
||||
});
|
||||
const payload = await response.json().catch(() => null) as {
|
||||
error?: string;
|
||||
birthTime?: unknown;
|
||||
chartBirth?: { fingerprint?: unknown };
|
||||
} | null;
|
||||
if (!response.ok) {
|
||||
throw new Error(payload?.error || "账户资料暂时无法保存。");
|
||||
}
|
||||
const fingerprint = readChartBirthFingerprint(payload);
|
||||
// One write path for the owner's birth data, shared with 星盘档案 (BUG-1081).
|
||||
const { profile: savedProfile, fingerprint } = await saveSelfProfile(nextProfile);
|
||||
if (fingerprint) pinChartSnapshotIdentity({ accountId: account.user.id, fingerprint });
|
||||
const savedProfile = applyPersistedBirthTime(nextProfile, payload?.birthTime);
|
||||
setAccount((current) => current ? { ...current, profile: savedProfile } : current);
|
||||
return savedProfile;
|
||||
}
|
||||
@@ -290,32 +247,6 @@ export function useProfileOnboarding(params: ProfileOnboardingParams) {
|
||||
return assessedProfile;
|
||||
}
|
||||
|
||||
async function saveProfile(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
if (!profileDraft.name.trim() || !isBirthTimeDraftReady(profileDraft) || !selectedBirthPlace(profileDraft) || !account || profileSaving) return;
|
||||
setProfileSaving(true);
|
||||
setProfileNotice("");
|
||||
setAccountError("");
|
||||
try {
|
||||
const declarationChanged = birthProfileDeclarationChanged(profile, profileDraft);
|
||||
const savedProfile = await persistProfile(profileDraft);
|
||||
setProfile(savedProfile);
|
||||
setProfileDraft(savedProfile);
|
||||
setRectificationError("");
|
||||
if (declarationChanged) {
|
||||
setBirthTimeConsultationConsent(createBirthTimeConsultationConsentState());
|
||||
void refreshAccount();
|
||||
}
|
||||
setProfileNotice(savedProfile.birthTimeStatus === "confirmed"
|
||||
? "出生资料已保存到云端,可在同一账号的其他设备使用。"
|
||||
: `出生资料已保存。${birthTimeConsultationOptionsCopy(savedProfile)}`);
|
||||
} catch (caught) {
|
||||
setAccountError(friendlyError(caught instanceof Error ? caught.message : "出生资料保存失败"));
|
||||
} finally {
|
||||
setProfileSaving(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function saveOnboardingName() {
|
||||
const name = composerDraftSnapshot().replace(/\s+/g, " ").trim().slice(0, 80);
|
||||
if (!name || !account || profileSaving) return;
|
||||
@@ -456,7 +387,6 @@ export function useProfileOnboarding(params: ProfileOnboardingParams) {
|
||||
persistGender,
|
||||
persistProfile,
|
||||
assessSavedBirthTime,
|
||||
saveProfile,
|
||||
saveOnboardingName,
|
||||
saveOnboardingBirth,
|
||||
editDeclaredBirthTimeDetails,
|
||||
|
||||
Reference in New Issue
Block a user