// pages-deals.jsx — Appartements (filter+plan), Investir (simulator), Contact // ────────────────────────────────────────────────────────────────────────── // APPARTEMENTS — filterable // ────────────────────────────────────────────────────────────────────────── function AppartementsPage() { const { t, setTweak } = useTheme(); const [filters, setFilters] = useState({ floor: "all", type: "all", orientation: "all", status: "available", maxPrice: 200000 }); const [selected, setSelected] = useState(null); const filtered = LOTS.filter((l) => (filters.floor === "all" || l.floor === Number(filters.floor)) && ( filters.type === "all" || l.type === Number(filters.type)) && ( filters.orientation === "all" || l.orientation === filters.orientation) && ( filters.status === "all" || l.status === filters.status) && l.price <= filters.maxPrice ); return ( Huit T2, deux typologies,
chacun son orientation.} intro="Filtrez selon votre étage, votre orientation, votre budget. Cliquez un lot pour voir le plan détaillé et lancer la mise en option." />
{/* Filters */}
setFilters({ ...filters, floor: v })} /> setFilters({ ...filters, type: v })} /> setFilters({ ...filters, orientation: v })} /> setFilters({ ...filters, status: v })} /> setFilters({ ...filters, maxPrice: v })} />
{/* Result count + view switch */}
{filtered.length} appartement{filtered.length > 1 ? "s" : ""} correspondant{filtered.length > 1 ? "s" : ""}
{[["grid", "Grille"], ["table", "Tableau"], ["plan", "Plan masse"]].map(([k, label]) => )}
{/* Views */} {t.lotsView === "grid" &&
{filtered.map((lot) => )}
} {t.lotsView === "table" && } {t.lotsView === "plan" && } {filtered.length === 0 &&
Aucun lot ne correspond à vos critères.
}
{selected && setSelected(null)} />}
); } function FilterSelect({ label, value, options, onChange }) { return ( ); } function FilterSlider({ label, value, min, max, step, onChange }) { return ( ); } function LotCard({ lot, onSelect }) { return (
onSelect(lot)} style={{ background: "var(--surface)", border: "1px solid var(--line)", cursor: lot.status === "sold" ? "not-allowed" : "pointer", opacity: lot.status === "sold" ? 0.55 : 1, transition: "transform .25s ease, box-shadow .25s ease" }} onMouseEnter={(e) => {if (lot.status !== "sold") {e.currentTarget.style.transform = "translateY(-4px)";e.currentTarget.style.boxShadow = "0 30px 60px -30px rgba(31,27,22,.25)";}}} onMouseLeave={(e) => {e.currentTarget.style.transform = "translateY(0)";e.currentTarget.style.boxShadow = "none";}}>
Type {lot.type}
Lot {lot.id}
{lot.floor}{lot.floor === 1 ? "er" : "e"} étage
{fmtPrice(lot.price)}
{fmtN(lot.price / lot.surface)} €/m²
« {lot.exposure} »
); } function SpecCell({ label, value }) { return (
{label}
{value}
); } function LotTable({ lots, onSelect }) { return (
LotÉtageTypeSurfaceLoggiaOrientationExpositionPrixStatut
{lots.map((lot) => )}
); } function PlanMasse({ lots, onSelect }) { // 2 floors (R+1, R+2) x 4 columns; render as wireframe-ish floor plates const floors = [2, 1]; return (
{floors.map((f) =>
R+{f}
{LOTS.filter((l) => l.floor === f).map((l) => { const inFilter = lots.some((x) => x.id === l.id); const color = !inFilter ? "var(--bg2)" : l.status === "sold" ? "var(--muted)" : l.status === "optioned" ? "var(--ink2)" : "var(--accent)"; return ( ); })}
)}
); } function LegendItem({ color, label }) { return ( {label} ); } function LotModal({ lot, onClose }) { useEffect(() => { const onEsc = (e) => e.key === "Escape" && onClose(); document.addEventListener("keydown", onEsc); document.body.style.overflow = "hidden"; return () => {document.removeEventListener("keydown", onEsc);document.body.style.overflow = "";}; }, [onClose]); return (
e.stopPropagation()} style={{ background: "var(--bg)", maxWidth: 1080, width: "100%", maxHeight: "90vh", overflow: "auto", display: "grid", gridTemplateColumns: "1.2fr 1fr", boxShadow: "0 40px 80px -20px rgba(0,0,0,.4)" }}>
Lot {lot.id} · R+{lot.floor} · Type {lot.type}

T2 · {lot.surface} m²

« {lot.exposure} »
Prix TTC {fmtPrice(lot.price)}
{fmtN(lot.price / lot.surface)} €/m² · compromis chez le notaire · frais notariés réduits
Loyer estimé HT
{lot.loyer} € /mois
Rendement brut
{lot.renta.toFixed(2).replace(".", ",")} %
); } function SpecBox({ label, value }) { return (
{label}
{value}
); } // ────────────────────────────────────────────────────────────────────────── // INVESTIR — simulator // ────────────────────────────────────────────────────────────────────────── function InvestirPage() { const [price, setPrice] = useState(190000); const [apport, setApport] = useState(30000); const [duree, setDuree] = useState(20); const [taux, setTaux] = useState(3.6); const [loyer, setLoyer] = useState(640); const emprunt = Math.max(0, price - apport); const mensualite = useMemo(() => { const r = taux / 100 / 12; const n = duree * 12; if (r === 0) return emprunt / n; return emprunt * r / (1 - Math.pow(1 + r, -n)); }, [emprunt, taux, duree]); const rentaBrute = loyer * 12 / price * 100; const cashflow = loyer - mensualite - 80; // rough charges return ( Un T2 à Orange,
c'est mathématique.} intro="Sur la grille NOVA, le rendement brut s'échelonne de 3,96 % (A24) à 4,11 % (A12) selon le lot, pour des loyers estimés de 580 à 660 € HT mensuels. Voici, en deux minutes, ce que peut donner un placement dans la résidence." />
{/* Inputs */}
Vos hypothèses v + " €"} />
{/* Outputs */}
Le résultat
= 0 ? "+" : "") + fmtN(cashflow) + " €"} label="Cashflow mensuel estimé" tone={cashflow >= 0 ? "positive" : "negative"} />
Note : simulation indicative. Charges, fiscalité et amortissement (LMNP) à valider avec votre conseiller. Nous vous mettons en relation avec notre partenaire courtier sur simple demande.
); } function SimInput({ label, value, setValue, min, max, step, unit, fmt }) { return (
{label} {fmt ? fmt(value) : `${value} ${unit || ""}`}
setValue(Number(e.target.value))} style={{ width: "100%", marginTop: 8, accentColor: "var(--accent)" }} />
{fmt ? fmt(min) : `${min} ${unit || ""}`} {fmt ? fmt(max) : `${max} ${unit || ""}`}
); } function ResultBlock({ value, label, big, tone }) { const color = tone === "positive" ? "var(--accent)" : tone === "negative" ? "var(--accent-dark)" : "var(--ink)"; return (
{value}
{label}
); } function DispositifCard({ tag, title, body, kpi, kpiLabel }) { return (
{tag}

{title}

{body}

{kpi}
{kpiLabel}
); } // ────────────────────────────────────────────────────────────────────────── // CONTACT // ────────────────────────────────────────────────────────────────────────── function ContactPage() { const [form, setForm] = useState({ nom: "", email: "", tel: "", projet: "habiter", message: "", consent: false }); const [submitted, setSubmitted] = useState(false); const submit = (e) => { e.preventDefault(); if (!form.nom || !form.email || !form.consent) return; setSubmitted(true); }; return ( Une question, une visite,
une plaquette ?} intro="Réponse sous 24 h ouvrées. Anne Magnoni, conseillère Myamo Développement, vous accompagne de la première question à la signature chez le notaire." />
{/* Form */}
{submitted ?

Merci, {form.nom.split(" ")[0]}.

Votre demande est bien reçue. Anne vous rappelle sous 24 h ouvrées au numéro indiqué, et vous a envoyé la plaquette commerciale à l'adresse {form.email}.

:
setForm({ ...form, nom: v })} required /> setForm({ ...form, email: v })} required /> setForm({ ...form, tel: v })} /> setForm({ ...form, projet: v })} options={[["habiter", "Habiter la résidence"], ["investir", "Investir (locatif)"], ["secondaire", "Résidence secondaire"], ["autre", "Autre"]]} /> setForm({ ...form, message: v })} placeholder="Vos questions, votre étage préféré, votre budget, vos disponibilités…" />
· Réponse sous 24 h
}
{/* Sidebar */}
); } function FormRow({ children }) { return
{children}
; } function FormField({ label, value, onChange, type = "text", placeholder, required }) { const Tag = type === "textarea" ? "textarea" : "input"; return ( ); } function FormSelect({ label, value, onChange, options }) { return ( ); } // expose Object.assign(window, { AppartementsPage, InvestirPage, ContactPage });