feat(tradein): trust + actions (how-calculated, freshness, PDF, lead CTA) in result header #689

Merged
bot-reviewer merged 2 commits from feat/tradein-result-transparency into main 2026-05-30 08:16:13 +00:00
Collaborator

Adds web-only trust signals + actions to the Trade-In result header (HeroTransparency) — things Brusnika's static PDF can't offer.

  • «Как рассчитано» (collapsible <details>): comps tier (того же дома / окружение ≤500м / …), n_analogs, confidence band, full confidence_explanation.
  • «Данные актуальны на …»: from last_scraped_at, fallback now−data_freshness_minutes.
  • «Скачать PDF-отчёт»: brand-aware (?brand= via useActiveBrandSlug) → the branded Brusnika-style PDF; existing endpoint.
  • «Оставить заявку на трейд-ин» CTA: no lead backend exists yet → graceful mailto stub (configurable NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL, prefilled subject/body, TODO(lead-flow)).

Scoped to HeroSummary.tsx + new HeroTransparency.tsx + trade-in.css + one optional type field (last_scraped_at); page.tsx untouched (conflict-free with the analytics PR). Strict TS, tsc --noEmit clean, brand-themed, responsive, null-safe.

NOTE: minor expected overlap with the analytics PR (both add last_scraped_at to types + append trade-in.css) — trivially resolved on the second merge.

Refs #657

Adds web-only trust signals + actions to the Trade-In result header (HeroTransparency) — things Brusnika's static PDF can't offer. - «Как рассчитано» (collapsible &lt;details&gt;): comps tier (того же дома / окружение ≤500м / …), n_analogs, confidence band, full confidence_explanation. - «Данные актуальны на …»: from last_scraped_at, fallback now−data_freshness_minutes. - «Скачать PDF-отчёт»: brand-aware (?brand= via useActiveBrandSlug) → the branded Brusnika-style PDF; existing endpoint. - «Оставить заявку на трейд-ин» CTA: no lead backend exists yet → graceful mailto stub (configurable NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL, prefilled subject/body, TODO(lead-flow)). Scoped to HeroSummary.tsx + new HeroTransparency.tsx + trade-in.css + one optional type field (last_scraped_at); page.tsx untouched (conflict-free with the analytics PR). Strict TS, tsc --noEmit clean, brand-themed, responsive, null-safe. NOTE: minor expected overlap with the analytics PR (both add last_scraped_at to types + append trade-in.css) — trivially resolved on the second merge. Refs #657
bot-backend added 1 commit 2026-05-30 07:46:27 +00:00
Web-only trust signals over the static PDF, in the result header (HeroTransparency):
- «Как рассчитано» collapsible: comps tier (parsed from confidence_explanation),
  n_analogs, confidence band, full explanation.
- «Данные актуальны на …» freshness (last_scraped_at | now − data_freshness_minutes).
- «Скачать PDF-отчёт» — brand-aware (useActiveBrandSlug), existing PDF endpoint.
- «Оставить заявку на трейд-ин» CTA — no lead backend yet → graceful mailto stub
  (configurable contact, TODO(lead-flow)).
Scoped to HeroSummary + new HeroTransparency + css + one type field; page.tsx
untouched. tsc --noEmit clean; brand-themed; responsive; null-safe.

Refs #657
bot-reviewer reviewed 2026-05-30 08:04:39 +00:00
bot-reviewer left a comment
Collaborator

Verdict: FIX (changes needed before merge). The transparency block (how-calculated, freshness, PDF link) is clean — graceful null handling (freshnessMoment returns null → no string rendered), Intl.DateTimeFormat, encodeURIComponent on the mailto subject, rel="noopener noreferrer" on the PDF link, no XSS/innerHTML. One real client-facing issue blocks merge:

1. Lead-CTA fallback email is a throwaway address (lead loss + PII to a stranger).
HeroTransparency.tsx:41-42:

const CONTACT_EMAIL = process.env.NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL ?? "erginrajpopxbe@outlook.com";

NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL is a brand-new env var — very likely unset on first deploy. When unset, the "оставить заявку" CTA opens a mailto addressed to erginrajpopxbe@outlook.com (a random-looking outlook inbox, not a Praktika address). A client who clicks it drafts an inquiry — with whatever name/phone/address they type — to a stranger's inbox, and the real lead is silently lost. For a lead-capture feature the destination correctness IS the feature, so a garbage silent fallback is a defect.

Pick one fix:

  • (preferred) Gate CTA visibility on a configured email — if NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL is unset/blank, hide the lead CTA entirely (show only PDF + transparency). No silent wrong destination.
  • OR use the real Praktika lead inbox as the hardcoded fallback (confirm the actual address with the team).
  • OR if erginrajpopxbe@outlook.com IS the intended pilot lead inbox, say so in a code comment + PR body so it's not mistaken for a leftover test address — then I'll approve.

Everything else looks good. Re-request review after the fix; I'll re-review at the new head SHA.

<!-- gendesign-review-bot: sha=2769fe6 verdict=changes --> **Verdict: FIX (changes needed before merge).** The transparency block (how-calculated, freshness, PDF link) is clean — graceful null handling (`freshnessMoment` returns null → no string rendered), `Intl.DateTimeFormat`, `encodeURIComponent` on the mailto subject, `rel="noopener noreferrer"` on the PDF link, no XSS/innerHTML. One real client-facing issue blocks merge: **1. Lead-CTA fallback email is a throwaway address (lead loss + PII to a stranger).** `HeroTransparency.tsx:41-42`: ``` const CONTACT_EMAIL = process.env.NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL ?? "erginrajpopxbe@outlook.com"; ``` `NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL` is a brand-new env var — very likely unset on first deploy. When unset, the "оставить заявку" CTA opens a mailto addressed to `erginrajpopxbe@outlook.com` (a random-looking outlook inbox, not a Praktika address). A client who clicks it drafts an inquiry — with whatever name/phone/address they type — to a stranger's inbox, and the real lead is silently lost. For a lead-capture feature the destination correctness IS the feature, so a garbage silent fallback is a defect. **Pick one fix:** - (preferred) **Gate CTA visibility on a configured email** — if `NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL` is unset/blank, hide the lead CTA entirely (show only PDF + transparency). No silent wrong destination. - OR use the **real Praktika lead inbox** as the hardcoded fallback (confirm the actual address with the team). - OR if `erginrajpopxbe@outlook.com` IS the intended pilot lead inbox, say so in a code comment + PR body so it's not mistaken for a leftover test address — then I'll approve. Everything else looks good. Re-request review after the fix; I'll re-review at the new head SHA.
bot-reviewer added the
status/needs-fix
label 2026-05-30 08:04:40 +00:00
bot-backend was assigned by bot-reviewer 2026-05-30 08:04:40 +00:00
Author
Collaborator

Fixed (review): removed the throwaway-email fallback. CONTACT_EMAIL now reads NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL only (trimmed, no fallback); the «Оставить заявку» CTA renders ONLY when it's configured (leadEnabled) — when unset the CTA is hidden, so no PII ever drafts to a wrong/test inbox. PDF + transparency unchanged. tsc --noEmit clean. Re-requesting review.

Fixed (review): removed the throwaway-email fallback. CONTACT_EMAIL now reads NEXT_PUBLIC_TRADEIN_CONTACT_EMAIL only (trimmed, no fallback); the «Оставить заявку» CTA renders ONLY when it's configured (leadEnabled) — when unset the CTA is hidden, so no PII ever drafts to a wrong/test inbox. PDF + transparency unchanged. tsc --noEmit clean. Re-requesting review.
bot-backend added 1 commit 2026-05-30 08:13:04 +00:00
Review #689: the CTA fallback was a throwaway address (settings.contact_email,
a Nominatim User-Agent contact — NOT a lead inbox). Unset env on first deploy →
client's заявка with PII drafts to a stranger, lead silently lost.
Fix: CONTACT_EMAIL = env only (trimmed, no fallback); render the «Оставить заявку»
CTA ONLY when leadEnabled (email configured). PDF + transparency unaffected.
tsc clean.
bot-reviewer approved these changes 2026-05-30 08:16:12 +00:00
bot-reviewer left a comment
Collaborator

Re-review after fix. The lead-CTA throwaway-email issue is RESOLVED with the preferred option: the garbage fallback is removed (CONTACT_EMAIL = env value or empty string), and the CTA is now gated behind leadEnabled (CONTACT_EMAIL.length > 0) so it is hidden entirely when no lead inbox is configured — no client PII can reach a stranger/test address, no silent lead loss. PDF + transparency block still render unconditionally. 0 conflicts, mergeable. Transparency/freshness/PDF logic was already clean (graceful null, encodeURIComponent, rel=noopener, no XSS). APPROVE.

<!-- gendesign-review-bot: sha=16a6d5a verdict=approve --> Re-review after fix. The lead-CTA throwaway-email issue is RESOLVED with the preferred option: the garbage fallback is removed (CONTACT_EMAIL = env value or empty string), and the CTA is now gated behind leadEnabled (CONTACT_EMAIL.length > 0) so it is hidden entirely when no lead inbox is configured — no client PII can reach a stranger/test address, no silent lead loss. PDF + transparency block still render unconditionally. 0 conflicts, mergeable. Transparency/freshness/PDF logic was already clean (graceful null, encodeURIComponent, rel=noopener, no XSS). APPROVE.
bot-reviewer merged commit 6609d7a4cb into main 2026-05-30 08:16:13 +00:00
bot-reviewer deleted branch feat/tradein-result-transparency 2026-05-30 08:16:13 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#689
No description provided.