Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions src/components/AirHeatIndexLineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,9 @@ const AirHeatIndexLineChart = ({ data }: Props) => {
.style('display', 'block');

const svgWidth = (svg.node() as SVGSVGElement).getBoundingClientRect().width;
const tooltipWidth = (tooltipDiv.node() as HTMLElement).getBoundingClientRect().width;
const isNearRightEdge = xPos + tooltipWidth + xOffset > svgWidth;
const tooltipWidth = 200;
const threshold = svgWidth * 0.55;
const isNearRightEdge = xPos > threshold;

tooltipDiv
.style('left', isNearRightEdge ? `${xPos - tooltipWidth - xOffset}px` : `${xPos + xOffset}px`)
Expand Down Expand Up @@ -292,8 +293,8 @@ const AirHeatIndexLineChart = ({ data }: Props) => {

return (
<div className='relative w-full h-[80%]'>
<svg ref={svgRef} className='w-full h-full'></svg>
<div id='tooltip' style={{ position: 'absolute', display: 'none' }}></div>
<svg ref={svgRef} className='w-full h-full overflow-x-hidden'></svg>
<div id='tooltip' style={{ width: '200px', position: 'absolute', display: 'none', pointerEvents: 'none' }}></div>
</div>
);
};
Expand Down
9 changes: 5 additions & 4 deletions src/components/AirTemperatureLineChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,9 @@ const AirTemperatureLineChart = ({ data }: Props) => {
.style('display', 'block');

const svgWidth = (svg.node() as SVGSVGElement).getBoundingClientRect().width;
const tooltipWidth = (tooltipDiv.node() as HTMLElement).getBoundingClientRect().width;
const isNearRightEdge = xPos + tooltipWidth + xOffset > svgWidth;
const tooltipWidth = 200;
const threshold = svgWidth * 0.55;
const isNearRightEdge = xPos > threshold;

const isAboveHistoricalMax = Math.round(closestDataPoint.tempmax) - Math.round(closestDataPoint.Normal_Temp_Max) > 0
const isAboveHistoricalMin = Math.round(closestDataPoint.tempmax) - Math.round(closestDataPoint.Normal_Temp_Max) > 0
Expand All @@ -201,7 +202,7 @@ const AirTemperatureLineChart = ({ data }: Props) => {
const tempMinDifference = Math.abs(Math.round(closestDataPoint.tempmin) - Math.round(closestDataPoint.Normal_Temp_Min))

tooltipDiv
.style('left', isNearRightEdge ? `${xPos - tooltipWidth - xOffset}px` : `${xPos + xOffset}px`)
.style('left', isNearRightEdge ? `${xPos - tooltipWidth}px` : `${xPos + xOffset}px`)
.style('top', `${yPos}px`)
.style('display', 'block')
.html(`
Expand Down Expand Up @@ -267,7 +268,7 @@ const AirTemperatureLineChart = ({ data }: Props) => {
return (
<div className='relative w-full h-[80%]'>
<svg ref={svgRef} className='w-full h-full'></svg>
<div id='tooltip' style={{ position: 'absolute', display: 'none' }}></div>
<div id='tooltip' style={{ width: '200px', position: 'absolute', display: 'none', pointerEvents: 'none' }}></div>
</div>
);
};
Expand Down
22 changes: 19 additions & 3 deletions src/components/NeighborhoodProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import mapboxgl, { Popup } from "mapbox-gl";
import { nta_dataset_info, out_door_heat_index } from '../App'

import NeighborhoodProfileBarChart from "../components/NeighborhoodProfileBarChart"
import { BORO_EXTENTS } from '../utils/format';


type Borough = "Brooklyn" | "Queens" | "Manhattan" | "Staten Island" | "Bronx"
Expand Down Expand Up @@ -283,14 +284,29 @@ const NeighborhoodProfile = () => {
}
}, [selectedDataset.value]);

// useEffect(()=>{
// // when boro changes zoom into borough extent
// const boro_extent = BORO_EXTENTS[selectedBoro]

// if(boro_extent && map.value){
// // @ts-ignore
// map.value.fitBounds(boro_extent.bounds, {
// padding: 50,
// duration: 200,
// });
// }
// },[selectedBoro])

return (
<div className={`transition-all duration-[1500ms] ${!isNeighborhoodProfileExpanded.value && "translate-y-[70vh] md:translate-y-0 md:translate-x-[calc(65vw)]"} absolute bottom-0 md:top-[3.125rem] md:right-0 flex items-center z-20`}>
<div className="absolute w-full h-full bottom-0 top-0 flex items-center z-20">
<div className="relative">
{
isTablet && <div className="flex items-center justify-center w-9 h-24 bg-[#1B1B1B] rounded-l-2xl cursor-pointer" onClick={clickHandler}>
isTablet && <div className="absolute flex md:-left-9 items-center justify-center w-9 h-24 bg-[#1B1B1B] rounded-l-2xl cursor-pointer" onClick={clickHandler}>
{isNeighborhoodProfileExpanded.value ? <ChevronRightIcon width={20} height={20} className="text-[#BDBDBD]" /> : <ChevronLeftIcon width={20} height={20} className="text-[#BDBDBD]" />}
</div>
}
<div className={`printable-white-bg md:flex md:flex-col md:justify-center md:gap-[4rem] px-6 md:px-10 pt-12 pb-6 md:pt-0 md:pb-0 w-[100vw] md:w-[65vw] h-[70vh] md:h-[calc(100vh_-_3.125rem)] bg-[#1B1B1B] rounded-[1rem] md:rounded-[0] overflow-y-auto scrollbar`}>
</div>
<div className={`w-full h-full printable-white-bg md:flex md:flex-col md:justify-center md:gap-[4rem] px-6 md:px-10 pt-12 pb-6 md:pt-0 md:pb-0 bg-[#1B1B1B] overflow-y-auto scrollbar`}>
<div className="md:flex md:gap-8 md:h-[30%]">
<div className="md:flex md:flex-col md:w-[50%] h-full">
<h2 className="text-regular md:text-subheadline text-gray_six">{clickedNeighborhoodInfo.value?.boro}</h2>
Expand Down
8 changes: 5 additions & 3 deletions src/components/WeatherStationProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,15 @@ const WeatherStationProfile = () => {


return (
<div className={`transition-all duration-[1500ms] ${!isWeatherStationProfileExpanded.value && "translate-y-[70vh] md:translate-y-0 md:translate-x-[65vw]"} absolute bottom-0 md:top-[3.125rem] md:right-0 flex items-center z-20`}>
<div className="absolute w-full h-full bottom-0 top-0 flex items-center z-20">
<div className="relative">
{
isTablet && <div className="flex items-center justify-center w-9 h-24 bg-[#1B1B1B] rounded-l-2xl cursor-pointer" onClick={clickHandler}>
isTablet && <div className="absolute flex md:-left-9 items-center justify-center w-9 h-24 bg-[#1B1B1B] rounded-l-2xl cursor-pointer" onClick={clickHandler}>
{isWeatherStationProfileExpanded.value ? <ChevronRightIcon width={20} height={20} className="text-[#BDBDBD]" /> : <ChevronLeftIcon width={20} height={20} className="text-[#BDBDBD]" />}
</div>
}
<div className={`md:flex md:flex-col md:justify-center md:gap-6 px-6 lg:px-10 pt-12 pb-6 md:pt-0 md:pb-0 w-[100vw] md:w-[65vw] h-[70vh] md:h-[calc(100vh_-_3.125rem)] bg-[#1B1B1B] rounded-[1rem] md:rounded-[0] overflow-y-auto scrollbar`}>
</div>
<div className={`w-full h-full md:flex md:flex-col md:justify-center md:gap-6 px-6 lg:px-10 pt-12 pb-6 md:pt-0 md:pb-0 bg-[#1B1B1B] rounded-[1rem] md:rounded-[0] overflow-y-auto scrollbar`}>
<div className="md:flex md:items-center md:gap-6 md:h-[25%] overflow-y-scroll">
<div className="md:flex md:flex-col md:justify-center md:gap-3 md:px-4 md:py-2 w-full h-full md:w-[70%] md:border-[1px] md:border-[#333] rounded-[0.5rem]">
<div className="flex justify-between items-start w-full">
Expand Down
2 changes: 2 additions & 0 deletions src/pages/Map.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
background: transparent !important;
border: none !important;
box-shadow: none !important;
z-index: 4 !important;
}

/* Remove any default styles applied to popup content */
.mapboxgl-popup.clicked-popup .mapboxgl-popup-content {
min-width: 0 !important; /* Remove max-width constraints */
background: transparent !important; /* Make the content background transparent */
margin: 0;
z-index: 3;
}

/* Hide the arrow of the popup */
Expand Down
39 changes: 29 additions & 10 deletions src/pages/MapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import MapDateSelections from '../components/MapDateSelections.js';
import WeatherStationProfile from '../components/WeatherStationProfile.js';
import Legends from '../components/Legends.js';
import "./Map.css"
import { signal } from '@preact/signals-react'
import { effect, signal } from '@preact/signals-react'
import { Dataset, datasets } from '../utils/datasets.js';
import { NtaProfileData, WeatherStationData } from '../types.js';
import { initializeView } from '../utils/datasets.js';
Expand All @@ -28,7 +28,7 @@ export const previousClickCor = signal<[number, number]>([0, 0])
export const clickedWeatherStationPopup = signal<mapboxgl.Popup | null>(null)
export const clickedNeighborhoodPopup = signal<mapboxgl.Popup | null>(null)
export const clickedNeighborhoodInfo = signal<{
code:string
code: string
boro: string,
nta: string
}>({
Expand Down Expand Up @@ -91,23 +91,42 @@ const MapPage = () => {
}, []);


// Debounce map resize to avoid excessive updates when profiles change
effect(() => {
const debounced = setTimeout(() => {
if (map?.value) {
console.log('resize')
map.value.resize()
}
const _ = isNeighborhoodProfileExpanded.value && isWeatherStationProfileExpanded.value
}, 100)

return () => clearTimeout(debounced)
})

return (
<div className='relative w-full h-full'>
{/* <div className='absolute top-0 left-[17.5vw] w-[2px] h-[100vh] bg-[#fe8585] z-[100000]'></div>
<div className='absolute top-1/2 left-1/2 w-[20px] h-[20px] bg-[#fe8585] z-[1000000] rounded-full transform -translate-x-1/2 -translate-y-1/2'></div> */}
<Nav />
{
selectedDataset.value?.name === "Weather Stations" && <WeatherStationProfile />
}
{
selectedDataset.value?.name !== "Weather Stations" && <NeighborhoodProfile />
}
<DatasetSelections />
<MapDateSelections />
<Legends />
<div className='w-full h-[calc(100%_-_3.125rem)]' ref={mapContainer} />
</div>

<div className="w-full h-[calc(100%_-_3.125rem)] flex flex-col md:flex-row">
<div className="flex-1 w-full h-full" ref={mapContainer} />
{isNeighborhoodProfileExpanded.value && selectedDataset?.value?.name !== "Weather Stations" && (
<div className="h-2/3 md:h-full md:w-8/12 relative">
<NeighborhoodProfile />
</div>
)}
{isWeatherStationProfileExpanded.value && selectedDataset?.value?.name === "Weather Stations" && (
<div className="h-2/3 md:h-full md:w-8/12 relative">
<WeatherStationProfile />
</div>
)}
</div>
</div>
);
};

Expand Down
59 changes: 57 additions & 2 deletions src/utils/format.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export const formatDateString = (dateString: string) => {
if(dateString.length === 4){
if (dateString.length === 4) {
return dateString
}

Expand All @@ -16,4 +16,59 @@ export const boroughExpand = {
'BK': 'Brooklyn',
'QN': 'Queens',
'SI': 'Staten Island'
}
}

interface BoroExtent {
center: [number, number];
zoom: number;
bounds?: [[number, number], [number, number]];
name: string;
}

export const BORO_EXTENTS: Record<string, BoroExtent> = {
'Staten Island': {
name: 'Staten Island',
center: [-74.1502, 40.5795],
zoom: 12,
bounds: [
[-74.2558, 40.4959],
[-74.0522, 40.6517]
]
},
'Brooklyn': {
name: 'Brooklyn',
center: [-73.9442, 40.6526],
zoom: 11.5,
bounds: [
[-74.0424, 40.5708],
[-73.8334, 40.7395]
]
},
'Queens': {
name: 'Queens',
center: [-73.7949, 40.7282],
zoom: 11.5,
bounds: [
[-73.9620, 40.5431],
[-73.7004, 40.8129]
]
},
'Manhattan': {
name: 'Manhattan',
center: [-73.9712, 40.7831],
zoom: 12,
bounds: [
[-74.0479, 40.6829],
[-73.9070, 40.8820]
]
},
'Bronx': {
name: 'Bronx',
center: [-73.8648, 40.8448],
zoom: 12,
bounds: [
[-73.9338, 40.7855],
[-73.7654, 40.9176]
]
}
};