brickwise 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/app/favorites/page.tsx +43 -11
- package/src/app/globals.css +6 -6
package/package.json
CHANGED
|
@@ -38,15 +38,27 @@ function matchesBedFilter(r: { bedrooms: number | null }, bedFilter: number[]):
|
|
|
38
38
|
return bedFilter.length === 0 || (r.bedrooms != null && bedFilter.includes(r.bedrooms));
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Relative color scale: red (lowest yield in the set) → turquoise (highest).
|
|
43
|
+
* Absolute thresholds made every Dubai listing green because yields are all high;
|
|
44
|
+
* scaling to the actual min/max makes the differences readable on the map.
|
|
45
|
+
*/
|
|
46
|
+
function yieldColor(y: number | null, min: number, max: number): string {
|
|
47
|
+
if (y == null) return "#8a8a8a";
|
|
48
|
+
const t = max > min ? Math.min(1, Math.max(0, (y - min) / (max - min))) : 0.5;
|
|
49
|
+
const hue = t * 174; // 0° red → 174° turquoise
|
|
50
|
+
return `hsl(${Math.round(hue)}, 66%, 44%)`;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
/** Min/max of the located favorites' yields, for the relative color scale. */
|
|
54
|
+
function yieldRange(rows: FavRow[] | null): { min: number; max: number } {
|
|
55
|
+
const ys = (rows ?? [])
|
|
56
|
+
.filter((r) => r.lat != null && r.lon != null && r.gross_yield != null)
|
|
57
|
+
.map((r) => r.gross_yield as number);
|
|
58
|
+
return ys.length ? { min: Math.min(...ys), max: Math.max(...ys) } : { min: 0, max: 1 };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function popupHtml(r: FavRow, min: number, max: number): string {
|
|
50
62
|
const img = r.images?.[0]?.medium || r.images?.[0]?.small;
|
|
51
63
|
const yieldTxt = r.gross_yield != null ? (r.gross_yield * 100).toFixed(1) + " %" : "sin datos";
|
|
52
64
|
return `
|
|
@@ -55,7 +67,7 @@ function popupHtml(r: FavRow): string {
|
|
|
55
67
|
<div style="font-weight:600;margin-top:6px;line-height:1.3">${r.title}</div>
|
|
56
68
|
<div style="color:#666;font-size:12px;margin-top:2px">${r.tower_name ?? ""}</div>
|
|
57
69
|
<div style="margin-top:4px;font-size:14px">
|
|
58
|
-
Rentabilidad: <span style="color:${yieldColor(r.gross_yield)};font-weight:700">${yieldTxt}</span>
|
|
70
|
+
Rentabilidad: <span style="color:${yieldColor(r.gross_yield, min, max)};font-weight:700">${yieldTxt}</span>
|
|
59
71
|
</div>
|
|
60
72
|
<div style="margin-top:6px;display:flex;gap:10px;font-size:12px">
|
|
61
73
|
<a href="/listing/${r.id}">Ver análisis</a>
|
|
@@ -193,19 +205,20 @@ export default function FavoritesMapPage() {
|
|
|
193
205
|
if (!L || !map || !mapReady || !rows) return;
|
|
194
206
|
Object.values(markersRef.current).forEach((m) => m.remove());
|
|
195
207
|
markersRef.current = {};
|
|
208
|
+
const { min, max } = yieldRange(rows);
|
|
196
209
|
const bounds: [number, number][] = [];
|
|
197
210
|
for (const r of rows) {
|
|
198
211
|
if (r.lat == null || r.lon == null) continue;
|
|
199
212
|
const y = r.gross_yield != null ? (r.gross_yield * 100).toFixed(1) + "%" : "—";
|
|
200
213
|
const icon = L.divIcon({
|
|
201
214
|
className: "",
|
|
202
|
-
html: `<div class="bw-pin" style="--pin-color:${yieldColor(r.gross_yield)}"><div class="bw-pin-label">${y}</div><div class="bw-pin-tail"></div></div>`,
|
|
215
|
+
html: `<div class="bw-pin" style="--pin-color:${yieldColor(r.gross_yield, min, max)}"><div class="bw-pin-label">${y}</div><div class="bw-pin-tail"></div></div>`,
|
|
203
216
|
iconSize: [0, 0],
|
|
204
217
|
iconAnchor: [0, 0],
|
|
205
218
|
});
|
|
206
219
|
const marker = L.marker([r.lat, r.lon], { icon })
|
|
207
220
|
.addTo(map)
|
|
208
|
-
.bindPopup(popupHtml(r), { maxWidth: 260, offset: [0, -34] });
|
|
221
|
+
.bindPopup(popupHtml(r, min, max), { maxWidth: 260, offset: [0, -34] });
|
|
209
222
|
marker.on("mouseover", () => {
|
|
210
223
|
setHoveredId(r.id);
|
|
211
224
|
document.getElementById(`fav-${r.id}`)?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
@@ -667,7 +680,26 @@ export default function FavoritesMapPage() {
|
|
|
667
680
|
/>
|
|
668
681
|
|
|
669
682
|
{/* ------------------------------------------------ map */}
|
|
670
|
-
<div
|
|
683
|
+
<div className="relative min-h-0 min-w-0 flex-1">
|
|
684
|
+
<div ref={containerRef} className="absolute inset-0" />
|
|
685
|
+
{(() => {
|
|
686
|
+
const { min, max } = yieldRange(rows);
|
|
687
|
+
if (!(max > min)) return null;
|
|
688
|
+
return (
|
|
689
|
+
<div className="pointer-events-none absolute bottom-4 left-3 z-[500] rounded border border-black/10 bg-white/90 px-2 py-1.5 text-[10px] text-neutral-700 shadow-lg dark:border-white/10 dark:bg-neutral-900/90 dark:text-neutral-200">
|
|
690
|
+
<div className="btn-font mb-1 text-[9px] text-neutral-500">Rentabilidad</div>
|
|
691
|
+
<div className="flex items-center gap-1.5">
|
|
692
|
+
<span>{(min * 100).toFixed(1)}%</span>
|
|
693
|
+
<span
|
|
694
|
+
className="h-2 w-24 rounded-sm"
|
|
695
|
+
style={{ background: `linear-gradient(90deg, hsl(0,66%,44%), hsl(87,66%,44%), hsl(174,66%,44%))` }}
|
|
696
|
+
/>
|
|
697
|
+
<span>{(max * 100).toFixed(1)}%</span>
|
|
698
|
+
</div>
|
|
699
|
+
</div>
|
|
700
|
+
);
|
|
701
|
+
})()}
|
|
702
|
+
</div>
|
|
671
703
|
</div>
|
|
672
704
|
);
|
|
673
705
|
}
|
package/src/app/globals.css
CHANGED
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
@theme {
|
|
29
|
-
/* Neutral dark grays anchored to the #
|
|
30
|
-
--color-neutral-950: #
|
|
31
|
-
--color-neutral-900: #
|
|
32
|
-
--color-neutral-800: #
|
|
33
|
-
--color-neutral-700: #
|
|
29
|
+
/* Neutral dark grays anchored to the #181818 background */
|
|
30
|
+
--color-neutral-950: #121212; /* deep insets / header */
|
|
31
|
+
--color-neutral-900: #181818; /* panels & cards == background */
|
|
32
|
+
--color-neutral-800: #2a2a2a; /* borders, dividers, hover (subtle) */
|
|
33
|
+
--color-neutral-700: #3a3a3a;
|
|
34
34
|
|
|
35
35
|
/* Brick accent — remaps every blue-* usage in the app to color ladrillo */
|
|
36
36
|
--color-blue-50: #faeee8;
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
|
|
59
59
|
@media (prefers-color-scheme: dark) {
|
|
60
60
|
:root {
|
|
61
|
-
--background: #
|
|
61
|
+
--background: #181818;
|
|
62
62
|
--foreground: #ededed;
|
|
63
63
|
}
|
|
64
64
|
}
|