v1.1.0/number values and efficacy
This commit is contained in:
+4
-2
@@ -11,6 +11,9 @@
|
||||
|
||||
# production
|
||||
*/build
|
||||
*/lib
|
||||
*/exportDB
|
||||
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
@@ -23,5 +26,4 @@ npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
*.cache
|
||||
*.log
|
||||
functions/src/backup.json
|
||||
*/*.log*
|
||||
|
||||
+137
-131
@@ -1,6 +1,6 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getPastResult = exports.saveResult = void 0;
|
||||
exports.getPastResult = exports.saveResult = exports.getStats = void 0;
|
||||
const functions = require("firebase-functions");
|
||||
const admin = require("firebase-admin");
|
||||
const firebaseSecret = require("./firebaseSecret.json");
|
||||
@@ -19,152 +19,120 @@ const params = {
|
||||
admin.initializeApp({
|
||||
credential: admin.credential.cert(params),
|
||||
});
|
||||
const VAX_NAMES = {
|
||||
PB: "Pfizer-BioNTech",
|
||||
MD: "Moderna",
|
||||
JJ: "J&J Janssen",
|
||||
};
|
||||
const VAX_DOSES = {
|
||||
ONE: "Dose 1",
|
||||
TWO: "Dose 2",
|
||||
};
|
||||
const serializeGaId = (_gaid) => {
|
||||
if (_gaid) {
|
||||
return _gaid.split(".").join("|");
|
||||
}
|
||||
return "";
|
||||
};
|
||||
const addResultToStats = async (data) => {
|
||||
const cleanData = Object.assign({}, data);
|
||||
delete cleanData.name;
|
||||
delete cleanData.dose;
|
||||
delete cleanData.age;
|
||||
delete cleanData.gid;
|
||||
const updateDoc = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
if (data.name === VAX_NAMES.PB || data.name === VAX_NAMES.MD) {
|
||||
Object.keys(VAX_DOSES).forEach((doseKey) => {
|
||||
const dose = VAX_DOSES[doseKey];
|
||||
Object.keys(cleanData[dose]).forEach((symptom) => {
|
||||
if (cleanData[dose][symptom]) {
|
||||
updateDoc[`${dose}.${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
Object.keys(cleanData).forEach((symptom) => {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
});
|
||||
}
|
||||
admin.firestore().collection("stats").doc(data.name).update(updateDoc);
|
||||
};
|
||||
const removeResultFromStats = async (data) => {
|
||||
const cleanData = Object.assign({}, data);
|
||||
delete cleanData.name;
|
||||
delete cleanData.dose;
|
||||
delete cleanData.age;
|
||||
delete cleanData.gid;
|
||||
const updateDoc = {
|
||||
count: admin.firestore.FieldValue.increment(-1),
|
||||
};
|
||||
if (data.name === VAX_NAMES.PB || data.name === VAX_NAMES.MD) {
|
||||
Object.keys(VAX_DOSES).forEach((doseKey) => {
|
||||
const dose = VAX_DOSES[doseKey];
|
||||
Object.keys(cleanData[dose]).forEach((symptom) => {
|
||||
if (cleanData[dose][symptom]) {
|
||||
updateDoc[`${dose}.${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(-1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
Object.keys(cleanData).forEach((symptom) => {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(-1);
|
||||
});
|
||||
}
|
||||
admin.firestore().collection("stats").doc(data.name).update(updateDoc);
|
||||
};
|
||||
exports.getStats = 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 = {};
|
||||
docs.forEach((vaxResult) => {
|
||||
returnData[vaxResult.name] = {};
|
||||
returnData[vaxResult.name] = vaxResult.result;
|
||||
});
|
||||
return returnData;
|
||||
});
|
||||
exports.saveResult = functions.https.onCall(async (data, context) => {
|
||||
if (!!data && !!context) {
|
||||
const { gid } = data;
|
||||
const docId = serializeGaId(gid);
|
||||
const docData = Object.assign({}, data);
|
||||
delete docData.gid;
|
||||
const existingData = await admin
|
||||
// Get existing result
|
||||
const existingResult = await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
.doc(docId)
|
||||
.doc(serializeGaId(gid))
|
||||
.get()
|
||||
.then((doc) => doc.data());
|
||||
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 = {};
|
||||
Object.keys(docData).forEach((symptom) => {
|
||||
// IF WAS TRUE, NOW FALSE = -1
|
||||
// IF WAS TRUE, NOW TRUE = 0
|
||||
// IF WAS FALSE, NOW TRUE = +1
|
||||
// IF WAS FALSE, NOW FALSE = 0
|
||||
let incrementValue = 0;
|
||||
if (existingData[symptom] === true && docData[symptom] === false) {
|
||||
incrementValue = -1;
|
||||
}
|
||||
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);
|
||||
.then((docSnap) => docSnap.data());
|
||||
// Update user result
|
||||
const cleanData = Object.assign({}, data);
|
||||
delete cleanData.gid;
|
||||
await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
.doc(serializeGaId(gid))
|
||||
.set(cleanData);
|
||||
// No existing result
|
||||
if (existingResult === undefined) {
|
||||
await addResultToStats(data);
|
||||
}
|
||||
else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(incrementValue);
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
}
|
||||
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 = {
|
||||
count: admin.firestore.FieldValue.increment(-1),
|
||||
};
|
||||
Object.keys(existingData).forEach((symptom) => {
|
||||
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);
|
||||
}
|
||||
else {
|
||||
undoDoc[`${existingData.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(existingData.name)
|
||||
.update(undoDoc);
|
||||
// PROCESS NEW DATA FOR USE
|
||||
// SAVE USER DATA
|
||||
await admin.firestore().collection("results").doc(docId).set(docData);
|
||||
delete docData.age;
|
||||
delete docData.name;
|
||||
delete docData.dose;
|
||||
// INCREMENT TOTAL RESPONSE COUNT
|
||||
const updateDoc = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
// INCREMENT VALUES FOR EACH SYMPTOM
|
||||
Object.keys(docData).forEach((symptom) => {
|
||||
if (docData[symptom] === true) {
|
||||
if (data.dose) {
|
||||
updateDoc[`${data.dose}.${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
}
|
||||
else if (existingData === undefined) {
|
||||
// DATA DOESN'T EXIST FOR USER
|
||||
// SAVE USER DATA
|
||||
await admin.firestore().collection("results").doc(docId).set(docData);
|
||||
delete docData.age;
|
||||
delete docData.name;
|
||||
delete docData.dose;
|
||||
// INCREMENT TOTAL RESPONSE COUNT
|
||||
const updateDoc = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
// INCREMENT VALUES FOR EACH SYMPTOM
|
||||
Object.keys(docData).forEach((symptom) => {
|
||||
if (docData[symptom] === true) {
|
||||
if (data.dose) {
|
||||
updateDoc[`${data.dose}.${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
await removeResultFromStats(existingResult);
|
||||
await addResultToStats(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
exports.getPastResult = functions.https.onCall(async (data, context) => {
|
||||
if (!!data && !!context) {
|
||||
const { gid } = data;
|
||||
let hasToUpdateDb = false;
|
||||
const existingData = await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
@@ -172,11 +140,49 @@ exports.getPastResult = functions.https.onCall(async (data, context) => {
|
||||
.get()
|
||||
.then((doc) => doc.data());
|
||||
if (existingData) {
|
||||
if (existingData["NAUSEA / VOMITING"]) {
|
||||
existingData["NAUSEA OR VOMITING"] =
|
||||
existingData["NAUSEA / VOMITING"];
|
||||
const returnData = Object.assign({}, existingData);
|
||||
if (existingData.name === VAX_NAMES.PB ||
|
||||
existingData.name === VAX_NAMES.MD) {
|
||||
Object.keys(VAX_DOSES).forEach((doseKey) => {
|
||||
const dose = VAX_DOSES[doseKey];
|
||||
if (!existingData[dose]) {
|
||||
hasToUpdateDb = true;
|
||||
const temp = {};
|
||||
Object.keys(existingData).forEach((symptom) => {
|
||||
if (symptom !== "name" &&
|
||||
symptom !== "age" &&
|
||||
symptom !== "dose") {
|
||||
if (existingData.dose === dose) {
|
||||
temp[symptom] = existingData[symptom];
|
||||
delete returnData[symptom];
|
||||
}
|
||||
return existingData;
|
||||
else {
|
||||
temp[symptom] = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
returnData[dose] = temp;
|
||||
}
|
||||
if (returnData[dose]["NAUSEA / VOMITING"]) {
|
||||
returnData["NAUSEA OR VOMITING"] =
|
||||
returnData["NAUSEA / VOMITING"];
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (returnData["NAUSEA / VOMITING"]) {
|
||||
returnData["NAUSEA OR VOMITING"] =
|
||||
returnData["NAUSEA / VOMITING"];
|
||||
}
|
||||
}
|
||||
if (hasToUpdateDb) {
|
||||
await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
.doc(serializeGaId(gid))
|
||||
.set(returnData);
|
||||
}
|
||||
return returnData;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -3,7 +3,7 @@
|
||||
"scripts": {
|
||||
"lint": "eslint --ext .js,.ts .",
|
||||
"build": "tsc",
|
||||
"serve": "npm run devenv && npm run build && $env:NODE_ENV=DEV && firebase emulators:start",
|
||||
"serve": "npm run devenv && npm run build && firebase emulators:start --import ./exportDB",
|
||||
"devenv": "SET NODE_ENV=dev",
|
||||
"shell": "npm run build && firebase functions:shell",
|
||||
"start": "npm run shell",
|
||||
|
||||
+155
-183
@@ -19,14 +19,15 @@ admin.initializeApp({
|
||||
credential: admin.credential.cert(params),
|
||||
});
|
||||
|
||||
type SideEffect = Record<string, boolean>;
|
||||
type DoseToSideEffect = Record<string, SideEffect>;
|
||||
type DBResult = {
|
||||
name : string;
|
||||
age : string;
|
||||
"J&J Janssen"? : SideEffect;
|
||||
"Moderna"? : DoseToSideEffect;
|
||||
"Pfizer-BioNTech"? : DoseToSideEffect;
|
||||
const VAX_NAMES : Record<string, string> = {
|
||||
PB: "Pfizer-BioNTech",
|
||||
MD: "Moderna",
|
||||
JJ: "J&J Janssen",
|
||||
};
|
||||
|
||||
const VAX_DOSES : Record<string, string> = {
|
||||
ONE: "Dose 1",
|
||||
TWO: "Dose 2",
|
||||
};
|
||||
|
||||
type SaveResultRequestData = {
|
||||
@@ -44,34 +45,93 @@ const serializeGaId = (_gaid: string): string => {
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const requestDataToDbData = (data: SaveResultRequestData) : DBResult => {
|
||||
console.log(data);
|
||||
return {name: "a", age: "d"};
|
||||
const addResultToStats = async (data : SaveResultRequestData) => {
|
||||
const cleanData : Record<string, any> =
|
||||
Object.assign({}, data);
|
||||
delete cleanData.name;
|
||||
delete cleanData.dose;
|
||||
delete cleanData.age;
|
||||
delete cleanData.gid;
|
||||
const updateDoc : Record<string, admin.firestore.FieldValue> = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
|
||||
const addResultToStats = async (data : DBResult) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
const removeResultFromStats = async (data : DBResult) => {
|
||||
console.log(data);
|
||||
};
|
||||
|
||||
const setResultInDb = async (data: SaveResultRequestData) => {
|
||||
const {name, age, dose} = data;
|
||||
const result : DBResult = {name, age};
|
||||
const rawResult : Record<string, boolean> = {};
|
||||
Object.keys(data).filter(k => data[k] === true || data[k] === false).forEach(k => {
|
||||
rawResult[k] = data[k];
|
||||
});
|
||||
if (!!dose.replace(/\s/g, "")) {
|
||||
result[name][dose][age] =
|
||||
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) => {
|
||||
if (cleanData[dose][symptom]) {
|
||||
let updateDocSymptom = symptom.replace("/", "OR");
|
||||
if (symptom === "DIARRHEA") {
|
||||
updateDocSymptom = "DIRRHEA";
|
||||
}
|
||||
await addResultToStats(requestDataToDbData(data));
|
||||
return result;
|
||||
updateDoc[`${dose}.${data.age}.${updateDocSymptom}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
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);
|
||||
});
|
||||
}
|
||||
admin.firestore().collection("stats").doc(data.name).update(updateDoc);
|
||||
};
|
||||
|
||||
const removeResultFromStats = async (data : FirebaseFirestore.DocumentData) => {
|
||||
const cleanData : Record<string, any> =
|
||||
Object.assign({}, data);
|
||||
delete cleanData.name;
|
||||
delete cleanData.dose;
|
||||
delete cleanData.age;
|
||||
delete cleanData.gid;
|
||||
const updateDoc : Record<string, admin.firestore.FieldValue> = {
|
||||
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) => {
|
||||
if (cleanData[dose][symptom]) {
|
||||
let updateDocSymptom = symptom.replace("/", "OR");
|
||||
if (symptom === "DIARRHEA") {
|
||||
updateDocSymptom = "DIRRHEA";
|
||||
}
|
||||
updateDoc[`${dose}.${data.age}.${updateDocSymptom}`] =
|
||||
admin.firestore.FieldValue.increment(-1);
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
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);
|
||||
});
|
||||
}
|
||||
admin.firestore().collection("stats").doc(data.name).update(updateDoc);
|
||||
};
|
||||
|
||||
export const getStats = 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<string, unknown> = {};
|
||||
docs.forEach((vaxResult) => {
|
||||
returnData[vaxResult.name] = {};
|
||||
returnData[vaxResult.name] = vaxResult.result;
|
||||
});
|
||||
return returnData;
|
||||
});
|
||||
|
||||
export const saveResult = functions.https.onCall(
|
||||
async (data: SaveResultRequestData, context) => {
|
||||
if (!!data && !!context) {
|
||||
@@ -83,174 +143,86 @@ export const saveResult = functions.https.onCall(
|
||||
.doc(serializeGaId(gid))
|
||||
.get()
|
||||
.then((docSnap) => docSnap.data());
|
||||
// No existing result
|
||||
if (existingResult === undefined) {
|
||||
// Set result
|
||||
setResultInDb(data);
|
||||
} else {
|
||||
const {dose, name, age} = data;
|
||||
if (existingResult.name === name && // Same vax
|
||||
existingResult.age === age && // Same age group
|
||||
!!dose.replace(/\s/g, "") && // Has dose sub category
|
||||
!existingResult[name][age][dose]) { // Dose not existing
|
||||
setResultInDb(data);
|
||||
} else {
|
||||
await removeResultFromStats(existingResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!!data && !!context) {
|
||||
const {gid} = data;
|
||||
const docId: string = serializeGaId(gid);
|
||||
const docData: Record<string, string | boolean> =
|
||||
// Update user result
|
||||
const cleanData : Record<string, any> =
|
||||
Object.assign({}, data);
|
||||
delete docData.gid;
|
||||
const existingData = await admin
|
||||
delete cleanData.gid;
|
||||
await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
.doc(docId)
|
||||
.get()
|
||||
.then((doc) => doc.data());
|
||||
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<string, admin.firestore.FieldValue> = {};
|
||||
Object.keys(docData).forEach((symptom : string) => {
|
||||
// IF WAS TRUE, NOW FALSE = -1
|
||||
// IF WAS TRUE, NOW TRUE = 0
|
||||
// IF WAS FALSE, NOW TRUE = +1
|
||||
// IF WAS FALSE, NOW FALSE = 0
|
||||
let incrementValue = 0;
|
||||
if (existingData[symptom] === true && docData[symptom] === false) {
|
||||
incrementValue = -1;
|
||||
} 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);
|
||||
.doc(serializeGaId(gid))
|
||||
.set(cleanData);
|
||||
// No existing result
|
||||
if (existingResult === undefined) {
|
||||
await addResultToStats(data);
|
||||
} else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(incrementValue);
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
} 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<string, admin.firestore.FieldValue> = {
|
||||
count: admin.firestore.FieldValue.increment(-1),
|
||||
};
|
||||
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);
|
||||
} else {
|
||||
undoDoc[`${existingData.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(existingData.name)
|
||||
.update(undoDoc);
|
||||
// PROCESS NEW DATA FOR USE
|
||||
// SAVE USER DATA
|
||||
await admin.firestore().collection("results").doc(docId).set(docData);
|
||||
delete docData.age;
|
||||
delete docData.name;
|
||||
delete docData.dose;
|
||||
// INCREMENT TOTAL RESPONSE COUNT
|
||||
const updateDoc : Record<string, admin.firestore.FieldValue> = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
// INCREMENT VALUES FOR EACH SYMPTOM
|
||||
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);
|
||||
} else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
} else if (existingData === undefined) {
|
||||
// DATA DOESN'T EXIST FOR USER
|
||||
// SAVE USER DATA
|
||||
await admin.firestore().collection("results").doc(docId).set(docData);
|
||||
delete docData.age;
|
||||
delete docData.name;
|
||||
delete docData.dose;
|
||||
// INCREMENT TOTAL RESPONSE COUNT
|
||||
const updateDoc : Record<string, admin.firestore.FieldValue> = {
|
||||
count: admin.firestore.FieldValue.increment(1),
|
||||
};
|
||||
// INCREMENT VALUES FOR EACH SYMPTOM
|
||||
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);
|
||||
} else {
|
||||
updateDoc[`${data.age}.${symptom.replace("/", "OR")}`] =
|
||||
admin.firestore.FieldValue.increment(1);
|
||||
}
|
||||
}
|
||||
});
|
||||
admin
|
||||
.firestore()
|
||||
.collection("stats")
|
||||
.doc(data.name)
|
||||
.update(updateDoc);
|
||||
await removeResultFromStats(existingResult);
|
||||
await addResultToStats(data);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export const getPastResult = functions.https.onCall(async (data : {gid:string}, context) => {
|
||||
export const getPastResult =
|
||||
functions.https.onCall(async (data : {gid:string}, context) => {
|
||||
if (!!data && !!context) {
|
||||
const {gid} = data;
|
||||
const existingData : admin.firestore.DocumentData | undefined = await admin
|
||||
let hasToUpdateDb = false;
|
||||
const existingData : admin.firestore.DocumentData | undefined =
|
||||
await admin
|
||||
.firestore()
|
||||
.collection("results")
|
||||
.doc(serializeGaId(gid))
|
||||
.get()
|
||||
.then((doc) => doc.data());
|
||||
if (existingData) {
|
||||
if (existingData["NAUSEA / VOMITING"]) {
|
||||
existingData["NAUSEA OR VOMITING"] =
|
||||
existingData["NAUSEA / VOMITING"];
|
||||
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<string, unknown> = {};
|
||||
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;
|
||||
}
|
||||
return existingData;
|
||||
}
|
||||
});
|
||||
returnData[dose] = temp;
|
||||
}
|
||||
if (returnData[dose]["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;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
.input-popup.expanded {
|
||||
height: 40vh;
|
||||
height: 50vh;
|
||||
}
|
||||
|
||||
.loading-bar-container {
|
||||
|
||||
@@ -331,6 +331,43 @@ footer .by {
|
||||
.input-popup-submit.submitted {
|
||||
background-color: #55c16c;
|
||||
}
|
||||
.input-popup-submit.errored {
|
||||
background-color: #c43d34;
|
||||
}
|
||||
|
||||
.input-popup.expanded::-webkit-scrollbar {
|
||||
width: 1.5rem;
|
||||
background-color: var(--color-tertiary);
|
||||
border-radius: 0 4rem 4rem 0;
|
||||
}
|
||||
.input-popup.expanded::-webkit-scrollbar-thumb {
|
||||
width: 1rem;
|
||||
background-color: var(--color-dim);
|
||||
border-radius: 0 4rem 4rem 0;
|
||||
}
|
||||
|
||||
.tip-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 2rem 4rem;
|
||||
padding-left: 2rem;
|
||||
border-radius: 1rem;
|
||||
margin-bottom: 2rem;
|
||||
border: 1px solid var(--color-secondary);
|
||||
}
|
||||
.tip-icon {
|
||||
font-size: 3rem;
|
||||
}
|
||||
.tip {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
.tip .overline {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
.tip .subheader {
|
||||
font-size: 3.2rem;
|
||||
}
|
||||
|
||||
@keyframes loading {
|
||||
0% {
|
||||
|
||||
@@ -22,7 +22,7 @@ footer {
|
||||
height: 10rem;
|
||||
}
|
||||
.input-popup.expanded {
|
||||
height: 50vh;
|
||||
height: 55vh;
|
||||
}
|
||||
|
||||
.loading-bar-container {
|
||||
|
||||
@@ -103,3 +103,7 @@ footer {
|
||||
.loading-bar-container {
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
.tip-container {
|
||||
width: fit-content;
|
||||
}
|
||||
+221
-96
@@ -20,6 +20,7 @@ if (window.location.host.startsWith("localhost")) {
|
||||
const fb_functions = firebase.functions();
|
||||
const saveResult = fb_functions.httpsCallable("saveResult");
|
||||
const getPastResult = fb_functions.httpsCallable("getPastResult");
|
||||
const getStats = fb_functions.httpsCallable("getStats");
|
||||
|
||||
const VAX_NAMES = {
|
||||
PB: "Pfizer-BioNTech",
|
||||
@@ -47,61 +48,76 @@ const VAX_AGES = {
|
||||
},
|
||||
};
|
||||
|
||||
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": "8",
|
||||
"RED AT SITE": "1",
|
||||
"SWELLING AT SITE": "1",
|
||||
FATIGUE: "5",
|
||||
HEADACHE: "4",
|
||||
"NEED PAIN MED": "3",
|
||||
"MUSCLE PAIN": "2",
|
||||
CHILLS: "1",
|
||||
DIRRHEA: "1",
|
||||
"JOINT PAIN": "1",
|
||||
FEVER: "<1",
|
||||
VOMITING: "<1",
|
||||
"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": "8",
|
||||
"RED AT SITE": "1",
|
||||
"SWELLING AT SITE": "1",
|
||||
FATIGUE: "6",
|
||||
HEADACHE: "5",
|
||||
"NEED PAIN MED": "5",
|
||||
"MUSCLE PAIN": "4",
|
||||
CHILLS: "4",
|
||||
"JOINT PAIN": "2",
|
||||
FEVER: "2",
|
||||
DIRRHEA: "1",
|
||||
VOMITING: "<1",
|
||||
"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": "7",
|
||||
"RED AT SITE": "1",
|
||||
"SWELLING AT SITE": "1",
|
||||
FATIGUE: "3",
|
||||
HEADACHE: "3",
|
||||
"NEED PAIN MED": "2",
|
||||
"MUSCLE PAIN": "1",
|
||||
CHILLS: "1",
|
||||
DIRRHEA: "1",
|
||||
"JOINT PAIN": "1",
|
||||
FEVER: "<1",
|
||||
VOMITING: "<1",
|
||||
"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": "7",
|
||||
"RED AT SITE": "1",
|
||||
"SWELLING AT SITE": "1",
|
||||
FATIGUE: "5",
|
||||
HEADACHE: "4",
|
||||
"NEED PAIN MED": "4",
|
||||
"MUSCLE PAIN": "3",
|
||||
CHILLS: "2",
|
||||
"JOINT PAIN": "2",
|
||||
DIRRHEA: "1",
|
||||
FEVER: "1",
|
||||
VOMITING: "<1",
|
||||
"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": "9",
|
||||
@@ -174,6 +190,33 @@ const JJ_OLDER_RESULT = {
|
||||
FEVER: "<1",
|
||||
};
|
||||
|
||||
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": 1,
|
||||
"65 & Older": 1,
|
||||
},
|
||||
"Dose 2": {
|
||||
"18 - 64": 1,
|
||||
"65 & Older": 1,
|
||||
},
|
||||
},
|
||||
"J&J Janssen": {
|
||||
"18 - 59": 1,
|
||||
"60 & Older": 1,
|
||||
},
|
||||
};
|
||||
|
||||
const VAX_RESULTS = {
|
||||
"Pfizer-BioNTech": {
|
||||
"Dose 1": {
|
||||
@@ -210,7 +253,7 @@ const ICONS = {
|
||||
"NEED PAIN MED": "💊",
|
||||
"MUSCLE PAIN": "😫",
|
||||
CHILLS: "🥶",
|
||||
DIRRHEA: "💩",
|
||||
DIARRHEA: "💩",
|
||||
"JOINT PAIN": "🦵",
|
||||
FEVER: "🤒",
|
||||
VOMITING: "🤮",
|
||||
@@ -227,6 +270,8 @@ class App extends React.Component {
|
||||
gid: "",
|
||||
showInputPopup: false,
|
||||
answers: {},
|
||||
fetchedResult : {},
|
||||
stats: {},
|
||||
loading: true,
|
||||
};
|
||||
}
|
||||
@@ -276,11 +321,7 @@ class App extends React.Component {
|
||||
const { data } = v;
|
||||
if (!!data) {
|
||||
const { name, age, dose } = data;
|
||||
this.setState({ name, age, dose, showInputPopup: true });
|
||||
delete data.name;
|
||||
delete data.age;
|
||||
delete data.dose;
|
||||
this.setState({ answers: data, loading: false });
|
||||
this.setState({ name, age, dose, showInputPopup: true, fetchedResult: data, answers: data, loading: false });
|
||||
const inputPopupSubmit = document.querySelector(
|
||||
".input-popup-submit"
|
||||
);
|
||||
@@ -302,7 +343,13 @@ class App extends React.Component {
|
||||
} else {
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
|
||||
getStats().then(v => this.setState({ stats: v.data }));
|
||||
}
|
||||
shouldShowDoses = () => {
|
||||
const { name } = this.state;
|
||||
return name && (name === VAX_NAMES.PB || name === VAX_NAMES.MD);
|
||||
};
|
||||
shouldShowAgeGroup = () => {
|
||||
const { name, dose } = this.state;
|
||||
switch (name) {
|
||||
@@ -373,25 +420,55 @@ class App extends React.Component {
|
||||
document.querySelector("#share-result").innerHTML = "Share ↗";
|
||||
}, 1500);
|
||||
};
|
||||
updateAnswers = (symptom) => {
|
||||
updateAnswers = (symptom, dose) => {
|
||||
const { answers } = this.state;
|
||||
const newAnswers = Object.assign({}, answers);
|
||||
if (answers[symptom]) {
|
||||
newAnswers[symptom] = !answers[symptom];
|
||||
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 = Object.assign({}, this.getResults());
|
||||
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, answers, {
|
||||
}
|
||||
const submitAnswers = Object.assign({}, symptoms, {
|
||||
name,
|
||||
dose,
|
||||
age,
|
||||
@@ -399,7 +476,12 @@ class App extends React.Component {
|
||||
});
|
||||
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");
|
||||
}
|
||||
@@ -408,10 +490,57 @@ class App extends React.Component {
|
||||
inputPopupSubmit.innerHTML = "UPDATE ANSWER";
|
||||
}, 1500);
|
||||
})
|
||||
.catch((err) => console.error("ERROR Saving Answer", err));
|
||||
.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 <div className="question-container" key={`answer-dose-${answerDose}`}>
|
||||
{!!answerDose ? (
|
||||
<h6 className="overline" data-font="sans">
|
||||
{answerDose}
|
||||
</h6>
|
||||
) : null}
|
||||
<p className="question" data-font="sans-italic">
|
||||
{ ((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)" }
|
||||
</p>
|
||||
<div className="answers-container">
|
||||
{Object.keys(result).map((symptom) => (
|
||||
<button
|
||||
key={`ans-${answerDose}-${symptom}`}
|
||||
data-font="sans-bold"
|
||||
className={`answer${
|
||||
!!answerDose
|
||||
? (answers[answerDose] && answers[answerDose][symptom])
|
||||
? " selected"
|
||||
: ""
|
||||
: answers[symptom]
|
||||
? " selected"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => this.updateAnswers(symptom, answerDose)}
|
||||
>
|
||||
{symptom}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>;
|
||||
};
|
||||
render() {
|
||||
const { name, dose, age, showInputPopup, answers, loading } = this.state;
|
||||
const { name, dose, age, showInputPopup, loading, fetchedResult } = this.state;
|
||||
let result = {};
|
||||
let resultAtSite = {};
|
||||
if (this.shouldShowResults()) {
|
||||
@@ -463,7 +592,7 @@ class App extends React.Component {
|
||||
name: v,
|
||||
dose: "",
|
||||
age: "",
|
||||
answers: {},
|
||||
answers: v === fetchedResult.name ? fetchedResult : {},
|
||||
showInputPopup: false,
|
||||
})
|
||||
}
|
||||
@@ -478,7 +607,7 @@ class App extends React.Component {
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{name && (name === VAX_NAMES.PB || name === VAX_NAMES.MD) ? (
|
||||
{this.shouldShowDoses() ? (
|
||||
<div className="question-container">
|
||||
<p className="question" data-font="sans-italic">
|
||||
Select Dose
|
||||
@@ -491,7 +620,6 @@ class App extends React.Component {
|
||||
this.setState({
|
||||
dose: v,
|
||||
age: "",
|
||||
answers: {},
|
||||
showInputPopup: false,
|
||||
})
|
||||
}
|
||||
@@ -519,7 +647,6 @@ class App extends React.Component {
|
||||
onClick={() =>
|
||||
this.setState({
|
||||
age: v,
|
||||
answers: {},
|
||||
showInputPopup: false,
|
||||
})
|
||||
}
|
||||
@@ -553,6 +680,27 @@ class App extends React.Component {
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{this.shouldShowResults() ? (
|
||||
<div className="tip-container">
|
||||
<div className="tip-icon">ⓘ</div>
|
||||
<div className="tip">
|
||||
<h6 style={{marginBottom: '1.2rem'}} className="overline" data-font="sans">
|
||||
NET EFFICACY
|
||||
</h6>
|
||||
<h6 className="overline" data-font="sans-italic">
|
||||
{name} was effective for
|
||||
</h6>
|
||||
<h3 className="subheader" data-font="sans-bold">
|
||||
{VAX_EFFICACY[name][age]}%
|
||||
</h3>
|
||||
<h6 className="overline" data-font="sans-italic">
|
||||
of people who took it, in the {age} age group
|
||||
</h6>
|
||||
</div>
|
||||
</div>
|
||||
) : null
|
||||
}
|
||||
|
||||
{this.shouldShowResults() ? (
|
||||
<div className="symptom-container">
|
||||
{Object.keys(resultAtSite).map((symptom) => (
|
||||
@@ -579,6 +727,7 @@ class App extends React.Component {
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
</main>
|
||||
{this.shouldShowResults() ? (
|
||||
<div className={`input-popup${showInputPopup ? " expanded" : ""}`}>
|
||||
@@ -606,41 +755,17 @@ class App extends React.Component {
|
||||
</div>
|
||||
<div className="input-popup-body">
|
||||
<p className="question" data-font="sans">
|
||||
I am in age group <strong>{age}</strong> and got
|
||||
<strong>{!!dose ? ` ${dose} ` : ""}</strong>
|
||||
{!!dose ? `of` : ""} the
|
||||
I am in age group <strong>{age}</strong> and got the
|
||||
<strong> {name}</strong> vaccine. I experienced:
|
||||
</p>
|
||||
<div className="question-container">
|
||||
<p className="question" data-font="sans-italic">
|
||||
(Select all side effects that you experienced)
|
||||
</p>
|
||||
<div className="answers-container">
|
||||
{Object.keys(resultAtSite).map((symptom) => (
|
||||
<button
|
||||
key={`ans-${symptom}`}
|
||||
data-font="sans-bold"
|
||||
className={`answer${answers[symptom] ? " selected" : ""}`}
|
||||
onClick={() => this.updateAnswers(symptom)}
|
||||
>
|
||||
{symptom}
|
||||
</button>
|
||||
))}
|
||||
{Object.keys(result).map((symptom) => (
|
||||
<button
|
||||
key={`ans-${symptom}`}
|
||||
data-font="sans-bold"
|
||||
className={`answer${answers[symptom] ? " selected" : ""}`}
|
||||
onClick={() => this.updateAnswers(symptom)}
|
||||
>
|
||||
{symptom}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
{this.shouldShowDoses()
|
||||
? Object.keys(VAX_DOSES).map((dose) =>
|
||||
this.getAnswerOptions(VAX_DOSES[dose])
|
||||
)
|
||||
: this.getAnswerOptions()}
|
||||
<div className="question-container">
|
||||
<p className="question" data-font="sans">
|
||||
You can comeback and update your experience later!
|
||||
You can comeback and update your experience at any time!
|
||||
</p>
|
||||
<p className="question" data-font="sans-italic">
|
||||
(Just use the same device)
|
||||
|
||||
Reference in New Issue
Block a user