diff --git a/apps/web/components/map/listing-map.tsx b/apps/web/components/map/listing-map.tsx
index 511f3f6..df681a1 100644
--- a/apps/web/components/map/listing-map.tsx
+++ b/apps/web/components/map/listing-map.tsx
@@ -104,7 +104,10 @@ export function ListingMap({ listings, onMarkerClick, selectedListingId, classNa
const el = document.createElement('button');
el.className = 'mapbox-price-marker';
const isSelected = selectedListingId === marker.listing.id;
- el.innerHTML = `${formatPrice(marker.listing.priceVND)}`;
+ const span = document.createElement('span');
+ if (isSelected) span.className = 'selected';
+ span.textContent = formatPrice(marker.listing.priceVND);
+ el.appendChild(span);
el.style.cssText = 'border:none;cursor:pointer;background:none;padding:0;';
el.addEventListener('click', (e) => {
@@ -129,38 +132,71 @@ export function ListingMap({ listings, onMarkerClick, selectedListingId, classNa
}
}, [markers, selectedListingId, onMarkerClick]);
+ function buildPopupContent(listing: ListingDetail): HTMLDivElement {
+ const container = document.createElement('div');
+ container.style.fontFamily = 'system-ui,sans-serif';
+
+ if (listing.property.media.length > 0) {
+ const img = document.createElement('img');
+ img.src = listing.property.media[0]!.url;
+ img.alt = listing.property.title;
+ img.style.cssText = 'width:100%;height:96px;object-fit:cover;border-radius:6px;margin-bottom:8px;';
+ container.appendChild(img);
+ }
+
+ const price = document.createElement('p');
+ price.style.cssText = 'font-weight:700;color:hsl(142.1,76.2%,36.3%);font-size:14px;margin:0 0 4px;';
+ price.textContent = `${formatPrice(listing.priceVND)} VND`;
+ container.appendChild(price);
+
+ const title = document.createElement('p');
+ title.style.cssText = 'font-size:13px;font-weight:500;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
+ title.textContent = listing.property.title;
+ container.appendChild(title);
+
+ const location = document.createElement('p');
+ location.style.cssText = 'font-size:12px;color:#666;margin:0 0 8px;';
+ location.textContent = `${listing.property.district}, ${listing.property.city}`;
+ container.appendChild(location);
+
+ const details = document.createElement('div');
+ details.style.cssText = 'display:flex;gap:4px;font-size:11px;margin-bottom:8px;';
+ const tagStyle = 'background:#f1f5f9;padding:2px 6px;border-radius:4px;';
+
+ const areaTag = document.createElement('span');
+ areaTag.style.cssText = tagStyle;
+ areaTag.textContent = `${listing.property.areaM2} m\u00B2`;
+ details.appendChild(areaTag);
+
+ if (listing.property.bedrooms != null) {
+ const bedTag = document.createElement('span');
+ bedTag.style.cssText = tagStyle;
+ bedTag.textContent = `${listing.property.bedrooms} PN`;
+ details.appendChild(bedTag);
+ }
+ if (listing.property.bathrooms != null) {
+ const bathTag = document.createElement('span');
+ bathTag.style.cssText = tagStyle;
+ bathTag.textContent = `${listing.property.bathrooms} WC`;
+ details.appendChild(bathTag);
+ }
+ container.appendChild(details);
+
+ const link = document.createElement('a');
+ link.href = `/listings/${listing.id}`;
+ link.style.cssText = 'display:block;text-align:center;font-size:12px;font-weight:500;color:hsl(142.1,76.2%,36.3%);text-decoration:none;';
+ link.textContent = 'Xem chi ti\u1EBFt \u2192';
+ container.appendChild(link);
+
+ return container;
+ }
+
function showPopup(map: mapboxgl.Map, marker: MapMarker) {
popupRef.current?.remove();
- const { listing } = marker;
- const imgHtml = listing.property.media.length > 0
- ? ``
- : '';
-
const popup = new mapboxgl.Popup({ offset: 25, maxWidth: '260px', closeButton: true })
.setLngLat([marker.lng, marker.lat])
- .setHTML(`
-
- ${formatPrice(listing.priceVND)} VND -
- -- ${listing.property.district}, ${listing.property.city} -
-