fix(tradein/v2): audit #2081 residual — 404 short-circuit, disabled-tab tooltips, stale hex token, ДКП decode (#2392)
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m42s
Deploy Trade-In / build-frontend (push) Successful in 2m17s
Deploy Trade-In / build-backend (push) Successful in 33s
Deploy Trade-In / deploy (push) Successful in 4m52s
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m42s
Deploy Trade-In / build-frontend (push) Successful in 2m17s
Deploy Trade-In / build-backend (push) Successful in 33s
Deploy Trade-In / deploy (push) Successful in 4m52s
This commit is contained in:
parent
dd222a4eb3
commit
98df57827e
3 changed files with 50 additions and 11 deletions
|
|
@ -439,9 +439,24 @@ export default function TradeInV2Page() {
|
|||
// Skip the restore fetch once we already hold a fresh result.
|
||||
const restored = useEstimate(freshResult === null ? urlId : null);
|
||||
|
||||
// L3 — once the restore-by-id fetch has confirmed the estimate does not
|
||||
// exist (404), `currentEstimateId` below drops to null so the sibling
|
||||
// dashboard hooks (analytics/location-coef/placement-history/sell-time,
|
||||
// all `enabled: estimate_id !== null`) don't each fire their own doomed
|
||||
// request against the same dead id. Hoisted above the sub-hooks (was
|
||||
// computed further down, after they'd already fired on the stale id).
|
||||
const restoreActive = urlId !== null && freshResult === null;
|
||||
const restoreError = restoreActive && restored.isError;
|
||||
const restoreNotFound =
|
||||
restoreError &&
|
||||
restored.error instanceof HTTPError &&
|
||||
restored.error.status === 404;
|
||||
|
||||
const estimate: AggregatedEstimate | null =
|
||||
freshResult ?? restored.data ?? null;
|
||||
const currentEstimateId = freshResult?.estimate_id ?? urlId;
|
||||
const currentEstimateId = restoreNotFound
|
||||
? null
|
||||
: (freshResult?.estimate_id ?? urlId);
|
||||
|
||||
// Per-user side data, independent of the current estimate. Both fail-soft
|
||||
// (retry:false): history feeds the «Предыдущие оценки» overlay (04), quota
|
||||
|
|
@ -486,13 +501,7 @@ export default function TradeInV2Page() {
|
|||
const sellTimeData = sellTime.data ?? null;
|
||||
|
||||
// ── Derived state flags ───────────────────────────────────────────────────
|
||||
const restoreActive = urlId !== null && freshResult === null;
|
||||
const restoreLoading = restoreActive && restored.isPending;
|
||||
const restoreError = restoreActive && restored.isError;
|
||||
const restoreNotFound =
|
||||
restoreError &&
|
||||
restored.error instanceof HTTPError &&
|
||||
restored.error.status === 404;
|
||||
|
||||
const loading = mutation.isPending || restoreLoading;
|
||||
const insufficient =
|
||||
|
|
|
|||
|
|
@ -175,6 +175,19 @@ export default function HistoryView({
|
|||
>
|
||||
{data.dkpHeader.title}
|
||||
</div>
|
||||
{/* M12 — расшифровка «ДКП» один раз на секцию, тем же lowercase
|
||||
hint-стилем что ObjectSummary.rowHint() (fontSize 8/letterSpacing
|
||||
0.2/muted3), а не uppercase ResultPanel §M8 стилем. */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: "8px",
|
||||
letterSpacing: 0.2,
|
||||
color: tokens.muted3,
|
||||
marginTop: 2,
|
||||
}}
|
||||
>
|
||||
ДКП · договор купли-продажи
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
|
|
|
|||
|
|
@ -156,7 +156,9 @@ export default function TopNav({
|
|||
fontSize="27"
|
||||
fontWeight="400"
|
||||
letterSpacing="11"
|
||||
fill="#6f8195"
|
||||
// L7 — stale literal from before the C1 contrast sweep darkened
|
||||
// the muted scale; token keeps this logo subtitle in sync.
|
||||
fill={tokens.muted}
|
||||
>
|
||||
ОЦЕНКА НЕДВИЖИМОСТИ
|
||||
</text>
|
||||
|
|
@ -370,7 +372,14 @@ export default function TopNav({
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div style={menuItemDisabledStyle} aria-disabled="true">
|
||||
{/* L5 — `title` gives the dimmed/non-interactive item a hover
|
||||
tooltip explaining WHY it's disabled, instead of a silent dead
|
||||
row (mirrored on Настройки/Помощь below). */}
|
||||
<div
|
||||
style={menuItemDisabledStyle}
|
||||
aria-disabled="true"
|
||||
title="Раздел «Профиль» скоро появится"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true">
|
||||
<circle
|
||||
cx="7.5"
|
||||
|
|
@ -412,7 +421,11 @@ export default function TopNav({
|
|||
</span>
|
||||
</div>
|
||||
|
||||
<div style={menuItemDisabledStyle} aria-disabled="true">
|
||||
<div
|
||||
style={menuItemDisabledStyle}
|
||||
aria-disabled="true"
|
||||
title="Раздел «Настройки» скоро появится"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true">
|
||||
<circle
|
||||
cx="7.5"
|
||||
|
|
@ -430,7 +443,11 @@ export default function TopNav({
|
|||
Настройки
|
||||
</div>
|
||||
|
||||
<div style={menuItemDisabledStyle} aria-disabled="true">
|
||||
<div
|
||||
style={menuItemDisabledStyle}
|
||||
aria-disabled="true"
|
||||
title="Раздел «Помощь» скоро появится"
|
||||
>
|
||||
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" aria-hidden="true">
|
||||
<circle
|
||||
cx="7.5"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue