setup map component to render correctly and visualize all listings in scrollable components
This commit is contained in:
parent
a8ee95b9d9
commit
8e41032c6c
23 changed files with 2183 additions and 342 deletions
|
|
@ -1,8 +1,13 @@
|
|||
import crossfilter from "crossfilter2";
|
||||
import * as d3 from "d3";
|
||||
import mapboxgl from "mapbox-gl";
|
||||
// import 'mapbox-gl/dist/mapbox-gl.css';
|
||||
import 'mapbox-gl/dist/mapbox-gl.css'; // this hides the map for some reason
|
||||
import { useEffect, useRef } from "react";
|
||||
import { renderToString } from 'react-dom/server';
|
||||
import "../assets/Map.css";
|
||||
import { Button } from "./ui/button";
|
||||
import { ScrollArea } from "./ui/scroll-area";
|
||||
import { Separator } from "./ui/separator";
|
||||
|
||||
export function Map(
|
||||
props: {
|
||||
|
|
@ -31,7 +36,7 @@ export function Map(
|
|||
// filter['countries'] = Array.from(new Set(data.features.map(function (d) { return d['properties']['country'] })));
|
||||
// rivets.bind(document.getElementById('overlay'), { filter: filter });
|
||||
const mapRef = useRef(mapboxgl.Map)
|
||||
const mapContainerRef = useRef('map')
|
||||
const mapContainerRef = useRef('map-container')
|
||||
useEffect(() => {
|
||||
mapboxgl.accessToken = 'pk.eyJ1IjoiZGktdG8iLCJhIjoiY2o0bnBoYXcxMW1mNzJ3bDhmc2xiNWttaiJ9.ZccatVk_4shzoAsEUXXecA';
|
||||
mapRef.current = new mapboxgl.Map({
|
||||
|
|
@ -72,10 +77,6 @@ export function Map(
|
|||
}
|
||||
|
||||
function update() {
|
||||
// close overlay
|
||||
var modal = document.getElementById('modal_overlay');
|
||||
modal.classList.toggle('modal-open');
|
||||
|
||||
// init heatmap
|
||||
heatmap = new HexgridHeatmap(mapRef.current, "hexgrid-heatmap", "waterway-label");
|
||||
heatmap.setIntensity(9); // dunno yet
|
||||
|
|
@ -193,77 +194,116 @@ export function Map(
|
|||
minY: latitude - searchBuffer,
|
||||
maxY: latitude + searchBuffer
|
||||
})
|
||||
const html = getListingDialogHTML(properties);
|
||||
if (properties.length > 0) {
|
||||
const listingDialogPopup = getListingDialog(properties);
|
||||
new mapboxgl.Popup()
|
||||
.setLngLat([longtitude, latitude])
|
||||
.setHTML(html)
|
||||
.setHTML(renderToString(listingDialogPopup))
|
||||
.setMaxWidth("500px")
|
||||
.addTo(mapRef.current);
|
||||
}
|
||||
}
|
||||
|
||||
function getListingDialogHTML(properties) {
|
||||
let listinHTMLs = [];
|
||||
function getListingDialog(properties) {
|
||||
let listingComponents = [];
|
||||
for (let property of properties) {
|
||||
listinHTMLs.push(getPropertyHTML(property));
|
||||
listingComponents.push(getPropertyComponent(property));
|
||||
}
|
||||
// separate them with a line
|
||||
const result = listinHTMLs.join('<hr>');
|
||||
const styledResult = `
|
||||
<div class="scrollable-panel">
|
||||
${result}
|
||||
</div>
|
||||
`
|
||||
console.log(listingComponents.length)
|
||||
return <ScrollArea className="rounded-md border">
|
||||
<div className="overflow-y-auto h-[500px] w-[500px] scrollbar-thin scrollbar-thumb-rounded">
|
||||
|
||||
return styledResult;
|
||||
<div className="propertyListingPopupItem" style={{ width: '100%' }}>
|
||||
Showing <strong>{properties.length}</strong> properties
|
||||
</div>
|
||||
{listingComponents.map((item) => {
|
||||
const scrollDiv = <div key={item.key}>
|
||||
{item}
|
||||
<Separator className="my-2" />
|
||||
</div>;
|
||||
return scrollDiv
|
||||
})}
|
||||
</div>
|
||||
</ScrollArea>;
|
||||
}
|
||||
function getPropertyHTML(property) {
|
||||
|
||||
function getPropertyComponent(property) {
|
||||
const priceHistoryHTMLs = property.properties.price_history.map((d) => {
|
||||
return `<li>${d.last_seen.split('T')[0]}: £${d.price}</li>`;
|
||||
return <li key={d.id}>${d.last_seen.split('T')[0]}: £${d.price}</li>;
|
||||
});
|
||||
|
||||
let priceHistoryHTML = '';
|
||||
let priceHistoryHTML = <></>;
|
||||
if (priceHistoryHTMLs.length > 1) {
|
||||
priceHistoryHTML = `
|
||||
<strong>Price history:</strong>
|
||||
<ul>
|
||||
${priceHistoryHTMLs.join('')}
|
||||
</ul>
|
||||
<br />
|
||||
`
|
||||
priceHistoryHTML =
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Price history:</strong>
|
||||
<ul>
|
||||
${priceHistoryHTMLs.join('')}
|
||||
</ul>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
}
|
||||
const lastSeenStr = property.properties.last_seen.split('T')[0];
|
||||
const lastSeenDays = Math.round((new Date() - new Date(lastSeenStr)) / (1000 * 60 * 60 * 24));
|
||||
return <div key={property.properties.url} style={{ display: 'flex', flexWrap: 'wrap' }}>
|
||||
<div className="propertyListingPopupItem" style={{ width: '100%' }}>
|
||||
<img src={property.properties.photo_thumbnail} />
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Available from:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
{property.properties.available_from}
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Price:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
£{property.properties.total_price}
|
||||
</div>
|
||||
{priceHistoryHTML}
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Rooms:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
|
||||
return `
|
||||
<div>
|
||||
<img src="${property.properties.photo_thumbnail}" style="width:100%; height:auto;">
|
||||
<p>
|
||||
<strong>Available from:</strong> ${property.properties.available_from}
|
||||
<br />
|
||||
<strong>Price:</strong> £${property.properties.total_price}
|
||||
<br />
|
||||
${priceHistoryHTML}
|
||||
<strong>Rooms:</strong> ${property.properties.rooms}
|
||||
<br />
|
||||
<strong>Area:</strong> ${property.properties.qm} m²
|
||||
<br />
|
||||
<strong>Price per area:</strong> £${property.properties.qmprice}/m²
|
||||
<br />
|
||||
<strong>Last seen:</strong> ${lastSeenDays} days ago
|
||||
<br />
|
||||
<strong>Agency:</strong> ${property.properties.agency}
|
||||
<br />
|
||||
<a href="${property.properties.url}" target="_blank">View Listing</a>
|
||||
</p>
|
||||
{property.properties.rooms}
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Area:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
{property.properties.qm} m²
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Price per area:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
£{property.properties.qmprice}/m²
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Last seen:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
{lastSeenDays} days ago
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
<strong>Agency:</strong>
|
||||
</div>
|
||||
<div className="propertyListingPopupItem">
|
||||
{property.properties.agency}
|
||||
</div>
|
||||
<div className="propertyListingPopupItem" style={{ width: '100%' }}>
|
||||
<Button asChild>
|
||||
<a href={property.properties.url} target="_blank">View Listing</a>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
}
|
||||
|
||||
return <>
|
||||
<div id='map' ref={mapContainerRef}></div>
|
||||
<div id='map-container' ref={mapContainerRef}></div>
|
||||
|
||||
<div id="legend">
|
||||
<svg id="svg">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue