feat(uat-batch-18): interest-berths defaults + a11y loading/hint fixes
- `addInterestBerth` insert-time defaults now match the locked
multi-berth EOI UX (queue B2):
is_in_eoi_bundle: true (was false)
is_specific_interest: matches `isPrimary` (was always true)
This means a newly-linked berth is covered by the EOI signature by
default but the public map only shows the primary as "Under Offer"
until the rep marks others isSpecificInterest. The two existing
integration tests pass explicit values so they're unaffected.
- A11y: `set-password` form's password-requirements hint linked via
aria-describedby so SR users hear the rules on focus.
- A11y: Loading fallbacks on set-password / portal/activate /
supplemental-info wrapped in role="status" aria-live="polite" with
sr-only "Loading" copy where only a spinner was visible.
tsc clean. 1419/1419 vitest pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -104,7 +104,9 @@ function SetPasswordInner() {
|
||||
if (token === null) {
|
||||
return (
|
||||
<BrandedAuthShell>
|
||||
<div className="text-center text-sm text-gray-500">Loading…</div>
|
||||
<div role="status" aria-live="polite" className="text-center text-sm text-gray-500">
|
||||
Loading…
|
||||
</div>
|
||||
</BrandedAuthShell>
|
||||
);
|
||||
}
|
||||
@@ -141,10 +143,13 @@ function SetPasswordInner() {
|
||||
type="password"
|
||||
autoComplete="new-password"
|
||||
disabled={isLoading}
|
||||
aria-describedby="password-hint"
|
||||
className={cn(errors.password && 'border-destructive focus-visible:ring-destructive')}
|
||||
{...register('password')}
|
||||
/>
|
||||
<p className="text-xs text-gray-500">At least {MIN_LENGTH} characters.</p>
|
||||
<p id="password-hint" className="text-xs text-gray-500">
|
||||
At least {MIN_LENGTH} characters.
|
||||
</p>
|
||||
{errors.password && <p className="text-sm text-destructive">{errors.password.message}</p>}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,7 +6,11 @@ export default function PortalActivatePage() {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-50 text-sm text-gray-500">
|
||||
<div
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
className="min-h-screen flex items-center justify-center bg-gray-50 text-sm text-gray-500"
|
||||
>
|
||||
Loading…
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -140,8 +140,9 @@ export default function SupplementalInfoPage({ params }: PageProps) {
|
||||
if (loading) {
|
||||
return (
|
||||
<BrandedAuthShell>
|
||||
<div className="flex items-center justify-center py-8">
|
||||
<div role="status" aria-live="polite" className="flex items-center justify-center py-8">
|
||||
<Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
|
||||
<span className="sr-only">Loading</span>
|
||||
</div>
|
||||
</BrandedAuthShell>
|
||||
);
|
||||
|
||||
@@ -272,14 +272,25 @@ export async function upsertInterestBerthTx(
|
||||
}
|
||||
}
|
||||
|
||||
// EOI bundle UX (locked 2026-05-18): a deal's EOI typically covers
|
||||
// every berth linked to the interest, but only the rep's "main"
|
||||
// berth (the primary) should show "Under Offer" on the public map.
|
||||
// The defaults below encode that workflow so reps don't have to
|
||||
// tick boxes for the common case:
|
||||
// • `is_in_eoi_bundle` defaults to TRUE for every newly-linked
|
||||
// berth (rep unticks for the rare carve-out).
|
||||
// • `is_specific_interest` defaults to TRUE only on the primary;
|
||||
// non-primary rows default to FALSE so the public map doesn't
|
||||
// light up extra berths.
|
||||
const isPrimary = opts.isPrimary ?? false;
|
||||
const [row] = await tx
|
||||
.insert(interestBerths)
|
||||
.values({
|
||||
interestId,
|
||||
berthId,
|
||||
isPrimary: opts.isPrimary ?? false,
|
||||
isSpecificInterest: opts.isSpecificInterest ?? true,
|
||||
isInEoiBundle: opts.isInEoiBundle ?? false,
|
||||
isPrimary,
|
||||
isSpecificInterest: opts.isSpecificInterest ?? isPrimary,
|
||||
isInEoiBundle: opts.isInEoiBundle ?? true,
|
||||
addedBy: opts.addedBy,
|
||||
notes: opts.notes,
|
||||
eoiBypassReason: setForUpdate.eoiBypassReason ?? null,
|
||||
|
||||
Reference in New Issue
Block a user