app/frontend/src/store/modules/agriseafoodopscreening/agriSeafoodOpScreeningForm.js
import moment from 'moment';
import commonFormService from '@/services/commonFormService';
import { FormNames } from '@/utils/constants';
import { SampleData, RandomCities } from './sampleData.js';
// Change the supplied state to the exact format required by the API endpoint
// Any data guards/sanitation can go in here
function transformToPost(state) {
// TODO: unit test this!
const copy = JSON.parse(JSON.stringify(state));
// Recursive remove all '' fields from body to post
// https://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript
// const cleanEmpty = copy => Object.entries(copy)
// .map(([k, v]) => [k, v && typeof v === 'object' ? cleanEmpty(v) : v])
// .reduce((a, [k, v]) => (v === '' ? a : { ...a, [k]: v }), {});
// Sanitize the optional fields in case they get checked, filled out, unchecked
if (!copy.location.accTents) {
delete copy.location.tentDetails;
}
if (!copy.location.accMotel) {
delete copy.location.motelName;
delete copy.location.motelAddressLine1;
delete copy.location.motelAddressLine2;
delete copy.location.motelCity;
delete copy.location.motelProvince;
delete copy.location.motelPostalCode;
}
const contacts = [copy.primaryContact, copy.covidContact];
copy.location.numberOfWorkers = Number.parseInt(copy.location.numberOfWorkers, 10);
const body = {
type: copy.type,
business: copy.business,
contacts: contacts,
attestation: copy.attestation,
location: copy.location
};
return body;
}
// Change the results of the API fetch to the store state format
function transformToState(data) {
// TODO: unit test this!
const copy = JSON.parse(JSON.stringify(data));
const primary = copy.contacts ? copy.contacts.find(({ contactType }) => contactType === 'PRIMARY') : {};
const covid = copy.contacts ? copy.contacts.find(({ contactType }) => contactType === 'COVID_COORDINATOR') : {};
copy.location.startDate = moment(copy.location.startDate).format('YYYY-MM-DD');
copy.location.endDate = moment(copy.location.endDate).format('YYYY-MM-DD');
return {
type: copy.operationType,
business: copy.business,
primaryContact: primary,
covidContact: covid,
attestation: copy.attestation,
location: copy.location
};
}
export default {
namespaced: true,
state: {
getFormError: '',
gettingForm: false,
submitting: false,
step: 0,
submissionComplete: false,
submissionDetails: null,
submissionError: '',
// Form schema
type: '',
business: {
name: '',
orgBookId: '',
addressLine1: '',
addressLine2: '',
city: '',
province: '',
postalCode: ''
},
primaryContact: {
contactType: 'PRIMARY',
firstName: '',
lastName: '',
phone1: '',
phone2: '',
email: ''
},
covidContact: {
contactType: 'COVID_COORDINATOR',
firstName: '',
lastName: '',
phone1: '',
phone2: '',
email: ''
},
location: {
startDate: '',
endDate: '',
city: '',
cityLatitude: undefined,
cityLongitude: undefined,
numberOfWorkers: '',
accTents: false,
tentDetails: '',
accMotel: false,
motelName: '',
motelAddressLine1: '',
motelAddressLine2: '',
motelCity: '',
motelProvince: '',
motelPostalCode: '',
accWorkersHome: false
},
attestation: {
guidelinesRead: false,
assessmentCompleted: false,
developedPlan: false,
protectionSignage: false,
workerContactPersonnel: false,
sharedSleepingDistancing: false,
sharedSleepingCommunication: false,
sharedSleepingProvidedAccommodations: false,
selfIsolateUnderstood: false,
selfIsolateAccommodation: false,
laundryServices: false,
wasteManagementGloves: false,
wasteManagementSchedule: false,
wasteManagementBags: false,
handWashingStations: false,
handWashingSoapWater: false,
handWashingWaterless: false,
handWashingPaperTowels: false,
handWashingSignage: false,
distancingMaintained: false,
distancingFaceShields: false,
disinfectingSchedule: false,
transportationSingleOccupant: false,
transportationBusesVans: false,
transportationHelicopter: false,
transportationTrucksCars: false,
transportationTravelPod: false,
transportationCleaningDistancing: false,
educationSignage: false,
educationContactPersonnel: false,
trainingCovid19: false,
trainingEtiquette: false,
trainingLocations: false,
trainingFirstAid: false,
trainingReporting: false,
mealsDistancing: false,
mealsDishware: false,
mealsDishwashing: false,
infectionSeparation: false,
infectionSymptoms: false,
infectionHeathLinkBC: false,
infectionSanitization: false,
infectedFeeding: false,
infectedHousekeeping: false,
infectedWaste: false,
infectionAccommodation: false,
certifyAccurateInformation: false,
agreeToInspection: false
}
},
getters: {
getFormError: state => state.getFormError,
gettingForm: state => state.gettingForm,
step: state => state.step,
submitting: state => state.submitting,
submissionComplete: state => state.submissionComplete,
submissionDetails: state => state.submissionDetails,
submissionError: state => state.submissionError,
// Form objects
operationType: state => state.type,
business: state => state.business,
primaryContact: state => state.primaryContact,
covidContact: state => state.covidContact,
attestation: state => state.attestation,
location: state => state.location
},
mutations: {
setGetFormError(state, errorMessage) {
state.getFormError = errorMessage;
},
setGettingForm(state, isGetting) {
state.gettingForm = isGetting;
},
setSubmitting(state, isSubmitting) {
state.submitting = isSubmitting;
},
setStep: (state, step) => {
window.scrollTo(0, 0);
state.step = step;
},
setSubmissionComplete(state) {
state.submissionComplete = true;
window.scrollTo(0, 0);
},
setSubmissionDetails(state, responseData) {
state.submissionDetails = responseData;
},
setSubmissionError(state, errorMessage) {
state.submissionError = errorMessage;
},
// Form updates
setOperationType(state, type) {
state.type = type;
},
updateBusiness: (state, obj) => {
Object.assign(state.business, obj);
},
updatePrimaryContact: (state, obj) => {
Object.assign(state.primaryContact, obj);
},
updateCovidContact: (state, obj) => {
Object.assign(state.covidContact, obj);
},
updateAttestation: (state, obj) => {
Object.assign(state.attestation, obj);
},
updateLocation: (state, obj) => {
Object.assign(state.location, obj);
}
},
actions: {
async getForm({ commit }, id) {
commit('setGettingForm', true);
commit('setGetFormError', '');
try {
const response = await commonFormService.getSubmission(FormNames.AGRISEAFOODOPSCREENING, id);
if (!response.data) {
throw new Error(`Failed to GET for ${id}`);
}
const transformed = transformToState(response.data);
commit('updateAttestation', transformed.attestation);
commit('updateBusiness', transformed.business);
commit('updatePrimaryContact', transformed.primaryContact);
commit('updateCovidContact', transformed.covidContact);
commit('updateLocation', transformed.location);
commit('setOperationType', transformed.type ? transformed.type.display : '');
commit('setSubmissionComplete');
} catch (error) {
console.error(`Error getting form: ${error}`); // eslint-disable-line no-console
commit('setGetFormError', 'An error occurred while attempting to fetch details. Please refresh and try again.');
} finally {
commit('setGettingForm', false);
}
},
async submitForm({ commit, state }) {
commit('setSubmitting', true);
commit('setSubmissionError', '');
try {
const body = transformToPost(state);
const response = await commonFormService.sendSubmission(FormNames.AGRISEAFOODOPSCREENING, body);
if (!response.data) {
throw new Error('No response data from API while submitting form');
}
commit('setSubmissionDetails', response.data);
commit('setSubmissionComplete');
} catch (error) {
console.error(`Error submitting form: ${error} - ${error.message}`); // eslint-disable-line no-console
commit('setSubmissionError', 'An error occurred while attempting to submit the form. Please try again.');
} finally {
commit('setSubmitting', false);
}
},
async sampleData({ commit }) {
commit('updateBusiness', SampleData.business);
commit('updatePrimaryContact', SampleData.primaryContact);
commit('updateCovidContact', SampleData.covidContact);
const l = SampleData.location;
l.city = RandomCities[Math.floor(Math.random() * RandomCities.length)];
commit('updateLocation', l);
}
}
};