fix(tradein): error/not-found/loading UI при restore по ?id= (#822) (#825)
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m33s
Deploy Trade-In / deploy (push) Successful in 36s
All checks were successful
Deploy Trade-In / changes (push) Successful in 5s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m33s
Deploy Trade-In / deploy (push) Successful in 36s
Co-authored-by: bot-frontend <bot-frontend@gendsgn.local> Co-committed-by: bot-frontend <bot-frontend@gendsgn.local>
This commit is contained in:
parent
1a733302c2
commit
31d24ffbdb
1 changed files with 41 additions and 0 deletions
|
|
@ -12,6 +12,7 @@ import { useQueryClient } from "@tanstack/react-query";
|
||||||
import "@/components/trade-in/trade-in.css";
|
import "@/components/trade-in/trade-in.css";
|
||||||
import type { AggregatedEstimate, TradeInEstimateInput, HouseType, RepairState } from "@/types/trade-in";
|
import type { AggregatedEstimate, TradeInEstimateInput, HouseType, RepairState } from "@/types/trade-in";
|
||||||
import { useEstimateMutation, useEstimate } from "@/lib/trade-in-api";
|
import { useEstimateMutation, useEstimate } from "@/lib/trade-in-api";
|
||||||
|
import { HTTPError } from "@/lib/api";
|
||||||
import { EstimateForm } from "@/components/trade-in/EstimateForm";
|
import { EstimateForm } from "@/components/trade-in/EstimateForm";
|
||||||
import { Topbar } from "@/components/trade-in/Topbar";
|
import { Topbar } from "@/components/trade-in/Topbar";
|
||||||
import { SourcesProgress } from "@/components/trade-in/SourcesProgress";
|
import { SourcesProgress } from "@/components/trade-in/SourcesProgress";
|
||||||
|
|
@ -127,6 +128,16 @@ export default function TradeInPage() {
|
||||||
}
|
}
|
||||||
: null);
|
: null);
|
||||||
|
|
||||||
|
// #822: restore по ?id= — отражаем загрузку/ошибку вместо молчаливого
|
||||||
|
// empty-state. Backend отдаёт 404 на missing/owner-mismatch/expired.
|
||||||
|
const restoreActive = urlEstimateId !== null && freshResult === null;
|
||||||
|
const restoreError = restoreActive && restoredEstimate.isError;
|
||||||
|
const restoreLoading = restoreActive && restoredEstimate.isPending;
|
||||||
|
const restoreNotFound =
|
||||||
|
restoreError &&
|
||||||
|
restoredEstimate.error instanceof HTTPError &&
|
||||||
|
restoredEstimate.error.status === 404;
|
||||||
|
|
||||||
// Надёжный input для «Что-если»: предпочитаем поля самой оценки (есть и при
|
// Надёжный input для «Что-если»: предпочитаем поля самой оценки (есть и при
|
||||||
// restore по ?id=, где resultData.input — stub с нулями), откатываемся на input.
|
// restore по ?id=, где resultData.input — stub с нулями), откатываемся на input.
|
||||||
// address/rooms обязательны для payload — берём из estimate, иначе из input.
|
// address/rooms обязательны для payload — берём из estimate, иначе из input.
|
||||||
|
|
@ -275,6 +286,36 @@ export default function TradeInPage() {
|
||||||
<ExposureCard estimate={resultData.estimate} />
|
<ExposureCard estimate={resultData.estimate} />
|
||||||
<OfferCard estimate={resultData.estimate} brandSlug={activeBrandSlug} />
|
<OfferCard estimate={resultData.estimate} brandSlug={activeBrandSlug} />
|
||||||
</>
|
</>
|
||||||
|
) : restoreError ? (
|
||||||
|
<article className="card">
|
||||||
|
<div className="card-body" style={{ padding: "48px 24px", textAlign: "center" }}>
|
||||||
|
<h3 style={{ fontSize: 16, fontWeight: 600, marginBottom: 6 }}>
|
||||||
|
{restoreNotFound
|
||||||
|
? "Отчёт не найден или недоступен"
|
||||||
|
: "Не удалось загрузить отчёт"}
|
||||||
|
</h3>
|
||||||
|
<p style={{ color: "var(--muted)", fontSize: 14, marginBottom: 16 }}>
|
||||||
|
{restoreNotFound
|
||||||
|
? "Ссылка устарела, отчёт удалён или у вас нет к нему доступа."
|
||||||
|
: "Произошла ошибка при загрузке отчёта. Попробуйте ещё раз."}
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn btn-primary"
|
||||||
|
onClick={() => router.replace("/")}
|
||||||
|
>
|
||||||
|
Новая оценка
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
) : restoreLoading ? (
|
||||||
|
<article className="card">
|
||||||
|
<div className="card-body" style={{ padding: "48px 24px", textAlign: "center" }}>
|
||||||
|
<p style={{ color: "var(--muted)", fontSize: 14 }}>
|
||||||
|
Загрузка отчёта…
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
) : (
|
) : (
|
||||||
<article className="card">
|
<article className="card">
|
||||||
<div className="card-body" style={{ padding: "48px 24px", textAlign: "center" }}>
|
<div className="card-body" style={{ padding: "48px 24px", textAlign: "center" }}>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue