fix(web): persist uncertain birth time as a start/end clock window

Users pick a clock range instead of a coarse period plus notes, so
rectification and window consult scan that range instead of a leftover afternoon bucket.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-22 20:48:01 +08:00
co-authored by Cursor
parent f3197ce3f6
commit 8ed6118b9a
31 changed files with 760 additions and 144 deletions
+35 -33
View File
@@ -6,7 +6,6 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
import { birthTimeConsultationOptionsCopy } from "@/lib/birth-time-consultation-consent";
import {
birthTimeDisplayState,
birthTimePeriodOptions,
birthTimeSourceDefaults,
birthTimeSourceOptions,
type BirthTimeDraft,
@@ -30,9 +29,18 @@ function splitBirthTime(value: string) {
type BirthClockSelectProps = {
readonly value: string;
readonly onChange: (value: string) => void;
readonly ariaLabel?: string;
readonly hourLabel?: string;
readonly minuteLabel?: string;
};
function BirthClockSelect({ value, onChange }: BirthClockSelectProps) {
function BirthClockSelect({
value,
onChange,
ariaLabel = "选择出生时间",
hourLabel = "出生时间小时",
minuteLabel = "出生时间分钟",
}: BirthClockSelectProps) {
const currentTime = value || "";
const [timeParts, setTimeParts] = useState(() => splitBirthTime(currentTime));
@@ -44,9 +52,9 @@ function BirthClockSelect({ value, onChange }: BirthClockSelectProps) {
};
return (
<div className="birth-time-clock-selects" aria-label="选择出生时间">
<div className="birth-time-clock-selects" aria-label={ariaLabel}>
<Select required value={timeParts.hour || null} onValueChange={(nextValue) => patchTime("hour", nextValue)}>
<SelectTrigger aria-label="出生时间小时">
<SelectTrigger aria-label={hourLabel}>
<SelectValue placeholder="时" />
</SelectTrigger>
<SelectContent className="birth-time-clock-menu" style={{ width: 108, minWidth: 108 }}>
@@ -55,7 +63,7 @@ function BirthClockSelect({ value, onChange }: BirthClockSelectProps) {
</Select>
<span className="birth-time-clock-separator" aria-hidden="true">:</span>
<Select required value={timeParts.minute || null} onValueChange={(nextValue) => patchTime("minute", nextValue)}>
<SelectTrigger aria-label="出生时间分钟">
<SelectTrigger aria-label={minuteLabel}>
<SelectValue placeholder="分" />
</SelectTrigger>
<SelectContent className="birth-time-clock-menu" style={{ width: 108, minWidth: 108 }}>
@@ -168,36 +176,28 @@ export function BirthTimeIntakeFields({ value, onPatch }: BirthTimeIntakeProps)
)}
{source === "period_only" && (
<div className="birth-time-detail-grid birth-time-period-details onboarding-card-reveal">
<div className="birth-time-detail-grid birth-time-window-details onboarding-card-reveal">
<p className="birth-time-window-intro"> 23:00 03:59</p>
<label>
<span></span>
<Select
required
value={value.birthTimePeriod || null}
onValueChange={(nextValue) => {
if (typeof nextValue === "string") onPatch({ birthTimePeriod: nextValue });
}}
>
<SelectTrigger aria-label="最接近的时间范围">
<SelectValue placeholder="请选择大致时段">
{(selectedValue) => birthTimePeriodOptions.find((option) => option.value === selectedValue)?.label ?? "请选择大致时段"}
</SelectValue>
</SelectTrigger>
<SelectContent>
{birthTimePeriodOptions.map((option) => (
<SelectItem key={option.value} value={option.value}>{option.label}</SelectItem>
))}
</SelectContent>
</Select>
<span></span>
<BirthClockSelect
key={`start-${value.declaredWindowStart}`}
value={value.declaredWindowStart}
ariaLabel="选择开始时间"
hourLabel="开始小时"
minuteLabel="开始分钟"
onChange={(declaredWindowStart) => onPatch({ declaredWindowStart })}
/>
</label>
<label>
<span></span>
<textarea
maxLength={240}
placeholder="例如:天刚亮、午饭前后、家人记得大约 6—8 点"
rows={2}
value={value.birthTimeClue}
onChange={(event) => onPatch({ birthTimeClue: event.target.value })}
<span></span>
<BirthClockSelect
key={`end-${value.declaredWindowEnd}`}
value={value.declaredWindowEnd}
ariaLabel="选择结束时间"
hourLabel="结束小时"
minuteLabel="结束分钟"
onChange={(declaredWindowEnd) => onPatch({ declaredWindowEnd })}
/>
</label>
<button
@@ -207,6 +207,8 @@ export function BirthTimeIntakeFields({ value, onPatch }: BirthTimeIntakeProps)
birthTimeSource: "unknown",
reportedTime: "",
birthTimePeriod: "",
declaredWindowStart: "",
declaredWindowEnd: "",
birthTimeClue: "",
uncertaintyBeforeMinutes: null,
uncertaintyAfterMinutes: null,
@@ -224,7 +226,7 @@ export function BirthTimeIntakeFields({ value, onPatch }: BirthTimeIntakeProps)
className="button-secondary"
type="button"
onClick={() => onPatch({ birthTimeSource: "period_only", birthTimeStatus: "reported" })}
></button>
></button>
</div>
)}
</div>