Add summary section to index.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :class="['bg-white shadow rounded-lg p-4 lg:p-8 max-w-none', prose ? 'prose lg:prose-base prose-headings:font-light prose-headings:text-violet-900 prose-h1:mb-0' : '']">
|
||||
<div :class="['bg-white shadow rounded-lg p-4 lg:p-8 max-w-none', prose ? 'prose lg:prose-base prose-headings:font-light prose-headings:text-violet-900 prose-h1:mb-0 prose-a:text-violet-700 prose-a:font-normal' : '']">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<StatCard>
|
||||
<template v-slot:heading>Confirmed Cases {{last_report_date ? humanDate(last_report_date) : ''}}</template>
|
||||
<template v-slot:value v-if="chips.today_cases != null">
|
||||
{{chips.today_cases.toLocaleString()}}
|
||||
<template v-slot:value v-if="chips.current_cases != null">
|
||||
{{chips.current_cases.toLocaleString()}}
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.today_case_change != null">
|
||||
<span v-if="chips.today_case_change > 0">Up </span>
|
||||
<span v-if="chips.today_case_change < 0">Down </span>
|
||||
<span :class="{'font-semibold': true, 'text-red-600': chips.today_case_change > 0, 'text-green-600': chips.today_case_change < 0}">
|
||||
{{Math.abs(chips.today_case_change).toLocaleString()}} ({{chips.today_case_change_percent}}%)
|
||||
<template v-slot:meta v-if="chips.current_case_change != null">
|
||||
<span v-if="chips.current_case_change > 0">Up </span>
|
||||
<span v-if="chips.current_case_change < 0">Down </span>
|
||||
<span :class="{'font-semibold': true, 'text-red-600': chips.current_case_change > 0, 'text-green-600': chips.current_case_change < 0}">
|
||||
{{Math.abs(chips.current_case_change).toLocaleString()}} ({{chips.current_case_change_percent}}%)
|
||||
</span> compared to previous day
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>Cases per 10,000 Residents {{last_report_date ? humanDate(last_report_date) : ''}}</template>
|
||||
<template v-slot:value v-if="chips.today_cases_per_capita != null">
|
||||
<span v-if="chips.population">~{{chips.today_cases_per_capita.toLocaleString()}}</span>
|
||||
<template v-slot:value v-if="chips.current_cases_per_capita != null">
|
||||
<span v-if="chips.population">~{{chips.current_cases_per_capita.toLocaleString()}}</span>
|
||||
<span v-else>No Data</span>
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.population">
|
||||
<span class="text-violet-500 font-semibold">{{chips.today_cases.toLocaleString()}}</span> out of <span class="text-violet-500 font-semibold">{{chips.population.toLocaleString()}}</span> residents
|
||||
<span class="text-violet-500 font-semibold">{{chips.current_cases.toLocaleString()}}</span> out of <span class="text-violet-500 font-semibold">{{chips.population.toLocaleString()}}</span> residents
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
@@ -68,14 +68,14 @@ const chips = reactive({
|
||||
return col(data, r, 'population')
|
||||
}),
|
||||
|
||||
today_cases: computed(() => {
|
||||
current_cases: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const r = data.value.rows.at(-1)
|
||||
return col(data, r, 'cases')
|
||||
}),
|
||||
|
||||
today_case_change: computed(() => {
|
||||
current_case_change: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data, data.value.rows.at(-1), 'cases')
|
||||
@@ -83,7 +83,7 @@ const chips = reactive({
|
||||
return today - yesterday
|
||||
}),
|
||||
|
||||
today_case_change_percent: computed(() => {
|
||||
current_case_change_percent: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data, data.value.rows.at(-1), 'cases')
|
||||
@@ -100,7 +100,7 @@ const chips = reactive({
|
||||
return Math.abs(percent.toFixed(1))
|
||||
}),
|
||||
|
||||
today_cases_per_capita: computed(() => {
|
||||
current_cases_per_capita: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const r = data.value.rows.at(-1)
|
||||
|
||||
@@ -28,8 +28,6 @@ watch(() => store.parameters.value.county, () => {
|
||||
refreshData()
|
||||
})
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -8,8 +8,6 @@ async function refreshData() {
|
||||
store.data.value = await fetch(`/data/overall/cases/combined.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -28,8 +28,6 @@ watch(() => store.parameters.value.county, () => {
|
||||
refreshData()
|
||||
})
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -8,8 +8,6 @@ async function refreshData() {
|
||||
store.data.value = await fetch(`/data/overall/deaths/combined.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -28,8 +28,6 @@ watch(() => store.parameters.value.county, () => {
|
||||
refreshData()
|
||||
})
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -5,11 +5,9 @@ const store = {
|
||||
}
|
||||
|
||||
async function refreshData() {
|
||||
store.data.value = await fetch(`/data/state/hospitalizations/combined.json`).then(res => res.json())
|
||||
store.data.value = await fetch(`/data/overall/hospitalizations/combined.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>7-Day Percent Positive</template>
|
||||
<template v-slot:heading>7-Day Test Positivity</template>
|
||||
<template v-slot:value v-if="chips.percent_positive">
|
||||
<span :class="{
|
||||
'text-green-600': chips.percent_positive < 2,
|
||||
@@ -41,7 +41,7 @@
|
||||
{{chips.percent_positive}}<span class="font-light">%</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.positive">
|
||||
<template v-slot:meta v-if="chips.percent_positive">
|
||||
<div class="inline-flex flex-wrap text-xs -mx-1">
|
||||
<div class="flex-1">
|
||||
<div class="px-1 text-green-600 font-medium whitespace-nowrap">Low: < 2%</div>
|
||||
|
||||
@@ -22,8 +22,6 @@ watch(() => store.parameters.value.county, () => {
|
||||
refreshData()
|
||||
})
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -23,8 +23,6 @@ async function refreshData() {
|
||||
}
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
@@ -8,8 +8,6 @@ async function refreshData() {
|
||||
store.data.value = await fetch(`/data/risk/health-conditions/health-conditions.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) {
|
||||
refreshData()
|
||||
}
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
|
||||
216
src/components/charts/summary/ChipsSummary.vue
Normal file
216
src/components/charts/summary/ChipsSummary.vue
Normal file
@@ -0,0 +1,216 @@
|
||||
<template>
|
||||
<StatCard>
|
||||
<template v-slot:heading>Tests Reported {{last_report_date ? humanDate(last_report_date) : ''}}</template>
|
||||
<template v-slot:value v-if="chips.current_testing">
|
||||
{{chips.current_testing.toLocaleString()}}
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.current_testing">
|
||||
PCR + Antigen
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.current_testing_change != null">
|
||||
<span v-if="chips.current_testing_change > 0">Up </span>
|
||||
<span v-if="chips.current_testing_change < 0">Down </span>
|
||||
<span class="font-semibold text-violet-600">
|
||||
{{Math.abs(chips.current_testing_change).toLocaleString()}} ({{chips.current_testing_change_percent}}%)
|
||||
</span> compared to previous day
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>7-Day Test Positivity</template>
|
||||
<template v-slot:value v-if="chips.percent_positive">
|
||||
<span :class="{
|
||||
'text-green-600': chips.percent_positive < 2,
|
||||
'text-yellow-500': chips.percent_positive >= 2 && chips.percent_positive < 5,
|
||||
'text-orange-500': chips.percent_positive >= 5 && chips.percent_positive < 20,
|
||||
'text-red-800': chips.percent_positive > 20
|
||||
}">
|
||||
{{chips.percent_positive}}<span class="font-light">%</span>
|
||||
</span>
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.percent_positive">
|
||||
<div class="inline-flex flex-wrap text-xs -mx-1">
|
||||
<div class="flex-1">
|
||||
<div class="px-1 text-green-600 font-medium whitespace-nowrap">Low: < 2%</div>
|
||||
<div class="px-1 text-yellow-600 font-medium whitespace-nowrap">Moderate < 5%</div>
|
||||
</div>
|
||||
<div class="flex-1">
|
||||
<div class="px-1 text-orange-600 font-medium whitespace-nowrap">High < 20%</div>
|
||||
<div class="px-1 text-red-700 font-medium whitespace-nowrap">Very high > 20%</div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="link block mt-2 text-xs" href="https://www.who.int/publications/i/item/considerations-in-adjusting-public-health-and-social-measures-in-the-context-of-covid-19-interim-guidanceLow">
|
||||
Source, see p. 18
|
||||
</a>
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>Confirmed Cases {{last_report_date ? humanDate(last_report_date) : ''}}</template>
|
||||
<template v-slot:value v-if="chips.current_cases != null">
|
||||
{{chips.current_cases.toLocaleString()}}
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.current_case_change != null">
|
||||
<span v-if="chips.current_case_change > 0">Up </span>
|
||||
<span v-if="chips.current_case_change < 0">Down </span>
|
||||
<span :class="{'font-semibold': true, 'text-red-600': chips.current_case_change > 0, 'text-green-600': chips.current_case_change < 0}">
|
||||
{{Math.abs(chips.current_case_change).toLocaleString()}} ({{chips.current_case_change_percent}}%)
|
||||
</span> compared to previous day
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>Confirmed Deaths {{last_report_date ? humanDate(last_report_date) : ''}}</template>
|
||||
<template v-slot:value v-if="chips.current_deaths != null">
|
||||
{{chips.current_deaths.toLocaleString()}}
|
||||
</template>
|
||||
<template v-slot:meta v-if="chips.current_death_change != null">
|
||||
<span v-if="chips.current_death_change > 0">Up </span>
|
||||
<span v-if="chips.current_death_change < 0">Down </span>
|
||||
<span :class="{'font-semibold': true, 'text-red-600': chips.current_death_change > 0, 'text-green-600': chips.current_death_change < 0}">
|
||||
{{Math.abs(chips.current_death_change).toLocaleString()}} ({{chips.current_death_change_percent}}%)
|
||||
</span> compared to previous day
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>Total Confirmed Cases</template>
|
||||
<template v-slot:value v-if="chips.total_cases != null">
|
||||
{{chips.total_cases.toLocaleString()}}
|
||||
</template>
|
||||
</StatCard>
|
||||
|
||||
<StatCard>
|
||||
<template v-slot:heading>Total Confirmed Deaths</template>
|
||||
<template v-slot:value v-if="chips.total_deaths != null">
|
||||
{{chips.total_deaths.toLocaleString()}}
|
||||
</template>
|
||||
</StatCard>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, computed } from 'vue'
|
||||
import { col, humanDate } from '@/components/charts/util'
|
||||
import store from '@/components/charts/summary/store.js'
|
||||
|
||||
const data = store.data
|
||||
|
||||
const last_report_date = computed(() => {
|
||||
if (!data.value) return null
|
||||
return data.value.last_report_date
|
||||
})
|
||||
|
||||
const chips = reactive({
|
||||
current_testing: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.testing, data.value.testing.current, 'combined_performed')
|
||||
}),
|
||||
|
||||
current_testing_change: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.testing, data.value.testing.current, 'combined_performed')
|
||||
const yesterday = col(data.value.testing, data.value.testing.prev, 'combined_performed')
|
||||
return today - yesterday
|
||||
}),
|
||||
|
||||
current_testing_change_percent: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.testing, data.value.testing.current, 'combined_performed')
|
||||
const yesterday = col(data.value.testing, data.value.testing.prev, 'combined_performed')
|
||||
const change = today - yesterday
|
||||
|
||||
const percent = change > 0
|
||||
? ((change / yesterday) * 100)
|
||||
: ((change / today) * 100)
|
||||
|
||||
if (Math.abs(percent) === Infinity) return 100
|
||||
if (isNaN(percent)) return 0
|
||||
|
||||
return Math.abs(percent.toFixed(1))
|
||||
}),
|
||||
|
||||
percent_positive: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.testing, data.value.testing.current, 'seven_day_percent_positive')
|
||||
}),
|
||||
|
||||
current_cases: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.cases, data.value.cases.current, 'cases')
|
||||
}),
|
||||
|
||||
current_case_change: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.cases, data.value.cases.current, 'cases')
|
||||
const yesterday = col(data.value.cases, data.value.cases.prev, 'cases')
|
||||
return today - yesterday
|
||||
}),
|
||||
|
||||
current_case_change_percent: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.cases, data.value.cases.current, 'cases')
|
||||
const yesterday = col(data.value.cases, data.value.cases.prev, 'cases')
|
||||
const change = today - yesterday
|
||||
|
||||
const percent = change > 0
|
||||
? ((change / yesterday) * 100)
|
||||
: ((change / today) * 100)
|
||||
|
||||
if (Math.abs(percent) === Infinity) return 100
|
||||
if (isNaN(percent)) return 0
|
||||
|
||||
return Math.abs(percent.toFixed(1))
|
||||
}),
|
||||
|
||||
current_deaths: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.deaths, data.value.deaths.current, 'deaths')
|
||||
}),
|
||||
|
||||
current_death_change: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.deaths, data.value.deaths.current, 'deaths')
|
||||
const yesterday = col(data.value.deaths, data.value.deaths.prev, 'deaths')
|
||||
return today - yesterday
|
||||
}),
|
||||
|
||||
current_death_change_percent: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
const today = col(data.value.deaths, data.value.deaths.current, 'deaths')
|
||||
const yesterday = col(data.value.deaths, data.value.deaths.prev, 'deaths')
|
||||
const change = today - yesterday
|
||||
|
||||
const percent = change > 0
|
||||
? ((change / yesterday) * 100)
|
||||
: ((change / today) * 100)
|
||||
|
||||
if (Math.abs(percent) === Infinity) return 100
|
||||
if (isNaN(percent)) return 0
|
||||
|
||||
return Math.abs(percent.toFixed(1))
|
||||
}),
|
||||
|
||||
total_cases: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.cases, data.value.cases.current, 'total_cases')
|
||||
}),
|
||||
|
||||
total_deaths: computed(() => {
|
||||
if (!data.value) return null
|
||||
|
||||
return col(data.value.deaths, data.value.deaths.current, 'total_deaths')
|
||||
})
|
||||
})
|
||||
|
||||
</script>
|
||||
13
src/components/charts/summary/store.js
Normal file
13
src/components/charts/summary/store.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import { reactive, ref, watch } from 'vue'
|
||||
|
||||
const store = {
|
||||
data: ref(null)
|
||||
}
|
||||
|
||||
async function refreshData() {
|
||||
store.data.value = await fetch(`/data/summary.json`).then(res => res.json())
|
||||
}
|
||||
|
||||
if (globalThis.window) refreshData()
|
||||
|
||||
export default store
|
||||
@@ -1,7 +1,7 @@
|
||||
export const colors = ['#f5f3ff','#ede9fe','#ddd6fe','#c4b5fd','#a78bfa','#8b5cf6','#7c3aed','#6d28d9','#5b21b6','#4c1d95']
|
||||
|
||||
export function col(data, row, column) {
|
||||
const index = data.value.headers.indexOf(column)
|
||||
const index = data.headers ? data.headers.indexOf(column) : data.value.headers.indexOf(column)
|
||||
if (index === -1) return null
|
||||
return row[index]
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<ul class="space-y-2 pb-2">
|
||||
<li>
|
||||
<router-link :to="{path: '/'}" class="text-base text-violet-900 font-bold flex flex-col rounded-lg p-2 px-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
Introduction
|
||||
Home
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
@@ -28,35 +28,16 @@
|
||||
<icon-mdi-grave-stone class="mr-2"></icon-mdi-grave-stone> deaths?
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-mdi-syringe class="mr-2"></icon-mdi-syringe> vaccinations?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Planned</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<!-- <li>
|
||||
<span class="flex font-bold px-3 py-1 text-violet-900">Which counties have the...</span>
|
||||
<ul class="space-y-1 py-2 ml-3">
|
||||
<li>
|
||||
<router-link :to="{path: '/cases'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-percent-outline class="mr-2"></icon-mdi-percent-outline> highest positivity rate?
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/cases'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-virus-outline class="mr-2"></icon-mdi-virus-outline> most cases by population?
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/cases'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-hospital-box-outline class="mr-2"></icon-mdi-hospital-box-outline> most hospitalizations by population?
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{path: '/cases'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
<icon-mdi-grave-stone class="mr-2"></icon-mdi-grave-stone> most deaths by population?
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</li> -->
|
||||
<li>
|
||||
<span class="flex font-bold px-3 py-1 text-violet-900">Who is most at-risk...</span>
|
||||
<span class="flex font-bold px-3 py-1 text-violet-900">Who is most at risk...</span>
|
||||
<ul class="space-y-1 py-2 ml-3">
|
||||
<li>
|
||||
<router-link :to="{path: '/risk/age'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800">
|
||||
@@ -69,18 +50,36 @@
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<!-- <router-link :to="{path: '/risk/gender'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800"> -->
|
||||
<!-- <router-link :to="{path: '/risk/ethnicity'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800"> -->
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-mdi-gender-male-female class="mr-2"></icon-mdi-gender-male-female> by gender?
|
||||
<icon-mdi-user class="mr-2"></icon-mdi-user> by ethnicity and sex?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Soon</span>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Planned</span>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<!-- <router-link :to="{path: '/risk/ethnicity'}" class="text-base rounded-lg flex items-center p-2 mr-3 hover:bg-violet-100 group" active-class="bg-violet-800 text-white hover:bg-violet-800"> -->
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-mdi-web class="mr-2"></icon-mdi-web> by ethnicity?
|
||||
<icon-mdi-syringe class="mr-2"></icon-mdi-syringe> by vaccination status?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Soon</span>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Planned</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<span class="flex font-bold px-3 py-1 text-violet-900">How many hospital...</span>
|
||||
<ul class="space-y-1 py-2 ml-3">
|
||||
<li class="flex items-center justify-between">
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-healthicons-ventilator class="mr-2"></icon-healthicons-ventilator> resources are available?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Planned</span>
|
||||
</li>
|
||||
<li class="flex items-center justify-between">
|
||||
<a href="#" class="text-base rounded-lg flex items-center p-2 mr-3 group opacity-50">
|
||||
<icon-healthicons-hospitalized class="mr-2"></icon-healthicons-hospitalized> patients have COVID?
|
||||
</a>
|
||||
<span class="rounded-lg bg-violet-700 text-white text-sm px-2 py-1 mr-3">Planned</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
<strong>Note:</strong> This is a citizen science project by <a href="https://thederf.com" class="link">Joshua Bemenderfer</a> and not affiliated with or endorsed in any way by the State of Georgia.
|
||||
</p>
|
||||
<ul class="flex items-center mt-4 lg:mt-0">
|
||||
<li class="text-center"><a href="/sources" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">Sources</a></li>
|
||||
<li class="text-center"><a href="/about" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">About</a></li>
|
||||
<li class="text-center"><a href="mailto:josh@thederf.com" target="_blank" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">Contact</a></li>
|
||||
<li class="text-center"><a href="/#sources" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">Sources</a></li>
|
||||
<li class="text-center"><a href="/#about" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">About</a></li>
|
||||
<li class="text-center"><a href="/#contact" class="font-normal text-violet-900 hover:bg-violet-100 rounded-lg p-2 px-3 block">Contact</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
@@ -1,8 +1,143 @@
|
||||
---
|
||||
title: Introduction
|
||||
title: Home / About / Sources
|
||||
---
|
||||
|
||||
<Card prose={true}>
|
||||
# Introduction
|
||||
<div id="about"></div>
|
||||
# About
|
||||
|
||||
This site exists to provide a simplified, targeted view into information provided by the [Georgia Department of Health (DPH)](https://dph.georgia.gov/covid-19-daily-status-report) on the COVID-19 pandemic.
|
||||
|
||||
While the DPH provides an excellent range of datasets and visualizations, how to understand their utility and interpret them is left as an exercise to the reader.<br/>
|
||||
Here I've attempted to provide explanations of the utility of certain statistics as well as provide some new visualizations not currently provided by the Department of Health dashboard.
|
||||
|
||||
### Disclaimer
|
||||
The data provided on this site is based on information made available by the Georgia Department of Health at the time of reporting.
|
||||
It may at times lack accuracy due to unreported, delayed, or improperly processed information.
|
||||
Reporting time and quality for certain statistics may vary depending on the processes of individual organizations and jurisdictions.
|
||||
|
||||
This site is manually built from daily DPH reports. I will attempt to have new data incorporated by 5:00 PM on weekdays. Updates may be delayed due to personal circumstances.
|
||||
|
||||
**For case reports**, at-home rapid tests are not accounted for. Case numbers may be much higher than reported if [test positivity](/overall/testing) is unusually high.
|
||||
|
||||
### The following additional reports are planned
|
||||
- **What is the overall trend in vaccinations?** - [Data available here](https://experience.arcgis.com/experience/3d8eea39f5c1443db1743a4cb8948a9c) as XLSX, pending processing.
|
||||
- **Who is most at risk by ethnicity and sex?** - Data available in daily reports, pending processing.
|
||||
- **Who is most at risk by vaccination status?** - Weekly reports on breakthrough cases and deaths [are available here](https://dph.georgia.gov/covid-19-breakthrough-reports), but challenging to process.
|
||||
- **How many hospital resources are available?** - [Data available here](https://www.arcgis.com/apps/opsdashboard/index.html#/47c1cee4d02542bea35bc3324d6cf5e3) but requires querying ArcGIS directly.
|
||||
- **How many hospital patients have COVID?** - [Data available here](https://www.arcgis.com/apps/opsdashboard/index.html#/e40c39564f724af7bfe8fd5d88deadb6) but requires querying ArcGIS directly.
|
||||
|
||||
**Please note:** *This is a citizen science project and is not affiliated with or endorsed in any way by the State of Georgia.*
|
||||
</Card>
|
||||
|
||||
<Card class="bg-violet-900">
|
||||
<div id="summary"></div>
|
||||
<div class="prose prose-invert lg:prose-base prose-headings:font-light prose-a:text-violet-700 prose-a:font-normal mb-2">
|
||||
# Summary of Current Overall Trends
|
||||
</div>
|
||||
|
||||
<p class="text-white prose prose-invert lg:prose-base mb-4">
|
||||
For more details, see reporting pages for:
|
||||
<div class="grid gap-2 grid-cols-2 sm:grid-cols-4 -mt-2">
|
||||
<RouterLink to={{path: '/overall/testing'}} class="text-center font-normal no-underline text-white bg-violet-700 hover:bg-violet-500 rounded-lg p-2 px-3 block w-full">Testing</RouterLink>
|
||||
<RouterLink to={{path: '/overall/testing'}} class="text-center font-normal no-underline text-white bg-violet-700 hover:bg-violet-500 rounded-lg p-2 px-3 block w-full">Cases</RouterLink>
|
||||
<RouterLink to={{path: '/overall/testing'}} class="text-center font-normal no-underline text-white bg-violet-700 hover:bg-violet-500 rounded-lg p-2 px-3 block w-full">Hospitalizations</RouterLink>
|
||||
<RouterLink to={{path: '/overall/testing'}} class="text-center font-normal no-underline text-white bg-violet-700 hover:bg-violet-500 rounded-lg p-2 px-3 block w-full">Deaths</RouterLink>
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<div class="grid gap-2 lg:gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3">
|
||||
<MapCases client:load class="sm:col-span-2 xl:col-span-1 xl:row-span-3"/>
|
||||
<ChipsSummary client:load/>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
|
||||
<Card prose={true}>
|
||||
<div id="sources"></div>
|
||||
# Sources
|
||||
|
||||
### Data Sources
|
||||
|
||||
- Georgia Department of Health, COVID-19 Daily Status Report - [https://ga-covid19.ondemand.sas.com/docs/ga_covid_data.zip](https://ga-covid19.ondemand.sas.com/docs/ga_covid_data.zip)
|
||||
- **Update Frequency** - The dataset above is updated each working day around 2:50 PM. I load it onto this site and rebuild shortly thereafter.
|
||||
- **Additional Data** - Some reports on this site may derive additional time-based information by comparing totals from multiple daily reports.
|
||||
- David Eldersveld, TopoJSON Collection, Georgia Counties TopoJSON - [https://github.com/deldersveld/topojson/blob/master/countries/us-states/GA-13-georgia-counties.json](https://github.com/deldersveld/topojson/blob/master/countries/us-states/GA-13-georgia-counties.json)
|
||||
- Tweaked and used for rendering county maps.
|
||||
|
||||
### Site Source Code
|
||||
|
||||
The source code for this website can be found at [https://git.thederf.com/thederf/ga-covid.thederf.com](https://git.thederf.com/thederf/ga-covid.thederf.com).
|
||||
|
||||
Feel free to build it yourself, take a look around, validate the reports, and [suggest improvements](#contact).<br/>
|
||||
*Note, the code is still very much in the "make it work" stage, and has much room for being simplified, abstracted, and cleaned up.*
|
||||
|
||||
#### Licensing
|
||||
|
||||
The source code and content of this site is provided under the [MIT license](https://opensource.org/licenses/MIT).<br/>
|
||||
Datasets, libraries, and other assets used on this site are distributed or used according to the licenses of the original copyright holders to the best of my knowledge.
|
||||
|
||||
#### Stack
|
||||
|
||||
- [îles](https://iles-docs.netlify.app/) - Generates static pages from MDX files and Vue components, with optional component-level client-side hydration.
|
||||
- Excellent for getting a site built with a modern tech stack and minimal extraneous config. Still in beta with some rough edges, but I greatly enjoyed working with it.
|
||||
- [Vue 3](https://v3.vuejs.org/) - Used for layout and client-side components such as charts.
|
||||
- [JSCharting](https://jscharting.com/) - Used for charts. Straightforward to get up and running with, but provides a vast array of data visualization options.
|
||||
- [TailwindCSS](https://tailwindcss.com/) - Because people keep telling me to try it. I get the appeal. It made style tweaking incredibly fast and fluid, but it definitely results in messy markup.
|
||||
|
||||
#### Building & Running
|
||||
|
||||
1. Clone repository using [git](https://git-scm.com/)
|
||||
```bash
|
||||
$ git clone https://git.thederf.com/thederf/ga-covid.thederf.com.git
|
||||
```
|
||||
2. Install dependencies using [npm](https://www.npmjs.com/) or your preferred [node.js](https://nodejs.org) package manager of choice.
|
||||
```bash
|
||||
$ cd ga-covid.thederf.com/
|
||||
$ npm install
|
||||
```
|
||||
3. (Optional) Rebuild the data json files.
|
||||
```bash
|
||||
npm run process:data
|
||||
```
|
||||
4. Run a local server for development
|
||||
```bash
|
||||
npm run dev
|
||||
```
|
||||
5. Build static site
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
#### File Tree
|
||||
|
||||
```txt
|
||||
data/ - Scripts for comverting the raw CSV source files into browser-friendly JSON, removing extraneous data points, and segmenting data into separate files.
|
||||
- parser.js - Data parser entrypoint.
|
||||
parser/... - Scripts for producing json files for specific reports.
|
||||
raw/
|
||||
- YYYY-MM-DD.zip - Raw Georgia DPH datasets from the link above, by date downloaded.
|
||||
Including historical datasets allows for building time-series reports for data provided exclusively in daily counts.
|
||||
...
|
||||
public/ - Static assets.
|
||||
maps/ - GeoJSON map files for rendering maps.
|
||||
data/ - Generated JSON files prepared for browser loading by the parser above.
|
||||
...
|
||||
src/
|
||||
assets/ - CSS & Image assets processed by Vite
|
||||
components/ - Vue components for rendering client-interactive parts of the website.
|
||||
charts/ - Components that handle chart & chip rendering.
|
||||
layouts/ - Vue components for laying out the site. Primarily server-rendered.
|
||||
pages/ - MDX files for site pages.
|
||||
...
|
||||
...
|
||||
```
|
||||
</Card>
|
||||
|
||||
<Card prose={true}>
|
||||
<div id="contact"></div>
|
||||
# Contact
|
||||
|
||||
If you have comments, concerns, requests, or recommendations, feel free to send me an email at
|
||||
[ga-covid@thederf.com](mailto:ga-covid@thederf.com).
|
||||
</Card>
|
||||
|
||||
@@ -14,7 +14,8 @@ title: What is the overall trend in testing?
|
||||
**For example:**<br/>
|
||||
If you get **10** positive results from **100** tests, the disease is probably spreading more widely than would be indicated if there were **50** positive results from **1,000** tests.
|
||||
|
||||
This discrepancy is often apparent on Mondays, where tests and cases from over the weekend might wind up in Monday's report.
|
||||
**Test Positivity** can serve as a rough proxy for inferring how many cases go unreported.<br/>
|
||||
If a high percentage of reported tests are coming back positive, odds are a significant number of cases are going unreported, especially when at-home tests are available.
|
||||
</Card>
|
||||
|
||||
<ParametersTesting client:load/>
|
||||
|
||||
@@ -3,13 +3,13 @@ title: Who is most at risk by health condition?
|
||||
---
|
||||
|
||||
<Card class="col-span-1" prose={true}>
|
||||
# Who is most at risk by condition?
|
||||
# Who is most at risk by health condition?
|
||||
|
||||
## What is this report useful for?
|
||||
|
||||
This report provides charts indicating the number of cases and deaths for a number of tracked medical conditions.
|
||||
|
||||
You may find it useful for assessing the relative risk of COVID to yourself or others.
|
||||
You may find it useful for assessing the relative risk of contracting COVID to yourself or others.
|
||||
</Card>
|
||||
|
||||
<div class="grid gap-2 lg:gap-4 grid-cols-1 xl:grid-cols-4">
|
||||
|
||||
Reference in New Issue
Block a user