From 049165d117964a59ef2b984876ee606a0fca8391 Mon Sep 17 00:00:00 2001 From: syro3 Date: Fri, 27 Mar 2026 18:49:04 +0800 Subject: [PATCH 1/2] number of permits in serializer and data endpoint test --- map/serializers.py | 4 +++- tests/test_views.py | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/map/serializers.py b/map/serializers.py index 03dd912..b541c06 100644 --- a/map/serializers.py +++ b/map/serializers.py @@ -31,4 +31,6 @@ def get_num_permits(self, obj): ] """ - pass + year = self.context.get("year") + num_permits = RestaurantPermit.objects.filter(community_area_id=str(obj.area_id), issue_date__year=year).count() + return num_permits diff --git a/tests/test_views.py b/tests/test_views.py index 24cc64e..933d7f2 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,3 +1,5 @@ +from urllib import response + import pytest from datetime import date @@ -21,6 +23,11 @@ def test_map_data_view(): community_area_id=area1.area_id, issue_date=date(2021, 2, 20) ) + #non-2021 permit for Beverly + RestaurantPermit.objects.create( + community_area_id=area1.area_id, issue_date=date(2020, 2, 20) + ) + # Test permits for Lincoln Park RestaurantPermit.objects.create( community_area_id=area2.area_id, issue_date=date(2021, 3, 10) @@ -39,3 +46,13 @@ def test_map_data_view(): # TODO: Complete the test by asserting that the /map-data/ endpoint # returns the correct number of permits for Beverly and Lincoln # Park in 2021 + + assert response.status_code == 200 + data = response.json() + + expected_response = [ + {"name": "Beverly", "num_permits": 2}, + {"name": "Lincoln Park", "num_permits": 3}, + ] + + assert response.json() == expected_response \ No newline at end of file From 7487fb32f1b9d5627898045edb4beb657be510a7 Mon Sep 17 00:00:00 2001 From: syro3 Date: Fri, 27 Mar 2026 21:46:36 +0800 Subject: [PATCH 2/2] fetch data, shade map, popups --- map/static/js/RestaurantPermitMap.js | 70 +++++++++++++++++++--------- 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/map/static/js/RestaurantPermitMap.js b/map/static/js/RestaurantPermitMap.js index 57f8ea0..29150b4 100644 --- a/map/static/js/RestaurantPermitMap.js +++ b/map/static/js/RestaurantPermitMap.js @@ -45,47 +45,75 @@ export default function RestaurantPermitMap() { 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 - */ + setCurrentYearData(data) }) }, [yearlyDataEndpoint]) + const totalPermits = currentYearData.reduce( + (sum, area) => sum + area.num_permits, + 0 + ) + + const maxNumPermits = Math.max( + ...currentYearData.map((area) => area.num_permits), + 0 + ) + function getColor(percentageOfPermits) { - /** - * TODO: Use this function in setAreaInteraction to set a community - * area's color using the communityAreaColors constant above - */ + + if (percentageOfPermits > 0.75) return communityAreaColors[3] + if (percentageOfPermits > 0.5) return communityAreaColors[2] + if (percentageOfPermits > 0.25) return communityAreaColors[1] + return communityAreaColors[0] } function setAreaInteraction(feature, layer) { - /** - * TODO: Use the methods below to: - * 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 - * permit count for the year - */ - layer.setStyle() - layer.on("", () => { - layer.bindPopup("") + + const areaName = feature.properties.community + const areaData = currentYearData.find((area) => area.name === areaName) + const numPermits = areaData ? areaData.num_permits : 0 + + // scaled by maxNumPermits instead of totalPermits to better differentiate between areas when total permits is very high + const percentageOfPermits = maxNumPermits > 0 ? numPermits / maxNumPermits : 0 + + layer.setStyle({ + fillColor: getColor(percentageOfPermits), + fillOpacity: percentageOfPermits === 0 ? 0 : 0.7, + weight: 1, + color: communityAreaColors[3], + }) + layer.bindPopup( + // permit with pluralization + `${areaName}

${numPermits} permit${numPermits === 1 ? "" : "s"} issued in ${year}

` + ) + layer.on("mouseover", () => { + layer.setStyle({ + fillOpacity: percentageOfPermits === 0 ? 0 : 0.9, + weight: 2, + }) layer.openPopup() }) + layer.on("mouseout", () => { + layer.setStyle({ + fillOpacity: percentageOfPermits === 0 ? 0 : 0.7, + weight: 1, + }) + layer.closePopup() + }) } 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 */} + Maximum number of restaurant permits in a single area: {maxNumPermits}