diff --git a/app/domain/types.ts b/app/domain/types.ts index 3ce9d560..6e02a86b 100644 --- a/app/domain/types.ts +++ b/app/domain/types.ts @@ -9,6 +9,10 @@ export interface CovidReport { symptoms: Symptoms; submissionTimestamp: number; age: string; + bodyTemperature?: string; + smokingHabit?: SmokingHabit; + isolationStatus?: IsolationStatus; + diagnosedWithOtherConditions?: boolean; } export type Symptoms = { @@ -26,6 +30,18 @@ export enum TestResult { PENDING = 'PENDING' } +export enum SmokingHabit { + CURRENTLY = 'CURRENTLY', + USED_TO = 'USED_TO', + NEVER = 'NEVER' +} + +export enum IsolationStatus { + NOT_IN_ISOLATION = 'NOT_IN_ISOLATION', + ISOLATION_DUE_TO_TRAVEL = 'ISOLATION_DUE_TO_TRAVEL', + ISOLATION_DUE_TO_CONTACT = 'ISOLATION_DUE_TO_CONTACT' +} + export enum Symptom { DRY_COUGH = 'DRY_COUGH', EXHAUSTION = 'EXHAUSTION', @@ -38,7 +54,8 @@ export enum Symptom { NO_TASTE = 'NO_TASTE', NO_SMELL = 'NO_SMELL', SLIME_COUGH = 'SLIME_COUGH', - RUNNY_NOSE = 'RUNNY_NOSE' + RUNNY_NOSE = 'RUNNY_NOSE', + NAUSEA_OR_VOMITING = 'NAUSEA_OR_VOMITING' } export interface AggregatedCovidReportData { diff --git a/app/locales/en.json b/app/locales/en.json index e137d150..d3eb401b 100644 --- a/app/locales/en.json +++ b/app/locales/en.json @@ -32,7 +32,7 @@ "BustByte AS": "BustByte AS", "and": "and", "volunteers": "volunteers", - "Privacy Policy": "Privacy Policy", + "Privacy Policy": "Privacy Statement", "Privacy": "Privacy", "Thank you for your contribution!": "Thank you for your contribution!", "The government has now launched their own self-report system, please use that instead.": "The government has now launched their own self-report system, please use that instead.", @@ -67,15 +67,15 @@ "Report your health condition": "Report your health condition", "Thank you for your contribution! Use this link if your health condition changes:": "Thank you for your contribution! Use this link if your health condition changes:", "Join the most important crowdsource! Regardless if you're healthy or not, please submit the form below – that is also valuable information!": "Join the most important crowdsource! Regardless if you're healthy or not, please submit the form below – that is also valuable information!", - "Geography and demography": "Geography and demography", + "Geography and demography": "Demography and geography", "Your age": "Your age", "Choose your age": "Choose your age", "Biological gender": "Biological gender/Sex", "Female": "Female", "Male": "Male", - "Zip code": "Zip code", + "Zip code": "Postal code / Zip code", "Testing and symptoms": "Testing and symptoms", - "Have you been in close contact with someone who was tested positive for COVID-19?": "Have you been in close contact with someone who was tested positive for COVID-19?", + "Have you been in close contact with someone who was tested positive for COVID-19?": "Have you been in close contact with someone who tested positive for COVID-19?", "Yes": "Yes", "No": "No", "Positive": "Positive", @@ -99,8 +99,8 @@ "Stuffy or runny nose": "Stuffy or runny nose", "When did the symptoms start?": "When did the symptoms start?", "How will my data be used?": "How will my data be used?", - "Your health information is stored anonymously, and can not be used to identify you.": "Your health information is stored anonymously, and can not be used to identify you.", - "Our privacy policy can be found here": "Our privacy policy can be found here", + "Your health information is stored anonymously, and can not be used to identify you.": "You are completely anonymous. The data you submit cannot be used to identify you.", + "Our privacy policy can be found here": "Our privacy statement can be found here", "I agree to my data being stored in accordance with the privacy statement": "I agree to my data being stored in accordance with the privacy statement", "Submit report": "Submit report", "Statistics": "Statistics", @@ -157,5 +157,19 @@ "United Kingdom": "The United Kingdom", "March 16": "March 16", "March 17": "March 17", - "at": "at" + "March 23": "March 23", + "at": "at", + "Nausea or vomiting": "Nausea or vomiting", + "Have you been diagnosed with any of the following conditions?": "Have you been diagnosed with any of the following conditions?", + "Diabetes mellitus, Hypertension, Ischemic heart disease, Asthma, Chronic lung disease, Chronic kidney disease": "Diabetes mellitus, Hypertension, Ischemic heart disease, Asthma, Chronic lung disease, Chronic kidney disease", + "I am currently:": "I am currently", + "Not in isolation": "Not in isolation", + "In isolation due to a recent international travel": "In isolation due to a recent international travel", + "In isolation due to contact with an individual who has been exposed to the coronavirus.": "In isolation due to contact with an individual who has been exposed to the coronavirus", + "Cigarette smoking habits:": "Cigarette smoking habits", + "I currently smoke": "I currently smoke", + "I used to smoke": "I used to smoke", + "I have never smoked": "I have never smoked", + "What is your current body temperature? (Celcius)": "What is your current body temperature in Celcius?", + "This field is optional": "This field is optional" } diff --git a/app/locales/nl.json b/app/locales/nl.json index f249ca2c..7f80673b 100644 --- a/app/locales/nl.json +++ b/app/locales/nl.json @@ -67,7 +67,7 @@ "Report your health condition": "Meld uw gezondheidstoestand", "Thank you for your contribution! Use this link if your health condition changes:": "Bedankt voor uw inzending! Gebruik deze link als uw gezondheidstoestand verandert:", "Join the most important crowdsource! Regardless if you're healthy or not, please submit the form below – that is also valuable information!": "Doe mee met Nederland's meest belangrijke crowdsource! Zelfs als u gezond bent, hopen we dat u het formulier indient - Ook dat is waardevolle informatie!", - "Geography and demography": "Geografie en demografie", + "Geography and demography": "Demografie en geografie", "Your age": "Uw leeftijd", "Choose your age": "Kies uw leeftijd", "Biological gender": "Biologisch geslacht/sekse", @@ -157,5 +157,19 @@ "To WHO.int": "naar rivm.nl", "March 16": "16 maart", "March 17": "17 maart", - "at": "om" + "March 23": "23 maart", + "at": "om", + "Nausea or vomiting": "Misselijkheid of braken", + "Have you been diagnosed with any of the following conditions?": "Bent u gediagnostiseerd met één van de volgende aandoeningen?", + "Diabetes mellitus, Hypertension, Ischemic heart disease, Asthma, Chronic lung disease, Chronic kidney disease": "Suikerziekte (Diabetes mellitus), Hoge bloeddruk (Hypertensie), Ischemische hartziekte, Astma, Chronische longaandoening, Chronische nieraandoening", + "I am currently:": "Momenteel ben ik", + "Not in isolation": "Niet geïsoleerd", + "In isolation due to a recent international travel": "Geïsoleerd vanwege een recent reisverbod", + "In isolation due to contact with an individual who has been exposed to the coronavirus.": "Geïsoleerd vanwege contact met een persoon die aan het coronavirus bloot is gesteld", + "Cigarette smoking habits:": "Roken", + "I currently smoke": "Ik rook", + "I used to smoke": "Ik heb gerookt", + "I have never smoked": "Ik heb nooit gerookt", + "What is your current body temperature? (Celcius)": "Wat is uw huidige lichaamstemperatuur? (Celcius)", + "This field is optional": "Dit veld is optioneel" } diff --git a/app/locales/no.json b/app/locales/no.json index bc55b082..e66eaf35 100644 --- a/app/locales/no.json +++ b/app/locales/no.json @@ -66,7 +66,7 @@ "Report your health condition": "Rapporter din helsetilstand", "Thank you for your contribution! Use this link if your health condition changes:": "Takk for ditt svar! Benytt denne lenken hvis helsetilstanden din endrer seg:", "Join the most important crowdsource! Regardless if you're healthy or not, please submit the form below – that is also valuable information!": "Bli med på Norges viktigste dugnad! Selv om du er frisk håper vi du sender inn skjemaet – det er også verdifull informasjon!", - "Geography and demography": "Geografi og demografi", + "Geography and demography": "Demografi og geografi", "Your age": "Din alder", "Choose your age": "Velg din alder", "Biological gender": "Biologisk kjønn", @@ -154,5 +154,22 @@ "United Kingdom": "Storbritannia", "March 16": "16. mars", "March 17": "17. mars", - "at": "kl." + "March 23": "23. mars", + "at": "kl.", + "https://who.int": "https://fhi.no", + "To WHO.int": "Til fhi.no", + "Netherlands": "Nederland", + "Nausea or vomiting": "Kvalme eller oppkast", + "Have you been diagnosed with any of the following conditions?": "Har du blitt diagnostisert med noen av disse sykdommene?", + "Diabetes mellitus, Hypertension, Ischemic heart disease, Asthma, Chronic lung disease, Chronic kidney disease": "Diabetes, høyt blodtrykk, hjertesykdom, astma, lungesykdom, nyresykdom", + "I am currently:": "Jeg er for tiden", + "Not in isolation": "Ikke i karantene", + "In isolation due to a recent international travel": "I karantene pga nylig reise internasjonalt", + "In isolation due to contact with an individual who has been exposed to the coronavirus.": "I karantene pga kontakt med en smittet person eller en person som har reist internasjonalt", + "Cigarette smoking habits:": "Røykevaner", + "I currently smoke": "Jeg røyker", + "I used to smoke": "Jeg røyket tidligere", + "I have never smoked": "Jeg har aldri røyket", + "What is your current body temperature? (Celcius)": "Hva er din kroppstemperatur i Celsius?", + "This field is optional": "Dette feltet er valgfritt" } diff --git a/app/routes/api-routes.ts b/app/routes/api-routes.ts index a549de06..8402cd99 100644 --- a/app/routes/api-routes.ts +++ b/app/routes/api-routes.ts @@ -99,7 +99,8 @@ const extractSymptomsAsZeroOrOne = ( [Symptom.NO_TASTE]: toZeroOrOne(symptoms.NO_TASTE), [Symptom.NO_SMELL]: toZeroOrOne(symptoms.NO_SMELL), [Symptom.SLIME_COUGH]: toZeroOrOne(symptoms.SLIME_COUGH), - [Symptom.RUNNY_NOSE]: toZeroOrOne(symptoms.RUNNY_NOSE) + [Symptom.RUNNY_NOSE]: toZeroOrOne(symptoms.RUNNY_NOSE), + [Symptom.NAUSEA_OR_VOMITING]: toZeroOrOne(symptoms.NAUSEA_OR_VOMITING) }); const reportToExposedCsvFormat = ( diff --git a/app/routes/report-routes.ts b/app/routes/report-routes.ts index dca34f26..2841aa32 100644 --- a/app/routes/report-routes.ts +++ b/app/routes/report-routes.ts @@ -1,6 +1,13 @@ import express, { Request } from 'express'; import rateLimit from 'express-rate-limit'; -import { Symptom, CovidReport, Sex, TestResult } from '../domain/types'; +import { + Symptom, + CovidReport, + Sex, + TestResult, + SmokingHabit, + IsolationStatus +} from '../domain/types'; import { CovidReportRepository } from '../repository/CovidReportRepository'; import { getPasscodeCreator } from '../util/PasscodeCreator'; import { aggregateCovidReports } from '../util/report-aggregator'; @@ -87,6 +94,32 @@ const createReportRateLimit = rateLimit({ keyGenerator: req => determineRemoteAddress(req) }); +const toSmokingHabit = (inputValue: string): SmokingHabit | undefined => { + if (inputValue === 'currently-smoking') { + return SmokingHabit.CURRENTLY; + } + if (inputValue === 'used-to-smoke') { + return SmokingHabit.USED_TO; + } + if (inputValue === 'never-smoked') { + return SmokingHabit.NEVER; + } + return undefined; +}; + +const toIsolationStatus = (inputValue: string): IsolationStatus | undefined => { + if (inputValue === 'not-in-isolation') { + return IsolationStatus.NOT_IN_ISOLATION; + } + if (inputValue === 'isolation-due-to-travel') { + return IsolationStatus.ISOLATION_DUE_TO_TRAVEL; + } + if (inputValue === 'isolation-due-to-contact') { + return IsolationStatus.ISOLATION_DUE_TO_CONTACT; + } + return undefined; +}; + router.post('/', createReportRateLimit, async (req, res) => { const acceptPrivacyPolicy = req.body['accept-privacy-policy'] === 'on'; if (!acceptPrivacyPolicy) { @@ -116,10 +149,17 @@ router.post('/', createReportRateLimit, async (req, res) => { [Symptom.NO_TASTE]: req.body['symptom-no-taste'] === 'on', [Symptom.NO_SMELL]: req.body['symptom-no-smell'] === 'on', [Symptom.SLIME_COUGH]: req.body['symptom-slime-cough'] === 'on', - [Symptom.RUNNY_NOSE]: req.body['symptom-runny-nose'] === 'on' + [Symptom.RUNNY_NOSE]: req.body['symptom-runny-nose'] === 'on', + [Symptom.NAUSEA_OR_VOMITING]: + req.body['symptom-nausea-or-vomiting'] === 'on' }, symptomStart: req.body['symptom-start'], hasBeenInContactWithInfected: req.body['been-in-contact-with'] === 'yes', + bodyTemperature: req.body['body-temperature'], + smokingHabit: toSmokingHabit(req.body['smoking-habits']), + isolationStatus: toIsolationStatus(req.body['isolation-status']), + diagnosedWithOtherConditions: + req.body['diagnosed-other-conditions'] === 'yes', submissionTimestamp: new Date().getTime() }; diff --git a/app/util/report-aggregator.test.ts b/app/util/report-aggregator.test.ts index 7ec030fd..10e4fda6 100644 --- a/app/util/report-aggregator.test.ts +++ b/app/util/report-aggregator.test.ts @@ -28,7 +28,8 @@ const reports: CovidReport[] = [ [Symptom.NO_TASTE]: false, [Symptom.NO_SMELL]: false, [Symptom.SLIME_COUGH]: false, - [Symptom.RUNNY_NOSE]: false + [Symptom.RUNNY_NOSE]: false, + [Symptom.NAUSEA_OR_VOMITING]: false }, submissionTimestamp: 123123123, age: '50' @@ -53,7 +54,8 @@ const reports: CovidReport[] = [ [Symptom.NO_TASTE]: false, [Symptom.NO_SMELL]: false, [Symptom.SLIME_COUGH]: false, - [Symptom.RUNNY_NOSE]: false + [Symptom.RUNNY_NOSE]: false, + [Symptom.NAUSEA_OR_VOMITING]: false }, submissionTimestamp: 123123123, age: '50' @@ -78,7 +80,8 @@ const reports: CovidReport[] = [ [Symptom.NO_TASTE]: false, [Symptom.NO_SMELL]: false, [Symptom.SLIME_COUGH]: false, - [Symptom.RUNNY_NOSE]: false + [Symptom.RUNNY_NOSE]: false, + [Symptom.NAUSEA_OR_VOMITING]: false }, submissionTimestamp: 123123123, age: '50' @@ -103,7 +106,8 @@ const reports: CovidReport[] = [ [Symptom.NO_TASTE]: false, [Symptom.NO_SMELL]: false, [Symptom.SLIME_COUGH]: false, - [Symptom.RUNNY_NOSE]: false + [Symptom.RUNNY_NOSE]: false, + [Symptom.NAUSEA_OR_VOMITING]: false }, submissionTimestamp: 123123123, age: '50' diff --git a/app/util/statistics.ts b/app/util/statistics.ts index cab2f4c0..c96bdd33 100644 --- a/app/util/statistics.ts +++ b/app/util/statistics.ts @@ -26,7 +26,8 @@ const symptomToLabelMap = { [Symptom.NO_TASTE]: 'Loss of sense of taste', [Symptom.NO_SMELL]: 'Loss of sense of smell', [Symptom.SLIME_COUGH]: 'Mucus cough', - [Symptom.RUNNY_NOSE]: 'Stuffy or runny nose' + [Symptom.RUNNY_NOSE]: 'Stuffy or runny nose', + [Symptom.NAUSEA_OR_VOMITING]: 'Nausea or vomiting' }; const symptomKeyToLabel = (symptomKey: Symptom): string => diff --git a/app/views/pages/report.ejs b/app/views/pages/report.ejs index e49b7cd1..00a96f2e 100644 --- a/app/views/pages/report.ejs +++ b/app/views/pages/report.ejs @@ -12,6 +12,10 @@ const hasBeenInContactWithInfected = profile && locals.profile.hasBeenInContactWithInfected; const symptomStart = profile && locals.profile.symptomStart; const testResult = profile && locals.profile.testResult; + const bodyTemperature = profile && locals.profile.bodyTemperature; + const isolationStatus = profile && locals.profile.isolationStatus; + const smokingHabit = profile && locals.profile.smokingHabit; + const diagnosedWithOtherConditions = profile && locals.profile.diagnosedWithOtherConditions; const symptoms = profile && locals.profile.symptoms; const symptomDryCough = symptoms && symptoms['DRY_COUGH']; const symptomFatigue = symptoms && symptoms['EXHAUSTION']; @@ -25,6 +29,7 @@ const symptomNoTaste = symptoms && symptoms['NO_TASTE']; const symptomSlimeCough = symptoms && symptoms['SLIME_COUGH']; const symptomRunnyNose = symptoms && symptoms['RUNNY_NOSE']; + const symptomNauseaOrVomiting = symptoms && symptoms['NAUSEA_OR_VOMITING']; function numberWithSpaces(x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "); @@ -295,6 +300,10 @@ > +
+ > + +
+
+
+ +

<%= __('Diabetes mellitus, Hypertension, Ischemic heart disease, Asthma, Chronic lung disease, Chronic kidney disease') %>

+
+
+ > + +
+
+ > + +
+
+
+
+
+
+ +
+
+ > + +
+
+ > + +
+
+ > + +
+
+
+
+
+
+ +
+
+ > + +
+
+ > + +
+
+ > + +
+
+
+
+
+
+ +

<%= __('This field is optional') %>

+ +
+

<%= __('How will my data be used?')%>

<%= __('Your health information is stored anonymously, and can not be used to identify you.')%>
<%= __('Our privacy policy can be found here')%>.

diff --git a/app/views/pages/statistics.ejs b/app/views/pages/statistics.ejs index 298ef7e3..808497c6 100644 --- a/app/views/pages/statistics.ejs +++ b/app/views/pages/statistics.ejs @@ -148,6 +148,10 @@ <%= __('Stuffy or runny nose') %> <%= __('March 17') %> <%= __('at') %> 16:28 + + <%= __('Nausea or vomiting') %> + <%= __('March 23') %> <%= __('at') %> 20:00 +