Merge pull request #246 from Safelite/feature/digital/SSR-313
Feature/digital/ssr 313
This commit is contained in:
commit
080b9b4b1c
37 changed files with 1584 additions and 673 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -24,4 +24,5 @@ pnpm-debug.log*
|
|||
|
||||
# Misc
|
||||
coverage/*
|
||||
junit.xml
|
||||
junit.xml
|
||||
/.vs
|
||||
|
|
|
|||
|
|
@ -14,5 +14,5 @@
|
|||
@import "@/styles/common-error-styles.scss";
|
||||
@import "@/styles/common-animations.scss";
|
||||
@import "@/styles/shared-input-button-styles.scss";
|
||||
@import "@/styles/client-customizations.scss"
|
||||
@import "@/styles/client-customizations.scss";
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const applicationConfig = {
|
|||
CLIENTTAG_QUERYSTRING: 'CientTag',
|
||||
GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY,
|
||||
ISS_DEV_CMS_DOMAIN: "https://digitalisscms.dev.safelite.io",
|
||||
CASH_PARENT_ACCOUNT_NUMBER: 167132
|
||||
};
|
||||
|
||||
export { applicationConfig };
|
||||
|
|
@ -2,7 +2,7 @@ const damageCustomLabels = Object.freeze({
|
|||
MATCH: 'match',
|
||||
REAR_WINDOW: 'rear window',
|
||||
SIDE_WINDOW: 'side window',
|
||||
WINDSHIELD: 'windshield',
|
||||
WINDSHIELD: 'windshield'
|
||||
});
|
||||
|
||||
export default damageCustomLabels;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ const damageLocationsCms = {
|
|||
SIDEDOOR: "SIDEDOOR",
|
||||
REARWINDOW: "REARWINDOW",
|
||||
DRIVERSIDE: "DRIVERSIDE",
|
||||
PASSENGERSIDE: "PASSENGERSIDE",
|
||||
PASSENGERSIDE: "PASSENGERSIDE"
|
||||
};
|
||||
|
||||
export { damageLocationsCms };
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const damageLocationsSelected = {
|
|||
DRIVERSIDE: "DriverSide",
|
||||
PASSENGERSIDE: "PassengerSide",
|
||||
STATIONARY: "Stationary",
|
||||
SLIDER: "Slider",
|
||||
SLIDER: "Slider"
|
||||
};
|
||||
|
||||
export { damageLocationsSelected };
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ const dynamicStrings = {
|
|||
GLOBAL_STATE: "globalState",
|
||||
CUSTOM: "custom",
|
||||
ROUTER_LINK: "routerLink:",
|
||||
MODAL_LINK: "modalLink"
|
||||
MODAL_LINK: "modalLink",
|
||||
TEXT_LINK: 'textLink'
|
||||
};
|
||||
|
||||
export { dynamicStrings };
|
||||
|
|
@ -18,8 +18,8 @@ const customMappings = {
|
|||
{ key: "Passenger Back", transformedValue: "passenger side back door" },
|
||||
{ key: "Passenger Vent", transformedValue: "passenger side vent glass" },
|
||||
{ key: "Passenger Quarter", transformedValue: "passenger side quarter panel" },
|
||||
{ key: "Passenger SlideDoor", transformedValue: "passenger side sliding door" },
|
||||
],
|
||||
{ key: "Passenger SlideDoor", transformedValue: "passenger side sliding door" }
|
||||
]
|
||||
};
|
||||
|
||||
// Gets an instance of a string where the dynamic portion of the text {custom:KeyName}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,10 @@ const endpoints = {
|
|||
url: "/parts/api/v1/parts/parts",
|
||||
method: "POST",
|
||||
},
|
||||
GetPriceOrderItems: {
|
||||
url: '/price/api/v1/price/order-items',
|
||||
method: 'GET'
|
||||
},
|
||||
GetCapabilityQuestions: {
|
||||
url: "/parts/api/v1/parts/capability-questions",
|
||||
method: "GET",
|
||||
|
|
@ -46,7 +50,19 @@ const endpoints = {
|
|||
GetPartFromCapabilityAnswer: {
|
||||
url: "/parts/api/v1/parts/part-from-capability-answer",
|
||||
method: "POST",
|
||||
},
|
||||
},
|
||||
GetWipers: {
|
||||
url: '/parts/api/v1/parts/wipers',
|
||||
method: 'GET'
|
||||
},
|
||||
GetRainDefense: {
|
||||
url: '/parts/api/v1/parts/rain-defense',
|
||||
method: 'GET'
|
||||
},
|
||||
GetSupportingItems: {
|
||||
url: '/parts/api/v1/parts/supporting-items',
|
||||
method: 'POST'
|
||||
},
|
||||
GetVehicle: {
|
||||
url: "/vehicle/api/v1/vehicle/lookup",
|
||||
method: "GET",
|
||||
|
|
@ -64,20 +80,20 @@ const endpoints = {
|
|||
method: "POST",
|
||||
},
|
||||
LookupVehicleByVin: {
|
||||
url: "/vehicle/api/v1/vehicle/lookup",
|
||||
method: "POST",
|
||||
url: "/vehicle/api/v1/vehicle/lookup",
|
||||
method: "POST",
|
||||
},
|
||||
LookupVinByAddress: {
|
||||
url: "/vehicle/api/v1/vehicle/lookup-vin-by-address",
|
||||
method: "POST",
|
||||
method: "POST",
|
||||
},
|
||||
LookupVinByPlate: {
|
||||
url: "/vehicle/api/v1/vehicle/lookup-vin-by-plate",
|
||||
method: "POST",
|
||||
},
|
||||
InitializeSession: {
|
||||
url: "/analytics/api/v1/analytics/initialize",
|
||||
method: "POST",
|
||||
url: "/analytics/api/v1/analytics/initialize",
|
||||
method: "POST",
|
||||
},
|
||||
GetExperimentsByUser: {
|
||||
url: "/analytics/api/v1/analytics/get-experiments",
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const errorMessages = {
|
|||
DAMAGE_OPTION_REQUIRED: "Please select an option",
|
||||
|
||||
POLICYHOLDER_FIRST_NAME_REQUIRED: "Please enter the policyholder first name",
|
||||
POLICYHOLDER_LAST_NAME_REQUIRED: "Please enter the policyholder last name",
|
||||
POLICYHOLDER_LAST_NAME_REQUIRED: "Please enter the policyholder last name"
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
const globalEvents = {
|
||||
Categories: {
|
||||
GLOBAL_ALERT: "GLOBAL_ALERT",
|
||||
GLOBAL_ALERT: "GLOBAL_ALERT"
|
||||
},
|
||||
SubCategories: {
|
||||
PAGE_NOT_FOUND: "PAGE_NOT_FOUND",
|
||||
},
|
||||
PAGE_NOT_FOUND: "PAGE_NOT_FOUND"
|
||||
}
|
||||
};
|
||||
|
||||
const globalEventTypes = {
|
||||
Success: "alert-success",
|
||||
Warning: "alert-warning",
|
||||
Info: "alert-info",
|
||||
Danger: "alert-danger",
|
||||
Danger: "alert-danger"
|
||||
};
|
||||
|
||||
export { globalEvents, globalEventTypes };
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
const experimentUniverses = {
|
||||
ISS_FUNNEL: "ISSFunnel",
|
||||
ISS_FUNNEL: "ISSFunnel"
|
||||
};
|
||||
|
||||
const experimentSettings = {
|
||||
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index",
|
||||
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index"
|
||||
};
|
||||
|
||||
const experimentTriggers = {
|
||||
SITE_ENTRY: "SiteEntry",
|
||||
PAGE_ENTRY: "PageEntry",
|
||||
PAGE_ENTRY: "PageEntry"
|
||||
};
|
||||
|
||||
export { experimentUniverses, experimentSettings, experimentTriggers };
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
export const headerKeys = {
|
||||
EXPERIMENT: "X-Experiment-Data",
|
||||
EXPERIMENT: "X-Experiment-Data"
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
const endpoints = {
|
||||
GetRouteInfo: {
|
||||
url: "https://mockey.qa.sagaws.net/service/ISS/Content/RouteInfo",
|
||||
method: "GET",
|
||||
},
|
||||
method: "GET"
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
|||
8
src/constants/part-type-strings.js
Normal file
8
src/constants/part-type-strings.js
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
const partTypeStrings = {
|
||||
FRONT_WIPER: 'FRONT WIPER',
|
||||
REAR_WIPER: 'REAR WIPER',
|
||||
RAIN_DEFENSE: 'RAIN DEFENSE',
|
||||
RECALIBRATION: 'RECALIBRATION'
|
||||
};
|
||||
|
||||
export { partTypeStrings };
|
||||
|
|
@ -49,5 +49,5 @@ export const states = {
|
|||
WA: "Washington",
|
||||
WV: "West Virginia",
|
||||
WI: "Wisconsin",
|
||||
WY: "Wyoming",
|
||||
WY: "Wyoming"
|
||||
};
|
||||
|
|
@ -34,7 +34,7 @@ const tintMap = {
|
|||
{ name: "gray tint privacy", src: "Glass-NoShade-GrayTint.svg" },
|
||||
|
||||
// No shade or tint
|
||||
{ name: "clear", src: "Glass-NoShade-NoTint.svg" },
|
||||
{ name: "clear", src: "Glass-NoShade-NoTint.svg" }
|
||||
],
|
||||
|
||||
windshield: [
|
||||
|
|
@ -69,8 +69,8 @@ const tintMap = {
|
|||
{ name: "gray tint privacy", src: "Windshield-NoShade-GrayTint.svg" },
|
||||
|
||||
// No shade or tint
|
||||
{ name: "clear", src: "Windshield-NoShade-NoTint.svg" },
|
||||
],
|
||||
{ name: "clear", src: "Windshield-NoShade-NoTint.svg" }
|
||||
]
|
||||
};
|
||||
|
||||
// Gets the tint image source string given the glass location, and the tint description (like 'Green Tint')
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const vehicleCategories = {
|
|||
COMMERCIALVAN: "COMMERCIAL VAN",
|
||||
SUV: "SUV",
|
||||
MOTORHOME: "MOTOR HOME",
|
||||
SEMI: "SEMI",
|
||||
SEMI: "SEMI"
|
||||
};
|
||||
|
||||
export { vehicleCategories };
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
const vinLookupMethodSelections = Object.freeze({
|
||||
MANUALVIN: 'ManualVin',
|
||||
LICENSEPLATE: 'LicensePlate',
|
||||
HOMEADDRESS: 'HomeAddress',
|
||||
HOMEADDRESS: 'HomeAddress'
|
||||
});
|
||||
|
||||
export {vinLookupMethodSelections};
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
:buttonLabel="answer.buttonLabel"
|
||||
:buttonLabelSubCopy="answer.buttonLabelSubCopy"
|
||||
:buttonBodyCopy="answer.buttonBodyCopy"
|
||||
:buttonAuxillaryCopy="answer.buttonAuxillaryCopy"
|
||||
:buttonAuxiliaryCopy="answer.buttonAuxiliaryCopy"
|
||||
:buttonFooterCopy="answer.buttonFooterCopy"
|
||||
:buttonImage="answer.buttonImage"
|
||||
:buttonImageId="answer.buttonImageId"
|
||||
|
|
@ -194,7 +194,7 @@ export default {
|
|||
altText: answer.altText ?? (answer.Name ? answer.Name : answer),
|
||||
buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText,
|
||||
buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy,
|
||||
buttonAuxillaryCopy: answer.buttonAuxillaryCopy ?? answer.buttonAuxillaryCopy,
|
||||
buttonAuxiliaryCopy: answer.buttonAuxiliaryCopy ?? answer.buttonAuxiliaryCopy,
|
||||
buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
||||
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
||||
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { dynamicStrings } from "@/constants/dynamic-strings";
|
||||
import { dynamicStrings } from '@/constants/dynamic-strings';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
export function fetchCmsContentForPage(issPage) {
|
||||
|
|
@ -18,7 +18,7 @@ export function fetchCmsContentForPage(issPage) {
|
|||
}
|
||||
else {
|
||||
// Else get the client override page.
|
||||
const pageName = issPage + "_" + clientName.toLowerCase().replace(/ /g, "");
|
||||
const pageName = issPage + '_' + clientName.toLowerCase().replace(/ /g, '');
|
||||
|
||||
return store.getPageData(pageName)
|
||||
.then(
|
||||
|
|
@ -26,7 +26,8 @@ export function fetchCmsContentForPage(issPage) {
|
|||
// Process the client override if it exists.
|
||||
return processPageData(baseResponse, clientResponse);
|
||||
},
|
||||
(error) => {
|
||||
(error) => {
|
||||
console.error(error);
|
||||
// Process the just the base if no client override exists.
|
||||
return processPageData(baseResponse, null);
|
||||
}
|
||||
|
|
@ -44,8 +45,11 @@ function processPageData(baseResponse, clientResponse) {
|
|||
const pageDataFromCms = {};
|
||||
let widgets = [];
|
||||
|
||||
if ( clientResponse === null )
|
||||
{
|
||||
if (!baseResponse?.data?.Result) {
|
||||
console.error('No result data found'); // Something has gone terribly wrong.
|
||||
return {}
|
||||
}
|
||||
if (!clientResponse?.data?.Result) {
|
||||
widgets = baseResponse.data.Result;
|
||||
}
|
||||
else
|
||||
|
|
@ -89,7 +93,7 @@ function processPageData(baseResponse, clientResponse) {
|
|||
|
||||
widgets.forEach((widget) => {
|
||||
// Global state value replacement.
|
||||
let widgetWithReplacements = findAndReplaceGlobalStateValues(
|
||||
const widgetWithReplacements = findAndReplaceGlobalStateValues(
|
||||
widget.Model,
|
||||
widget.Name
|
||||
);
|
||||
|
|
@ -103,7 +107,7 @@ function processPageData(baseResponse, clientResponse) {
|
|||
}
|
||||
|
||||
pageDataFromCms[widgetWithReplacements.Name] = [
|
||||
widgetWithReplacements.Model,
|
||||
widgetWithReplacements.Model
|
||||
];
|
||||
});
|
||||
|
||||
|
|
@ -121,7 +125,7 @@ function processPageData(baseResponse, clientResponse) {
|
|||
function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
||||
const objWithReplacements = {
|
||||
Name: widgetName,
|
||||
Model: {},
|
||||
Model: {}
|
||||
};
|
||||
|
||||
Object.keys(widgetModel).forEach((key) => {
|
||||
|
|
@ -140,13 +144,13 @@ function findAndReplaceGlobalStateValues(widgetModel, widgetName) {
|
|||
// This is a recursive function, it will call itself until it runs out of items to iterate on given the object.
|
||||
function processWidgetItemForReplacement(widgetModel, key) {
|
||||
// If we have a string, and it needs to be replaced.
|
||||
if (typeof widgetModel[key] === "string") {
|
||||
if (typeof widgetModel[key] === 'string') {
|
||||
widgetModel[key] = processIfStatements(
|
||||
widgetModel[key],
|
||||
dynamicStrings.GLOBAL_STATE,
|
||||
getStoreValueFromString
|
||||
);
|
||||
|
||||
|
||||
if (widgetModel[key].includes(dynamicStrings.GLOBAL_STATE)) {
|
||||
widgetModel[key] = mapStringToState(widgetModel[key]);
|
||||
}
|
||||
|
|
@ -158,7 +162,7 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
|||
|
||||
// If we have an object. array, etc
|
||||
if (
|
||||
typeof widgetModel[key] === "object" &&
|
||||
typeof widgetModel[key] === 'object' &&
|
||||
Object.keys(widgetModel[key]).length
|
||||
) {
|
||||
Object.keys(widgetModel[key]).forEach((item) => {
|
||||
|
|
@ -173,47 +177,43 @@ function processWidgetItemForReplacement(widgetModel, key) {
|
|||
}
|
||||
|
||||
function mapStringToModal(str) {
|
||||
let startIndex = str.indexOf("{" + dynamicStrings.MODAL_LINK);
|
||||
let linkToReplace = str.substring(startIndex, str.length);
|
||||
linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf("}") + 1);
|
||||
const startIndex = str.indexOf('{' + dynamicStrings.MODAL_LINK);
|
||||
const linkToReplace = str.substring(startIndex, str.length);
|
||||
linkToReplace = linkToReplace.substring(0, linkToReplace.indexOf('}') + 1);
|
||||
|
||||
let params = linkToReplace.substring((dynamicStrings.MODAL_LINK).length + 2, linkToReplace.length -1);
|
||||
let splitParams = params.split(",");
|
||||
const params = linkToReplace.substring((dynamicStrings.MODAL_LINK).length + 2, linkToReplace.length -1)
|
||||
const splitParams = params.split(',');
|
||||
|
||||
const bodyText = '<a modalTarget="' + splitParams[0] + '" class="modal-text" aria-label="Modal window">' + splitParams[1] + '</a>';
|
||||
|
||||
let bodyText = '<a modalTarget="' + splitParams[0] + '" class="modal-text" aria-label="Modal window">' + splitParams[1] + '</a>';
|
||||
let returnVal = str.replace(linkToReplace, bodyText);
|
||||
|
||||
if (returnVal.includes(dynamicStrings.MODAL_LINK)) {
|
||||
returnVal = mapStringToModal(returnVal);
|
||||
returnVal = mapStringToModal(returnVal)
|
||||
}
|
||||
return returnVal;
|
||||
return returnVal
|
||||
}
|
||||
|
||||
// Function to convert a string, into a matching global state item.
|
||||
function mapStringToState(str) {
|
||||
// Pull all matches out of the string.
|
||||
const regexExp = new RegExp("{(.*?):(.*?)}", "g");
|
||||
const regexExp = new RegExp('{([^{}]*?):([^{}]*?)}', 'g');
|
||||
const regexMatches = [...str.matchAll(regexExp)];
|
||||
const globalStateMatches = regexMatches.filter(match => {
|
||||
return match[1] === dynamicStrings.GLOBAL_STATE;
|
||||
});
|
||||
|
||||
// Our final string value that will be built from the matches.
|
||||
let stringBuilder = "";
|
||||
let stringBuilder = '';
|
||||
|
||||
for (const match of globalStateMatches) {
|
||||
// Reset store state for each match.
|
||||
let storeState = useMainStore();
|
||||
|
||||
for (const s of match[2].split(".")) {
|
||||
if (storeState[s] != undefined) {
|
||||
storeState = storeState[s];
|
||||
} else {
|
||||
return ""; // if we can't map our string to state data, return an empty string.
|
||||
}
|
||||
const valueFromStore = getStoreValueFromString(match[2]);
|
||||
if (!valueFromStore) {
|
||||
console.warning('Unable to resolve global state data.');
|
||||
return '' // if we can't map our string to state data, return an empty string.
|
||||
}
|
||||
|
||||
const stringWithReplacement = str.replace(match[0], storeState);
|
||||
const stringWithReplacement = str.replace(match[0], valueFromStore);
|
||||
|
||||
// If we still have values we need to substitute, call this function again.
|
||||
if (stringWithReplacement.includes(dynamicStrings.GLOBAL_STATE)) {
|
||||
|
|
@ -227,18 +227,19 @@ function mapStringToState(str) {
|
|||
return stringBuilder.trimStart();
|
||||
}
|
||||
|
||||
|
||||
function getStoreValueFromString(str) {
|
||||
let storeOrStateObject = useMainStore();
|
||||
for (const s of str.split('.')) {
|
||||
if (s === 'getters') continue;
|
||||
if (storeOrStateObject[s] != undefined) {
|
||||
storeOrStateObject = storeOrStateObject[s];
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
return storeOrStateObject;
|
||||
if (!str) return '';
|
||||
|
||||
let storeOrStateObject = useMainStore();
|
||||
for (const s of str.split('.')) {
|
||||
if (s === 'getters') continue; //For backward compatability
|
||||
if (storeOrStateObject[s] != undefined) {
|
||||
storeOrStateObject = storeOrStateObject[s];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return storeOrStateObject ?? '';
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
|
@ -246,173 +247,179 @@ function getStoreValueFromString(str) {
|
|||
///////////////////////////////////
|
||||
|
||||
/**
|
||||
* Recursive function - replaces all instances of if statements from the CMS that utilize the specified ifConditionKeyword
|
||||
* @param {*} str string - Input string to be processed
|
||||
* @param {*} ifConditionKeyword string - Defines which if statements to process ex: 'globalState'
|
||||
* @param {*} replacePlaceholderCallback function - Callback to replace CMS placeholder values
|
||||
* @returns The processed string
|
||||
*/
|
||||
* Recursive function - replaces all instances of if statements from the CMS that utilize the specified ifConditionKeyword
|
||||
* @param {*} str string - Input string to be processed
|
||||
* @param {*} ifConditionKeyword string - Defines which if statements to process ex: 'globalState'
|
||||
* @param {*} replacePlaceholderCallback function - Callback to replace CMS placeholder values
|
||||
* @returns The processed string
|
||||
*/
|
||||
export function processIfStatements(str, ifConditionKeyword, replacePlaceholderCallback) {
|
||||
const containsRelevantIfStatement = new RegExp('{if:' + ifConditionKeyword + ':.+?}', 'g').test(
|
||||
str
|
||||
);
|
||||
//str = str.replace(/\r?\n|\r/g, '');
|
||||
const containsRelevantIfStatement = new RegExp('{if:' + ifConditionKeyword + ':.+?}', 'g').test(
|
||||
str
|
||||
);
|
||||
|
||||
const hasEmbeddedCrLf = /\r?\n|\r/g.test(str);
|
||||
if (!containsRelevantIfStatement || hasEmbeddedCrLf) {
|
||||
return str;
|
||||
} else {
|
||||
const ifStatementRegexExpression = getIfStatementRegexExpression();
|
||||
const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)];
|
||||
const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword(
|
||||
ifStatementRegexMatches,
|
||||
ifConditionKeyword
|
||||
);
|
||||
executeIfStatementAndSetProcessedStrings(
|
||||
completeIfStatementArray,
|
||||
replacePlaceholderCallback
|
||||
);
|
||||
const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches);
|
||||
return processIfStatements(
|
||||
reconstructedPostProcessedString,
|
||||
ifConditionKeyword,
|
||||
replacePlaceholderCallback
|
||||
);
|
||||
}
|
||||
const hasEmbeddedCrLf = /\r?\n|\r/g.test(str);
|
||||
if (hasEmbeddedCrLf) {
|
||||
console.warning('Processing of conditional string was skipped. String has embedded carriage return/linefeed.');
|
||||
}
|
||||
if (!containsRelevantIfStatement || hasEmbeddedCrLf) {
|
||||
return str;
|
||||
} else {
|
||||
const ifStatementRegexExpression = getIfStatementRegexExpression();
|
||||
const ifStatementRegexMatches = [...str.matchAll(ifStatementRegexExpression)];
|
||||
const completeIfStatementArray = getAndFlagFirstNonNestedIfStatementWithKeyword(
|
||||
ifStatementRegexMatches,
|
||||
ifConditionKeyword
|
||||
);
|
||||
executeIfStatementAndSetProcessedStrings(
|
||||
completeIfStatementArray,
|
||||
replacePlaceholderCallback
|
||||
);
|
||||
const reconstructedPostProcessedString = joinProcessedRegexArray(ifStatementRegexMatches);
|
||||
return processIfStatements(
|
||||
reconstructedPostProcessedString,
|
||||
ifConditionKeyword,
|
||||
replacePlaceholderCallback
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function getAndFlagFirstNonNestedIfStatementWithKeyword(matches, ifConditionKeyword) {
|
||||
let index = 0;
|
||||
for (const match of matches) {
|
||||
if (match.groups.isIfStatement && match.groups.ifConditionType === ifConditionKeyword) {
|
||||
let interiorIndex = 0;
|
||||
let nestedLevel = 0;
|
||||
let elseStatementIndex = null;
|
||||
for (const interiorMatch of matches.slice(index + 1)) {
|
||||
if (interiorMatch.groups.isIfStatement) {
|
||||
if (interiorMatch.groups.ifConditionType === ifConditionKeyword) {
|
||||
break;
|
||||
} else {
|
||||
nestedLevel++;
|
||||
}
|
||||
} else if (interiorMatch.groups.isElseStatement) {
|
||||
if (!nestedLevel) {
|
||||
elseStatementIndex = interiorIndex + 1;
|
||||
}
|
||||
} else if (interiorMatch.groups.isEndStatement) {
|
||||
if (nestedLevel) {
|
||||
nestedLevel--;
|
||||
} else {
|
||||
const ifStatementArray = matches.slice(index, index + interiorIndex + 2);
|
||||
flagMatchesForProcessing(ifStatementArray, elseStatementIndex);
|
||||
return ifStatementArray;
|
||||
}
|
||||
}
|
||||
interiorIndex++;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
console.error('Did not find end in conditional logic');
|
||||
return matches;
|
||||
let index = 0;
|
||||
for (const match of matches) {
|
||||
if (match.groups.isIfStatement && match.groups.ifConditionType === ifConditionKeyword) {
|
||||
let interiorIndex = 0;
|
||||
let nestedLevel = 0;
|
||||
let elseStatementIndex = null;
|
||||
for (const interiorMatch of matches.slice(index + 1)) {
|
||||
if (interiorMatch.groups.isIfStatement) {
|
||||
if (interiorMatch.groups.ifConditionType === ifConditionKeyword) {
|
||||
break;
|
||||
} else {
|
||||
nestedLevel++;
|
||||
}
|
||||
} else if (interiorMatch.groups.isElseStatement) {
|
||||
if (!nestedLevel) {
|
||||
elseStatementIndex = interiorIndex + 1;
|
||||
}
|
||||
} else if (interiorMatch.groups.isEndStatement) {
|
||||
if (nestedLevel) {
|
||||
nestedLevel--;
|
||||
} else {
|
||||
const ifStatementArray = matches.slice(index, index + interiorIndex + 2);
|
||||
flagMatchesForProcessing(ifStatementArray, elseStatementIndex);
|
||||
return ifStatementArray;
|
||||
}
|
||||
}
|
||||
interiorIndex++;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
console.error('Did not find end in conditional logic');
|
||||
return matches;
|
||||
}
|
||||
|
||||
function flagMatchesForProcessing(matches, elseStatementIndex) {
|
||||
matches[0].isFlaggedForProcessing = true;
|
||||
matches[matches.length - 1].isFlaggedForProcessing = true;
|
||||
if (elseStatementIndex) {
|
||||
matches[elseStatementIndex].isFlaggedForProcessing = true;
|
||||
}
|
||||
matches[0].isFlaggedForProcessing = true;
|
||||
matches[matches.length - 1].isFlaggedForProcessing = true;
|
||||
if (elseStatementIndex) {
|
||||
matches[elseStatementIndex].isFlaggedForProcessing = true;
|
||||
}
|
||||
}
|
||||
|
||||
function joinProcessedRegexArray(regexMatches) {
|
||||
let processedString = '';
|
||||
regexMatches.forEach((match) => {
|
||||
const rawString = match[0];
|
||||
processedString += match.groups.processedString ?? rawString;
|
||||
});
|
||||
return processedString;
|
||||
let processedString = '';
|
||||
regexMatches.forEach((match) => {
|
||||
const rawString = match[0];
|
||||
processedString += match.groups.processedString ?? rawString;
|
||||
});
|
||||
return processedString;
|
||||
}
|
||||
|
||||
function executeIfStatementAndSetProcessedStrings(ifStatementArray, replacePlaceholderCallback) {
|
||||
const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition);
|
||||
let isInsideDesiredBlock = ifCondition;
|
||||
const ifCondition = replacePlaceholderCallback(ifStatementArray[0].groups.ifCondition);
|
||||
let isInsideDesiredBlock = ifCondition;
|
||||
|
||||
ifStatementArray.forEach((entry) => {
|
||||
if (entry.groups.isElseStatement && entry.isFlaggedForProcessing) {
|
||||
isInsideDesiredBlock = !ifCondition;
|
||||
} else if (entry.groups.isEndStatement && entry.isFlaggedForProcessing) {
|
||||
isInsideDesiredBlock = true;
|
||||
}
|
||||
setProcessedStringOnEntry(entry, isInsideDesiredBlock);
|
||||
});
|
||||
ifStatementArray.forEach((entry) => {
|
||||
if (entry.groups.isElseStatement && entry.isFlaggedForProcessing) {
|
||||
isInsideDesiredBlock = !ifCondition;
|
||||
} else if (entry.groups.isEndStatement && entry.isFlaggedForProcessing) {
|
||||
isInsideDesiredBlock = true;
|
||||
}
|
||||
setProcessedStringOnEntry(entry, isInsideDesiredBlock);
|
||||
});
|
||||
}
|
||||
|
||||
function setProcessedStringOnEntry(entry, isInsideDesiredBlock) {
|
||||
if (!isInsideDesiredBlock) {
|
||||
entry.groups.processedString = '';
|
||||
} else {
|
||||
if (entry.groups.isIfStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.ifTrailingString
|
||||
: entry[0];
|
||||
} else if (entry.groups.isElseStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.elseTrailingString
|
||||
: entry[0];
|
||||
} else {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.endTrailingString
|
||||
: entry[0];
|
||||
}
|
||||
}
|
||||
if (!isInsideDesiredBlock) {
|
||||
entry.groups.processedString = '';
|
||||
} else {
|
||||
if (entry.groups.isIfStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.ifTrailingString
|
||||
: entry[0];
|
||||
} else if (entry.groups.isElseStatement) {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.elseTrailingString
|
||||
: entry[0];
|
||||
} else {
|
||||
entry.groups.processedString = entry.isFlaggedForProcessing
|
||||
? entry.groups.endTrailingString
|
||||
: entry[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getIfStatementRegexExpression() {
|
||||
// Matches but does not capture:
|
||||
// {if:...} or {else} or {end}
|
||||
const anyLogicOperatorNonCapture = '(?:{(?:end|else|if:.*?)})';
|
||||
// NOTE: ?<variableName> syntax stores the captured match like so: match.groups.variableName
|
||||
const matchStartOfString =
|
||||
'(?<processedString>^.+?)' + // Match and Capture all characters (lazy), cannot be empty
|
||||
'(?=(?:{if))'; // Looks ahead but does not capture {if
|
||||
const matchIfOperator =
|
||||
'(?<isIfStatement>{if:)' + // Match & Capture {if:
|
||||
'(?<ifConditionType>.*?):' + // Match all chars up to and including next ':' - Capture all chars up to ':'
|
||||
'(?<ifCondition>.*?)}' + // Match all chars up to and including next '}' - Capture all chars up to '}'
|
||||
'(?<ifTrailingString>.*?)' + // Match and Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchElseOperator =
|
||||
'(?<isElseStatement>{else})' + // Match & Capture {else}
|
||||
'(?<elseTrailingString>.*?)' + // Match & Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchEndOperator =
|
||||
'(?<isEndStatement>{end})' + // Match & Capture {end}
|
||||
'(?<endTrailingString>.*?)' + // Match & Capture all chracters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
'|$)'; // Looks ahead but does not capture the next logic operator
|
||||
// Combine all matching patterns, separated by 'or' pipes
|
||||
return new RegExp(
|
||||
matchStartOfString +
|
||||
'|' +
|
||||
matchIfOperator +
|
||||
'|' +
|
||||
matchElseOperator +
|
||||
'|' +
|
||||
matchEndOperator,
|
||||
'g'
|
||||
);
|
||||
// Matches but does not capture:
|
||||
// {if:...} or {else} or {end}
|
||||
const anyLogicOperatorNonCapture = '(?:{(?:end|else|if:.*?)})';
|
||||
// NOTE: ?<variableName> syntax stores the captured match like so: match.groups.variableName
|
||||
const matchStartOfString =
|
||||
'(?<processedString>^.+?)' + // Match and Capture all characters (lazy), cannot be empty
|
||||
'(?=(?:{if))'; // Looks ahead but does not capture {if
|
||||
const matchIfOperator =
|
||||
'(?<isIfStatement>{if:)' + // Match & Capture {if:
|
||||
'(?<ifConditionType>.*?):' + // Match all chars up to and including next ':' - Capture all chars up to ':'
|
||||
'(?<ifCondition>.*?)}' + // Match all chars up to and including next '}' - Capture all chars up to '}'
|
||||
'(?<ifTrailingString>.*?)' + // Match and Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchElseOperator =
|
||||
'(?<isElseStatement>{else})' + // Match & Capture {else}
|
||||
'(?<elseTrailingString>.*?)' + // Match & Capture all characters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
')'; // Looks ahead but does not capture the next logic operator
|
||||
const matchEndOperator =
|
||||
'(?<isEndStatement>{end})' + // Match & Capture {end}
|
||||
'(?<endTrailingString>.*?)' + // Match & Capture all chracters (lazy), can be empty
|
||||
'(?=' +
|
||||
anyLogicOperatorNonCapture +
|
||||
'|$)'; // Looks ahead but does not capture the next logic operator
|
||||
// Combine all matching patterns, separated by 'or' pipes
|
||||
return new RegExp(
|
||||
matchStartOfString +
|
||||
'|' +
|
||||
matchIfOperator +
|
||||
'|' +
|
||||
matchElseOperator +
|
||||
'|' +
|
||||
matchEndOperator,
|
||||
'g'
|
||||
);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
// End of If Statement Processing Logic //
|
||||
//////////////////////////////////////////
|
||||
|
||||
export function doesCopyContainTextLink(copy) {
|
||||
return copy.includes(dynamicStrings.TEXT_LINK);
|
||||
}
|
||||
|
||||
export function setupModalLinks(context) {
|
||||
context.$nextTick(() => {
|
||||
const elements = document.getElementsByClassName("modal-text")
|
||||
|
|
@ -430,23 +437,35 @@ export function doesCopyContainRouterLink(copy) {
|
|||
return copy.includes(this.dynamicStrings.ROUTER_LINK);
|
||||
}
|
||||
|
||||
/**
|
||||
* splits copy on { ... } such as {routerlink: ...}
|
||||
* @returns array of strings
|
||||
*/
|
||||
export function splitCopyOnCMSPlaceHolder(copy) {
|
||||
// splits copy on { ... } such as {routerlink: ...}
|
||||
return copy.split(/{(.*?)}/g);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string2 of input following this pattern: {string1:string2,string3}
|
||||
* @returns string
|
||||
*/
|
||||
export function getRouterLinkRouteFromCopy(copy) {
|
||||
// sample input: {routerLink:estimate,provide your VIN}
|
||||
// first split would return 'estimate,provide your VIN'
|
||||
// second split would return 'estimate'
|
||||
return copy.split(":")[1].split(",")[0];
|
||||
return copy.split(':')[1].split(',')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns string3 of input following this pattern: { string1: string2, string3 }
|
||||
* @returns string
|
||||
*/
|
||||
export function getRouterLinkDisplayTextFromCopy(copy) {
|
||||
// sample input: {routerLink:estimate,provide your VIN}
|
||||
// first split would return 'estimate,provide your VIN'
|
||||
// second split would return 'provide your VIN'
|
||||
return copy.split(":")[1].split(",")[1];
|
||||
return copy.split(':')[1].split(',')[1];
|
||||
}
|
||||
|
||||
// Copy returned from the CMS that has newlines will return blocks wrapped in
|
||||
|
|
@ -455,5 +474,5 @@ export function getRouterLinkDisplayTextFromCopy(copy) {
|
|||
// attributes present
|
||||
export function splitCMSCopyOnParagraphTag(copy) {
|
||||
// filter removes empty strings that are a result of string.split with regex
|
||||
return copy.split(/(?:<p(?:.*?)>)|(?:<\/p>)/g).filter((paragraph) => paragraph !== "");
|
||||
return copy.split(/(?:<p(?:.*?)>)|(?:<\/p>)/g).filter((paragraph) => paragraph !== '');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
<img id="siteFooterImage" :src="footerImageURL" />
|
||||
</div>
|
||||
<footer class="footer container-fluid fixed-bottom g-5 bg-light py-4" id="infoBox">
|
||||
<div class="row d-flex flex-row-reverse align-items-center vw-100">
|
||||
<div class="row d-flex flex-row-reverse align-items-center vw-100 mx-0">
|
||||
<div class="col button-col d-flex" id="stacked" >
|
||||
<buttonMain
|
||||
v-if="!isForwardButtonHidden"
|
||||
|
|
|
|||
|
|
@ -30,13 +30,13 @@ export default({
|
|||
isDismissible: false,
|
||||
messageCopy: "",
|
||||
messageHeadline: "",
|
||||
type: "",
|
||||
type: ""
|
||||
},
|
||||
headerAnswers: null
|
||||
};
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
cmsWidgetName: String
|
||||
},
|
||||
computed: {
|
||||
imageSrc()
|
||||
|
|
@ -51,7 +51,7 @@ export default({
|
|||
return {
|
||||
"background-color": this.headerAnswers ? this.headerAnswers.HexCode : "#FFFFFF"
|
||||
};
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const answers = this.getCmsContent(this.cmsWidgetName, "Answers");
|
||||
|
|
|
|||
|
|
@ -13,11 +13,14 @@ describe("site sub header", () => {
|
|||
};
|
||||
|
||||
it("should contain the cms content", () => {
|
||||
const wrapper = shallowMount(siteSubHeader, {
|
||||
const wrapper = shallowMount(siteSubHeader, {
|
||||
propsData: {
|
||||
justification: '',
|
||||
issContainingPage: ''
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
wrapper.getCmsContent = jest.fn();
|
||||
const actual = wrapper.find("span");
|
||||
expect(actual.html()).toContain(subHeaderText);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,8 +12,8 @@
|
|||
/>
|
||||
</h5>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-center container-fluid overflow-hidden">
|
||||
<p class="text-center small fw-normal mb-0 subheader-secondary">
|
||||
<div class="d-flex align-items-center container-fluid overflow-hidden" :class="justifySubheader">
|
||||
<p class="text-center fw-normal mb-0 subheader-secondary" :class="alternateFormatting">
|
||||
<span>
|
||||
{{ subText }}
|
||||
</span>
|
||||
|
|
@ -31,23 +31,33 @@ import buttonBack from "@/iss-components/site-sub-header/button-back/button-back
|
|||
props: {
|
||||
cmsWidgetName: String,
|
||||
hasBackButton: Boolean,
|
||||
justification: String,
|
||||
issContainingPage: String
|
||||
},
|
||||
computed: {
|
||||
content()
|
||||
{
|
||||
content() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "SubHeaderText")
|
||||
},
|
||||
subText()
|
||||
{
|
||||
return this.getCmsContent(this.cmsWidgetName, "SecondaryText")
|
||||
subText() {
|
||||
const subText = this.getCmsContent(this.cmsWidgetName, "SecondaryText");
|
||||
return subText ?? '';
|
||||
},
|
||||
backButtonAccessibleText()
|
||||
{
|
||||
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText")
|
||||
backButtonAccessibleText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText")
|
||||
},
|
||||
headerColor() {
|
||||
return this.subText ? "dark-header" : "light-header";
|
||||
},
|
||||
justifySubheader() {
|
||||
return (this.justification?.toLowerCase() === 'left') ?
|
||||
'justify-content-left' :
|
||||
'justify-content-center';
|
||||
},
|
||||
alternateFormatting() {
|
||||
return (this.issContainingPage?.toLowerCase() === 'service-packages') ?
|
||||
'service-packages-subtext mt-4 mb-2 px-5' :
|
||||
'small';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
clickEvent() {
|
||||
|
|
@ -60,22 +70,27 @@ import buttonBack from "@/iss-components/site-sub-header/button-back/button-back
|
|||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.dark-header {
|
||||
color: $black;
|
||||
}
|
||||
.dark-header {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.light-header {
|
||||
color: $gray-550;
|
||||
}
|
||||
.light-header {
|
||||
color: $gray-550;
|
||||
}
|
||||
|
||||
h5 {
|
||||
line-height: 32px;
|
||||
h5 {
|
||||
line-height: 32px;
|
||||
|
||||
button {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
p.small {
|
||||
color: $gray-550;
|
||||
}
|
||||
p.service-packages-subtext {
|
||||
font-weight: 500 !important;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
button {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
p.small {
|
||||
color: $gray-550;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
<template>
|
||||
<buttonQuestion ref="buttonQuestion"
|
||||
:answers="servicePackageAnswers"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="servicePackageRadio"
|
||||
:buttonTypeObject="servicePackageRadio"
|
||||
v-model="selectedPackageName"
|
||||
:validationRules="validationRules"
|
||||
:isRequired="isRequired" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question';
|
||||
import { processIfStatements } from '@/helpers/cms-content-helper';
|
||||
import { damageLocationsSelected as glassLocations } from '@/constants/damage-locations-selected';
|
||||
import servicePackageRadio from './service-package-radio/service-package-radio';
|
||||
import { partTypeStrings } from '@/constants/part-type-strings';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
const packageNames = {
|
||||
TIER_ONE: 'TierOne',
|
||||
TIER_TWO: 'TierTwo',
|
||||
TIER_THREE: 'TierThree',
|
||||
};
|
||||
export default {
|
||||
name: 'servicePackageQuestion',
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
groupName: String,
|
||||
validationRules: String,
|
||||
isRequired: Boolean,
|
||||
availableLineItems: []
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
servicePackageRadio: servicePackageRadio,
|
||||
selectedPackageName: null
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
availableLineItems() {
|
||||
const store = useMainStore();
|
||||
if (this.allGlassPartsAndSupportingItemsHavePrices(store.order.lineItems)) {
|
||||
this.selectDefaultPackage();
|
||||
}
|
||||
},
|
||||
selectedPackageName(newValue) {
|
||||
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
|
||||
this.$emit('vapsItemsSelected', VapsProductsInSelectedPackage);
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
nullSafeAvailableLineItems() {
|
||||
return this.availableLineItems ?? [];
|
||||
},
|
||||
servicePackageAnswers() {
|
||||
if (!this.cmsWidgetName) return {};
|
||||
const cmsAnswersContent = [
|
||||
{
|
||||
Name: 'TierOne',
|
||||
cmsWidgetName: 'EconomyServicePackage'
|
||||
},
|
||||
{
|
||||
Name: 'TierTwo',
|
||||
cmsWidgetName: 'StandardServicePackage'
|
||||
},
|
||||
{
|
||||
Name: 'TierThree',
|
||||
cmsWidgetName: 'PremiumServicePackage'
|
||||
}
|
||||
];
|
||||
//if cms content has not yet loaded, skip
|
||||
if (this.getCmsContent(cmsAnswersContent[0].cmsWidgetName, 'HeaderText') == '') {
|
||||
return {};
|
||||
}
|
||||
const modifiedAnswers = cmsAnswersContent.map((answer) => ({
|
||||
value: answer.Name,
|
||||
buttonLabel: this.getHeaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.cmsWidgetName),
|
||||
buttonBodyCopy: this.getBodyTextFromCms(answer.cmsWidgetName),
|
||||
buttonAuxiliaryCopy: this.getPackagePriceString(answer.Name),
|
||||
buttonFooterCopy: this.getFooterTextFromCms(answer.cmsWidgetName)
|
||||
}
|
||||
));
|
||||
return modifiedAnswers;
|
||||
},
|
||||
frontWipersApplicableForTierTwo() {
|
||||
const store = useMainStore();
|
||||
const frontWipersAreAvailable = this.lineItemsContainsPartType(
|
||||
partTypeStrings.FRONT_WIPER
|
||||
);
|
||||
const isRepair = store.order.damage.isRepair;
|
||||
const glassToReplaceContainsWindshield = this.glassToReplaceContainsGlassLocation(
|
||||
glassLocations.WINDSHIELD
|
||||
);
|
||||
if (frontWipersAreAvailable) {
|
||||
if (isRepair) {
|
||||
return true;
|
||||
} else {
|
||||
if (glassToReplaceContainsWindshield) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
rearWiperApplicableForTierTwo() {
|
||||
const rearWiperIsAvailable = this.lineItemsContainsPartType(partTypeStrings.REAR_WIPER);
|
||||
return (
|
||||
this.glassToReplaceContainsGlassLocation(glassLocations.REAR) &&
|
||||
rearWiperIsAvailable
|
||||
);
|
||||
},
|
||||
frontWipersApplicableForTierThree() {
|
||||
const frontWipersAreAvailable = this.lineItemsContainsPartType(partTypeStrings.FRONT_WIPER);
|
||||
return frontWipersAreAvailable;
|
||||
},
|
||||
rearWiperApplicableForTierThree() {
|
||||
const rearWiperIsAvailable = this.lineItemsContainsPartType(partTypeStrings.REAR_WIPER);
|
||||
const frontWipersAreAvailable = this.lineItemsContainsPartType(partTypeStrings.FRONT_WIPER);
|
||||
return (
|
||||
rearWiperIsAvailable &&
|
||||
(this.glassToReplaceContainsGlassLocation(glassLocations.REAR) ||
|
||||
!frontWipersAreAvailable)
|
||||
);
|
||||
},
|
||||
rainDefenseApplicableForTierThree() {
|
||||
if (
|
||||
this.rearWiperApplicableForTierTwo &&
|
||||
!this.frontWipersApplicableForTierTwo &&
|
||||
this.frontWipersApplicableForTierThree
|
||||
) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
shouldDisplayTierTwoPackage() {
|
||||
return this.frontWipersApplicableForTierTwo || this.rearWiperApplicableForTierTwo;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
processIfStatements,
|
||||
getHeaderTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, 'HeaderText');
|
||||
},
|
||||
getSubheaderTextFromCms(cmsWidgetName) {
|
||||
return this.getCmsContent(cmsWidgetName, 'SubheaderText');
|
||||
},
|
||||
getBodyTextFromCms(cmsWidgetName) {
|
||||
const bodyText = this.getCmsContent(cmsWidgetName, "BodyText");
|
||||
return this.processIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
||||
},
|
||||
getFooterTextFromCms(cmsWidgetName) {
|
||||
const footerText = this.getCmsContent(cmsWidgetName, "FooterText");
|
||||
return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
|
||||
},
|
||||
getPackagePriceString(packageName) {
|
||||
const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2);
|
||||
return '$' + formattedPriceFloat;
|
||||
},
|
||||
getPackagePrice(packageName) {
|
||||
let priceFloat = 0;
|
||||
if (packageName === packageNames.TIER_TWO) {
|
||||
priceFloat += this.getTierTwoPackageVapsPrice();
|
||||
} else if (packageName === packageNames.TIER_THREE) {
|
||||
priceFloat += this.getTierThreePackageVapsPrice();
|
||||
}
|
||||
return priceFloat;
|
||||
},
|
||||
getTierTwoPackageVapsPrice() {
|
||||
let vapsPrice = 0;
|
||||
const priceFrontWipers = this.frontWipersApplicableForTierTwo;
|
||||
const priceRearWipers = this.rearWiperApplicableForTierTwo;
|
||||
this.nullSafeAvailableLineItems.forEach((item) => {
|
||||
if (
|
||||
(priceFrontWipers &&
|
||||
item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) ||
|
||||
(priceRearWipers && item.partType.toUpperCase() === partTypeStrings.REAR_WIPER)
|
||||
) {
|
||||
vapsPrice += this.getTotalLineItemPrice(item);
|
||||
}
|
||||
});
|
||||
return vapsPrice;
|
||||
},
|
||||
getTierThreePackageVapsPrice() {
|
||||
let vapsPrice = 0;
|
||||
const priceFrontWipers = this.frontWipersApplicableForTierThree;
|
||||
const priceRearWipers = this.rearWiperApplicableForTierThree;
|
||||
const priceRainDefense = this.rainDefenseApplicableForTierThree;
|
||||
this.nullSafeAvailableLineItems.forEach((item) => {
|
||||
if (
|
||||
(priceFrontWipers &&
|
||||
item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) ||
|
||||
(priceRearWipers &&
|
||||
item.partType.toUpperCase() === partTypeStrings.REAR_WIPER) ||
|
||||
(priceRainDefense &&
|
||||
item.partType.toUpperCase() === partTypeStrings.RAIN_DEFENSE)
|
||||
) {
|
||||
vapsPrice += this.getTotalLineItemPrice(item);
|
||||
}
|
||||
});
|
||||
return vapsPrice;
|
||||
},
|
||||
selectDefaultPackage() {
|
||||
const store = useMainStore();
|
||||
const vapsFromStore = store.lineItems.vaps;
|
||||
let lowestTierForPackage = packageNames.TIER_ONE;
|
||||
if (vapsFromStore?.length > 0) {
|
||||
vapsFromStore.every((vapsItem) => {
|
||||
let lowestTierForThisItem = this.getLowestTierForThisItem(vapsItem);
|
||||
if (lowestTierForThisItem === packageNames.TIER_THREE) {
|
||||
lowestTierForPackage = packageNames.TIER_THREE;
|
||||
return false;
|
||||
} else if (lowestTierForThisItem === packageNames.TIER_TWO) {
|
||||
lowestTierForPackage = packageNames.TIER_TWO;
|
||||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.selectedPackageName = lowestTierForPackage;
|
||||
},
|
||||
allGlassPartsAndSupportingItemsHavePrices(lineItems) {
|
||||
if (lineItems?.glassParts) {
|
||||
for (let i = 0; i < lineItems.glassParts.length; i++) {
|
||||
if (this.priceIsNullOrZero(lineItems.glassParts[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineItems?.supportingItems) {
|
||||
for (let i = 0; i < lineItems.supportingItems.length; i++) {
|
||||
if (this.priceIsNullOrZero(lineItems.supportingItems[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
priceIsNullOrZero(lineItem) {
|
||||
return (
|
||||
(lineItem.kitPrice == null || lineItem.kitPrice == 0) &&
|
||||
(lineItem.laborAmount == null || lineItem.laborAmount == 0) &&
|
||||
(lineItem.sellingPrice == null || lineItem.sellingPrice == 0)
|
||||
);
|
||||
},
|
||||
getLowestTierForThisItem(vapsItem) {
|
||||
let lowestTierForThisItem = null;
|
||||
switch (vapsItem.partType) {
|
||||
case partTypeStrings.FRONT_WIPER:
|
||||
if (this.frontWipersApplicableForTierThree) {
|
||||
lowestTierForThisItem = packageNames.TIER_THREE;
|
||||
}
|
||||
if (this.frontWipersApplicableForTierTwo) {
|
||||
lowestTierForThisItem = packageNames.TIER_TWO;
|
||||
}
|
||||
break;
|
||||
case partTypeStrings.REAR_WIPER:
|
||||
if (this.rearWiperApplicableForTierThree) {
|
||||
lowestTierForThisItem = packageNames.TIER_THREE;
|
||||
}
|
||||
if (this.rearWiperApplicableForTierTwo) {
|
||||
lowestTierForThisItem = packageNames.TIER_TWO;
|
||||
}
|
||||
break;
|
||||
case partTypeStrings.RAIN_DEFENSE:
|
||||
if (this.rainDefenseApplicableForTierThree) {
|
||||
lowestTierForThisItem = packageNames.TIER_THREE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return lowestTierForThisItem;
|
||||
},
|
||||
getVapsLineItemsForSelectedPackage(packageName) {
|
||||
const vapsLineItemsForSelectedPackage = [];
|
||||
if (packageName === packageNames.TIER_TWO) {
|
||||
if (this.frontWipersApplicableForTierTwo) {
|
||||
vapsLineItemsForSelectedPackage.push(
|
||||
...this.getLineItemsContainingPartType(partTypeStrings.FRONT_WIPER)
|
||||
);
|
||||
}
|
||||
if (this.rearWiperApplicableForTierTwo) {
|
||||
vapsLineItemsForSelectedPackage.push(
|
||||
...this.getLineItemsContainingPartType(partTypeStrings.REAR_WIPER)
|
||||
);
|
||||
}
|
||||
} else if (packageName === packageNames.TIER_THREE) {
|
||||
if (this.frontWipersApplicableForTierThree) {
|
||||
vapsLineItemsForSelectedPackage.push(
|
||||
...this.getLineItemsContainingPartType(partTypeStrings.FRONT_WIPER)
|
||||
);
|
||||
}
|
||||
if (this.rearWiperApplicableForTierThree) {
|
||||
vapsLineItemsForSelectedPackage.push(
|
||||
...this.getLineItemsContainingPartType(partTypeStrings.REAR_WIPER)
|
||||
);
|
||||
}
|
||||
if (this.rainDefenseApplicableForTierThree) {
|
||||
vapsLineItemsForSelectedPackage.push(
|
||||
...this.getLineItemsContainingPartType(partTypeStrings.RAIN_DEFENSE)
|
||||
);
|
||||
}
|
||||
}
|
||||
return vapsLineItemsForSelectedPackage;
|
||||
},
|
||||
getCustomValueFromString(str) {
|
||||
switch (str) {
|
||||
case 'isRecalibrationOnOrder':
|
||||
return this.isRecalibrationOnOrder;
|
||||
case 'frontWipersApplicableForTierTwo':
|
||||
return this.frontWipersApplicableForTierTwo;
|
||||
case 'rearWiperApplicableForTierTwo':
|
||||
return this.rearWiperApplicableForTierTwo;
|
||||
case 'frontWipersApplicableForTierThree':
|
||||
return this.frontWipersApplicableForTierThree;
|
||||
case 'rearWiperApplicableForTierThree':
|
||||
return this.rearWiperApplicableForTierThree;
|
||||
case 'rainDefenseApplicableForTierThree':
|
||||
return this.rainDefenseApplicableForTierThree;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
},
|
||||
getLineItemsContainingPartType(partType) {
|
||||
const partTypeMatches = this.nullSafeAvailableLineItems.filter(
|
||||
(lineItem) => lineItem.partType.toUpperCase() === partType
|
||||
);
|
||||
return partTypeMatches;
|
||||
},
|
||||
lineItemsContainsPartType(partType) {
|
||||
const partTypeMatches = this.getLineItemsContainingPartType(partType);
|
||||
return !!partTypeMatches.length;
|
||||
},
|
||||
glassToReplaceContainsGlassLocation(glassLocation) {
|
||||
const store = useMainStore();
|
||||
const glassLocationMatches =
|
||||
store.order.damage.glassToReplace?.filter(
|
||||
(glassToReplace) => glassToReplace.glassLocation === glassLocation
|
||||
) ?? [];
|
||||
return !!glassLocationMatches.length;
|
||||
},
|
||||
getTotalLineItemPrice(lineItem) {
|
||||
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
import { mount } from "@vue/test-utils"
|
||||
import servicePackageRadio from "./service-package-radio"
|
||||
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin"
|
||||
|
||||
describe("service-package-radio.vue", () => {
|
||||
it("Should include buttonLabel in html", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const outputHtml = wrapper.html()
|
||||
|
||||
// Assert
|
||||
expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabel"]))
|
||||
})
|
||||
|
||||
it("Should include buttonLabelAuxillaryCopy in html", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const outputHtml = wrapper.html()
|
||||
|
||||
// Assert
|
||||
expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelAuxillaryCopy"]))
|
||||
})
|
||||
|
||||
it("Should include buttonLabelSubCopy in html", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const outputHtml = wrapper.html()
|
||||
|
||||
// Assert
|
||||
expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonLabelSubCopy"]))
|
||||
})
|
||||
it("Should include buttonFooterCopy in html", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const outputHtml = wrapper.html()
|
||||
|
||||
// Assert
|
||||
expect(outputHtml).toEqual(expect.stringContaining(mockProps["buttonFooterCopy"]))
|
||||
})
|
||||
it("Should get 5 strings from getArrayOfListItemsFromRawCmsCopy when provided with a dashed (x5) buttonBodyCopy", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
// Act
|
||||
const results = wrapper.vm.getArrayOfListItemsFromRawCmsCopy(wrapper.vm.buttonBodyCopy)
|
||||
|
||||
// Assert
|
||||
expect(results.length).toBe(5)
|
||||
})
|
||||
it("Should get strings from getArrayOfListItemsFromRawCmsCopy without dashes when provided with a dashed buttonBodyCopy", async () => {
|
||||
// Arrange
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: mockProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const results = wrapper.vm.getArrayOfListItemsFromRawCmsCopy(wrapper.vm.buttonBodyCopy)
|
||||
|
||||
// Assert
|
||||
const fileredResults = results.filter((result) => {
|
||||
return result.includes(" -");
|
||||
})
|
||||
expect(fileredResults.length).toBe(0)
|
||||
})
|
||||
it("Should get 5 strings from getArrayOfListItemsFromRawCmsCopy when buttonBodyCopy has 6 total dashes, but one is empty ", async () => {
|
||||
// Arrange
|
||||
const moddedProps = mockProps
|
||||
moddedProps["buttonBodyCopy"] = "- buttonBodyCopy test copy - 2 - 3 - 4 - 5 -"
|
||||
let { wrapper } = setupMocks({
|
||||
mountOptionsMockData: {
|
||||
propsData: moddedProps,
|
||||
},
|
||||
})
|
||||
|
||||
// Act
|
||||
const results = wrapper.vm.getArrayOfListItemsFromRawCmsCopy(wrapper.vm.buttonBodyCopy)
|
||||
|
||||
// Assert
|
||||
expect(results.length).toBe(5)
|
||||
})
|
||||
})
|
||||
|
||||
const mockProps = {
|
||||
buttonLabel: 'buttonLabel test copy',
|
||||
buttonLabelAuxillaryCopy: 'buttonLabelAuxillaryCopy test copy',
|
||||
buttonLabelSubCopy: 'buttonLabelSubCopy test copy',
|
||||
buttonBodyCopy: '- buttonBodyCopy test copy - 2 - 3 - 4 - 5',
|
||||
buttonFooterCopy: 'buttonFooterCopy test copy'
|
||||
}
|
||||
|
||||
function setupMocks({ mountOptionsMockData = {} }) {
|
||||
const wrapper = mount(servicePackageRadio, {
|
||||
...mountOptionsMockData,
|
||||
mixins: [inputButtonWrapperMixin]
|
||||
})
|
||||
|
||||
return { wrapper }
|
||||
}
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
<template>
|
||||
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
|
||||
<div class="package-label mb-4"
|
||||
:class="[this.buttonLabelSubCopy ? 'has-subheader' : '']"
|
||||
for="testradio">
|
||||
<div class="package-specs">
|
||||
<p class="m-0">
|
||||
<span v-html="this.buttonLabel"></span>
|
||||
<span class="pricing-info" v-html="this.buttonAuxiliaryCopy"></span>
|
||||
</p>
|
||||
<p class="sub-label m-0"
|
||||
v-if="this.buttonLabelSubCopy"
|
||||
v-html="this.buttonLabelSubCopy"></p>
|
||||
<div>
|
||||
<ul >
|
||||
<li v-for="listItem in this.arrayOfListItemsFromBodyText" :key="listItem" class="mb-0">
|
||||
<!-- no textLink -->
|
||||
<span v-if="!doesCopyContainTextLink(listItem)"
|
||||
v-html="listItem"></span>
|
||||
<!-- with textLink -->
|
||||
<template v-else
|
||||
v-for="copy in splitCopyOnCMSPlaceHolder(listItem)"
|
||||
:key="copy">
|
||||
<span v-if="!doesCopyContainTextLink(copy)" v-html="copy"></span>
|
||||
<span v-else>
|
||||
<textLink linkType="text"
|
||||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
href="#!"
|
||||
@click-event="
|
||||
$emit('buttonEvent', {
|
||||
eventName: 'openModal',
|
||||
args: getRouterLinkRouteFromCopy(copy),
|
||||
})
|
||||
"
|
||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
||||
aria-label="Modal window" />
|
||||
</span>
|
||||
</template>
|
||||
</li>
|
||||
</ul>
|
||||
<!-- End of body text parsing -->
|
||||
<!--ms-n6-->
|
||||
<div class="package-footer fw-bold caption mt-4 ml-n4 mr-3"
|
||||
v-if="this.buttonFooterCopy"
|
||||
v-html="this.buttonFooterCopy"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</baseInputButton>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import baseInputButton from '@/digital-components/base-input-button/base-input-button';
|
||||
import textLink from '@/ux-components/text-link/text-link';
|
||||
import inputButtonWrapperMixin from '@/mixins/input-button-wrapper-mixin';
|
||||
import {
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
getRouterLinkRouteFromCopy,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
doesCopyContainTextLink,
|
||||
} from '@/helpers/cms-content-helper';
|
||||
export default {
|
||||
name: 'servicePackageRadio',
|
||||
mixins: [inputButtonWrapperMixin],
|
||||
components: {
|
||||
baseInputButton,
|
||||
textLink,
|
||||
},
|
||||
computed: {
|
||||
arrayOfListItemsFromBodyText() {
|
||||
return this.getArrayOfListItemsFromRawCmsCopy(this.buttonBodyCopy);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
getRouterLinkRouteFromCopy,
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
doesCopyContainTextLink,
|
||||
stripUlTagFromCopy(copy) {
|
||||
return copy;
|
||||
},
|
||||
getArrayOfListItemsFromRawCmsCopy(copy) {
|
||||
if (copy) {
|
||||
return copy
|
||||
.split('- ') //At some point we'll want a better delimiter
|
||||
.filter((lineItem) => lineItem);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ml-n4 {
|
||||
margin-left: -$spacer * 2;
|
||||
}
|
||||
.mr-3 {
|
||||
margin-right: $spacer * 1.5;
|
||||
}
|
||||
.package-main {
|
||||
.package-wrapper {
|
||||
margin: 0.5rem 0;
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: -9999px;
|
||||
|
||||
+ .package-label {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
padding: 1rem;
|
||||
border: 1px solid $gray-300;
|
||||
box-shadow: 0px 4px 8px -4px rgba(0, 0, 0, 0.15), 0px 4px 24px -8px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0.5rem;
|
||||
overflow: hidden;
|
||||
min-height: 60px;
|
||||
|
||||
&.has-subheader {
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: relative;
|
||||
top: 5px;
|
||||
margin-right: 1rem;
|
||||
border-radius: 50%;
|
||||
border: 1px solid $gray-500;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
min-width: 16px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 19px;
|
||||
top: 24px;
|
||||
border-radius: 50%;
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
min-width: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
+ .package-label {
|
||||
&:before {
|
||||
border: 1px solid #8e9292;
|
||||
box-shadow: 0px 0px 0px 4px #9fcee6, 0px 1px 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:checked {
|
||||
+ .package-label {
|
||||
.package-specs {
|
||||
max-height: 1000px;
|
||||
}
|
||||
}
|
||||
|
||||
+ .package-label {
|
||||
.package-specs {
|
||||
.hide-when-closed {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ .package-label {
|
||||
background-color: $blue-100;
|
||||
border: 1px solid $blue;
|
||||
max-height: 500px;
|
||||
}
|
||||
|
||||
+ .package-label {
|
||||
&:before {
|
||||
box-shadow: 0px 0px 0px 1px $blue;
|
||||
}
|
||||
}
|
||||
|
||||
+ .package-label {
|
||||
&:after {
|
||||
background: $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
+ .package-label {
|
||||
&:before {
|
||||
border: 2px solid $blue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.package-footer {
|
||||
color: $red;
|
||||
}
|
||||
|
||||
.package-specs {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
max-height: 1000px;
|
||||
transition: all 0.5s ease;
|
||||
|
||||
p {
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
span {
|
||||
&.pricing-info {
|
||||
color: $green;
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.sub-label {
|
||||
color: $green;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
margin: 1rem 0 0 -.6rem;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.714;
|
||||
|
||||
a {
|
||||
line-height: 1.714;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes slideaway {
|
||||
from {
|
||||
display: block;
|
||||
}
|
||||
|
||||
to {
|
||||
transform: translateY(40px);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
150
src/layouts/service-packages/service-packages.vue
Normal file
150
src/layouts/service-packages/service-packages.vue
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<div class="page-container-grouped-styles">
|
||||
<loadingModal ref="loadingModal" />
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget"
|
||||
justification="left"
|
||||
issContainingPage="service-packages"/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<servicePackageQuestion ref="servicePackage"
|
||||
cmsWidgetName="ServicePackage"
|
||||
groupName="ServicePackageQuestion"
|
||||
:availableLineItems="availableLineItems"
|
||||
@vapsItemsSelected="vapsItemsSelectedAction"
|
||||
v-on="{ 'buttonEvent.openModal': openModalAction }"
|
||||
validationRules="option-required"
|
||||
isRequired />
|
||||
<textBlock cmsWidgetName="PriceDisclaimerWidget"
|
||||
justifyText="left"
|
||||
typeStyle="caption"
|
||||
style="margin-bottom: 6rem;"
|
||||
class="mt-2 mx-6" />
|
||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
||||
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
<siteFooter cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import siteHeader from '@/iss-components/site-header/site-header';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import servicePackageQuestion from './service-package-question/service-package-question';
|
||||
import textBlock from '@/digital-components/text-block/text-block';
|
||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal';
|
||||
import loadingModal from '@/iss-components/loading-modal/loading-modal.vue';
|
||||
import { settleAllPromises } from '@/helpers/layout-helper';
|
||||
import { useMainStore } from "@/store";
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import { errorMessages } from '@/constants/error-messages';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
|
||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'service-packages',
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const store = useMainStore();
|
||||
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
const wipersPromise = await store.getWipers();
|
||||
const rainDefensePromise = await store.getRainDefense();
|
||||
const supportingItemsPromise = await store.getSupportingItems();
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'wipers',
|
||||
promise: wipersPromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'rainDefense',
|
||||
promise: rainDefensePromise,
|
||||
},
|
||||
{
|
||||
resultKey: 'supportingItems',
|
||||
promise: supportingItemsPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
const clonedGlassParts = store.order.lineItems.glassParts
|
||||
? JSON.parse(JSON.stringify(store.order.lineItems.glassParts))
|
||||
: [];
|
||||
const availableLineItems = [
|
||||
resultMap.rainDefense,
|
||||
...resultMap.supportingItems,
|
||||
...resultMap.wipers,
|
||||
...clonedGlassParts,
|
||||
];
|
||||
|
||||
const pricingResults = await store.getPriceOrderItems(availableLineItems);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.pricedGlassParts = clonedGlassParts;
|
||||
vm.supportingItems = resultMap.supportingItems;
|
||||
vm.availableLineItems = pricingResults;
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedVaps: null,
|
||||
availableLineItems: null,
|
||||
supportingItems: null,
|
||||
pricedGlassParts: null
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openModalAction(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
arePagePrerequisitesValid() {
|
||||
const store = useMainStore();
|
||||
return (
|
||||
store.order.serviceLocation.zipCode &&
|
||||
store.order.serviceLocation.zipCodeCtu &&
|
||||
(store.order.damage.isRepair ||
|
||||
(store.order.lineItems?.glassParts != null &&
|
||||
store.order.lineItems.glassParts.length > 0)) &&
|
||||
store.order.referralNumber?.length !== 6
|
||||
);
|
||||
},
|
||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||
this.selectedVaps = vapsItemsSelected;
|
||||
},
|
||||
backButtonAction() {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
//TODO: save items
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
siteSubHeader,
|
||||
Form, /* eslint-disable-line */
|
||||
textBlock,
|
||||
servicePackageQuestion,
|
||||
loadingModal,
|
||||
contentGroupModal
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -22,6 +22,12 @@ const vueApp = createApp(App);
|
|||
*/
|
||||
vueApp.config.unwrapInjectedRef = true;
|
||||
|
||||
vueApp.config.compilerOptions.isCustomElement = (tag) => {
|
||||
return (tag === 'siteSubHeader' ||
|
||||
tag === 'ServicePackages' ||
|
||||
tag === 'servicePackageQuestion');
|
||||
}
|
||||
|
||||
// Pinia
|
||||
const pinia = createPinia();
|
||||
vueApp.use(pinia);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default {
|
|||
buttonLabel: [Number, String],
|
||||
buttonLabelSubCopy: String,
|
||||
buttonBodyCopy: String,
|
||||
buttonAuxillaryCopy: String,
|
||||
buttonAuxiliaryCopy: String,
|
||||
buttonFooterCopy: String,
|
||||
buttonImage: String,
|
||||
buttonImageId: String,
|
||||
|
|
|
|||
|
|
@ -285,8 +285,7 @@ describe("vehicle-questions-mixin", () => {
|
|||
const testCases = [
|
||||
[issPageValues.PART_QUESTIONS, issPageValues.VEHICLE_PARTS, true],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.VEHICLE_PARTS, false],
|
||||
[issPageValues.QUOTE, issPageValues.VEHICLE_PARTS, false],
|
||||
[issPageValues.QUOTE, issPageValues.QUOTE, false],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.REVEAL, false],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.PART_QUESTIONS, false],
|
||||
[issPageValues.PART_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, true],
|
||||
[issPageValues.MOLDING_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, true],
|
||||
|
|
@ -310,8 +309,7 @@ describe("vehicle-questions-mixin", () => {
|
|||
const testCases = [
|
||||
[issPageValues.PART_QUESTIONS, issPageValues.VEHICLE_PARTS, false],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.VEHICLE_PARTS, false],
|
||||
[issPageValues.QUOTE, issPageValues.VEHICLE_PARTS, true],
|
||||
[issPageValues.QUOTE, issPageValues.QUOTE, false],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.SERVICE_LOCATION, true],
|
||||
[issPageValues.VEHICLE_PARTS, issPageValues.PART_QUESTIONS, true],
|
||||
[issPageValues.PART_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false],
|
||||
[issPageValues.MOLDING_QUESTIONS, issPageValues.CAPABILITY_QUESTIONS, false],
|
||||
|
|
@ -2079,188 +2077,9 @@ describe("vehicle-questions-mixin", () => {
|
|||
);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO KO UNSKIP FOR QUOTE MVP
|
||||
describe.skip("should go to quote page", () => {
|
||||
test("single glass location selected, has no part questions and has one part => go to heritage funnel", async () => {
|
||||
// Arrange
|
||||
const partsOrQuestions = [
|
||||
{
|
||||
glassName: "Single",
|
||||
glassLocation: "Windshield",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FW04186GTYN",
|
||||
description: "solar, soundproofing, lane keep assist",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: true,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: [
|
||||
{
|
||||
partNumber: "GGG 3563 KIT",
|
||||
partType: "MOULDING",
|
||||
description: "Kit, Top & Sides ",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions,
|
||||
});
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
{ query: { issPage: "vin-lookup" } }
|
||||
);
|
||||
});
|
||||
|
||||
test("multiple glass locations selected, each has one part and no part questions => go to heritage funnel", async () => {
|
||||
// Arrange
|
||||
const partsOrQuestions = [
|
||||
{
|
||||
glassName: "Single",
|
||||
glassLocation: "Windshield",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FW04186GTYN",
|
||||
description: "solar, soundproofing, lane keep assist",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: true,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: [
|
||||
{
|
||||
partNumber: "GGG 3563 KIT",
|
||||
partType: "MOULDING",
|
||||
description: "Kit, Top & Sides ",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
{
|
||||
glassName: "Back",
|
||||
glassLocation: "Driver",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FD25457GTYN",
|
||||
description: "solar, driver side, rear",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
{
|
||||
glassName: "Front",
|
||||
glassLocation: "Driver",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FD27090GTYN",
|
||||
description: "solar, driver side, front",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
{
|
||||
glassName: "Vent",
|
||||
glassLocation: "Driver",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FV25459GTNN",
|
||||
description: "solar, driver side, rear",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
{
|
||||
glassName: "Stationary",
|
||||
glassLocation: "Rear",
|
||||
parts: [
|
||||
{
|
||||
partNumber: "FB25460GTYN",
|
||||
description: "heated glass, solar",
|
||||
color: "Green Tint",
|
||||
requiresRecalibration: false,
|
||||
requiresCapabilityQuestions: false,
|
||||
childParts: null,
|
||||
},
|
||||
],
|
||||
partQuestions: null,
|
||||
},
|
||||
];
|
||||
|
||||
const { wrapper } = setupMocks({
|
||||
partsOrQuestions: partsOrQuestions,
|
||||
});
|
||||
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateForward(partsOrQuestions);
|
||||
|
||||
// Assert
|
||||
expect(useMainStore.updateGlassParts).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
{ query: { issPage: "vin-lookup" } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("navigateBack", () => {
|
||||
|
||||
test("current page is quote and there are capability questions => go to capability questions", () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ issPage: issPageValues.QUOTE });
|
||||
wrapper.vm.hasCapabilityQuestions = jest.fn().mockReturnValue(true);
|
||||
|
||||
// Act
|
||||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
|
||||
{ query: { issPage: issPageValues.QUOTE } }
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is quote and there are part questions and molding questions => go to molding questions", () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ issPage: issPageValues.QUOTE });
|
||||
wrapper.vm.hasPartQuestions = jest.fn().mockReturnValue(true);
|
||||
wrapper.vm.hasChildPartQuestions = jest.fn().mockReturnValue(true);
|
||||
|
||||
// Act
|
||||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
{ query: { issPage: issPageValues.QUOTE } }
|
||||
);
|
||||
});
|
||||
|
||||
test("current page is molding questions and there are part questions, multiple parts to choose, and capability questions => go to vehicle-parts", () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ issPage: issPageValues.MOLDING_QUESTIONS });
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ const routes = [
|
|||
console.log(error);
|
||||
GoToStartOn404(next);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}];
|
||||
|
||||
|
|
@ -77,10 +78,10 @@ const router = createRouter({
|
|||
scrollBehavior(to, from, savedPosition) {
|
||||
// always scroll to top
|
||||
return { top: 0 }
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
router.afterEach((to, from) => { /*eslint-disable-line*/
|
||||
|
||||
const store = useMainStore();
|
||||
// Update lastPageVisited in the store
|
||||
|
|
@ -110,12 +111,12 @@ async function GetRouteInfoFromPageName(pageName) {
|
|||
routeData.push({
|
||||
path: "/",
|
||||
name: `${key}`,
|
||||
component: lazyLoadComponent(jsonFromResponse[key].LayoutName),
|
||||
component: lazyLoadComponent(jsonFromResponse[key].LayoutName)
|
||||
});
|
||||
});
|
||||
|
||||
return routeData;
|
||||
};
|
||||
}
|
||||
|
||||
//Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example.
|
||||
router.overrideNavigation = (
|
||||
|
|
@ -145,7 +146,7 @@ router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
}
|
||||
|
||||
// Navigate to the next route, depending on the scenario.
|
||||
function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) {
|
||||
function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) { /*eslint-disable-line*/
|
||||
if (!scenario) {
|
||||
console.error("No scenario provided. Please review the routing table.");
|
||||
return;
|
||||
|
|
@ -174,7 +175,7 @@ function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
router.push({
|
||||
name: "root",
|
||||
query: Object.assign(optionalQuery, {
|
||||
issPage: matchingScenarioMap.destinationIssPageValue,
|
||||
issPage: matchingScenarioMap.destinationIssPageValue
|
||||
}),
|
||||
params: optionalParams
|
||||
});
|
||||
|
|
@ -186,8 +187,8 @@ function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
// Navigate to an external url.
|
||||
function navigateToUrl(url, optionalQuery = {}) {
|
||||
// possibly show some loading screen in the future here.
|
||||
let externalUrl = new URL(url);
|
||||
|
||||
const externalUrl = new URL(url);
|
||||
|
||||
for (const queryKey in optionalQuery) {
|
||||
externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]);
|
||||
}
|
||||
|
|
@ -223,7 +224,7 @@ function GoToStartOn404(next) {
|
|||
router.addRoute({
|
||||
path: "/",
|
||||
name: errorPageName,
|
||||
component: lazyLoadComponent(errorPageName),
|
||||
component: lazyLoadComponent(errorPageName)
|
||||
});
|
||||
|
||||
// Put item on the bus
|
||||
|
|
@ -234,13 +235,13 @@ function GoToStartOn404(next) {
|
|||
isDismissible: true,
|
||||
messageCopy: "You can get a quote by starting on this page.",
|
||||
messageHeadline: "We're sorry, something went wrong.",
|
||||
type: globalEventTypes.Danger,
|
||||
type: globalEventTypes.Danger
|
||||
}
|
||||
);
|
||||
|
||||
next({
|
||||
name: errorPageName,
|
||||
query: {issPage: errorPageName },
|
||||
query: {issPage: errorPageName }
|
||||
});
|
||||
|
||||
};
|
||||
|
|
@ -253,14 +254,14 @@ async function runExperiments(nextPage) {
|
|||
await store.runExperimentsForTrigger({
|
||||
userId: getDeviceIdValue(),
|
||||
triggerEvent: experimentTriggers.SITE_ENTRY,
|
||||
triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE,
|
||||
triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE
|
||||
});
|
||||
}
|
||||
|
||||
await store.runExperimentsForTrigger({
|
||||
userId: getDeviceIdValue(),
|
||||
triggerEvent: experimentTriggers.PAGE_ENTRY,
|
||||
triggerValue: nextPage,
|
||||
triggerValue: nextPage
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,31 +1,28 @@
|
|||
export const issPageValues = {
|
||||
ENTRY_PAGE: "entry-page",
|
||||
WELCOME_PAGE: "welcome-page",
|
||||
POLICY_HOLDER_DETAILS: "policy-holder-details",
|
||||
VEHICLE_MAKE: "vehicle-make",
|
||||
VEHICLE_YEAR: "vehicle-year",
|
||||
VEHICLE_MODEL: "vehicle-model",
|
||||
VEHICLE_STYLE: "vehicle-style",
|
||||
VEHICLE_DAMAGE: "vehicle-damage",
|
||||
VEHICLE_LOOKUP: "vehicle-lookup",
|
||||
ADDRESS_LOOKUP: "address-lookup",
|
||||
ADDRESS_VEHICLES: "address-vehicles",
|
||||
LICENSE_PLATE_LOOKUP: "license-plate-lookup",
|
||||
VIN_LOOKUP: "vin-lookup",
|
||||
VEHICLE_PARTS: "vehicle-parts",
|
||||
PART_QUESTIONS: "part-questions",
|
||||
MOLDING_QUESTIONS: "molding-questions",
|
||||
CAPABILITY_QUESTIONS: "capability-questions",
|
||||
COVERAGE_STATEMENT: "coverage-statement",
|
||||
PROVIDER_PREFERENCE: "provider-preference",
|
||||
SERVICE_LOCATION: "service-location",
|
||||
SCHEDULE_PAGE: "schedule-page",
|
||||
CONTACT_DETAILS: "contact-details",
|
||||
PAYMENT_PAGE: "payment-page",
|
||||
REVEAL: "reveal",
|
||||
ESTIMATE: "estimate",
|
||||
ADDRESS_VEHICLES: "address-vehicles",
|
||||
QUOTE: "quote",
|
||||
HERITAGE: "heritage",
|
||||
ENTRY_PAGE: 'entry-page',
|
||||
WELCOME_PAGE: 'welcome-page',
|
||||
|
||||
ADDRESS_LOOKUP: 'address-lookup',
|
||||
ADDRESS_VEHICLES: 'address-vehicles',
|
||||
CAPABILITY_QUESTIONS: 'capability-questions',
|
||||
ESTIMATE: 'estimate',
|
||||
COVERAGE_STATEMENT: 'coverage-statement',
|
||||
LICENSE_PLATE_LOOKUP: 'license-plate-lookup',
|
||||
MOLDING_QUESTIONS: 'molding-questions',
|
||||
PART_QUESTIONS: 'part-questions',
|
||||
POLICY_HOLDER_DETAILS: 'policy-holder-details',
|
||||
PROVIDER_PREFERENCE: 'provider-preference',
|
||||
REVEAL: 'reveal',
|
||||
REVIEW_ORDER: 'review-order',
|
||||
SERVICE_LOCATION: 'service-location',
|
||||
SERVICE_PACKAGE: 'service-package',
|
||||
VEHICLE_DAMAGE: 'vehicle-damage',
|
||||
VEHICLE_LOOKUP: 'vehicle-lookup',
|
||||
VEHICLE_MAKE: 'vehicle-make',
|
||||
VEHICLE_MODEL: 'vehicle-model',
|
||||
VEHICLE_PARTS: 'vehicle-parts',
|
||||
VEHICLE_STYLE: 'vehicle-style',
|
||||
VEHICLE_YEAR: 'vehicle-year',
|
||||
VIN_LOOKUP: 'vin-lookup'
|
||||
};
|
||||
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios";
|
||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
|
||||
// Get store from router/index.js instead of importing it here to get updated values
|
||||
const routingTable = function(store) {
|
||||
|
|
@ -14,8 +14,8 @@ const routingTable = function(store) {
|
|||
{
|
||||
scenario: navigationScenarios.SELECTED_YEAR,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MAKE
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.VEHICLE_MAKE,
|
||||
|
|
@ -27,19 +27,19 @@ const routingTable = function(store) {
|
|||
{
|
||||
scenario: navigationScenarios.SELECTED_MAKE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MODEL
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.VEHICLE_MODEL,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MAKE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MAKE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_MODEL,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_STYLE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_STYLE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -48,11 +48,11 @@ const routingTable = function(store) {
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MODEL,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_MODEL
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_STYLE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -61,298 +61,298 @@ const routingTable = function(store) {
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_STYLE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_STYLE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_VIN,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_MANUAL_VIN,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_LICENSE_PLATE,
|
||||
destinationIssPageValue: issPageValues.LICENSE_PLATE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.LICENSE_PLATE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_HOME_ADDRESS,
|
||||
destinationIssPageValue: issPageValues.ADDRESS_LOOKUP,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.ADDRESS_LOOKUP
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.VIN_LOOKUP,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.LICENSE_PLATE_LOOKUP,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.PART_QUESTIONS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.VEHICLE_PARTS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.REVEAL,
|
||||
destinationIssPageValue: issPageValues.REVEAL
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.ADDRESS_LOOKUP,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
|
||||
destinationIssPageValue: issPageValues.ADDRESS_VEHICLES,
|
||||
destinationIssPageValue: issPageValues.ADDRESS_VEHICLES
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.ADDRESS_VEHICLES,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.ADDRESS_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.ADDRESS_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.ENTRY_PAGE,
|
||||
|
|
@ -364,8 +364,8 @@ const routingTable = function(store) {
|
|||
{
|
||||
scenario: navigationScenarios.MOVE_FORWARD_ENTRY_PAGE,
|
||||
destinationIssPageValue: issPageValues.WELCOME_PAGE
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.WELCOME_PAGE,
|
||||
|
|
@ -377,8 +377,8 @@ const routingTable = function(store) {
|
|||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WELCOME_PAGE,
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.POLICY_HOLDER_DETAILS,
|
||||
|
|
@ -390,55 +390,54 @@ const routingTable = function(store) {
|
|||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_HOLDER_DETAILS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_YEAR
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VIN_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_LOOKUP
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.PART_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MULTIPLE_PARTS_TO_CHOOSE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_PARTS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.MOLDING_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.CAPABILITY_QUESTIONS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_COVERAGE_STATEMENT,
|
||||
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE,
|
||||
},
|
||||
],
|
||||
|
||||
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.PROVIDER_PREFERENCE,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE,
|
||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION,
|
||||
},
|
||||
],
|
||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.SERVICE_LOCATION,
|
||||
|
|
@ -447,40 +446,52 @@ const routingTable = function(store) {
|
|||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.PROVIDER_PREFERENCE,
|
||||
},
|
||||
|
||||
],
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.SERVICE_PACKAGES
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.SCHEDULE_PAGE,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION,
|
||||
},
|
||||
|
||||
],
|
||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.CONTACT_DETAILS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.SCHEDULE_PAGE,
|
||||
destinationIssPageValue: issPageValues.SCHEDULE_PAGE
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.SERVICE_PACKAGE,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.SERVICE_LOCATION
|
||||
},
|
||||
|
||||
],
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.REVIEW_ORDER
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
issPageValue: issPageValues.PAYMENT_PAGE,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.REVIEW_PAGE,
|
||||
},
|
||||
|
||||
],
|
||||
},
|
||||
|
||||
destinationIssPageValue: issPageValues.REVIEW_PAGE
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ const getDefaultState = () => {
|
|||
state: null,
|
||||
zipCode: null,
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
},
|
||||
lastName: null
|
||||
}
|
||||
},
|
||||
damage: {
|
||||
isRepair: null,
|
||||
|
|
@ -39,7 +39,7 @@ const getDefaultState = () => {
|
|||
glassToReplace: null,
|
||||
partQuestionAnswers: null,
|
||||
moldingQuestionAnswers: null,
|
||||
capabilityQuestionAnswers: null,
|
||||
capabilityQuestionAnswers: null
|
||||
},
|
||||
policy: {
|
||||
policyNumber: null,
|
||||
|
|
@ -47,7 +47,7 @@ const getDefaultState = () => {
|
|||
damageCause: null,
|
||||
damageState: null,
|
||||
damageCity: null,
|
||||
isDamageGlassOnly: null,
|
||||
isDamageGlassOnly: null
|
||||
},
|
||||
customer: {
|
||||
address: {
|
||||
|
|
@ -55,12 +55,12 @@ const getDefaultState = () => {
|
|||
streetAddress2: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCode: null
|
||||
},
|
||||
firstName: null,
|
||||
lastName: null,
|
||||
emailAddress: null,
|
||||
phoneNumber: null,
|
||||
phoneNumber: null
|
||||
},
|
||||
serviceLocation: {
|
||||
address: null,
|
||||
|
|
@ -78,16 +78,14 @@ const getDefaultState = () => {
|
|||
payment: {
|
||||
isInsurance: true,
|
||||
insuranceCoverage: {
|
||||
isVerified: false,
|
||||
},
|
||||
isVerified: false
|
||||
}
|
||||
},
|
||||
referralNumber: null,
|
||||
referralDate: null,
|
||||
referralDate: null
|
||||
},
|
||||
applicationUser: {
|
||||
lastPageVisited: null,
|
||||
experiments: [],
|
||||
triggeredSiteEntry: false,
|
||||
eventBus: [],
|
||||
pageData: {},
|
||||
savedSessionTimeout: getDateForSavedSessionTimeout(),
|
||||
|
|
@ -95,7 +93,7 @@ const getDefaultState = () => {
|
|||
savedSessionId: null,
|
||||
crmCustomerId: null,
|
||||
lastPageVisited: null,
|
||||
triggeredSiteEntry: false,
|
||||
triggeredSiteEntry: false
|
||||
},
|
||||
issConfig: {
|
||||
clientName: "Generic Insurance", // this is the default and will be overriden by the client's name
|
||||
|
|
@ -106,7 +104,7 @@ const getDefaultState = () => {
|
|||
isAuthenticated: false, // Indicates if user is authenticated or not.
|
||||
enableTPAFlow: false, // Indicates if the TPA flow is supported for this client.
|
||||
returnURL: null,
|
||||
returnURL2: null,
|
||||
returnURL2: null
|
||||
}
|
||||
};
|
||||
};
|
||||
|
|
@ -120,6 +118,7 @@ export const useMainStore = defineStore({
|
|||
vehicle: (state) => state.order.vehicle,
|
||||
damage: (state) => state.order.damage,
|
||||
lineItems: (state) => state.order.lineItems,
|
||||
hasAnyNonWindshieldGlassParts: (state) => !state.order.policy.isDamageGlassOnly,
|
||||
eventBusItem: (state) => ( eventCategory, eventSubCategory) => {
|
||||
|
||||
const matchedEvent = state.applicationUser.eventBus.find(
|
||||
|
|
@ -235,8 +234,8 @@ export const useMainStore = defineStore({
|
|||
licenseLastName: licenseLastName,
|
||||
licenseStreetAddress: licenseStreetAddress,
|
||||
licenseZip: licenseZip,
|
||||
licenseState: licenseState,
|
||||
},
|
||||
licenseState: licenseState
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -245,14 +244,14 @@ export const useMainStore = defineStore({
|
|||
method: endpoints.GetRouteInfo.method,
|
||||
endpoint: endpoints.GetRouteInfo.url(applicationConfig.APPLICATION_ABBREVIATION),
|
||||
payload: {
|
||||
pageName: pageName,
|
||||
pageName: pageName
|
||||
},
|
||||
});
|
||||
},
|
||||
getHomepageName() {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetHomepageInfo.method,
|
||||
endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION),
|
||||
endpoint: endpoints.GetHomepageInfo.url(applicationConfig.APPLICATION_ABBREVIATION)
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -260,7 +259,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetPageData.method,
|
||||
endpoint: endpoints.GetPageData.url(applicationConfig.APPLICATION_ABBREVIATION, pageName),
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -269,7 +268,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleYears.method,
|
||||
endpoint: endpoints.GetVehicleYears.url,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -277,7 +276,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleMakes.method,
|
||||
endpoint: endpoints.GetVehicleMakes.url + this.order.vehicle.year,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -285,7 +284,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleModels.method,
|
||||
endpoint: `${endpoints.GetVehicleModels.url}/${this.order.vehicle.year}/${this.order.vehicle.make}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -293,7 +292,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetVehicleStyles.method,
|
||||
endpoint: `${endpoints.GetVehicleStyles.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -301,7 +300,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
methods: endpoints.GetDamageOptions.method,
|
||||
endpoint: `${endpoints.GetDamageOptions.url}/${carId}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
getIsVinbyAddressPermissible(){
|
||||
|
|
@ -309,36 +308,36 @@ export const useMainStore = defineStore({
|
|||
const response = globalMethods.callHttpClient({
|
||||
method:endpoints.IsVinbyAddressPermissible.method,
|
||||
endpoint:`${endpoints.IsVinbyAddressPermissible.url}?state=${this.order.customer.address.state}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
return response;
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status,
|
||||
},
|
||||
status: responseError.status
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
async lookupVinByPlate(licensePlate, licenseState) {
|
||||
try {
|
||||
const response = await globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVinByPlate.method,
|
||||
endpoint: endpoints.LookupVinByPlate.url,
|
||||
payload: {
|
||||
licensePlate: licensePlate,
|
||||
licenseState: licenseState,
|
||||
},
|
||||
});
|
||||
try {
|
||||
const response = await globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVinByPlate.method,
|
||||
endpoint: endpoints.LookupVinByPlate.url,
|
||||
payload: {
|
||||
licensePlate: licensePlate,
|
||||
licenseState: licenseState
|
||||
}
|
||||
});
|
||||
|
||||
return response;
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status,
|
||||
},
|
||||
};
|
||||
}
|
||||
return response;
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// PartsOrQuestions API Actions
|
||||
|
|
@ -363,8 +362,8 @@ export const useMainStore = defineStore({
|
|||
carId: carId,
|
||||
glassPieces: glassArrayForPayload,
|
||||
zip: zipCode,
|
||||
vin: vin,
|
||||
},
|
||||
vin: vin
|
||||
}
|
||||
});
|
||||
|
||||
// Flatten location and name properties
|
||||
|
|
@ -398,8 +397,8 @@ export const useMainStore = defineStore({
|
|||
glassPieces: glassArrayForPayload,
|
||||
answerResults: resultsArrayForPayload,
|
||||
zip: zipCode,
|
||||
vin: vin,
|
||||
},
|
||||
vin: vin
|
||||
}
|
||||
});
|
||||
|
||||
// Flatten location and name properties
|
||||
|
|
@ -413,7 +412,7 @@ export const useMainStore = defineStore({
|
|||
getCapabilityQuestions(carId, partNumber) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetCapabilityQuestions.method,
|
||||
endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`,
|
||||
endpoint: `${endpoints.GetCapabilityQuestions.url}/${carId}/${partNumber}`
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -431,11 +430,101 @@ export const useMainStore = defineStore({
|
|||
method: endpoints.GetPartFromCapabilityAnswer.method,
|
||||
endpoint: endpoints.GetPartFromCapabilityAnswer.url,
|
||||
payload: {
|
||||
part,
|
||||
capabilityAnswerResults: capabilityQuestionAnswersForPart,
|
||||
},
|
||||
part,
|
||||
capabilityAnswerResults: capabilityQuestionAnswersForPart
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
async getWipers() {
|
||||
const carId = this.order.vehicle.carId;
|
||||
///WARNING
|
||||
///TODO: this is temp test code until serviceLocation is complete.
|
||||
//const serviceZipCode = this.order.serviceLocation.zipCode;
|
||||
const serviceZipCode = '44902';
|
||||
return globalMethods
|
||||
.callHttpClient({
|
||||
method: endpoints.GetWipers.method,
|
||||
endpoint: `${endpoints.GetWipers.url}/${carId}/${serviceZipCode}`
|
||||
})
|
||||
.catch((error) => {
|
||||
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
|
||||
console.error(error);
|
||||
return [];
|
||||
});
|
||||
},
|
||||
|
||||
async getRainDefense() {
|
||||
return globalMethods
|
||||
.callHttpClient({
|
||||
method: endpoints.GetRainDefense.method,
|
||||
endpoint: `${endpoints.GetRainDefense.url}`
|
||||
})
|
||||
.catch((error) => {
|
||||
// The wiper service sometimes returns 500s on legitimate carId/zipCode combination - return empty array instead of breaking flow
|
||||
console.error(error);
|
||||
return [];
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
async getSupportingItems() {
|
||||
const glassPartsArray = this.order.lineItems.glassParts ?? [];
|
||||
const carId = this.order.vehicle.carId;
|
||||
const isRepair = this.order.damage.isRepair;
|
||||
const numberOfChips = this.order.damage.numberOfChips;
|
||||
|
||||
return globalMethods
|
||||
.callHttpClient({
|
||||
method: endpoints.GetSupportingItems.method,
|
||||
endpoint: endpoints.GetSupportingItems.url,
|
||||
payload: {
|
||||
carId: carId,
|
||||
serviceType: isRepair ? 'Repair' : 'Replace',
|
||||
parentAccountNumber: applicationConfig.CASH_PARENT_ACCOUNT_NUMBER,
|
||||
parts: glassPartsArray,
|
||||
numberOfRepairChips: isRepair ? numberOfChips : 0
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
async getPriceOrderItems(availableLineItems) {
|
||||
let zipCodeToUse = this.order.serviceLocation.zipCode;
|
||||
let ctuToUse = this.order.serviceLocation.zipCodeCtu;
|
||||
const availableLineItemsFormattedForRequest =
|
||||
getLineItemQueryStringForPricing(availableLineItems);
|
||||
const vehicle = this.order.vehicle;
|
||||
|
||||
///WARNING
|
||||
///TODO: this is temp test code until serviceLocation is complete.
|
||||
/// and ctu is available. Also, EON may need to be implemented.
|
||||
zipCodeToUse = "44902"
|
||||
ctuToUse = "01820"
|
||||
let queryString =
|
||||
`ParentAccountNumber=${applicationConfig.CASH_PARENT_ACCOUNT_NUMBER}` +
|
||||
`&CTU=${ctuToUse}` +
|
||||
`&CarId=${vehicle.carId}` +
|
||||
`&Make=${vehicle.make}` +
|
||||
`&Model=${vehicle.model}` +
|
||||
`&Year=${vehicle.year}` +
|
||||
`&EON=0` +
|
||||
`&ZipCode=${zipCodeToUse}` +
|
||||
`${availableLineItemsFormattedForRequest}`;
|
||||
|
||||
|
||||
const response = await globalMethods
|
||||
.callHttpClient({
|
||||
method: endpoints.GetPriceOrderItems.method,
|
||||
endpoint: `${endpoints.GetPriceOrderItems.url}?${queryString}`
|
||||
}).catch((error) => {
|
||||
console.error(error);
|
||||
return [];
|
||||
});
|
||||
|
||||
availableLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems)
|
||||
|
||||
return availableLineItems;
|
||||
},
|
||||
|
||||
lookupVehicleByVin(vin) {
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.LookupVehicleByVin.method,
|
||||
|
|
@ -451,7 +540,7 @@ export const useMainStore = defineStore({
|
|||
.callHttpClient({
|
||||
methods: endpoints.GetVehicle.method,
|
||||
endpoint: `${endpoints.GetVehicle.url}/${this.order.vehicle.year}/${this.order.vehicle.make}/${this.order.vehicle.model}/${this.order.vehicle.style}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
})
|
||||
.then((response) => {
|
||||
this.updateVehicle(response.data);
|
||||
|
|
@ -775,7 +864,7 @@ export const useMainStore = defineStore({
|
|||
this.updateCapabilityQuestionAnswers(null);
|
||||
this.updatePageData({
|
||||
page: issPageValues.CAPABILITY_QUESTIONS,
|
||||
data: null,
|
||||
data: null
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -850,9 +939,9 @@ export const useMainStore = defineStore({
|
|||
userPartitionNumber: experiment.userPartitionNumber,
|
||||
assignmentId: experiment.assignmentId,
|
||||
sessionKey: sessionKey,
|
||||
pageName: pageName,
|
||||
},
|
||||
},
|
||||
pageName: pageName
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
logPageView({ userId, sessionKey, pageName, sessionId, action, event, shouldUseSessionId, experimentsForUser })
|
||||
|
|
@ -873,7 +962,7 @@ export const useMainStore = defineStore({
|
|||
method: endpoints.LogPageView.method,
|
||||
endpoint: endpoints.LogPageView.url,
|
||||
payload: payload,
|
||||
logApiCall: false,
|
||||
logApiCall: false
|
||||
});
|
||||
},
|
||||
logCustomEvent({ userId, sessionKey, pageName, sessionId, category, action, label, value, shouldUseSessionId, experimentsForUser})
|
||||
|
|
@ -892,14 +981,14 @@ export const useMainStore = defineStore({
|
|||
label: label,
|
||||
value: value,
|
||||
shouldUseSessionId: shouldUseSessionId,
|
||||
experimentsForUser: experimentsForUser,
|
||||
experimentsForUser: experimentsForUser
|
||||
};
|
||||
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.LogCustomEvent.method,
|
||||
endpoint: endpoints.LogCustomEvent.url,
|
||||
payload: payload,
|
||||
logApiCall: false,
|
||||
logApiCall: false
|
||||
});
|
||||
},
|
||||
initializeSession({ userId, sessionId, userAgent, referrer }) {
|
||||
|
|
@ -911,14 +1000,14 @@ export const useMainStore = defineStore({
|
|||
userAgent: userAgent,
|
||||
operatorId: "WEB",
|
||||
userName: "SafeliteISS",
|
||||
referrer: referrer,
|
||||
referrer: referrer
|
||||
};
|
||||
|
||||
return globalMethods.callHttpClient({
|
||||
method: endpoints.InitializeSession.method,
|
||||
endpoint: endpoints.InitializeSession.url,
|
||||
payload: payload,
|
||||
logApiCall: false,
|
||||
logApiCall: false
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -937,7 +1026,7 @@ export const useMainStore = defineStore({
|
|||
return globalMethods.callHttpClient({
|
||||
method: endpoints.GetExperimentsByUser.method,
|
||||
endpoint: `${endpoints.GetExperimentsByUser.url}/${userId}`,
|
||||
payload: {},
|
||||
payload: {}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -951,13 +1040,13 @@ export const useMainStore = defineStore({
|
|||
userId: userId,
|
||||
triggerEvent: triggerEvent,
|
||||
triggerValue: triggerValue,
|
||||
experimentOrder: this.experimentOrder,
|
||||
experimentOrder: this.experimentOrder
|
||||
};
|
||||
|
||||
const response = await globalMethods.callHttpClient({
|
||||
method: endpoints.RunExperimentsForTrigger.method,
|
||||
endpoint: endpoints.RunExperimentsForTrigger.url,
|
||||
payload: payload,
|
||||
payload: payload
|
||||
});
|
||||
|
||||
this.updateExperiments(response.data.experiments);
|
||||
|
|
@ -966,14 +1055,14 @@ export const useMainStore = defineStore({
|
|||
async validateZip({ zip }) {
|
||||
return await globalMethods.callHttpClient({
|
||||
methods: endpoints.ValidateZip.method,
|
||||
endpoint: `${endpoints.ValidateZip.url}/${zip}`,
|
||||
endpoint: `${endpoints.ValidateZip.url}/${zip}`
|
||||
});
|
||||
},
|
||||
|
||||
async validateClientTag(clientTag) {
|
||||
return await globalMethods.callHttpClient({
|
||||
methods: endpoints.ValidateClientTag.method,
|
||||
endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`,
|
||||
endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -1124,7 +1213,7 @@ function convertGlassPieceNamingForApi(glassArray) {
|
|||
glassArray.forEach((glass) => {
|
||||
converted.push({
|
||||
location: glass.glassLocation,
|
||||
name: glass.glassName,
|
||||
name: glass.glassName
|
||||
});
|
||||
});
|
||||
return converted;
|
||||
|
|
@ -1137,7 +1226,7 @@ function convertResultsForApi(resultsArray) {
|
|||
converted.push({
|
||||
location: answer.glassLocation,
|
||||
name: answer.glassName,
|
||||
result: answer.result,
|
||||
result: answer.result
|
||||
});
|
||||
});
|
||||
return converted;
|
||||
|
|
@ -1164,3 +1253,31 @@ function getAllPartNumbers(partsOrQuestions) {
|
|||
.join(",")
|
||||
: [];
|
||||
}
|
||||
|
||||
function addPricesToLineItems(lineItems, pricingLineItems) {
|
||||
lineItems.forEach((lineItem) => {
|
||||
const lineItemIndex = pricingLineItems.findIndex(
|
||||
(pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber
|
||||
)
|
||||
if (lineItem.childParts) {
|
||||
addPricesToLineItems(lineItem.childParts, pricingLineItems)
|
||||
}
|
||||
const pricedLineItem = pricingLineItems.splice(lineItemIndex, 1)[0]
|
||||
lineItem.laborAmount = pricedLineItem.laborAmount
|
||||
lineItem.sellingPrice = pricedLineItem.sellingPrice
|
||||
lineItem.kitPrice = pricedLineItem.kitPrice
|
||||
});
|
||||
return lineItems;
|
||||
}
|
||||
|
||||
function getLineItemQueryStringForPricing(lineItems) {
|
||||
return lineItems
|
||||
.map((lineItem) => {
|
||||
let queryStringSnippet = `&LineItems=${lineItem.partNumber}`;
|
||||
if (lineItem.childParts) {
|
||||
queryStringSnippet += getLineItemQueryStringForPricing(lineItem.childParts);
|
||||
}
|
||||
return queryStringSnippet;
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost";
|
|||
process.env.VUE_APP_GOOGLE_PLACES_API_KEY =
|
||||
"AIzaSyCuLhQcDdZTTb4JzpUFms1OCch2dk5lHF0";
|
||||
|
||||
|
||||
// GA & GTM
|
||||
// NOTE: Using the old ISS site GTM Cotnainer ID for now, will create a new one soon.
|
||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-KKNWZ3');";
|
||||
|
|
@ -26,7 +25,7 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
},
|
||||
configureWebpack: {
|
||||
devtool: 'source-map'
|
||||
configureWebpack: {
|
||||
devtool: 'source-map',
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue