'use strict'; //import firebase from "firebase/app"; //import "firebase/functions"; // //const FIREBASE_CONFIG = { // apiKey: "AIzaSyDKw8HXWRn3dtkIRETv-BxtwnklZIpIkxU", // authDomain: "vaxandme.firebaseapp.com", // projectId: "vaxandme", // storageBucket: "vaxandme.appspot.com", // messagingSenderId: "614738281692", // appId: "1:614738281692:web:7a89e0af76675e4f0ea019", // measurementId: "G-N016TVJ6JC", //}; // //firebase.initializeApp(FIREBASE_CONFIG); // //if (window.location.host !== "www.vaxand.me") { // firebase.functions().useEmulator(window.location.host.split(":")[0], 5001); //} // //const fb_functions = firebase.functions(); //const saveResult = fb_functions.httpsCallable("saveResultV1"); //const getPastResult = fb_functions.httpsCallable("getPastResultV1"); //const getStats = fb_functions.httpsCallable("getStatsV1"); const saveResult = () => new Promise((resolve, reject) => reject()); const getPastResult = () => new Promise((resolve, reject) => reject()); const getStats = () => new Promise((resolve, reject) => reject()); const VAX_NAMES = { PB: "Pfizer-BioNTech", MD: "Moderna", JJ: "J&J Janssen", }; const VAX_DOSES = { ONE: "Dose 1", TWO: "Dose 2", }; const VAX_AGES = { "Pfizer-BioNTech": { YOUNGER: "18 - 55", OLDER: "56 & Older", }, Moderna: { YOUNGER: "18 - 64", OLDER: "65 & Older", }, "J&J Janssen": { YOUNGER: "18 - 59", OLDER: "60 & Older", }, }; const VAX_EFFICACY = { "Pfizer-BioNTech": { "18 - 55": 95.3, "56 & Older": 93.8, }, Moderna: { "18 - 64": 95.6, "65 & Older": 86.4, }, "J&J Janssen": { "18 - 59": 66.1, "60 & Older": 66.2, }, }; const PB_DOSE1_YOUNGER_RESULT = { "PAIN AT SITE": 1904, "RED AT SITE": 104, "SWELLING AT SITE": 132, FATIGUE: 1085, HEADACHE: 959, "NEED PAIN MED": 638, "MUSCLE PAIN": 487, CHILLS: 321, DIARRHEA: 255, "JOINT PAIN": 251, FEVER: 85, VOMITING: 28, }; const PB_DOSE2_YOUNGER_RESULT = { "PAIN AT SITE": 1632, "RED AT SITE": 123, "SWELLING AT SITE": 132, FATIGUE: 1247, HEADACHE: 1085, "NEED PAIN MED": 945, "MUSCLE PAIN": 783, CHILLS: 737, "JOINT PAIN": 459, FEVER: 331, DIARRHEA: 219, VOMITING: 40, }; const PB_DOSE1_OLDER_RESULT = { "PAIN AT SITE": 1282, "RED AT SITE": 85, "SWELLING AT SITE": 118, FATIGUE: 615, HEADACHE: 454, "NEED PAIN MED": 358, "MUSCLE PAIN": 251, CHILLS: 113, DIARRHEA: 147, "JOINT PAIN": 155, FEVER: 26, VOMITING: 9, }; const PB_DOSE2_OLDER_RESULT = { "PAIN AT SITE": 1098, "RED AT SITE": 120, "SWELLING AT SITE": 124, FATIGUE: 839, HEADACHE: 647, "NEED PAIN MED": 625, "MUSCLE PAIN": 477, CHILLS: 377, "JOINT PAIN": 313, DIARRHEA: 137, FEVER: 181, VOMITING: 11, }; const MD_DOSE1_YOUNGER_RESULT = { "PAIN AT SITE": 9908, "RED AT SITE": 344, "SWELLING AT SITE": 2089, HEADACHE: 4030, FATIGUE: 4384, "MUSCLE PAIN": 2699, "JOINT PAIN": 1893, "NAUSEA OR VOMITING": 1068, FEVER: 105, CHILLS: 1051, }; const MD_DOSE2_YOUNGER_RESULT = { "PAIN AT SITE": 9873, "RED AT SITE": 982, "SWELLING AT SITE": 3164, FATIGUE: 7430, HEADACHE: 6898, "JOINT PAIN": 4993, CHILLS: 5341, FEVER: 1908, "NAUSEA OR VOMITING": 2348, "MUSCLE PAIN": 6769, }; const MD_DOSE1_OLDER_RESULT = { "PAIN AT SITE": 2782, "RED AT SITE": 86, "SWELLING AT SITE": 396, HEADACHE: 921, FATIGUE: 1251, "MUSCLE PAIN": 742, "JOINT PAIN": 618, "NAUSEA OR VOMITING": 194, CHILLS: 202, FEVER: 10, }; const MD_DOSE2_OLDER_RESULT = { "PAIN AT SITE": 3070, "RED AT SITE": 275, "SWELLING AT SITE": 715, FATIGUE: 2152, HEADACHE: 1704, "MUSCLE PAIN": 1739, "JOINT PAIN": 1291, CHILLS: 1141, "NAUSEA OR VOMITING": 437, FEVER: 370, }; const JJ_YOUNGER_RESULT = { "PAIN AT SITE": 1193, "RED AT SITE": 184, "SWELLING AT SITE": 142, HEADACHE: 905, FATIGUE: 891, "MUSCLE PAIN": 796, "NEED PAIN MED": 538, "NAUSEA OR VOMITING": 315, FEVER: 261, }; const JJ_OLDER_RESULT = { "PAIN AT SITE": 439, "RED AT SITE": 61, "SWELLING AT SITE": 36, HEADACHE: 401, FATIGUE: 392, "MUSCLE PAIN": 317, "NAUSEA OR VOMITING": 162, "NEED PAIN MED": 130, FEVER: 41, }; const VAX_COUNTS = { "Pfizer-BioNTech": { "Dose 1": { "18 - 55": 2291, "56 & Older": 1802, }, "Dose 2": { "18 - 55": 2098, "56 & Older": 1660, }, }, Moderna: { "Dose 1": { "18 - 64": 11406, "65 & Older": 3762, }, "Dose 2": { "18 - 64": 10985, "65 & Older": 3692, }, }, "J&J Janssen": { "18 - 59": 2036, "60 & Older": 1320, }, }; const VAX_RESULTS = { "Pfizer-BioNTech": { "Dose 1": { "18 - 55": PB_DOSE1_YOUNGER_RESULT, "56 & Older": PB_DOSE1_OLDER_RESULT, }, "Dose 2": { "18 - 55": PB_DOSE2_YOUNGER_RESULT, "56 & Older": PB_DOSE2_OLDER_RESULT, }, }, Moderna: { "Dose 1": { "18 - 64": MD_DOSE1_YOUNGER_RESULT, "65 & Older": MD_DOSE1_OLDER_RESULT, }, "Dose 2": { "18 - 64": MD_DOSE2_YOUNGER_RESULT, "65 & Older": MD_DOSE2_OLDER_RESULT, }, }, "J&J Janssen": { "18 - 59": JJ_YOUNGER_RESULT, "60 & Older": JJ_OLDER_RESULT, }, }; const ICONS = { "PAIN AT SITE": "💪", "RED AT SITE": "🔴", "SWELLING AT SITE": "💢", FATIGUE: "🥱", HEADACHE: "🤕", "NEED PAIN MED": "💊", "MUSCLE PAIN": "😫", CHILLS: "🥶", DIARRHEA: "💩", "JOINT PAIN": "🦵", FEVER: "🤒", VOMITING: "🤮", "NAUSEA OR VOMITING": "🤮", }; const DATA_CHOICES = { VNM: "Vax&Me Only", VNM_FDA: "Vax&Me + FDA", FDA: "FDA Only", }; class App extends React.Component { constructor(props) { super(props); this.state = { name: "", dose: "", age: "", gid: "", showInputPopup: false, answers: {}, fetchedResult: {}, stats: {}, loading: true, dataSource: DATA_CHOICES.FDA, loadingMessage: "Gettings stats...", }; } componentDidMount() { const params = window.location.pathname .toUpperCase() .split("/") .filter((v) => v.length > 0); if (params) { if (params[0] && VAX_NAMES[params[0]]) { const name = VAX_NAMES[params[0]]; this.setState({ name }); switch (name) { case VAX_NAMES.PB: case VAX_NAMES.MD: if (params[1] && VAX_DOSES[params[1]]) { const dose = VAX_DOSES[params[1]]; this.setState({ dose }); if (params[2] && VAX_AGES[name][params[2]]) { const age = VAX_AGES[name][params[2]]; this.setState({ age }); } } break; case VAX_NAMES.JJ: if (params[1] && VAX_AGES[name][params[1]]) { const age = VAX_AGES[name][params[1]]; this.setState({ age }); } break; default: break; } } } getStats() .then((v) => { // GET & SET STATS this.setState({ stats: v.data, loadingMessage: "Checking for existing answers...", dataSource: DATA_CHOICES.VNM_FDA, }); // HAS GID? if (window.gtag) { // GET GID window.gtag("get", "G-7VZCY223NG", "client_id", (client_id) => { // GOT GID? if (!!client_id) { // SAVE GID this.setState({ gid: client_id }); // GET PAST ANSWER FOR GID getPastResult({ gid: client_id }) .then((v) => { const { data } = v; if (!!data) { const { name, age, dose } = data; this.setState({ name, age, dose, showInputPopup: true, fetchedResult: data, answers: data, loading: false, }); const inputPopupSubmit = document.querySelector( ".input-popup-submit" ); if (inputPopupSubmit) { inputPopupSubmit.classList.add("submitted"); inputPopupSubmit.innerHTML = "UPDATE ANSWER"; } window.localStorage.setItem("hasExistingAnswer", true); } else { this.setState({ loading: false }); } }) .catch((err) => { console.error("ERROR Getting Past Answer", err); this.setState({ loading: false }); }); } else { this.setState({ loading: false }); } }); } else { this.setState({ loading: false }); } }) .catch((err) => { console.error("ERROR GETTING STATS", err); this.setState({ loading: false }); }); } shouldShowDoses = () => { const { name, loading } = this.state; if (loading) { return false; } return name && (name === VAX_NAMES.PB || name === VAX_NAMES.MD); }; shouldShowAgeGroup = () => { const { name, dose, loading } = this.state; if (loading) { return false; } switch (name) { case VAX_NAMES.JJ: return true; case VAX_NAMES.MD: case VAX_NAMES.PB: return !!dose; default: return false; } }; shouldShowResults = () => { const { name, dose, age, loading } = this.state; if (loading) { return false; } switch (name) { case VAX_NAMES.JJ: return !!age; case VAX_NAMES.MD: case VAX_NAMES.PB: return !!dose && !!age; default: return false; } }; getResults = () => { const { name, dose, age, loading } = this.state; if (loading) { return null; } switch (name) { case VAX_NAMES.JJ: return VAX_RESULTS[name][age]; case VAX_NAMES.MD: case VAX_NAMES.PB: return VAX_RESULTS[name][dose][age]; default: return null; } }; copyShareLink = () => { const { name, dose, age } = this.state; let SHARE_URL = window.location.host; const serialize_name = Object.keys(VAX_NAMES).filter( (k) => VAX_NAMES[k] === name )[0]; const serialize_dose = Object.keys(VAX_DOSES).filter( (k) => VAX_DOSES[k] === dose )[0]; const serialize_age = Object.keys(VAX_AGES[name]).filter( (k) => VAX_AGES[name][k] === age )[0]; if (serialize_name) { SHARE_URL += `/${serialize_name}`; } if (serialize_dose) { SHARE_URL += `/${serialize_dose}`; } if (serialize_age) { SHARE_URL += `/${serialize_age}`; } const copyTextInput = document.createElement("input"); document.body.appendChild(copyTextInput); copyTextInput.value = SHARE_URL.toLowerCase(); copyTextInput.select(); document.execCommand("copy"); copyTextInput.remove(); document.querySelector("#share-result").innerHTML = "Copied Link"; setTimeout(() => { document.querySelector("#share-result").innerHTML = "Share ↗"; }, 1500); }; updateAnswers = (symptom, dose) => { const { answers } = this.state; const newAnswers = Object.assign({}, answers); if (!!dose) { if (!newAnswers[dose]) { newAnswers[dose] = {}; } if (newAnswers[dose][symptom]) { newAnswers[dose][symptom] = !newAnswers[dose][symptom]; } else { newAnswers[dose][symptom] = true; } } else { if (newAnswers[symptom]) { newAnswers[symptom] = !newAnswers[symptom]; } else { newAnswers[symptom] = true; } } this.setState({ answers: newAnswers }); }; submitAnswer = () => { document.querySelector(".input-popup-submit").innerHTML = "SENDING..."; const { name, dose, age, answers, gid } = this.state; const result = this.getResults(); const symptoms = {}; delete answers.name; delete answers.dose; delete answers.age; if (!!dose) { symptoms[VAX_DOSES.ONE] = {}; symptoms[VAX_DOSES.TWO] = {}; Object.keys(VAX_DOSES).forEach((dose) => { Object.keys(result).forEach((symptom) => { symptoms[VAX_DOSES[dose]][symptom] = false; if (answers[VAX_DOSES[dose]] && answers[VAX_DOSES[dose]][symptom]) { symptoms[VAX_DOSES[dose]][symptom] = true; } }); }); } else { Object.keys(result).forEach((symptom) => { symptoms[symptom] = false; if (answers[symptom]) { symptoms[symptom] = true; } }); } const submitAnswers = Object.assign({}, symptoms, { name, dose, age, gid, }); saveResult(submitAnswers) .then(() => { delete submitAnswers.gid; this.setState({ fetchedResult: submitAnswers }); const inputPopupSubmit = document.querySelector(".input-popup-submit"); if (inputPopupSubmit.classList.contains("errored")) { inputPopupSubmit.classList.remove("errored"); } if (!inputPopupSubmit.classList.contains("submitted")) { inputPopupSubmit.classList.add("submitted"); } inputPopupSubmit.innerHTML = "THANK YOU!"; setTimeout(() => { inputPopupSubmit.innerHTML = "UPDATE ANSWER"; }, 1500); }) .catch((err) => { const inputPopupSubmit = document.querySelector(".input-popup-submit"); if (!inputPopupSubmit.classList.contains("errored")) { inputPopupSubmit.classList.add("errored"); } if (inputPopupSubmit.classList.contains("submitted")) { inputPopupSubmit.classList.remove("submitted"); } inputPopupSubmit.innerHTML = "UH OH...UNABLE TO SEND"; setTimeout(() => { inputPopupSubmit.innerHTML = "TRY AGAIN"; }, 1500); console.error("ERROR Saving Answer", err); }); }; getAnswerOptions = (answerDose) => { const { answers, dose } = this.state; const result = this.getResults(); return (
{!!answerDose ? (
{answerDose}
) : null}

{dose === VAX_DOSES.ONE && answerDose === VAX_DOSES.TWO ? "(You can comeback later to tell us about Dose 2)" : "(Select all side effects that you experienced)"}

{Object.keys(result).map((symptom) => ( ))}
); }; getStatForSymptom = (symptom) => { const { dataSource, name, dose, age, stats } = this.state; switch (dataSource) { case DATA_CHOICES.FDA: if (!!dose) { return Math.ceil( (VAX_RESULTS[name][dose][age][symptom] / VAX_COUNTS[name][dose][age]) * 10 ); } else { return Math.ceil( (VAX_RESULTS[name][age][symptom] / VAX_COUNTS[name][age]) * 10 ); } case DATA_CHOICES.VNM: if (Object.keys(stats).length > 0) { if (!!dose) { return Math.ceil( (stats[name][dose][age][symptom] / stats[name][dose][age].count) * 10 ); } else { return Math.ceil( (stats[name][age][symptom] / stats[name][age].count) * 10 ); } } else { return 0; } case DATA_CHOICES.VNM_FDA: let symptomCount = 0; let totalCount = 0; if (Object.keys(stats).length > 0) { if (!!dose) { symptomCount = VAX_RESULTS[name][dose][age][symptom] + stats[name][dose][age][symptom]; totalCount = VAX_COUNTS[name][dose][age] + stats[name][dose][age].count; } else { symptomCount = VAX_RESULTS[name][age][symptom] + stats[name][age][symptom]; totalCount = VAX_COUNTS[name][age] + stats[name][age].count; } } else { symptomCount = VAX_RESULTS[name][dose][age][symptom]; totalCount = VAX_COUNTS[name][dose][age]; } return Math.ceil((symptomCount / totalCount) * 10); default: return 1; } }; getSampleSize = () => { const { dataSource, name, dose, age, stats } = this.state; switch (dataSource) { case DATA_CHOICES.FDA: if (!!dose) { return VAX_COUNTS[name][dose][age]; } else { return VAX_COUNTS[name][age]; } case DATA_CHOICES.VNM: if (Object.keys(stats).length > 0) { if (!!dose) { return stats[name][dose][age].count; } else { return stats[name][age].count; } } else { return 0; } case DATA_CHOICES.VNM_FDA: let totalCount = 0; if (Object.keys(stats).length > 0) { if (!!dose) { totalCount = VAX_COUNTS[name][dose][age] + stats[name][dose][age].count; } else { totalCount = VAX_COUNTS[name][age] + stats[name][age].count; } } else { totalCount = VAX_COUNTS[name][dose][age]; } return totalCount; default: return 0; } }; render() { const { name, dose, age, showInputPopup, loading, fetchedResult, dataSource, loadingMessage, stats, } = this.state; let result = {}; let resultAtSite = {}; if (this.shouldShowResults()) { result = Object.assign({}, this.getResults()); Object.keys(result).forEach((s) => { if (s.includes("AT SITE")) { resultAtSite[s] = result[s]; delete result[s]; } }); } return (
Getting vaccinated?

Find out what to expect.

{loading ? (

{loadingMessage}

) : null} {!loading ? (

Select Vaccine

{Object.values(VAX_NAMES).map((v) => ( ))}
) : null} {this.shouldShowDoses() ? (

Select Dose

{Object.values(VAX_DOSES).map((v) => ( ))}
) : null} {this.shouldShowAgeGroup() ? (

Select Age Group

{Object.values(VAX_AGES[name]).map((v) => ( ))}
) : null} {this.shouldShowResults() ? (

Here's what to expect.

Share ↗
Download Chart ↗
Use data from:
Based on {` ${this.getSampleSize() .toString() .replace(/\B(?=(\d{3})+(?!\d))/g, ",")} `} individual experiences
{Object.keys(stats).length < 1 ? (
Failed to get stats from Vax&Me
) : null}
) : null} {this.shouldShowResults() ? (
{/*
ⓘ
*/}
NET EFFICACY

{VAX_EFFICACY[name][age]}%

of vaccine trial participants who took the {name}{" "} vaccine (in the {age} age group) did not get COVID-19
See Data Sources ↗
What is efficacy? ↗
) : null} {this.shouldShowResults() ? (
{Object.keys(resultAtSite).map((symptom) => (
{ICONS[symptom]}

{symptom}

{this.getStatForSymptom(symptom)}/10

))} {Object.keys(result).map((symptom) => (
{ICONS[symptom]}

{symptom}

{this.getStatForSymptom(symptom)}/10

))}
) : null}
{this.shouldShowResults() ? (
this.setState({ showInputPopup: !showInputPopup })} >
Already vaxxed?

Tell us how it went.

{showInputPopup ? (

I am in age group {age} and got the {name} vaccine. I experienced:

{this.shouldShowDoses() ? Object.keys(VAX_DOSES).map((dose) => this.getAnswerOptions(VAX_DOSES[dose]) ) : this.getAnswerOptions()}

You can comeback and update your experience at any time!

(Just use the same device)

) : null} {showInputPopup ? (
SUBMIT
) : null}
) : null}
); } } const domContainer = document.querySelector('#root'); const root = ReactDOM.createRoot(domContainer); root.render(React.createElement(App));