diff --git a/map/serializers.py b/map/serializers.py index 03dd912..8953812 100644 --- a/map/serializers.py +++ b/map/serializers.py @@ -31,4 +31,7 @@ def get_num_permits(self, obj): ] """ - pass + return RestaurantPermit.objects.filter( + community_area_id=obj.area_id, + issue_date__year=self.context["year"], + ).count() diff --git a/map/static/js/RestaurantPermitMap.js b/map/static/js/RestaurantPermitMap.js index 57f8ea0..ce023e8 100644 --- a/map/static/js/RestaurantPermitMap.js +++ b/map/static/js/RestaurantPermitMap.js @@ -1,24 +1,24 @@ -import React, { useEffect, useState } from "react" +import React, { useEffect, useState } from "react"; -import { MapContainer, TileLayer, GeoJSON } from "react-leaflet" +import { MapContainer, TileLayer, GeoJSON } from "react-leaflet"; -import "leaflet/dist/leaflet.css" +import "leaflet/dist/leaflet.css"; -import RAW_COMMUNITY_AREAS from "../../../data/raw/community-areas.geojson" +import RAW_COMMUNITY_AREAS from "../../../data/raw/community-areas.geojson"; function YearSelect({ setFilterVal }) { // Filter by the permit issue year for each restaurant - const startYear = 2026 + const startYear = 2026; const years = [...Array(11).keys()].map((increment) => { - return startYear - increment - }) + return startYear - increment; + }); const options = years.map((year) => { return ( - ) - }) + ); + }); return ( <> @@ -33,65 +33,93 @@ function YearSelect({ setFilterVal }) { {options} > - ) + ); } export default function RestaurantPermitMap() { - const communityAreaColors = ["#eff3ff", "#bdd7e7", "#6baed6", "#2171b5"] + const communityAreaColors = ["#eff3ff", "#bdd7e7", "#6baed6", "#2171b5"]; + + const [maxNumPermits, setMaxNumPermits] = useState([]); + const [totalPermits, setTotalPermits] = useState([]); - const [currentYearData, setCurrentYearData] = useState([]) - const [year, setYear] = useState(2026) + const [currentYearData, setCurrentYearData] = useState([]); + const [year, setYear] = useState(2026); - const yearlyDataEndpoint = `/map-data/?year=${year}` + const yearlyDataEndpoint = `/map-data/?year=${year}`; useEffect(() => { - fetch() + fetch(yearlyDataEndpoint) .then((res) => res.json()) .then((data) => { /** * TODO: Fetch the data needed to supply to map with data */ - }) - }, [yearlyDataEndpoint]) + setCurrentYearData(data); + let max = 0; + let total = 0; + data.forEach((area) => { + total += area.num_permits; + if (area.num_permits > max) { + max = area.num_permits; + } + }); + + setMaxNumPermits(max); + setTotalPermits(total); + }); + }, [yearlyDataEndpoint]); function getColor(percentageOfPermits) { /** - * TODO: Use this function in setAreaInteraction to set a community + * TODO: Use this function in setAreaInteraction to set a community * area's color using the communityAreaColors constant above */ + return communityAreaColors[Math.min(Math.ceil(percentageOfPermits / 25), 3)]; } function setAreaInteraction(feature, layer) { /** * TODO: Use the methods below to: - * 1) Shade each community area according to what percentage of + * 1) Shade each community area according to what percentage of * permits were issued there in the selected year - * 2) On hover, display a popup with the community area's raw + * 2) On hover, display a popup with the community area's raw * permit count for the year */ - layer.setStyle() - layer.on("", () => { - layer.bindPopup("") - layer.openPopup() - }) + const areaData = currentYearData.find( + (area) => area.name === feature.properties.community, + ); + const percentage = (areaData.num_permits / maxNumPermits) * 100; + + layer.setStyle({ + fillColor: getColor(percentage), + fillOpacity: 0.7, + color: "black", + weight: 1, + }); + layer.on("mouseover", + () => { + layer.bindPopup( + `${areaData.name} +
Year: ${year}
+Restaurant permits: ${areaData.num_permits}
` + ); + layer.openPopup(); + }, + ); } return ( <>- Restaurant permits issued this year: {/* TODO: display this value */} + Restaurant permits issued this year: {totalPermits}
Maximum number of restaurant permits in a single area: - {/* TODO: display this value */} + {maxNumPermits}
-