feat: integrate birth time journey into onboarding

This commit is contained in:
Jesse_Chen
2026-07-17 16:19:11 +08:00
parent 73fe62e9c3
commit 49054172ac
19 changed files with 1136 additions and 104 deletions
@@ -8,11 +8,13 @@ import {
import {
createBirthTimeJourneyService,
RectificationCaseNotFoundError,
RectificationQuestionsUnavailableError,
} from "@/lib/birth-time-journey-service";
import {
createSupabaseBirthTimeJourneyStore,
BirthTimeJourneyStoreError,
} from "@/lib/birth-time-journey-store";
import { createAdminSupabaseClient } from "@/lib/supabase/admin";
import { isSupabaseConfigurationError } from "@/lib/supabase/config";
import { createServerSupabaseClient } from "@/lib/supabase/server";
@@ -21,6 +23,7 @@ export const maxDuration = 60;
const eventSchema = z.discriminatedUnion("type", [
z.object({ type: z.literal("assess") }).strict(),
z.object({ type: z.literal("resume"), caseId: z.string().uuid() }).strict(),
z.object({
type: z.literal("answer_question"),
caseId: z.string().uuid(),
@@ -40,8 +43,10 @@ async function requestPayload(request: Request): Promise<unknown> {
export async function POST(request: Request) {
let supabase: Awaited<ReturnType<typeof createServerSupabaseClient>>;
let journeyStoreClient: ReturnType<typeof createAdminSupabaseClient>;
try {
supabase = await createServerSupabaseClient();
journeyStoreClient = createAdminSupabaseClient();
} catch (error) {
if (isSupabaseConfigurationError(error)) {
return NextResponse.json(
@@ -69,7 +74,7 @@ export async function POST(request: Request) {
}
const service = createBirthTimeJourneyService({
store: createSupabaseBirthTimeJourneyStore(supabase),
store: createSupabaseBirthTimeJourneyStore(journeyStoreClient),
engine: createJyotishBirthTimeJourneyEngine(),
});
@@ -98,6 +103,8 @@ export async function POST(request: Request) {
parsed.data.questionId,
parsed.data.answer,
));
case "resume":
return NextResponse.json(await service.resume(user.id, parsed.data.caseId));
default: {
const exhaustive: never = parsed.data;
return exhaustive;
@@ -116,6 +123,12 @@ export async function POST(request: Request) {
{ status: 404 },
);
}
if (error instanceof RectificationQuestionsUnavailableError) {
return NextResponse.json(
{ error: "校正问题暂不可用", message: "当前资料已安全保留,请稍后重新评估。" },
{ status: 409 },
);
}
if (error instanceof BirthTimeJourneyStoreError || error instanceof BirthTimeJourneyEngineError) {
return NextResponse.json(
{ error: "生时评估暂时不可用", message: "已保留当前资料,请稍后重试。" },
+3 -2
View File
@@ -44,7 +44,8 @@ function hasCompleteBirthProfile(profile: Record<string, unknown>) {
return Boolean(
profile.name
&& profile.birth_date
&& profile.birth_time
&& (profile.active_birth_time || profile.birth_time)
&& (profile.birth_time_status === "confirmed" || (!profile.birth_time_status && profile.birth_time))
&& profile.country_code
&& profile.province_code
&& profile.city_code,
@@ -74,7 +75,7 @@ export async function POST() {
const { data: profile, error: profileError } = await admin
.from("profiles")
.select("name,birth_date,birth_time,country_code,province_code,city_code,onboarding_payload,onboarding_version,onboarding_generated_at")
.select("name,birth_date,birth_time,active_birth_time,birth_time_status,country_code,province_code,city_code,onboarding_payload,onboarding_version,onboarding_generated_at")
.eq("id", user.id)
.maybeSingle();