diff --git a/docker-compose.yml b/docker-compose.yml index a743cce..1c541f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,6 +41,7 @@ services: postgres: container_name: map-postgres image: postgis/postgis + platform: linux/amd64 healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s diff --git a/map/models.py b/map/models.py index 2733741..2d48ea1 100644 --- a/map/models.py +++ b/map/models.py @@ -21,3 +21,6 @@ class RestaurantPermit(models.Model): street_name = models.CharField(max_length=32, null=True, blank=True) location = gis_models.PointField(null=True, blank=True) community_area_id = models.CharField(max_length=2, null=True, blank=True) + + def __str__(self): + return f'Permit ID: {self.permit_id}, Area: {self.community_area_id}' diff --git a/map/serializers.py b/map/serializers.py index 03dd912..cac257e 100644 --- a/map/serializers.py +++ b/map/serializers.py @@ -30,5 +30,5 @@ def get_num_permits(self, obj): } ] """ - - pass + count = RestaurantPermit.objects.filter(community_area_id = obj.area_id, issue_date__year=self.context.get('year')).count() + return count \ No newline at end of file diff --git a/map/static/js/RestaurantPermitMap.js b/map/static/js/RestaurantPermitMap.js index 57f8ea0..ea90755 100644 --- a/map/static/js/RestaurantPermitMap.js +++ b/map/static/js/RestaurantPermitMap.js @@ -1,5 +1,4 @@ -import React, { useEffect, useState } from "react" - +import React, { useEffect, useState, useCallback } from "react" import { MapContainer, TileLayer, GeoJSON } from "react-leaflet" import "leaflet/dist/leaflet.css" @@ -45,24 +44,30 @@ 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]) - function getColor(percentageOfPermits) { - /** - * TODO: Use this function in setAreaInteraction to set a community - * area's color using the communityAreaColors constant above - */ + // Dynamic breaks from current data + const percents = currentYearData.map(d => d.num_permits / totalPermits * + 100).sort((a,b)=>a-b); + const q1 = percents[Math.floor(percents.length * 0.25)]; + const q2 = percents[Math.floor(percents.length * 0.50)]; + const q3 = percents[Math.floor(percents.length * 0.75)]; + if (percentageOfPermits >= q3) return communityAreaColors[3]; + if (percentageOfPermits >= q2) return communityAreaColors[2]; + if (percentageOfPermits >= q1) return communityAreaColors[1]; + return communityAreaColors[0]; } - function setAreaInteraction(feature, layer) { + const setAreaInteraction = /** * TODO: Use the methods below to: * 1) Shade each community area according to what percentage of @@ -70,22 +75,46 @@ export default function RestaurantPermitMap() { * 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() - }) + useCallback((feature, layer) => { + const name = feature.properties.community; + const communityAreaData = currentYearData.find(d => d.name === name); + const countPermits = communityAreaData?.num_permits || 0; + const percentageOfPermits = totalPermits > 0 ? countPermits/totalPermits * 100 : 0; + layer.setStyle({ fillOpacity: 0.9, fillColor: getColor(percentageOfPermits) }) + layer.on('mouseover', () => { + layer.bindPopup(`${feature.properties.community}: ${communityAreaData.num_permits} permits`) + layer.openPopup() + }) + ;} ,[currentYearData]); + + function getTotalandMaxNumPermits(currentYearData) { + // This could be two functions instead of one, and that would be nicer from a test/maintenance perspective, + // but it will be faster to compute both results together. + let totalPermits = 0; + // Maximum number of permits held by a single community area in current year data + let maxNumPermits = 0 + for (const community_area of currentYearData) { + totalPermits += community_area.num_permits + if (community_area.num_permits > maxNumPermits) { + maxNumPermits = community_area.num_permits + } + } + return { totalPermits, maxNumPermits }; } + const computedTotals = getTotalandMaxNumPermits(currentYearData); + const totalPermits = computedTotals.totalPermits; + const maxNumPermits = computedTotals.maxNumPermits; + 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}