Compare commits
2 commits
main
...
feat/801-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbb3c64cd6 | ||
|
|
a34686ac38 |
2 changed files with 330 additions and 4 deletions
|
|
@ -5,7 +5,17 @@
|
||||||
// photo_url=null у всех лотов — намеренно, чтобы не тянуть внешние картинки
|
// photo_url=null у всех лотов — намеренно, чтобы не тянуть внешние картинки
|
||||||
// (чистый оффлайн-рендер для lighthouse/axe).
|
// (чистый оффлайн-рендер для lighthouse/axe).
|
||||||
|
|
||||||
import type { AggregatedEstimate, AnalogLot, TradeInEstimateInput } from "@/types/trade-in";
|
import type {
|
||||||
|
AggregatedEstimate,
|
||||||
|
AnalogLot,
|
||||||
|
HouseAnalyticsResponse,
|
||||||
|
HouseInfoForEstimate,
|
||||||
|
IMVBenchmarkResponse,
|
||||||
|
PlacementHistoryItem,
|
||||||
|
SalesVsListingsResponse,
|
||||||
|
SellTimeSensitivityResponse,
|
||||||
|
TradeInEstimateInput,
|
||||||
|
} from "@/types/trade-in";
|
||||||
|
|
||||||
const analogs: AnalogLot[] = [
|
const analogs: AnalogLot[] = [
|
||||||
{
|
{
|
||||||
|
|
@ -187,3 +197,217 @@ export const FIXTURE_INPUT: TradeInEstimateInput = {
|
||||||
repair_state: "good",
|
repair_state: "good",
|
||||||
has_balcony: true,
|
has_balcony: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── IMV Benchmark fixture ─────────────────────────────────────────────────────
|
||||||
|
// available:true обязательно — иначе IMVBenchmark возвращает null.
|
||||||
|
export const FIXTURE_IMV: IMVBenchmarkResponse = {
|
||||||
|
available: true,
|
||||||
|
cache_key: "ekb:preview-house:2k",
|
||||||
|
recommended_price: 10_200_000,
|
||||||
|
lower_price: 9_400_000,
|
||||||
|
higher_price: 11_000_000,
|
||||||
|
market_count: 7,
|
||||||
|
fetched_at: "2026-05-30T12:00:00Z",
|
||||||
|
our_median_price: 9_850_000,
|
||||||
|
diff_pct: -3.4,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── HouseInfo fixture ─────────────────────────────────────────────────────────
|
||||||
|
// houses.length > 0 обязательно — иначе HouseInfoCard возвращает null.
|
||||||
|
export const FIXTURE_HOUSES: HouseInfoForEstimate[] = [
|
||||||
|
{
|
||||||
|
house_id: 42001,
|
||||||
|
ext_house_id: "ekb-repin-75",
|
||||||
|
address: "Екатеринбург, ул. Репина, 75",
|
||||||
|
short_address: "Репина, 75",
|
||||||
|
lat: 56.84,
|
||||||
|
lon: 60.57,
|
||||||
|
year_built: 2018,
|
||||||
|
total_floors: 11,
|
||||||
|
house_type: "monolith",
|
||||||
|
passenger_elevators: 2,
|
||||||
|
cargo_elevators: 1,
|
||||||
|
has_concierge: false,
|
||||||
|
closed_yard: true,
|
||||||
|
has_playground: true,
|
||||||
|
parking_type: "подземная",
|
||||||
|
developer_name: "Атомстройкомплекс",
|
||||||
|
rating: 4.3,
|
||||||
|
reviews_count: 28,
|
||||||
|
raw_characteristics: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// ── PlacementHistory fixture ──────────────────────────────────────────────────
|
||||||
|
// items.length > 0 обязательно — иначе PlacementHistoryCard возвращает null.
|
||||||
|
export const FIXTURE_PLACEMENT: PlacementHistoryItem[] = [
|
||||||
|
{
|
||||||
|
id: 1001,
|
||||||
|
source: "avito",
|
||||||
|
house_id: 42001,
|
||||||
|
ext_item_id: "avito-preview-1001",
|
||||||
|
title: "2к, 54 м², 7/16 эт.",
|
||||||
|
rooms: 2,
|
||||||
|
area_m2: 54,
|
||||||
|
floor: 7,
|
||||||
|
total_floors: 16,
|
||||||
|
start_price: 10_200_000,
|
||||||
|
start_price_date: "2025-11-01",
|
||||||
|
last_price: 9_700_000,
|
||||||
|
last_price_date: "2026-03-15",
|
||||||
|
removed_date: "2026-04-10",
|
||||||
|
exposure_days: 160,
|
||||||
|
notes: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1002,
|
||||||
|
source: "cian",
|
||||||
|
house_id: 42001,
|
||||||
|
ext_item_id: "cian-preview-1002",
|
||||||
|
title: "2к, 57 м², 4/10 эт.",
|
||||||
|
rooms: 2,
|
||||||
|
area_m2: 57,
|
||||||
|
floor: 4,
|
||||||
|
total_floors: 10,
|
||||||
|
start_price: 9_800_000,
|
||||||
|
start_price_date: "2025-09-10",
|
||||||
|
last_price: 9_500_000,
|
||||||
|
last_price_date: "2025-12-20",
|
||||||
|
removed_date: "2026-01-05",
|
||||||
|
exposure_days: 117,
|
||||||
|
notes: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1003,
|
||||||
|
source: "avito",
|
||||||
|
house_id: 42001,
|
||||||
|
ext_item_id: "avito-preview-1003",
|
||||||
|
title: "2к, 55 м², 5/11 эт.",
|
||||||
|
rooms: 2,
|
||||||
|
area_m2: 55,
|
||||||
|
floor: 5,
|
||||||
|
total_floors: 11,
|
||||||
|
start_price: 9_500_000,
|
||||||
|
start_price_date: "2025-06-01",
|
||||||
|
last_price: 9_100_000,
|
||||||
|
last_price_date: "2025-08-30",
|
||||||
|
removed_date: "2025-09-05",
|
||||||
|
exposure_days: 96,
|
||||||
|
notes: null,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
// ── HouseAnalytics fixture ────────────────────────────────────────────────────
|
||||||
|
// kpi.total_lots > 0 обязательно — иначе HouseAnalyticsSection возвращает null.
|
||||||
|
// price_history >= 2 точки — для рендера PriceHistoryChart.
|
||||||
|
// recent_sold > 0 — для рендера RecentSoldList.
|
||||||
|
export const FIXTURE_ANALYTICS: HouseAnalyticsResponse = {
|
||||||
|
house_ids: [42001],
|
||||||
|
radius_m: 0,
|
||||||
|
kpi: {
|
||||||
|
total_lots: 38,
|
||||||
|
sold_count: 24,
|
||||||
|
sold_rate_pct: 63.2,
|
||||||
|
median_exposure_days: 112,
|
||||||
|
median_bargain_pct: 4.8,
|
||||||
|
},
|
||||||
|
price_history: [
|
||||||
|
{ year: 2022, source: "avito_imv", median_price_per_m2: 155_000, n_lots: 6, median_price_rub: 8_525_000 },
|
||||||
|
{ year: 2023, source: "avito_imv", median_price_per_m2: 161_000, n_lots: 9, median_price_rub: 8_855_000 },
|
||||||
|
{ year: 2024, source: "avito_imv", median_price_per_m2: 170_000, n_lots: 12, median_price_rub: 9_350_000 },
|
||||||
|
{ year: 2025, source: "avito_imv", median_price_per_m2: 176_000, n_lots: 11, median_price_rub: 9_680_000 },
|
||||||
|
],
|
||||||
|
recent_sold: [
|
||||||
|
{
|
||||||
|
id: 2001,
|
||||||
|
source: "avito_imv",
|
||||||
|
rooms: 2,
|
||||||
|
area_m2: 54,
|
||||||
|
floor: 7,
|
||||||
|
start_price: 10_200_000,
|
||||||
|
last_price: 9_700_000,
|
||||||
|
removed_date: "2026-04-10",
|
||||||
|
exposure_days: 160,
|
||||||
|
discount_pct: 4.9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2002,
|
||||||
|
source: "avito_imv",
|
||||||
|
rooms: 2,
|
||||||
|
area_m2: 57,
|
||||||
|
floor: 4,
|
||||||
|
start_price: 9_800_000,
|
||||||
|
last_price: 9_500_000,
|
||||||
|
removed_date: "2026-01-05",
|
||||||
|
exposure_days: 117,
|
||||||
|
discount_pct: 3.1,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// ── SellTimeSensitivity fixture ───────────────────────────────────────────────
|
||||||
|
export const FIXTURE_SELLTIME: SellTimeSensitivityResponse = {
|
||||||
|
house_ids: [42001],
|
||||||
|
radius_m: 0,
|
||||||
|
target_median_price_per_m2: 178_000,
|
||||||
|
buckets: [
|
||||||
|
{ price_premium_label: "cheap", price_premium_pct: -5, median_exposure_days: 38, p25_days: 21, p75_days: 55, n_lots: 8 },
|
||||||
|
{ price_premium_label: "median", price_premium_pct: 0, median_exposure_days: 112, p25_days: 60, p75_days: 160, n_lots: 14 },
|
||||||
|
{ price_premium_label: "plus5", price_premium_pct: 5, median_exposure_days: 185, p25_days: 90, p75_days: 240, n_lots: 10 },
|
||||||
|
{ price_premium_label: "plus10", price_premium_pct: 10, median_exposure_days: 270, p25_days: 150, p75_days: 360, n_lots: 6 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Секция 12: StreetDealsCard — useSalesVsListings(address, area_m2, rooms).
|
||||||
|
// Guard: street != null И pairs.length > 0 — иначе return null.
|
||||||
|
export const FIXTURE_SALES: SalesVsListingsResponse = {
|
||||||
|
street: "Репина",
|
||||||
|
period_months: 24,
|
||||||
|
window_days: 180,
|
||||||
|
area_tolerance: 0.15,
|
||||||
|
total_deals: 9,
|
||||||
|
deals_with_listings: 5,
|
||||||
|
linkage_rate_pct: 55.6,
|
||||||
|
median_discount_pct: -6.2,
|
||||||
|
data_quality: "house_linked",
|
||||||
|
pairs: [
|
||||||
|
{
|
||||||
|
deal_id: 9001,
|
||||||
|
deal_date: "2026-04-18",
|
||||||
|
deal_price_rub: 8_900_000,
|
||||||
|
deal_price_per_m2: 161_818,
|
||||||
|
deal_area_m2: 55,
|
||||||
|
deal_rooms: 2,
|
||||||
|
deal_floor: 6,
|
||||||
|
deal_address: "Екатеринбург, ул. Репина, 75/2",
|
||||||
|
listing_id: 50001,
|
||||||
|
listing_source: "avito",
|
||||||
|
listing_source_url: "https://www.avito.ru/ekaterinburg/kvartiry/preview-d1",
|
||||||
|
listing_date: "2026-03-20",
|
||||||
|
listing_price_rub: 9_500_000,
|
||||||
|
listing_price_per_m2: 172_727,
|
||||||
|
listing_area_m2: 55,
|
||||||
|
days_listing_to_deal: 29,
|
||||||
|
discount_pct: -6.3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
deal_id: 9002,
|
||||||
|
deal_date: "2026-02-27",
|
||||||
|
deal_price_rub: 9_100_000,
|
||||||
|
deal_price_per_m2: 159_649,
|
||||||
|
deal_area_m2: 57,
|
||||||
|
deal_rooms: 2,
|
||||||
|
deal_floor: 9,
|
||||||
|
deal_address: "Екатеринбург, ул. Репина, 73",
|
||||||
|
listing_id: 50002,
|
||||||
|
listing_source: "cian",
|
||||||
|
listing_source_url: "https://www.cian.ru/sale/flat/preview-d2",
|
||||||
|
listing_date: "2026-01-30",
|
||||||
|
listing_price_rub: 9_700_000,
|
||||||
|
listing_price_per_m2: 170_175,
|
||||||
|
listing_area_m2: 57,
|
||||||
|
days_listing_to_deal: 28,
|
||||||
|
discount_pct: -6.2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,25 @@
|
||||||
* Локально: echo NEXT_PUBLIC_ENABLE_PREVIEW=1 > .env.local && npm run dev
|
* Локально: echo NEXT_PUBLIC_ENABLE_PREVIEW=1 > .env.local && npm run dev
|
||||||
* → http://localhost:3000/ui-preview/estimate
|
* → http://localhost:3000/ui-preview/estimate
|
||||||
* CI: собрать с флагом, поднять next start, навести axe/lighthouse.
|
* CI: собрать с флагом, поднять next start, навести axe/lighthouse.
|
||||||
|
*
|
||||||
|
* Секции (1:1 с page.tsx строки 228-276):
|
||||||
|
* 1. SourcesProgress — estimate prop
|
||||||
|
* 2. WhatIfPanel — baseEstimate + baseInput props
|
||||||
|
* 3. HeroSummary — estimate + input props
|
||||||
|
* 4. IMVBenchmark — benchmark prop (FIXTURE_IMV, available:true)
|
||||||
|
* 5. CianValuationCard — data prop
|
||||||
|
* 6. HouseInfoCard — houses prop (FIXTURE_HOUSES, length>0)
|
||||||
|
* 7. PlacementHistoryCard — estimateId; seed queryKey "placement-history"
|
||||||
|
* 8. HouseAnalyticsSection — estimateId; seed "house-analytics" + "sell-time-sensitivity"
|
||||||
|
* 9. PhotoUpload — estimateId (upload-UI; fetch photo может тихо упасть — ок)
|
||||||
|
* 10. ListingsCard — estimate + estimateId; seed "cian-price-changes" пустым
|
||||||
|
* 11. DealsCard — estimate prop
|
||||||
|
* 12. StreetDealsCard — estimate prop
|
||||||
|
* 13. MapCard — estimate prop (analogs имеют lat/lon → пины есть)
|
||||||
|
* 14. DistributionCard — estimate prop
|
||||||
|
* 15. PriceTrendCard — estimate prop
|
||||||
|
* 16. ExposureCard — estimate prop
|
||||||
|
* 17. OfferCard — estimate + brandSlug=null props
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
|
@ -27,14 +46,35 @@ import { DealsCard } from "@/components/trade-in/DealsCard";
|
||||||
import { DistributionCard } from "@/components/trade-in/DistributionCard";
|
import { DistributionCard } from "@/components/trade-in/DistributionCard";
|
||||||
import { ExposureCard } from "@/components/trade-in/ExposureCard";
|
import { ExposureCard } from "@/components/trade-in/ExposureCard";
|
||||||
import { HeroSummary } from "@/components/trade-in/HeroSummary";
|
import { HeroSummary } from "@/components/trade-in/HeroSummary";
|
||||||
|
import { HouseAnalyticsSection } from "@/components/trade-in/HouseAnalyticsSection";
|
||||||
|
import { HouseInfoCard } from "@/components/trade-in/HouseInfoCard";
|
||||||
|
import { IMVBenchmark } from "@/components/trade-in/IMVBenchmark";
|
||||||
|
import { ListingsCard } from "@/components/trade-in/ListingsCard";
|
||||||
|
import { MapCard } from "@/components/trade-in/MapCard";
|
||||||
|
import { OfferCard } from "@/components/trade-in/OfferCard";
|
||||||
|
import { PhotoUpload } from "@/components/trade-in/PhotoUpload";
|
||||||
|
import { PlacementHistoryCard } from "@/components/trade-in/PlacementHistoryCard";
|
||||||
import { PriceTrendCard } from "@/components/trade-in/PriceTrendCard";
|
import { PriceTrendCard } from "@/components/trade-in/PriceTrendCard";
|
||||||
|
import { SourcesProgress } from "@/components/trade-in/SourcesProgress";
|
||||||
import { StreetDealsCard } from "@/components/trade-in/StreetDealsCard";
|
import { StreetDealsCard } from "@/components/trade-in/StreetDealsCard";
|
||||||
|
import { WhatIfPanel } from "@/components/trade-in/WhatIfPanel";
|
||||||
import { ME_QUERY_KEY, type UserScope } from "@/lib/useMe";
|
import { ME_QUERY_KEY, type UserScope } from "@/lib/useMe";
|
||||||
|
|
||||||
import { FIXTURE_ESTIMATE, FIXTURE_INPUT } from "./fixture";
|
import {
|
||||||
|
FIXTURE_ANALYTICS,
|
||||||
|
FIXTURE_ESTIMATE,
|
||||||
|
FIXTURE_HOUSES,
|
||||||
|
FIXTURE_IMV,
|
||||||
|
FIXTURE_INPUT,
|
||||||
|
FIXTURE_PLACEMENT,
|
||||||
|
FIXTURE_SALES,
|
||||||
|
FIXTURE_SELLTIME,
|
||||||
|
} from "./fixture";
|
||||||
|
|
||||||
const ENABLED = process.env.NEXT_PUBLIC_ENABLE_PREVIEW === "1";
|
const ENABLED = process.env.NEXT_PUBLIC_ENABLE_PREVIEW === "1";
|
||||||
|
|
||||||
|
const PREVIEW_ID = FIXTURE_ESTIMATE.estimate_id;
|
||||||
|
|
||||||
// Фейковый authorized-юзер: засеивается в QueryClient → useMe/useBrand резолвятся
|
// Фейковый authorized-юзер: засеивается в QueryClient → useMe/useBrand резолвятся
|
||||||
// оффлайн (никакого /me, /quota, /brand), generic-бренд (brand=null).
|
// оффлайн (никакого /me, /quota, /brand), generic-бренд (brand=null).
|
||||||
const PREVIEW_USER: UserScope = {
|
const PREVIEW_USER: UserScope = {
|
||||||
|
|
@ -52,7 +92,26 @@ function PreviewContent() {
|
||||||
queries: { retry: false, staleTime: Infinity, refetchOnWindowFocus: false },
|
queries: { retry: false, staleTime: Infinity, refetchOnWindowFocus: false },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
// /me — пропускает RouteGuard без сетевого запроса
|
||||||
qc.setQueryData(ME_QUERY_KEY, PREVIEW_USER);
|
qc.setQueryData(ME_QUERY_KEY, PREVIEW_USER);
|
||||||
|
// Секция 7: PlacementHistoryCard — useEstimatePlacementHistory
|
||||||
|
qc.setQueryData(["trade-in", "estimate", PREVIEW_ID, "placement-history"], FIXTURE_PLACEMENT);
|
||||||
|
// Секция 8: HouseAnalyticsSection — useEstimateHouseAnalytics + useEstimateSellTimeSensitivity
|
||||||
|
qc.setQueryData(["trade-in", "estimate", PREVIEW_ID, "house-analytics"], FIXTURE_ANALYTICS);
|
||||||
|
qc.setQueryData(["trade-in", "estimate", PREVIEW_ID, "sell-time-sensitivity"], FIXTURE_SELLTIME);
|
||||||
|
// Секция 10: ListingsCard — useEstimateCianPriceChanges (пустой = graceful)
|
||||||
|
qc.setQueryData(["trade-in", "estimate", PREVIEW_ID, "cian-price-changes"], []);
|
||||||
|
// Секция 12: StreetDealsCard — useSalesVsListings(address, area_m2, rooms)
|
||||||
|
qc.setQueryData(
|
||||||
|
[
|
||||||
|
"trade-in",
|
||||||
|
"sales-vs-listings",
|
||||||
|
FIXTURE_ESTIMATE.target_address,
|
||||||
|
FIXTURE_ESTIMATE.area_m2,
|
||||||
|
FIXTURE_ESTIMATE.rooms,
|
||||||
|
],
|
||||||
|
FIXTURE_SALES,
|
||||||
|
);
|
||||||
return qc;
|
return qc;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -62,18 +121,61 @@ function PreviewContent() {
|
||||||
(flex-column gap, --container ширина). Без них карточки рендерились узко/«мобильно». */}
|
(flex-column gap, --container ширина). Без них карточки рендерились узко/«мобильно». */}
|
||||||
<main className="page">
|
<main className="page">
|
||||||
<section className="result-col">
|
<section className="result-col">
|
||||||
|
{/* 1. SourcesProgress */}
|
||||||
|
<SourcesProgress estimate={FIXTURE_ESTIMATE} isPending={false} />
|
||||||
|
|
||||||
|
{/* 2. WhatIfPanel */}
|
||||||
|
<WhatIfPanel baseEstimate={FIXTURE_ESTIMATE} baseInput={FIXTURE_INPUT} />
|
||||||
|
|
||||||
|
{/* 3. HeroSummary */}
|
||||||
<HeroSummary
|
<HeroSummary
|
||||||
estimate={FIXTURE_ESTIMATE}
|
estimate={FIXTURE_ESTIMATE}
|
||||||
input={FIXTURE_INPUT}
|
input={FIXTURE_INPUT}
|
||||||
onResubmit={() => {}}
|
onResubmit={() => {}}
|
||||||
isResubmitting={false}
|
isResubmitting={false}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
{/* 4. IMVBenchmark — передаём пропом напрямую (available:true → не null) */}
|
||||||
|
<IMVBenchmark benchmark={FIXTURE_IMV} isLoading={false} />
|
||||||
|
|
||||||
|
{/* 5. CianValuationCard */}
|
||||||
<CianValuationCard data={FIXTURE_ESTIMATE.cian_valuation} />
|
<CianValuationCard data={FIXTURE_ESTIMATE.cian_valuation} />
|
||||||
<DistributionCard estimate={FIXTURE_ESTIMATE} />
|
|
||||||
|
{/* 6. HouseInfoCard — передаём пропом напрямую (length>0 → не null) */}
|
||||||
|
<HouseInfoCard houses={FIXTURE_HOUSES} isLoading={false} />
|
||||||
|
|
||||||
|
{/* 7. PlacementHistoryCard — useEstimatePlacementHistory; queryKey засеян выше */}
|
||||||
|
<PlacementHistoryCard estimateId={PREVIEW_ID} />
|
||||||
|
|
||||||
|
{/* 8. HouseAnalyticsSection — useEstimateHouseAnalytics; queryKeys засеяны выше */}
|
||||||
|
<HouseAnalyticsSection estimateId={PREVIEW_ID} />
|
||||||
|
|
||||||
|
{/* 9. PhotoUpload — рендерит upload-UI; fetch фото может тихо упасть — ок */}
|
||||||
|
<PhotoUpload estimateId={PREVIEW_ID} />
|
||||||
|
|
||||||
|
{/* 10. ListingsCard — cian-price-changes засеян пустым массивом */}
|
||||||
|
<ListingsCard estimate={FIXTURE_ESTIMATE} estimateId={PREVIEW_ID} />
|
||||||
|
|
||||||
|
{/* 11. DealsCard */}
|
||||||
<DealsCard estimate={FIXTURE_ESTIMATE} />
|
<DealsCard estimate={FIXTURE_ESTIMATE} />
|
||||||
|
|
||||||
|
{/* 12. StreetDealsCard */}
|
||||||
<StreetDealsCard estimate={FIXTURE_ESTIMATE} />
|
<StreetDealsCard estimate={FIXTURE_ESTIMATE} />
|
||||||
<ExposureCard estimate={FIXTURE_ESTIMATE} />
|
|
||||||
|
{/* 13. MapCard — analogs имеют lat/lon → пины есть; Leaflet CDN → тайлы из сети (ок) */}
|
||||||
|
<MapCard estimate={FIXTURE_ESTIMATE} />
|
||||||
|
|
||||||
|
{/* 14. DistributionCard */}
|
||||||
|
<DistributionCard estimate={FIXTURE_ESTIMATE} />
|
||||||
|
|
||||||
|
{/* 15. PriceTrendCard */}
|
||||||
<PriceTrendCard estimate={FIXTURE_ESTIMATE} />
|
<PriceTrendCard estimate={FIXTURE_ESTIMATE} />
|
||||||
|
|
||||||
|
{/* 16. ExposureCard */}
|
||||||
|
<ExposureCard estimate={FIXTURE_ESTIMATE} />
|
||||||
|
|
||||||
|
{/* 17. OfferCard */}
|
||||||
|
<OfferCard estimate={FIXTURE_ESTIMATE} brandSlug={null} />
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</QueryClientProvider>
|
</QueryClientProvider>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue