diff --git a/gatsby-browser.js b/gatsby-browser.js
index 5b7f52c..91ec0da 100644
--- a/gatsby-browser.js
+++ b/gatsby-browser.js
@@ -6,6 +6,7 @@ export const wrapPageElement = ({ element, props }) => {
{element}
diff --git a/gatsby-node.js b/gatsby-node.js
index f3db385..14dc0fa 100644
--- a/gatsby-node.js
+++ b/gatsby-node.js
@@ -17,6 +17,14 @@ const formatCaseCountNumber = n => {
return n.replace(/[,]/gi, "")
}
+const trimAndParseInt = str => {
+ try {
+ return parseInt(str.trim().replace(",", ""))
+ } catch (err) {
+ return 0
+ }
+}
+
const parseReportDate = memoize(dateStr => {
return parse(dateStr, "M/d/yy", new Date())
})
@@ -297,6 +305,46 @@ exports.createPages = async ({ graphql, actions }) => {
})
})
+ const vaccinations = results.data.vaccinations.nodes.reduce(
+ (final, current) => {
+ const {
+ town,
+ ageGroup,
+ population,
+ fullyVaccinated,
+ partiallyVaccinated,
+ } = current
+
+ if (town === "Town") return final
+
+ let color = "black"
+ try {
+ color = allNormalized[town].color
+ } catch (err) {}
+
+ final[town] = final[town] || {
+ townName: town,
+ color: color,
+ totalEligible: 0,
+ totalFullyVaccinated: 0,
+ totalPartiallyVaccinated: 0,
+ }
+
+ if (ageGroup !== "Total") {
+ final[town].totalEligible =
+ final[town].totalEligible + trimAndParseInt(population)
+ final[town].totalFullyVaccinated =
+ final[town].totalFullyVaccinated + trimAndParseInt(fullyVaccinated)
+ final[town].totalPartiallyVaccinated =
+ final[town].totalPartiallyVaccinated +
+ trimAndParseInt(partiallyVaccinated)
+ }
+
+ return final
+ },
+ {}
+ )
+
const productTemplate = path.resolve(`src/templates/index.js`)
createPage({
@@ -304,19 +352,21 @@ exports.createPages = async ({ graphql, actions }) => {
component: productTemplate,
context: {
townCounts: allNormalized,
+ vaccinations,
},
})
- //if (process.env.NODE_ENV === "production") {
- Object.keys(populations).map(townName => {
- createPage({
- path: `/${slugify(townName, { lower: true })}/`,
- component: productTemplate,
- context: {
- townCounts: allNormalized,
- townName: townName,
- },
+ if (process.env.NODE_ENV === "production") {
+ Object.keys(populations).map(townName => {
+ createPage({
+ path: `/${slugify(townName, { lower: true })}/`,
+ component: productTemplate,
+ context: {
+ townCounts: allNormalized,
+ townName: townName,
+ vaccinations,
+ },
+ })
})
- })
- //}
+ }
}
diff --git a/gatsby-ssr.js b/gatsby-ssr.js
index 73ab133..e8158b0 100644
--- a/gatsby-ssr.js
+++ b/gatsby-ssr.js
@@ -6,6 +6,7 @@ export const wrapPageElement = ({ element, props }) => {
{element}
diff --git a/src/components/App/index.js b/src/components/App/index.js
index f3783e0..047e4fe 100644
--- a/src/components/App/index.js
+++ b/src/components/App/index.js
@@ -1,14 +1,20 @@
import React from "react"
import SearchBox from "../SearchBox"
import { observer } from "mobx-react"
+import { useStore } from "../../stores/global"
import Header from "../Header"
import Grid from "@material-ui/core/Grid"
import FAQ from "../FAQ"
import loadable from "@loadable/component"
+import VaccinationTable from "../VaccinationTable"
+import Box from "@material-ui/core/Box"
+import Typography from "@material-ui/core/Typography"
const Chart = loadable(() => import("../Chart"))
-export default observer(() => {
+export default observer(props => {
+ const { selectedTowns } = useStore()
+
return (
<>
@@ -23,6 +29,20 @@ export default observer(() => {
{typeof window !== "undefined" && }
+ {selectedTowns.length !== 0 && (
+
+
+
+ Vaccinations
+
+
+
+
+ )}
{
+ const { selectedTowns, vaccinations } = useStore()
+
+ const selectedTownsStr = JSON.stringify(selectedTowns)
+
+ const towns = useMemo(() => {
+ const selectedTownNames = selectedTowns.map(st => st.town)
+ return Object.values(vaccinations).filter(({ townName }) => {
+ return selectedTownNames.indexOf(townName) > -1
+ })
+ }, [selectedTownsStr, vaccinations, selectedTowns])
+
+ return (
+
+
+ Percentage of eligible residents who are vaccinated
+
+
+ Town
+ Fully Vaccinated
+ Fully & Partially Vaccinated
+
+
+
+ {towns.map(
+ ({
+ townName,
+ color,
+ totalEligible,
+ totalFullyVaccinated,
+ totalPartiallyVaccinated,
+ }) => (
+
+
+ {townName}
+
+
+ {Math.round((totalFullyVaccinated / totalEligible) * 100)}%
+
+
+ {Math.round(
+ ((totalFullyVaccinated + totalPartiallyVaccinated) /
+ totalEligible) *
+ 100
+ )}
+ %
+
+
+ )
+ )}
+
+
+
+ )
+})
diff --git a/src/stores/global.js b/src/stores/global.js
index 2c900a0..d361e30 100644
--- a/src/stores/global.js
+++ b/src/stores/global.js
@@ -67,6 +67,8 @@ class GlobalStore {
dataTypes = DATA_TYPES
+ vaccinations = {}
+
setTownCounts = (counts = []) => {
this.townCounts = counts.reduce((final, current) => {
final[current.town] = current
@@ -137,9 +139,15 @@ const initializedGlobalStore = new GlobalStore()
const storeContext = React.createContext(initializedGlobalStore)
-export const GlobalStoreProvider = ({ initialTown, townCounts, children }) => {
+export const GlobalStoreProvider = ({
+ initialTown,
+ townCounts,
+ vaccinations,
+ children,
+}) => {
initializedGlobalStore.availableTowns = Object.values(townCounts)
initializedGlobalStore.townCounts = townCounts
+ initializedGlobalStore.vaccinations = vaccinations
if (initialTown) {
initializedGlobalStore.selectedTowns = [
diff --git a/src/templates/index.js b/src/templates/index.js
index a069130..8296a8c 100644
--- a/src/templates/index.js
+++ b/src/templates/index.js
@@ -5,9 +5,9 @@ import App from "../components/App"
const getPageDescription = town => {
if (town) {
- return `Track and compare COVID-19 cases in ${town} and towns throughout Massachusetts.`
+ return `Track and compare COVID-19 cases and vaccinations in ${town} and towns throughout Massachusetts.`
} else {
- return `Track and compare COVID-19 cases towns throughout Massachusetts.`
+ return `Track and compare COVID-19 cases and vaccinations towns throughout Massachusetts.`
}
}
@@ -17,7 +17,7 @@ const IndexPage = props => {
diff --git a/yarn.lock b/yarn.lock
index 11642be..8345860 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10851,9 +10851,9 @@ path-key@^3.0.0, path-key@^3.1.0:
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
path-parse@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
- integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-starts-with@^1.0.0:
version "1.0.0"