diff --git a/firebase.json b/firebase.json index 4128b13..d488395 100644 --- a/firebase.json +++ b/firebase.json @@ -54,12 +54,15 @@ }, "emulators": { "functions": { + "host": "192.168.86.46", "port": 5001 }, "firestore": { + "host": "192.168.86.46", "port": 8080 }, "hosting": { + "host": "192.168.86.46", "port": 5000 }, "ui": { diff --git a/functions/package.json b/functions/package.json index e433c9c..fc11679 100644 --- a/functions/package.json +++ b/functions/package.json @@ -1,5 +1,5 @@ { - "name": "functions", + "name": "vaxandme-api", "scripts": { "lint": "eslint --ext .js,.ts .", "build": "tsc", diff --git a/functions/src/index.ts b/functions/src/index.ts index a6abe10..cc0fb8f 100644 --- a/functions/src/index.ts +++ b/functions/src/index.ts @@ -19,24 +19,39 @@ admin.initializeApp({ credential: admin.credential.cert(params), }); -const VAX_NAMES : Record = { +const VAX_NAMES: Record = { PB: "Pfizer-BioNTech", MD: "Moderna", JJ: "J&J Janssen", }; -const VAX_DOSES : Record = { +const VAX_DOSES: Record = { ONE: "Dose 1", TWO: "Dose 2", }; +const VAX_AGES: Record> = { + "Pfizer-BioNTech": { + YOUNGER: "18 - 55", + OLDER: "56 & Older", + }, + "Moderna": { + YOUNGER: "18 - 64", + OLDER: "65 & Older", + }, + "J&J Janssen": { + YOUNGER: "18 - 59", + OLDER: "60 & Older", + }, +}; + type SaveResultRequestData = { name: string; age: string; dose: string; gid: string; } & { - [x: string] : boolean; + [x: string]: boolean; }; const serializeGaId = (_gaid: string): string => { @@ -46,86 +61,90 @@ const serializeGaId = (_gaid: string): string => { return ""; }; -const addResultToStats = async (data : SaveResultRequestData) => { - const cleanData : Record = - Object.assign({}, data); +const addResultToStats = async (data: SaveResultRequestData) => { + const cleanData: Record = Object.assign({}, data); delete cleanData.name; delete cleanData.dose; delete cleanData.age; delete cleanData.gid; - const updateDoc : Record = { + const updateDoc: Record = { count: admin.firestore.FieldValue.increment(1), }; if (data.name === VAX_NAMES.PB || data.name === VAX_NAMES.MD) { if (data.dose === VAX_DOSES.ONE) { - updateDoc[`${VAX_DOSES.ONE}.${data.age}.count`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${VAX_DOSES.ONE}.${data.age}.count` + ] = admin.firestore.FieldValue.increment(1); } else if (data.dose === VAX_DOSES.TWO) { - updateDoc[`${VAX_DOSES.ONE}.${data.age}.count`] = - admin.firestore.FieldValue.increment(1); - updateDoc[`${VAX_DOSES.TWO}.${data.age}.count`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${VAX_DOSES.ONE}.${data.age}.count` + ] = admin.firestore.FieldValue.increment(1); + updateDoc[ + `${VAX_DOSES.TWO}.${data.age}.count` + ] = admin.firestore.FieldValue.increment(1); } - Object.keys(VAX_DOSES).forEach((doseKey : string) => { - const dose : string = VAX_DOSES[doseKey]; - Object.keys(cleanData[dose]).forEach((symptom : string) => { + Object.keys(VAX_DOSES).forEach((doseKey: string) => { + const dose: string = VAX_DOSES[doseKey]; + Object.keys(cleanData[dose]).forEach((symptom: string) => { if (cleanData[dose][symptom]) { let updateDocSymptom = symptom.replace("/", "OR"); if (symptom === "DIARRHEA") { updateDocSymptom = "DIRRHEA"; } - updateDoc[`${dose}.${data.age}.${updateDocSymptom}`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${dose}.${data.age}.${updateDocSymptom}` + ] = admin.firestore.FieldValue.increment(1); } }); }); } else { - updateDoc[`${data.age}.count`] = - admin.firestore.FieldValue.increment(1); - Object.keys(cleanData).forEach((symptom : string) => { + updateDoc[`${data.age}.count`] = admin.firestore.FieldValue.increment(1); + Object.keys(cleanData).forEach((symptom: string) => { let updateDocSymptom = symptom.replace("/", "OR"); if (symptom === "DIARRHEA") { updateDocSymptom = "DIRRHEA"; } - updateDoc[`${data.age}.${updateDocSymptom}`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${data.age}.${updateDocSymptom}` + ] = admin.firestore.FieldValue.increment(1); }); } admin.firestore().collection("stats").doc(data.name).update(updateDoc); }; -const removeResultFromStats = async (data : FirebaseFirestore.DocumentData) => { - const cleanData : Record = - Object.assign({}, data); +const removeResultFromStats = async (data: FirebaseFirestore.DocumentData) => { + const cleanData: Record = Object.assign({}, data); delete cleanData.name; delete cleanData.dose; delete cleanData.age; delete cleanData.gid; - const updateDoc : Record = { + const updateDoc: Record = { count: admin.firestore.FieldValue.increment(-1), }; if (data.name === VAX_NAMES.PB || data.name === VAX_NAMES.MD) { - Object.keys(VAX_DOSES).forEach((doseKey : string) => { - const dose : string = VAX_DOSES[doseKey]; - Object.keys(cleanData[dose]).forEach((symptom : string) => { + Object.keys(VAX_DOSES).forEach((doseKey: string) => { + const dose: string = VAX_DOSES[doseKey]; + Object.keys(cleanData[dose]).forEach((symptom: string) => { if (cleanData[dose][symptom]) { let updateDocSymptom = symptom.replace("/", "OR"); if (symptom === "DIARRHEA") { updateDocSymptom = "DIRRHEA"; } - updateDoc[`${dose}.${data.age}.${updateDocSymptom}`] = - admin.firestore.FieldValue.increment(-1); + updateDoc[ + `${dose}.${data.age}.${updateDocSymptom}` + ] = admin.firestore.FieldValue.increment(-1); } }); }); } else { - Object.keys(cleanData).forEach((symptom : string) => { + Object.keys(cleanData).forEach((symptom: string) => { let updateDocSymptom = symptom.replace("/", "OR"); if (symptom === "DIARRHEA") { updateDocSymptom = "DIRRHEA"; } - updateDoc[`${data.age}.${updateDocSymptom}`] = - admin.firestore.FieldValue.increment(-1); + updateDoc[ + `${data.age}.${updateDocSymptom}` + ] = admin.firestore.FieldValue.increment(-1); }); } admin.firestore().collection("stats").doc(data.name).update(updateDoc); @@ -134,18 +153,67 @@ const removeResultFromStats = async (data : FirebaseFirestore.DocumentData) => { /** * FUNCTIONS FROM V1.1.0 TO CURRENT */ -export const getStatsV1 = functions.https.onCall( - async () => { - const stats = await admin.firestore().collection("stats").get(); - const docs = stats.docs - .map((docSnap) => ({name: docSnap.id, result: docSnap.data()})); - const returnData : Record = {}; - docs.forEach((vaxResult) => { - returnData[vaxResult.name] = {}; - returnData[vaxResult.name] = vaxResult.result; +export const getStatsV1 = functions.https.onCall(async () => { + const stats = await admin.firestore().collection("stats").get(); + const docs = stats.docs.map((docSnap) => ({ + name: docSnap.id, + result: docSnap.data(), + })); + const returnData: Record = {}; + docs.forEach((vaxResult) => { + if (vaxResult.name === VAX_NAMES.PB || vaxResult.name === VAX_NAMES.MD) { + Object.keys(VAX_DOSES).forEach((doseKey) => { + const dose: string = VAX_DOSES[doseKey]; + Object.keys(VAX_AGES[vaxResult.name]).forEach((ageKey) => { + const age: string = VAX_AGES[vaxResult.name][ageKey]; + if (vaxResult.result[dose][age]["NAUSEA / VOMITING"] >= 0) { + if (vaxResult.result[dose][age]["NAUSEA OR VOMITING"] >= 0) { + vaxResult.result[dose][age]["NAUSEA OR VOMITING"] += + vaxResult.result[dose][age]["NAUSEA / VOMITING"]; + } else { + vaxResult.result[dose][age]["NAUSEA OR VOMITING"] = + vaxResult.result[dose][age]["NAUSEA / VOMITING"]; + } + } + if (vaxResult.result[dose][age]["DIRRHEA"] >= 0) { + if (vaxResult.result[dose][age]["DIARRHEA"] >= 0) { + vaxResult.result[dose][age]["DIARRHEA"] += + vaxResult.result[dose][age]["DIRRHEA"]; + } else { + vaxResult.result[dose][age]["DIARRHEA"] = + vaxResult.result[dose][age]["DIRRHEA"]; + } + } + }); }); - return returnData; - }); + } else { + Object.keys(VAX_AGES[vaxResult.name]).forEach((ageKey) => { + const age: string = VAX_AGES[vaxResult.name][ageKey]; + if (vaxResult.result[age]["NAUSEA / VOMITING"] >= 0) { + if (vaxResult.result[age]["NAUSEA OR VOMITING"] >= 0) { + vaxResult.result[age]["NAUSEA OR VOMITING"] += + vaxResult.result[age]["NAUSEA / VOMITING"]; + } else { + vaxResult.result[age]["NAUSEA OR VOMITING"] = + vaxResult.result[age]["NAUSEA / VOMITING"]; + } + } + if (vaxResult.result[age]["DIRRHEA"] >= 0) { + if (vaxResult.result[age]["DIARRHEA"] >= 0) { + vaxResult.result[age]["DIARRHEA"] += + vaxResult.result[age]["DIRRHEA"]; + } else { + vaxResult.result[age]["DIARRHEA"] = + vaxResult.result[age]["DIRRHEA"]; + } + } + }); + } + returnData[vaxResult.name] = {}; + returnData[vaxResult.name] = vaxResult.result; + }); + return returnData; +}); export const saveResultV1 = functions.https.onCall( async (data: SaveResultRequestData, context) => { @@ -159,8 +227,7 @@ export const saveResultV1 = functions.https.onCall( .get() .then((docSnap) => docSnap.data()); // Update user result - const cleanData : Record = - Object.assign({}, data); + const cleanData: Record = Object.assign({}, data); delete cleanData.gid; await admin .firestore() @@ -175,73 +242,80 @@ export const saveResultV1 = functions.https.onCall( await addResultToStats(data); } } - }); + } +); -export const getPastResultV1 = - functions.https.onCall(async (data : {gid:string}, context) => { - if (!!data && !!context) { - const {gid} = data; - let hasToUpdateDb = false; - const existingData : admin.firestore.DocumentData | undefined = +export const getPastResultV1 = functions.https.onCall( + async (data: { gid: string }, context) => { + if (!!data && !!context) { + const {gid} = data; + let hasToUpdateDb = false; + const existingData: admin.firestore.DocumentData | undefined = await admin .firestore() .collection("results") .doc(serializeGaId(gid)) .get() .then((doc) => doc.data()); - if (existingData) { - const returnData : admin.firestore.DocumentData | undefined = - Object.assign({}, existingData); - if (existingData.name === VAX_NAMES.PB || - existingData.name === VAX_NAMES.MD) { - Object.keys(VAX_DOSES).forEach((doseKey : string) => { - const dose : string = VAX_DOSES[doseKey]; - if (!existingData[dose]) { - hasToUpdateDb = true; - const temp : Record = {}; - Object.keys(existingData).forEach((symptom) => { - if (symptom !== "name" && + if (existingData) { + const returnData: + | admin.firestore.DocumentData + | undefined = Object.assign({}, existingData); + if ( + existingData.name === VAX_NAMES.PB || + existingData.name === VAX_NAMES.MD + ) { + Object.keys(VAX_DOSES).forEach((doseKey: string) => { + const dose: string = VAX_DOSES[doseKey]; + if (!existingData[dose]) { + hasToUpdateDb = true; + const temp: Record = {}; + Object.keys(existingData).forEach((symptom) => { + if ( + symptom !== "name" && symptom !== "age" && - symptom !== "dose") { - if (existingData.dose === dose) { - temp[symptom] = existingData[symptom]; - delete returnData[symptom]; - } else { - temp[symptom] = false; + symptom !== "dose" + ) { + if (existingData.dose === dose) { + temp[symptom] = existingData[symptom]; + delete returnData[symptom]; + } else { + temp[symptom] = false; + } } - } - }); - returnData[dose] = temp; - } - if (returnData[dose]["NAUSEA / VOMITING"]) { + }); + returnData[dose] = temp; + } + if (returnData[dose]["NAUSEA / VOMITING"]) { + returnData[dose]["NAUSEA OR VOMITING"] = + returnData[dose]["NAUSEA / VOMITING"]; + } + if (returnData[dose]["DIRRHEA"]) { + returnData[dose]["DIARRHEA"] = returnData["DIRRHEA"]; + } + }); + } else { + if (returnData["NAUSEA / VOMITING"]) { returnData["NAUSEA OR VOMITING"] = returnData["NAUSEA / VOMITING"]; } if (returnData["DIRRHEA"]) { returnData["DIARRHEA"] = returnData["DIRRHEA"]; } - }); - } else { - if (returnData["NAUSEA / VOMITING"]) { - returnData["NAUSEA OR VOMITING"] = - returnData["NAUSEA / VOMITING"]; } - if (returnData["DIRRHEA"]) { - returnData["DIARRHEA"] = returnData["DIRRHEA"]; + if (hasToUpdateDb) { + await admin + .firestore() + .collection("results") + .doc(serializeGaId(gid)) + .set(returnData); } + return returnData; } - if (hasToUpdateDb) { - await admin - .firestore() - .collection("results") - .doc(serializeGaId(gid)) - .set(returnData); - } - return returnData; } + return undefined; } - return undefined; - }); +); /** * FUNCTIONS FROM V1.0.0 TO V1.0.1 @@ -252,7 +326,7 @@ export const saveResult = functions.https.onCall( const {gid} = data; const docId: string = serializeGaId(gid); const docData: Record = - Object.assign({}, data); + Object.assign({}, data); delete docData.gid; const existingData = await admin .firestore() @@ -260,16 +334,19 @@ export const saveResult = functions.https.onCall( .doc(docId) .get() .then((doc) => doc.data()); - if (existingData !== undefined && existingData !== docData && - existingData.name === docData.name) { + if ( + existingData !== undefined && + existingData !== docData && + existingData.name === docData.name + ) { // DATA EXISTS FOR USER // BUT DIFF DATA SENT FOR UPDATE await admin.firestore().collection("results").doc(docId).set(docData); delete docData.age; delete docData.name; delete docData.dose; - const updateDoc : Record = {}; - Object.keys(docData).forEach((symptom : string) => { + const updateDoc: Record = {}; + Object.keys(docData).forEach((symptom: string) => { // IF WAS TRUE, NOW FALSE = -1 // IF WAS TRUE, NOW TRUE = 0 // IF WAS FALSE, NOW TRUE = +1 @@ -277,17 +354,20 @@ export const saveResult = functions.https.onCall( let incrementValue = 0; if (existingData[symptom] === true && docData[symptom] === false) { incrementValue = -1; - } else if (existingData[symptom] === false && - docData[symptom] === true) { + } else if ( + existingData[symptom] === false && + docData[symptom] === true + ) { incrementValue = 1; } if (data.dose) { updateDoc[ - `${data.dose}.${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(incrementValue); + `${data.dose}.${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(incrementValue); } else { - updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(incrementValue); + updateDoc[ + `${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(incrementValue); } }); admin @@ -295,25 +375,27 @@ export const saveResult = functions.https.onCall( .collection("stats") .doc(data.name) .update(updateDoc); - } else if (existingData !== undefined && existingData !== docData && - existingData.name !== docData.name) { + } else if ( + existingData !== undefined && + existingData !== docData && + existingData.name !== docData.name + ) { // UNDO DATA FOR OLD VAX // DECREMENT VALUES FOR EACH SYMPTOM ON OLD VAX - const undoDoc : Record = { + const undoDoc: Record = { count: admin.firestore.FieldValue.increment(-1), }; - Object.keys(existingData).forEach((symptom : string) => { - if (symptom !== "name" && symptom !== "dose" && - symptom !== "age" ) { + Object.keys(existingData).forEach((symptom: string) => { + if (symptom !== "name" && symptom !== "dose" && symptom !== "age") { if (existingData[symptom] === true) { if (existingData.dose) { - undoDoc[ - `${existingData.dose}.${existingData.age}.${ - symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(-1); + undoDoc[`${existingData.dose}.${existingData.age}.${ + symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(-1); } else { - undoDoc[`${existingData.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(-1); + undoDoc[ + `${existingData.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(-1); } } } @@ -330,19 +412,20 @@ export const saveResult = functions.https.onCall( delete docData.name; delete docData.dose; // INCREMENT TOTAL RESPONSE COUNT - const updateDoc : Record = { + const updateDoc: Record = { count: admin.firestore.FieldValue.increment(1), }; // INCREMENT VALUES FOR EACH SYMPTOM - Object.keys(docData).forEach((symptom : string) => { + Object.keys(docData).forEach((symptom: string) => { if (docData[symptom] === true) { if (data.dose) { updateDoc[ - `${data.dose}.${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(1); + `${data.dose}.${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(1); } else { - updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(1); } } }); @@ -359,19 +442,20 @@ export const saveResult = functions.https.onCall( delete docData.name; delete docData.dose; // INCREMENT TOTAL RESPONSE COUNT - const updateDoc : Record = { + const updateDoc: Record = { count: admin.firestore.FieldValue.increment(1), }; // INCREMENT VALUES FOR EACH SYMPTOM - Object.keys(docData).forEach((symptom : string) => { + Object.keys(docData).forEach((symptom: string) => { if (docData[symptom] === true) { if (data.dose) { updateDoc[ - `${data.dose}.${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(1); + `${data.dose}.${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(1); } else { - updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] = - admin.firestore.FieldValue.increment(1); + updateDoc[ + `${data.age}.${symptom.replace("/", "OR")}` + ] = admin.firestore.FieldValue.increment(1); } } }); @@ -382,12 +466,13 @@ export const saveResult = functions.https.onCall( .update(updateDoc); } } - }); + } +); export const getPastResult = functions.https.onCall(async (data, context) => { if (!!data && !!context) { const {gid} = data; - const existingData : admin.firestore.DocumentData | undefined = await admin + const existingData: admin.firestore.DocumentData | undefined = await admin .firestore() .collection("results") .doc(serializeGaId(gid)) @@ -395,8 +480,7 @@ export const getPastResult = functions.https.onCall(async (data, context) => { .then((doc) => doc.data()); if (existingData) { if (existingData["NAUSEA / VOMITING"]) { - existingData["NAUSEA OR VOMITING"] = - existingData["NAUSEA / VOMITING"]; + existingData["NAUSEA OR VOMITING"] = existingData["NAUSEA / VOMITING"]; } return existingData; } diff --git a/website/package.json b/website/package.json index 28845a3..f52f52e 100644 --- a/website/package.json +++ b/website/package.json @@ -1,6 +1,6 @@ { "name": "vaxandme", - "version": "0.1.0", + "version": "1.1.0", "private": true, "dependencies": { "firebase": "^8.4.1", diff --git a/website/public/styles/extrasmall.css b/website/public/styles/extrasmall.css index e51f295..df7d9d7 100644 --- a/website/public/styles/extrasmall.css +++ b/website/public/styles/extrasmall.css @@ -392,22 +392,23 @@ footer .by { animation: 2s ease-out 0s infinite loading; } -.result-header-contianer { +.result-header-container { display: flex; - align-items: flex-start; + align-items: center; margin-top: 5rem; flex-direction: column; margin-bottom: 2rem; } -.result-header-contianer .symptom-container { - margin-top: 0; +.result-header-container .symptom-container { + margin: 0; flex: 1; width: 100%; } .result-header-select { width: 100%; + margin-top: 2rem; } .result-header-select .overline { @@ -415,6 +416,17 @@ footer .by { margin-bottom: 0.75rem; } + +.result-header-select .overline.errored { + margin-bottom: 0; + margin-top: 0.75rem; + color: #c43d34; +} +.result-header-select .overline.success { + margin-bottom: 0; + margin-top: 0.75rem; +} + .result-header-select select { background-color: var(--color-tertiary); border-radius: 1rem; diff --git a/website/public/styles/medium.css b/website/public/styles/medium.css index bf6937e..6951a27 100644 --- a/website/public/styles/medium.css +++ b/website/public/styles/medium.css @@ -109,16 +109,16 @@ footer { } -.result-header-contianer { - margin-bottom: 0; +.result-header-container { flex-direction: row; } -.result-header-contianer .symptom-container { +.result-header-container .symptom-container { width: fit-content; } .result-header-select { + margin-top: 0rem; width: fit-content; padding-left: 3rem; border-left: 1px solid var(--color-secondary); diff --git a/website/src/index.js b/website/src/index.js index 04f51a7..d568881 100644 --- a/website/src/index.js +++ b/website/src/index.js @@ -14,8 +14,8 @@ const FIREBASE_CONFIG = { }; firebase.initializeApp(FIREBASE_CONFIG); -if (window.location.host.startsWith("localhost")) { - firebase.functions().useEmulator("localhost", 5001); +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"); @@ -280,6 +280,7 @@ class App extends React.Component { stats: {}, loading: true, dataSource: DATA_CHOICES.FDA, + loadingMessage: "Gettings stats...", }; } componentDidMount() { @@ -315,58 +316,78 @@ class App extends React.Component { } } - if (!window.localStorage.getItem("hasExistingAnswer")) { - this.setState({ loading: false }); - } - - if (window.gtag) { - window.gtag("get", "G-7VZCY223NG", "client_id", (client_id) => { - if (!!client_id) { - this.setState({ gid: client_id }); - 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, + 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 }); }); - 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); + } else { this.setState({ loading: false }); - }); + } + }); + } else { + this.setState({ loading: false }); } + }) + .catch((err) => { + console.error("ERROR GETTING STATS", err); + this.setState({ loading: false }); }); - } else { - this.setState({ loading: false }); - } - - getStats().then((v) => this.setState({ stats: v.data })); } shouldShowDoses = () => { - const { name } = this.state; + const { name, loading } = this.state; + if (loading) { + return false; + } return name && (name === VAX_NAMES.PB || name === VAX_NAMES.MD); }; shouldShowAgeGroup = () => { - const { name, dose } = this.state; + const { name, dose, loading } = this.state; + if (loading) { + return false; + } switch (name) { case VAX_NAMES.JJ: return true; @@ -378,7 +399,10 @@ class App extends React.Component { } }; shouldShowResults = () => { - const { name, dose, age } = this.state; + const { name, dose, age, loading } = this.state; + if (loading) { + return false; + } switch (name) { case VAX_NAMES.JJ: return !!age; @@ -390,7 +414,10 @@ class App extends React.Component { } }; getResults = () => { - const { name, dose, age } = this.state; + const { name, dose, age, loading } = this.state; + if (loading) { + return null; + } switch (name) { case VAX_NAMES.JJ: return VAX_RESULTS[name][age]; @@ -558,6 +585,96 @@ class App extends React.Component { ); }; + 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, @@ -567,6 +684,8 @@ class App extends React.Component { loading, fetchedResult, dataSource, + loadingMessage, + stats, } = this.state; let result = {}; let resultAtSite = {}; @@ -598,7 +717,7 @@ class App extends React.Component { {loading ? (

- Checking for existing answers... + {loadingMessage}

@@ -690,7 +809,7 @@ class App extends React.Component { ) : null} {this.shouldShowResults() ? ( -
+

Here's what to expect.

+
+ 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} @@ -757,12 +889,7 @@ class App extends React.Component { {symptom}

- {Math.ceil( - (!!dose - ? resultAtSite[symptom] / VAX_COUNTS[name][dose][age] - : resultAtSite[symptom] / VAX_COUNTS[name][age]) * 10 - )} - /10 + {this.getStatForSymptom(symptom)}/10

))} @@ -773,12 +900,7 @@ class App extends React.Component { {symptom}

- {Math.ceil( - (!!dose - ? result[symptom] / VAX_COUNTS[name][dose][age] - : result[symptom] / VAX_COUNTS[name][age]) * 10 - )} - /10 + {this.getStatForSymptom(symptom)}/10

))} @@ -809,32 +931,36 @@ class App extends React.Component { ▼
-
-

- 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()} -
+ {showInputPopup ? ( +

- You can comeback and update your experience at any time! -

-

- (Just use the same device) + 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) +

+
-
-
- SUBMIT -
+ ) : null} + {showInputPopup ? ( +
+ SUBMIT +
+ ) : null}
) : null}