diff --git a/map/serializers.py b/map/serializers.py index 03dd912..2986839 100644 --- a/map/serializers.py +++ b/map/serializers.py @@ -6,29 +6,16 @@ class CommunityAreaSerializer(serializers.ModelSerializer): class Meta: model = CommunityArea - fields = ["name", "num_permits"] + fields = ["name", "area_id", "num_permits"] num_permits = serializers.SerializerMethodField() def get_num_permits(self, obj): - """ - TODO: supplement each community area object with the number - of permits issued in the given year. + year = self.context.get("year") + if not year: + return 0 - e.g. The endpoint /map-data/?year=2017 should return something like: - [ - { - "ROGERS PARK": { - area_id: 17, - num_permits: 2 - }, - "BEVERLY": { - area_id: 72, - num_permits: 2 - }, - ... - } - ] - """ - - pass + return RestaurantPermit.objects.filter( + community_area_id=str(obj.area_id), + issue_date__year=year, + ).count() diff --git a/map/static/js/RestaurantPermitMap.js b/map/static/js/RestaurantPermitMap.js index 57f8ea0..6abd600 100644 --- a/map/static/js/RestaurantPermitMap.js +++ b/map/static/js/RestaurantPermitMap.js @@ -6,19 +6,14 @@ import "leaflet/dist/leaflet.css" import RAW_COMMUNITY_AREAS from "../../../data/raw/community-areas.geojson" -function YearSelect({ setFilterVal }) { - // Filter by the permit issue year for each restaurant +function YearSelect({ filterVal, setFilterVal }) { const startYear = 2026 - const years = [...Array(11).keys()].map((increment) => { - return startYear - increment - }) - const options = years.map((year) => { - return ( - - {year} - - ) - }) + const years = [...Array(11).keys()].map((increment) => startYear - increment) + const options = years.map((year) => ( + + {year} + + )) return ( <> @@ -28,6 +23,7 @@ function YearSelect({ setFilterVal }) { setFilterVal(e.target.value)} > {options} @@ -45,34 +41,49 @@ 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 = currentYearData.reduce( + (max, area) => Math.max(max, 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 areaNumber = feature.properties.area_numbe + const areaData = currentYearData.find( + (area) => String(area.area_id) === String(areaNumber) + ) + const numPermits = areaData ? areaData.num_permits : 0 + const percentage = maxNumPermits > 0 ? numPermits / maxNumPermits : 0 + + layer.setStyle({ + fillColor: getColor(percentage), + weight: 1, + opacity: 1, + color: "#666", + fillOpacity: 0.7, + }) + + layer.on("mouseover", () => { + layer.bindPopup( + `${feature.properties.community}Permits: ${numPermits}` + ) layer.openPopup() }) } @@ -81,11 +92,11 @@ export default function RestaurantPermitMap() { <> - 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} ) : null} diff --git a/tests/test_views.py b/tests/test_views.py index 24cc64e..34d2090 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,7 +1,7 @@ import pytest from datetime import date -from django.shortcuts import reverse +from django.urls import reverse from rest_framework.test import APIClient from map.models import CommunityArea, RestaurantPermit @@ -9,33 +9,46 @@ @pytest.mark.django_db def test_map_data_view(): - # Create some test community areas - area1 = CommunityArea.objects.create(name="Beverly", area_id="1") - area2 = CommunityArea.objects.create(name="Lincoln Park", area_id="2") + area1 = CommunityArea.objects.create(name="Beverly", area_id=1) + area2 = CommunityArea.objects.create(name="Lincoln Park", area_id=2) - # Test permits for Beverly + # Beverly: 2 permits in 2021 RestaurantPermit.objects.create( - community_area_id=area1.area_id, issue_date=date(2021, 1, 15) + community_area_id=str(area1.area_id), issue_date=date(2021, 1, 15) ) RestaurantPermit.objects.create( - community_area_id=area1.area_id, issue_date=date(2021, 2, 20) + community_area_id=str(area1.area_id), issue_date=date(2021, 2, 20) ) - # Test permits for Lincoln Park + # Lincoln Park: 3 permits in 2021 RestaurantPermit.objects.create( - community_area_id=area2.area_id, issue_date=date(2021, 3, 10) + community_area_id=str(area2.area_id), issue_date=date(2021, 3, 10) ) RestaurantPermit.objects.create( - community_area_id=area2.area_id, issue_date=date(2021, 2, 14) + community_area_id=str(area2.area_id), issue_date=date(2021, 2, 14) ) RestaurantPermit.objects.create( - community_area_id=area2.area_id, issue_date=date(2021, 6, 22) + community_area_id=str(area2.area_id), issue_date=date(2021, 6, 22) + ) + + # A permit in a different year should not be counted + RestaurantPermit.objects.create( + community_area_id=str(area1.area_id), issue_date=date(2020, 5, 1) ) - # Query the map data endpoint client = APIClient() - response = client.get(reverse("map_data", query={"year": 2021})) + response = client.get(reverse("map_data"), {"year": 2021}) + + assert response.status_code == 200 + + data = response.json() + assert len(data) == 2 + + beverly = next(area for area in data if area["name"] == "Beverly") + lincoln_park = next(area for area in data if area["name"] == "Lincoln Park") + + assert beverly["num_permits"] == 2 + assert beverly["area_id"] == 1 - # 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 lincoln_park["num_permits"] == 3 + assert lincoln_park["area_id"] == 2
- 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}