Порт пиксель-дизайна МЕРА Оценка (HUD/blueprint) в новую страницу /trade-in/v2 — v1 (/trade-in) не тронут. - markup-first: данные из fixtures.ts (sample-данные дизайна), без API - tokens.ts (палитра HUD), types.ts, fixtures.ts (foundation) - Manrope + IBM Plex Mono через next/font (self-hosted) - NAV + HERO (фото) + 01 Параметры + 02 Результат + 03 Сводка + FOOTER - overlay-секции: Продажи в доме / Аналогичные объявления / Аналитика / Предыдущие оценки - drawer Коэффициент локации - интерактив (вкладки→overlay, drawer, дропдауны) на локальном useState Wiring к боевым ручкам — отдельной задачей (см. issue).
958 lines
27 KiB
TypeScript
958 lines
27 KiB
TypeScript
"use client";
|
||
|
||
// 01 ПАРАМЕТРЫ КВАРТИРЫ — left card of the /trade-in/v2 "МЕРА Оценка" port.
|
||
// Faithful markup port (МЕРА Оценка.dc.html lines 146-240). Markup-first: all
|
||
// values come from fixtures (no API). Dropdowns / balcony toggle drive local UI
|
||
// state only. Hover/active + @keyframes live in a pp-prefixed local <style>.
|
||
|
||
import { useState, type CSSProperties } from "react";
|
||
import { tokens } from "./tokens";
|
||
import { object, dropdownOptions } from "./fixtures";
|
||
|
||
type DdKey = "rooms" | "houseType" | "repair" | "radius" | "crm" | null;
|
||
|
||
interface DdProps {
|
||
open: boolean;
|
||
onToggle: () => void;
|
||
value: string;
|
||
options: string[];
|
||
onSelect: (v: string) => void;
|
||
mono: boolean;
|
||
triggerFontSize: number;
|
||
optionFontSize: number;
|
||
variant?: "solid" | "dashed";
|
||
openUp?: boolean;
|
||
triggerHeight?: number;
|
||
triggerBg?: string;
|
||
triggerColor?: string;
|
||
caretColor?: string;
|
||
}
|
||
|
||
function Dd({
|
||
open,
|
||
onToggle,
|
||
value,
|
||
options,
|
||
onSelect,
|
||
mono,
|
||
triggerFontSize,
|
||
optionFontSize,
|
||
variant = "solid",
|
||
openUp = false,
|
||
triggerHeight = 33,
|
||
triggerBg = tokens.surface.w62,
|
||
triggerColor = tokens.ink,
|
||
caretColor = tokens.muted2,
|
||
}: DdProps) {
|
||
const panelStyle: CSSProperties = {
|
||
position: "absolute",
|
||
left: 0,
|
||
right: 0,
|
||
background: tokens.surface.w98,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 6,
|
||
zIndex: 30,
|
||
padding: 3,
|
||
...(openUp
|
||
? {
|
||
bottom: "calc(100% + 4px)",
|
||
boxShadow: "0 -10px 26px rgba(40,80,130,.18)",
|
||
}
|
||
: {
|
||
top: "calc(100% + 4px)",
|
||
boxShadow: "0 10px 26px rgba(40,80,130,.18)",
|
||
}),
|
||
};
|
||
|
||
return (
|
||
<div style={{ position: "relative" }}>
|
||
<div
|
||
className={
|
||
variant === "dashed" ? "pp-dd-trigger-dashed" : "pp-dd-trigger"
|
||
}
|
||
onClick={onToggle}
|
||
style={{
|
||
height: triggerHeight,
|
||
background: triggerBg,
|
||
borderRadius: 6,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "space-between",
|
||
padding: "0 13px",
|
||
fontFamily: mono ? tokens.font.mono : tokens.font.sans,
|
||
fontSize: triggerFontSize,
|
||
color: triggerColor,
|
||
cursor: "pointer",
|
||
}}
|
||
>
|
||
{value}
|
||
<span
|
||
style={{
|
||
color: caretColor,
|
||
fontSize: 9,
|
||
fontFamily: tokens.font.sans,
|
||
}}
|
||
>
|
||
▼
|
||
</span>
|
||
</div>
|
||
{open && (
|
||
<div style={panelStyle}>
|
||
{options.map((o) => (
|
||
<div
|
||
key={o}
|
||
className="pp-dd-opt"
|
||
onClick={() => onSelect(o)}
|
||
style={{
|
||
padding: "7px 10px",
|
||
fontSize: optionFontSize,
|
||
fontFamily: mono ? tokens.font.mono : tokens.font.sans,
|
||
borderRadius: 4,
|
||
cursor: "pointer",
|
||
color: o === value ? tokens.accent : tokens.ink,
|
||
fontWeight: o === value ? 600 : 400,
|
||
}}
|
||
>
|
||
{o}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
);
|
||
}
|
||
|
||
const styles = `
|
||
@keyframes pp-pulsedot{0%,100%{opacity:.45}50%{opacity:1}}
|
||
.pp-dot{animation:pp-pulsedot 2.6s ease-in-out infinite}
|
||
.pp-dd-trigger{border:1px solid ${tokens.line};transition:border-color .15s}
|
||
.pp-dd-trigger:hover{border-color:${tokens.accent}}
|
||
.pp-dd-trigger-dashed{border:1px dashed ${tokens.line};transition:border-color .15s}
|
||
.pp-dd-trigger-dashed:hover{border-color:${tokens.accent}}
|
||
.pp-dd-opt{transition:background .15s}
|
||
.pp-dd-opt:hover{background:rgba(46,139,255,.1)}
|
||
.pp-eval-btn{background:linear-gradient(90deg,rgba(255,255,255,.7),rgba(233,242,252,.7));box-shadow:0 0 0 0 rgba(46,139,255,0);transition:all .18s}
|
||
.pp-eval-btn:hover{background:linear-gradient(90deg,rgba(46,139,255,.12),rgba(46,139,255,.18));box-shadow:0 6px 22px rgba(46,139,255,.28)}
|
||
.pp-eval-btn:active{transform:translateY(1px)}
|
||
`;
|
||
|
||
const hintLabel: CSSProperties = {
|
||
fontSize: 9.5,
|
||
letterSpacing: 1.5,
|
||
color: tokens.muted2,
|
||
marginBottom: 3,
|
||
};
|
||
|
||
const optHint: CSSProperties = {
|
||
fontSize: 9,
|
||
color: tokens.muted4,
|
||
};
|
||
|
||
const fieldRow: CSSProperties = {
|
||
display: "grid",
|
||
gridTemplateColumns: "1fr 1fr",
|
||
gap: 12,
|
||
};
|
||
|
||
const textField: CSSProperties = {
|
||
height: 33,
|
||
background: tokens.surface.w62,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 6,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
padding: "0 13px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 14,
|
||
};
|
||
|
||
export default function ParamsPanel() {
|
||
const [openDd, setOpenDd] = useState<DdKey>(null);
|
||
const [rooms, setRooms] = useState(object.rooms);
|
||
const [houseType, setHouseType] = useState(object.houseType);
|
||
const [repair, setRepair] = useState(object.repair);
|
||
const [radius, setRadius] = useState("500 м");
|
||
const [crm, setCrm] = useState(dropdownOptions.crm[0]);
|
||
const [balcony, setBalcony] = useState(object.balcony);
|
||
|
||
const toggle = (k: Exclude<DdKey, null>) =>
|
||
setOpenDd((cur) => (cur === k ? null : k));
|
||
const pick = (setter: (v: string) => void) => (v: string) => {
|
||
setter(v);
|
||
setOpenDd(null);
|
||
};
|
||
|
||
const balOn: CSSProperties = {
|
||
border: `1px solid ${tokens.accent}`,
|
||
color: tokens.accent,
|
||
fontWeight: 600,
|
||
background: "rgba(46,139,255,.1)",
|
||
};
|
||
const balOff: CSSProperties = {
|
||
border: `1px solid ${tokens.line}`,
|
||
color: tokens.muted,
|
||
fontWeight: 400,
|
||
background: "transparent",
|
||
};
|
||
const balBase: CSSProperties = {
|
||
flex: 1,
|
||
borderRadius: 6,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
fontSize: 11,
|
||
letterSpacing: 1,
|
||
cursor: "pointer",
|
||
transition: "all .15s",
|
||
};
|
||
|
||
return (
|
||
<div
|
||
style={{
|
||
position: "relative",
|
||
background: tokens.surface.w50,
|
||
backdropFilter: "blur(6px)",
|
||
border: `1px solid ${tokens.line2}`,
|
||
borderRadius: 8,
|
||
padding: "16px 18px",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
}}
|
||
>
|
||
<style>{styles}</style>
|
||
|
||
{/* HUD corner brackets */}
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: -1,
|
||
top: -1,
|
||
width: 13,
|
||
height: 13,
|
||
borderLeft: `1.5px solid ${tokens.bracket}`,
|
||
borderTop: `1.5px solid ${tokens.bracket}`,
|
||
}}
|
||
/>
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
right: -1,
|
||
bottom: -1,
|
||
width: 13,
|
||
height: 13,
|
||
borderRight: `1.5px solid ${tokens.bracket}`,
|
||
borderBottom: `1.5px solid ${tokens.bracket}`,
|
||
}}
|
||
/>
|
||
|
||
{/* header */}
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "baseline",
|
||
justifyContent: "space-between",
|
||
marginBottom: 13,
|
||
}}
|
||
>
|
||
<div style={{ display: "flex", alignItems: "baseline", gap: 10 }}>
|
||
<span
|
||
style={{
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 15,
|
||
color: tokens.accent,
|
||
}}
|
||
>
|
||
01
|
||
</span>
|
||
<span style={{ fontSize: 13, fontWeight: 600, letterSpacing: 2 }}>
|
||
ПАРАМЕТРЫ КВАРТИРЫ
|
||
</span>
|
||
</div>
|
||
<span
|
||
style={{
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 10,
|
||
letterSpacing: 1,
|
||
color: tokens.muted2,
|
||
}}
|
||
>
|
||
ШАГ 1/1
|
||
</span>
|
||
</div>
|
||
|
||
{/* MAP */}
|
||
<div
|
||
style={{
|
||
position: "relative",
|
||
height: 140,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 6,
|
||
overflow: "hidden",
|
||
background: tokens.mapBg,
|
||
flex: "0 0 auto",
|
||
}}
|
||
>
|
||
<svg
|
||
viewBox="0 0 440 210"
|
||
preserveAspectRatio="xMidYMid slice"
|
||
style={{
|
||
position: "absolute",
|
||
inset: 0,
|
||
width: "100%",
|
||
height: "100%",
|
||
}}
|
||
>
|
||
<rect width="440" height="210" fill="#e6edf4" />
|
||
<g stroke="#dbe5ef" strokeWidth={1}>
|
||
<path d="M0 38H440M0 78H440M0 118H440M0 158H440M0 198H440" />
|
||
<path d="M40 0V210M110 0V210M180 0V210M250 0V210M320 0V210M390 0V210" />
|
||
</g>
|
||
<g stroke="#f5f8fc" strokeWidth={8} strokeLinecap="round">
|
||
<path d="M-10 92 H450" />
|
||
<path d="M150 -10 V220" />
|
||
<path d="M-10 30 L260 0" />
|
||
</g>
|
||
<g stroke="#eef3f9" strokeWidth={5}>
|
||
<path d="M300 -10 L470 150" />
|
||
<path d="M-10 170 H450" />
|
||
</g>
|
||
<path d="M150 92 L470 200" stroke="#cfe0f3" strokeWidth={6} />
|
||
<g fill="none" stroke="#2e8bff" strokeDasharray="3 4">
|
||
<circle cx="208" cy="100" r="44" opacity={0.55} />
|
||
<circle cx="208" cy="100" r="80" opacity={0.4} />
|
||
<circle cx="208" cy="100" r="112" opacity={0.28} />
|
||
</g>
|
||
<circle cx="208" cy="100" r="80" fill="#2e8bff" opacity={0.04} />
|
||
</svg>
|
||
|
||
{/* center pin */}
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: "47%",
|
||
top: "48%",
|
||
transform: "translate(-50%,-100%)",
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
alignItems: "center",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 6,
|
||
background: tokens.surface.w85,
|
||
border: `1px solid ${tokens.accent}`,
|
||
borderRadius: 4,
|
||
padding: "4px 8px",
|
||
whiteSpace: "nowrap",
|
||
boxShadow: "0 3px 10px rgba(46,139,255,.25)",
|
||
}}
|
||
>
|
||
<span
|
||
style={{
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: "50%",
|
||
background: tokens.accent,
|
||
}}
|
||
/>
|
||
<span style={{ fontSize: 11, fontWeight: 600 }}>
|
||
{object.address}
|
||
</span>
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 0,
|
||
height: 0,
|
||
borderLeft: "5px solid transparent",
|
||
borderRight: "5px solid transparent",
|
||
borderTop: `7px solid ${tokens.accent}`,
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
{/* analog price pins */}
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: "5%",
|
||
top: "13%",
|
||
background: tokens.surface.w70,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
padding: "3px 7px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 9,
|
||
lineHeight: 1.4,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
12,7 млн ₽<br />
|
||
<span style={{ color: tokens.muted }}>54 м²</span>
|
||
</div>
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
right: "32%",
|
||
top: "8%",
|
||
background: tokens.surface.w70,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
padding: "3px 7px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 9,
|
||
lineHeight: 1.4,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
7,6 млн ₽<br />
|
||
<span style={{ color: tokens.muted }}>44 м²</span>
|
||
</div>
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
right: "3%",
|
||
top: "36%",
|
||
background: tokens.surface.w70,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
padding: "3px 7px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 9,
|
||
lineHeight: 1.4,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
22,4 млн ₽<br />
|
||
<span style={{ color: tokens.muted }}>55 м²</span>
|
||
</div>
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: "13%",
|
||
bottom: "9%",
|
||
background: tokens.surface.w70,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
padding: "3px 7px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 9,
|
||
lineHeight: 1.4,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
15,9 млн ₽<br />
|
||
<span style={{ color: tokens.muted }}>55 м²</span>
|
||
</div>
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
right: "14%",
|
||
bottom: "11%",
|
||
background: tokens.surface.w70,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
padding: "3px 7px",
|
||
fontFamily: tokens.font.mono,
|
||
fontSize: 9,
|
||
lineHeight: 1.4,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
14,9 млн ₽<br />
|
||
<span style={{ color: tokens.muted }}>56 м²</span>
|
||
</div>
|
||
|
||
{/* analog dots */}
|
||
<span
|
||
style={{
|
||
position: "absolute",
|
||
left: "18%",
|
||
top: "30%",
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: "50%",
|
||
background: tokens.accent,
|
||
border: `1.5px solid ${tokens.dotStroke}`,
|
||
}}
|
||
/>
|
||
<span
|
||
style={{
|
||
position: "absolute",
|
||
right: "34%",
|
||
top: "28%",
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: "50%",
|
||
background: tokens.dealDot,
|
||
border: `1.5px solid ${tokens.dotStroke}`,
|
||
}}
|
||
/>
|
||
<span
|
||
style={{
|
||
position: "absolute",
|
||
left: "30%",
|
||
bottom: "24%",
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: "50%",
|
||
background: tokens.accent,
|
||
border: `1.5px solid ${tokens.dotStroke}`,
|
||
}}
|
||
/>
|
||
|
||
{/* map controls */}
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
right: 9,
|
||
bottom: 9,
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
gap: 5,
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
width: 24,
|
||
height: 24,
|
||
background: tokens.surface.w80,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
cursor: "pointer",
|
||
transition: "all .15s",
|
||
fontSize: 15,
|
||
color: tokens.muted,
|
||
}}
|
||
>
|
||
+
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 24,
|
||
height: 24,
|
||
background: tokens.surface.w80,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
cursor: "pointer",
|
||
transition: "all .15s",
|
||
fontSize: 15,
|
||
color: tokens.muted,
|
||
}}
|
||
>
|
||
−
|
||
</div>
|
||
<div
|
||
style={{
|
||
width: 24,
|
||
height: 24,
|
||
background: tokens.surface.w80,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 4,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
cursor: "pointer",
|
||
transition: "all .15s",
|
||
color: tokens.accent,
|
||
}}
|
||
>
|
||
<svg width="13" height="13" viewBox="0 0 13 13" fill="none">
|
||
<circle cx="6.5" cy="6.5" r="4" stroke="#2e8bff" />
|
||
<line x1="6.5" y1="0" x2="6.5" y2="2.5" stroke="#2e8bff" />
|
||
<line x1="6.5" y1="10.5" x2="6.5" y2="13" stroke="#2e8bff" />
|
||
<line x1="0" y1="6.5" x2="2.5" y2="6.5" stroke="#2e8bff" />
|
||
<line x1="10.5" y1="6.5" x2="13" y2="6.5" stroke="#2e8bff" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
{/* map corner bracket */}
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: 8,
|
||
top: 8,
|
||
width: 12,
|
||
height: 12,
|
||
borderLeft: `1.5px solid ${tokens.accent}`,
|
||
borderTop: `1.5px solid ${tokens.accent}`,
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
{/* radius row */}
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 14,
|
||
marginTop: 13,
|
||
flex: "0 0 auto",
|
||
}}
|
||
>
|
||
<span style={{ fontSize: 10, letterSpacing: 1.5, color: tokens.muted }}>
|
||
РАДИУС АНАЛИЗА
|
||
</span>
|
||
<div style={{ position: "relative" }}>
|
||
<div
|
||
onClick={() => toggle("radius")}
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 8,
|
||
background: tokens.surface.w60,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 5,
|
||
padding: "6px 10px",
|
||
fontSize: 12,
|
||
fontFamily: tokens.font.mono,
|
||
cursor: "pointer",
|
||
}}
|
||
>
|
||
<span>{radius}</span>
|
||
<span style={{ color: tokens.muted2, fontSize: 9 }}>▼</span>
|
||
</div>
|
||
{openDd === "radius" && (
|
||
<div
|
||
style={{
|
||
position: "absolute",
|
||
left: 0,
|
||
right: 0,
|
||
top: "calc(100% + 4px)",
|
||
background: tokens.surface.w98,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 6,
|
||
boxShadow: "0 10px 26px rgba(40,80,130,.18)",
|
||
zIndex: 30,
|
||
padding: 3,
|
||
minWidth: 78,
|
||
}}
|
||
>
|
||
{dropdownOptions.radius.map((o) => (
|
||
<div
|
||
key={o}
|
||
className="pp-dd-opt"
|
||
onClick={() => pick(setRadius)(o)}
|
||
style={{
|
||
padding: "7px 10px",
|
||
fontSize: 13,
|
||
fontFamily: tokens.font.mono,
|
||
borderRadius: 4,
|
||
cursor: "pointer",
|
||
color: o === radius ? tokens.accent : tokens.ink,
|
||
fontWeight: o === radius ? 600 : 400,
|
||
}}
|
||
>
|
||
{o}
|
||
</div>
|
||
))}
|
||
</div>
|
||
)}
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 16,
|
||
fontSize: 10.5,
|
||
color: tokens.muted,
|
||
marginLeft: "auto",
|
||
}}
|
||
>
|
||
<span style={{ display: "flex", alignItems: "center", gap: 6 }}>
|
||
<span
|
||
style={{
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: "50%",
|
||
background: tokens.accent,
|
||
}}
|
||
/>
|
||
Объявления
|
||
</span>
|
||
<span style={{ display: "flex", alignItems: "center", gap: 6 }}>
|
||
<span
|
||
style={{
|
||
width: 8,
|
||
height: 8,
|
||
borderRadius: "50%",
|
||
background: tokens.dealDot,
|
||
}}
|
||
/>
|
||
Сделки
|
||
</span>
|
||
</div>
|
||
</div>
|
||
|
||
{/* INPUTS */}
|
||
<div
|
||
style={{
|
||
marginTop: 10,
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
gap: 5,
|
||
flex: 1,
|
||
minHeight: 0,
|
||
}}
|
||
>
|
||
<div>
|
||
<div style={hintLabel}>АДРЕС (YANDEX / NOMINATIM)</div>
|
||
<div style={{ position: "relative" }}>
|
||
<div
|
||
style={{
|
||
height: 33,
|
||
background: tokens.surface.w62,
|
||
border: `1px solid ${tokens.line}`,
|
||
borderRadius: 6,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
padding: "0 38px 0 13px",
|
||
fontSize: 13,
|
||
color: tokens.ink,
|
||
}}
|
||
>
|
||
{object.address} · Куйбышева, 48…
|
||
</div>
|
||
<svg
|
||
style={{
|
||
position: "absolute",
|
||
right: 12,
|
||
top: "50%",
|
||
transform: "translateY(-50%)",
|
||
}}
|
||
width="15"
|
||
height="15"
|
||
viewBox="0 0 15 15"
|
||
fill="none"
|
||
>
|
||
<circle cx="7.5" cy="7.5" r="4.5" stroke="#2e8bff" />
|
||
<line x1="7.5" y1="0" x2="7.5" y2="3" stroke="#2e8bff" />
|
||
<line x1="7.5" y1="12" x2="7.5" y2="15" stroke="#2e8bff" />
|
||
<line x1="0" y1="7.5" x2="3" y2="7.5" stroke="#2e8bff" />
|
||
<line x1="12" y1="7.5" x2="15" y2="7.5" stroke="#2e8bff" />
|
||
</svg>
|
||
</div>
|
||
</div>
|
||
|
||
<div style={fieldRow}>
|
||
<div>
|
||
<div style={hintLabel}>ПЛОЩАДЬ, М²</div>
|
||
<div style={textField}>{object.area}</div>
|
||
</div>
|
||
<div>
|
||
<div style={hintLabel}>КОМНАТ</div>
|
||
<Dd
|
||
open={openDd === "rooms"}
|
||
onToggle={() => toggle("rooms")}
|
||
value={rooms}
|
||
options={dropdownOptions.rooms}
|
||
onSelect={pick(setRooms)}
|
||
mono
|
||
triggerFontSize={14}
|
||
optionFontSize={13}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div style={fieldRow}>
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>ЭТАЖ</span>
|
||
<span style={optHint}>если знаешь</span>
|
||
</div>
|
||
<div style={textField}>{object.floor}</div>
|
||
</div>
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>ВСЕГО ЭТАЖЕЙ</span>
|
||
<span style={optHint}>если знаешь</span>
|
||
</div>
|
||
<div style={textField}>{object.totalFloors}</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div
|
||
style={{
|
||
fontSize: 10,
|
||
color: tokens.hint,
|
||
lineHeight: 1.4,
|
||
marginTop: -3,
|
||
}}
|
||
>
|
||
1-й и последний этаж снижают цену на 5–10% — заполни если знаешь
|
||
</div>
|
||
|
||
<div style={fieldRow}>
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>ГОД ПОСТРОЙКИ</span>
|
||
<span style={optHint}>опц.</span>
|
||
</div>
|
||
<div style={textField}>{object.year}</div>
|
||
</div>
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>ТИП ДОМА</span>
|
||
<span style={optHint}>опц.</span>
|
||
</div>
|
||
<Dd
|
||
open={openDd === "houseType"}
|
||
onToggle={() => toggle("houseType")}
|
||
value={houseType}
|
||
options={dropdownOptions.houseType}
|
||
onSelect={pick(setHouseType)}
|
||
mono={false}
|
||
triggerFontSize={13}
|
||
optionFontSize={12}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<div style={fieldRow}>
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>СОСТОЯНИЕ РЕМОНТА</span>
|
||
<span style={optHint}>опц.</span>
|
||
</div>
|
||
<Dd
|
||
open={openDd === "repair"}
|
||
onToggle={() => toggle("repair")}
|
||
value={repair}
|
||
options={dropdownOptions.repair}
|
||
onSelect={pick(setRepair)}
|
||
mono={false}
|
||
triggerFontSize={13}
|
||
optionFontSize={12}
|
||
/>
|
||
</div>
|
||
<div>
|
||
<div style={hintLabel}>БАЛКОН / ЛОДЖИЯ</div>
|
||
<div style={{ height: 40, display: "flex", gap: 6 }}>
|
||
<div
|
||
onClick={() => setBalcony(false)}
|
||
style={{ ...balBase, ...(balcony ? balOff : balOn) }}
|
||
>
|
||
НЕТ
|
||
</div>
|
||
<div
|
||
onClick={() => setBalcony(true)}
|
||
style={{ ...balBase, ...(balcony ? balOn : balOff) }}
|
||
>
|
||
ДА
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div>
|
||
<div style={{ display: "flex", justifyContent: "space-between" }}>
|
||
<span style={hintLabel}>CRM — ДЛЯ МЕНЕДЖЕРА</span>
|
||
<span style={optHint}>опц.</span>
|
||
</div>
|
||
<Dd
|
||
open={openDd === "crm"}
|
||
onToggle={() => toggle("crm")}
|
||
value={crm}
|
||
options={dropdownOptions.crm}
|
||
onSelect={pick(setCrm)}
|
||
mono={false}
|
||
triggerFontSize={12}
|
||
optionFontSize={12}
|
||
variant="dashed"
|
||
openUp
|
||
triggerHeight={34}
|
||
triggerBg={tokens.surface.w50}
|
||
triggerColor={tokens.hint}
|
||
caretColor={tokens.muted4}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
{/* button */}
|
||
<button
|
||
type="button"
|
||
className="pp-eval-btn"
|
||
style={{
|
||
marginTop: 9,
|
||
height: 46,
|
||
width: "100%",
|
||
border: `1px solid ${tokens.accent}`,
|
||
borderRadius: 7,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
position: "relative",
|
||
cursor: "pointer",
|
||
fontFamily: tokens.font.sans,
|
||
color: tokens.ink,
|
||
flex: "0 0 auto",
|
||
}}
|
||
>
|
||
<span style={{ fontSize: 14, fontWeight: 600, letterSpacing: 3 }}>
|
||
ОЦЕНИТЬ КВАРТИРУ
|
||
</span>
|
||
<span
|
||
style={{
|
||
position: "absolute",
|
||
right: 16,
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "center",
|
||
width: 26,
|
||
height: 26,
|
||
border: `1px solid ${tokens.accent}`,
|
||
borderRadius: "50%",
|
||
color: tokens.accent,
|
||
}}
|
||
>
|
||
→
|
||
</span>
|
||
</button>
|
||
|
||
{/* cache status */}
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
justifyContent: "space-between",
|
||
marginTop: 11,
|
||
flex: "0 0 auto",
|
||
fontSize: 9.5,
|
||
letterSpacing: 1.5,
|
||
color: tokens.muted2,
|
||
}}
|
||
>
|
||
<span>КЭШ ПО АДРЕСУ — 24 Ч</span>
|
||
<span
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
gap: 6,
|
||
color: tokens.success,
|
||
}}
|
||
>
|
||
<span
|
||
className="pp-dot"
|
||
style={{
|
||
width: 7,
|
||
height: 7,
|
||
borderRadius: "50%",
|
||
background: tokens.success,
|
||
boxShadow: `0 0 6px ${tokens.success}`,
|
||
}}
|
||
/>
|
||
ГОТОВ
|
||
</span>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|