Merge branch 'develop' into feature/CASH-823
This commit is contained in:
commit
7a2bd42034
11 changed files with 226 additions and 151 deletions
|
|
@ -2,14 +2,18 @@
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Urbanist:ital,wght@0,100..900;1,100..900&display=swap");
|
||||||
body {
|
body {
|
||||||
font-family: Roboto;
|
font-family: Urbanist, Arial, Helvetica, sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
}
|
}
|
||||||
|
body h3 {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
body .validation-info {
|
body .validation-info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -31,7 +35,7 @@ body .form-group {
|
||||||
body .headerlinecontainer .headerline1 {
|
body .headerlinecontainer .headerline1 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
margin: 24px 0;
|
margin: 24px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +96,7 @@ body .creditCardSpecific div .headerlinecontainer {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
body .creditCardSpecific div label {
|
body .creditCardSpecific div label {
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
body .creditCardSpecific #infoRow2 {
|
body .creditCardSpecific #infoRow2 {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
@ -268,6 +272,7 @@ body .cc-error-container #alert-message {
|
||||||
#fmg-checkout-shared #other-payments-container label span.paymentOptionText {
|
#fmg-checkout-shared #other-payments-container label span.paymentOptionText {
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
#fmg-checkout-shared #other-payments-container #afterpayParentLink label > span:first-of-type {
|
#fmg-checkout-shared #other-payments-container #afterpayParentLink label > span:first-of-type {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,19 @@
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
|
||||||
|
@import url("https://fonts.googleapis.com/css2?family=Urbanist:ital,wght@0,100..900;1,100..900&display=swap");
|
||||||
body {
|
body {
|
||||||
font-family: Roboto;
|
font-family: Urbanist, Arial, Helvetica, sans-serif;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
color: #000;
|
color: #000;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
.validation-info {
|
.validation-info {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
@ -37,7 +42,7 @@ body {
|
||||||
.headerline1 {
|
.headerline1 {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
line-height: 32px;
|
line-height: 32px;
|
||||||
font-weight: 400;
|
font-weight: 500;
|
||||||
margin: 24px 0;
|
margin: 24px 0;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
@ -98,7 +103,7 @@ body {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
label {
|
label {
|
||||||
font-weight: 500;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#infoRow2 {
|
#infoRow2 {
|
||||||
|
|
@ -325,6 +330,7 @@ body {
|
||||||
&.paymentOptionText {
|
&.paymentOptionText {
|
||||||
margin: auto 0;
|
margin: auto 0;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,16 @@ export default {
|
||||||
FirstName: transfer.data.first_name,
|
FirstName: transfer.data.first_name,
|
||||||
LastName: transfer.data.last_name,
|
LastName: transfer.data.last_name,
|
||||||
Email: transfer.data.email,
|
Email: transfer.data.email,
|
||||||
Subject: transfer.data.chat_summary, // for now passing in chat_summery in Subject. But this will be changed in future.
|
Subject: transfer.data.chat_summary,
|
||||||
};
|
};
|
||||||
|
window.embedded_svc.settings.extraPrechatFormDetails = [
|
||||||
|
{
|
||||||
|
label: "Scarlett AI Summary",
|
||||||
|
value: transfer.data.chat_summary,
|
||||||
|
transcriptFields: ["Scarlett_AI_Summary__c"],
|
||||||
|
displayToAgent: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
if (
|
if (
|
||||||
window.embedded_svc.liveAgentAPI &&
|
window.embedded_svc.liveAgentAPI &&
|
||||||
typeof window.embedded_svc.liveAgentAPI.startChat === "function"
|
typeof window.embedded_svc.liveAgentAPI.startChat === "function"
|
||||||
|
|
|
||||||
|
|
@ -117,6 +117,10 @@
|
||||||
<span>{{ amountPaidText }}</span>
|
<span>{{ amountPaidText }}</span>
|
||||||
<span>{{ getLineItemAmount(amountPaid) }}</span>
|
<span>{{ getLineItemAmount(amountPaid) }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="donationCartItem" class="donation-amount">
|
||||||
|
<span>{{ donationCartItemName }}</span>
|
||||||
|
<span>{{ getLineItemAmount(donationCartItem.subTotal) }}</span>
|
||||||
|
</div>
|
||||||
<div class="amount-due">
|
<div class="amount-due">
|
||||||
<span>{{ amountDueText }}</span>
|
<span>{{ amountDueText }}</span>
|
||||||
<span>{{ getLineItemAmount(amountDue, showCoverageAsPending) }}</span>
|
<span>{{ getLineItemAmount(amountDue, showCoverageAsPending) }}</span>
|
||||||
|
|
@ -472,10 +476,6 @@ export default {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.donationCartItem) {
|
|
||||||
cartItems.push(this.donationCartItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cartItems;
|
return cartItems;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -1309,12 +1309,15 @@ export default {
|
||||||
.sub-total,
|
.sub-total,
|
||||||
.sales-tax,
|
.sales-tax,
|
||||||
.amount-due,
|
.amount-due,
|
||||||
.amount-paid {
|
.amount-paid,
|
||||||
font-weight: 500;
|
.donation-amount {
|
||||||
|
font-family:
|
||||||
|
UrbanistSemibold, AvertaSemibold; //Okay to remove AvertaSemibold after 2025.06.19 merge/release
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
.sub-total {
|
.sub-total {
|
||||||
border-top: 1px solid $green;
|
border-top: 1px solid $green;
|
||||||
|
background-color: $green-100;
|
||||||
}
|
}
|
||||||
.service-type,
|
.service-type,
|
||||||
.deductible {
|
.deductible {
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { queryStrings } from "@/constants/query-strings";
|
import { queryStrings } from "@/constants/query-strings";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { consumeQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
import { peekQueryFromStash } from "@/router/methods/helpers/querystring-stash";
|
||||||
|
|
||||||
// Define Validation Rules
|
// Define Validation Rules
|
||||||
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||||
|
|
@ -100,7 +100,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
const zip =
|
const zip =
|
||||||
consumeQueryFromStash(queryStrings.ZIP_CODE) ??
|
peekQueryFromStash(queryStrings.ZIP_CODE) ??
|
||||||
store.getters.order.serviceLocation.zipCode;
|
store.getters.order.serviceLocation.zipCode;
|
||||||
|
|
||||||
var vinByAddressPromise;
|
var vinByAddressPromise;
|
||||||
|
|
|
||||||
|
|
@ -616,8 +616,11 @@ export default {
|
||||||
// TODO - WILL NEED TO SAVE THE APPOINTMENT TYPE ALSO (AND ANYTHING ELSE THAT SERVICE-LOCATION DID TOO)
|
// TODO - WILL NEED TO SAVE THE APPOINTMENT TYPE ALSO (AND ANYTHING ELSE THAT SERVICE-LOCATION DID TOO)
|
||||||
this.updateSupportingItems();
|
this.updateSupportingItems();
|
||||||
|
|
||||||
if (this.waitListRequested) {
|
if (this.displayWaitList) {
|
||||||
var gaLabel = this.isMobileSelected ? "checked_mobile" : "checked_inshop";
|
var gaLabel = "";
|
||||||
|
const status = this.waitListRequested ? "checked" : "unchecked";
|
||||||
|
const type = store.getters.isMobileAppointment ? "mobile" : "inshop";
|
||||||
|
gaLabel = `${status}_${type}`;
|
||||||
|
|
||||||
const currentDate = new Date();
|
const currentDate = new Date();
|
||||||
const dateString = this.isMobileSelected
|
const dateString = this.isMobileSelected
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { reactive } from "vue";
|
import { reactive } from "vue";
|
||||||
|
import { debugLog } from "@/helpers/debug-log-helper";
|
||||||
|
|
||||||
const queryStash = reactive({
|
const queryStash = reactive({
|
||||||
queries: [],
|
queries: [],
|
||||||
|
|
@ -27,10 +28,18 @@ export function stashAllQueries(toRoute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function getStashedQuery(key) {
|
function getStashedQuery(key) {
|
||||||
|
debugLog(`Fetching querystring with key:`, key);
|
||||||
const match = queryStash.queries.find(
|
const match = queryStash.queries.find(
|
||||||
(entry) => entry?.key?.toLowerCase() === key?.toLowerCase()
|
(entry) => entry?.key?.toLowerCase() === key?.toLowerCase()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
debugLog(`Found result:`, match.value);
|
||||||
|
debugLog(`Already consumed:`, match.used);
|
||||||
|
} else {
|
||||||
|
debugLog(`Found no result`);
|
||||||
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
14
src/router/methods/route-logic/payment.js
Normal file
14
src/router/methods/route-logic/payment.js
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import store from "@/store";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||||
|
import { debugLog } from "@/helpers/debug-log-helper";
|
||||||
|
|
||||||
|
export async function paymentBeforeEnter(to, from) {
|
||||||
|
const piaType = store.getters.order?.payment?.piaType;
|
||||||
|
debugLog(`Entering payment with type =`, piaType);
|
||||||
|
|
||||||
|
if (piaType === paymentMethods.PAYPAL) {
|
||||||
|
debugLog(`Changing to payment type =`, paymentMethods.CREDIT_CARD);
|
||||||
|
await store.dispatch(storeActions.SAVE_PAYMENT_METHOD_CHOICE, paymentMethods.CREDIT_CARD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -11,6 +11,7 @@ import { autoRouteBeforeEnter } from "@/router/methods/route-logic/auto-route";
|
||||||
import { errorBeforeEnter } from "@/router/methods/route-logic/error";
|
import { errorBeforeEnter } from "@/router/methods/route-logic/error";
|
||||||
import { restartBeforeEnter } from "@/router/methods/route-logic/restart";
|
import { restartBeforeEnter } from "@/router/methods/route-logic/restart";
|
||||||
import { paymentMethodBeforeEnter } from "@/router/methods/route-logic/payment-method";
|
import { paymentMethodBeforeEnter } from "@/router/methods/route-logic/payment-method";
|
||||||
|
import { paymentBeforeEnter } from "@/router/methods/route-logic/payment";
|
||||||
|
|
||||||
export const routes = [
|
export const routes = [
|
||||||
// Non-virtual pages.
|
// Non-virtual pages.
|
||||||
|
|
@ -32,7 +33,7 @@ export const routes = [
|
||||||
createRoute(routeData.SCHEDULE),
|
createRoute(routeData.SCHEDULE),
|
||||||
createRoute(routeData.CUSTOMER_DETAILS),
|
createRoute(routeData.CUSTOMER_DETAILS),
|
||||||
createRoute(routeData.PAYMENT_METHOD, paymentMethodBeforeEnter),
|
createRoute(routeData.PAYMENT_METHOD, paymentMethodBeforeEnter),
|
||||||
createRoute(routeData.PAYMENT),
|
createRoute(routeData.PAYMENT, paymentBeforeEnter),
|
||||||
createRoute(routeData.PAYMENT_PIA_RETURN),
|
createRoute(routeData.PAYMENT_PIA_RETURN),
|
||||||
createRoute(routeData.CONFIRMATION),
|
createRoute(routeData.CONFIRMATION),
|
||||||
createRoute(routeData.RETURN_USER),
|
createRoute(routeData.RETURN_USER),
|
||||||
|
|
|
||||||
|
|
@ -1072,33 +1072,6 @@ export const getters = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
|
||||||
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTimeSlotsAdditionalEventData(
|
|
||||||
provisionalTriggers,
|
|
||||||
zipCode,
|
|
||||||
firstAvailableAppointmentDateString,
|
|
||||||
shopAppointmentType
|
|
||||||
) {
|
|
||||||
var numberOfDays = null;
|
|
||||||
if (firstAvailableAppointmentDateString)
|
|
||||||
numberOfDays = getDateDifferenceInDays(
|
|
||||||
new Date().toISOString().split("T")[0],
|
|
||||||
firstAvailableAppointmentDateString
|
|
||||||
);
|
|
||||||
|
|
||||||
if (shopAppointmentType)
|
|
||||||
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(
|
|
||||||
","
|
|
||||||
)}`;
|
|
||||||
else
|
|
||||||
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(
|
|
||||||
","
|
|
||||||
)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Export Actions
|
// Export Actions
|
||||||
export const actions = {
|
export const actions = {
|
||||||
// Vehicle API Actions
|
// Vehicle API Actions
|
||||||
|
|
@ -2059,20 +2032,31 @@ export const actions = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
let hasCalled = timeSlotCallFlags.shop;
|
||||||
|
if (!hasCalled) {
|
||||||
|
timeSlotCallFlags.shop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
method: endpoints.GetShopTimeSlots.method,
|
method: endpoints.GetShopTimeSlots.method,
|
||||||
endpoint: endpoints.GetShopTimeSlots.url,
|
endpoint: endpoints.GetShopTimeSlots.url,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
additionalSuccessEventDataHandler: (response) =>
|
};
|
||||||
|
|
||||||
|
// Only set handler if this is the very first call in this session
|
||||||
|
if (!hasCalled) {
|
||||||
|
options.additionalSuccessEventDataHandler = (response) =>
|
||||||
getTimeSlotsAdditionalEventData(
|
getTimeSlotsAdditionalEventData(
|
||||||
response.data.provisionalTriggers,
|
response.data.provisionalTriggers,
|
||||||
order.serviceLocation.zipCode,
|
order.serviceLocation.zipCode,
|
||||||
response.data.days?.[0]?.date,
|
response.data.days?.[0]?.date,
|
||||||
shopAppointmentType
|
shopAppointmentType
|
||||||
),
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return globalMethods.callHttpClient(options);
|
||||||
},
|
},
|
||||||
|
|
||||||
getMobileTimeSlots(context, { payload: { startDate, endDate }, pageNameToLog }) {
|
getMobileTimeSlots(context, { payload: { startDate, endDate }, pageNameToLog }) {
|
||||||
|
|
@ -2116,19 +2100,30 @@ export const actions = {
|
||||||
zipCode: order.serviceLocation.zipCode,
|
zipCode: order.serviceLocation.zipCode,
|
||||||
};
|
};
|
||||||
|
|
||||||
return globalMethods.callHttpClient({
|
let hasCalled = timeSlotCallFlags.mobile;
|
||||||
|
if (!hasCalled) {
|
||||||
|
timeSlotCallFlags.mobile = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
method: endpoints.GetMobileTimeSlots.method,
|
method: endpoints.GetMobileTimeSlots.method,
|
||||||
endpoint: endpoints.GetMobileTimeSlots.url,
|
endpoint: endpoints.GetMobileTimeSlots.url,
|
||||||
payload: payload,
|
payload: payload,
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
pageNameToLog: pageNameToLog,
|
pageNameToLog: pageNameToLog,
|
||||||
additionalSuccessEventDataHandler: (response) =>
|
};
|
||||||
|
|
||||||
|
// Only set handler if this is the very first call in this session
|
||||||
|
if (!hasCalled) {
|
||||||
|
options.additionalSuccessEventDataHandler = (response) =>
|
||||||
getTimeSlotsAdditionalEventData(
|
getTimeSlotsAdditionalEventData(
|
||||||
response.data.provisionalTriggers,
|
response.data.provisionalTriggers,
|
||||||
order.serviceLocation.zipCode,
|
order.serviceLocation.zipCode,
|
||||||
response.data.days?.[0]?.date
|
response.data.days?.[0]?.date
|
||||||
),
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
|
return globalMethods.callHttpClient(options);
|
||||||
},
|
},
|
||||||
|
|
||||||
getMobilePremiumFee(context, { pageNameToLog }) {
|
getMobilePremiumFee(context, { pageNameToLog }) {
|
||||||
|
|
@ -3457,100 +3452,6 @@ export default createStore({
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Private Functions
|
|
||||||
|
|
||||||
function getHasRecalibrationPart(state) {
|
|
||||||
return containsRecalParts(state.order.lineItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
|
||||||
if (!arrayOfObjects) return null;
|
|
||||||
|
|
||||||
return arrayOfObjects.sort((a, b) => {
|
|
||||||
if (a[propertyName] < b[propertyName]) return -1;
|
|
||||||
else if (a[propertyName] > b[propertyName]) return 1;
|
|
||||||
else return 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertGlassPieceNamingForApi(glassArray) {
|
|
||||||
if (!glassArray || glassArray.length === 0) return [];
|
|
||||||
|
|
||||||
// check if array already converted. (likely when a session has been saved previously and then reloaded)
|
|
||||||
if (glassArray[0].location !== undefined) {
|
|
||||||
return glassArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
const converted = [];
|
|
||||||
glassArray.forEach((glass) => {
|
|
||||||
converted.push({
|
|
||||||
location: glass.glassLocation,
|
|
||||||
name: glass.glassName,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return converted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertResultsForApi(resultsArray) {
|
|
||||||
if (!resultsArray) return [];
|
|
||||||
const converted = [];
|
|
||||||
resultsArray.forEach((answer) => {
|
|
||||||
converted.push({
|
|
||||||
location: answer.glassLocation,
|
|
||||||
name: answer.glassName,
|
|
||||||
result: answer.result,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return converted;
|
|
||||||
}
|
|
||||||
|
|
||||||
function convertGlassPieceNamingFromApi(glassArray) {
|
|
||||||
glassArray.forEach((glass) => {
|
|
||||||
glass.glassLocation = glass.glassPiece.location;
|
|
||||||
glass.glassName = glass.glassPiece.name;
|
|
||||||
delete glass.glassPiece;
|
|
||||||
return glass;
|
|
||||||
});
|
|
||||||
return glassArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
lineItem.salesTax = pricedLineItem.salesTax;
|
|
||||||
});
|
|
||||||
|
|
||||||
return lineItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addTaxesToPricedLineItems(pricedLineItems, taxingLineItems = []) {
|
|
||||||
pricedLineItems.forEach((pricedLineItem) => {
|
|
||||||
const lineItemIndex = taxingLineItems.findIndex(
|
|
||||||
(taxingLineItem) => taxingLineItem.partNumber === pricedLineItem.partNumber
|
|
||||||
);
|
|
||||||
|
|
||||||
if (pricedLineItem.childParts) {
|
|
||||||
addTaxesToPricedLineItems(pricedLineItem.childParts, taxingLineItems);
|
|
||||||
}
|
|
||||||
|
|
||||||
const taxedLineItem = taxingLineItems.splice(lineItemIndex, 1)[0];
|
|
||||||
pricedLineItem.salesTax = taxedLineItem?.salesTax ?? 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
return pricedLineItems;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItems) {
|
export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItems) {
|
||||||
// clone the lineItems array because what we're passing in is referencing the store directly
|
// clone the lineItems array because what we're passing in is referencing the store directly
|
||||||
const lineItems = deepClone(storeLineItems);
|
const lineItems = deepClone(storeLineItems);
|
||||||
|
|
@ -3658,6 +3559,127 @@ export function getArrayOfAllLineItemsAndChildParts(lineItems) {
|
||||||
return consolidatedLineItemsArray;
|
return consolidatedLineItemsArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Private Functions
|
||||||
|
|
||||||
|
function getNonFalseValuesOfPropertyInArrayOfObjects(array, propertyName) {
|
||||||
|
return (array ?? []).map((x) => x[propertyName]).filter((x) => x);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTimeSlotsAdditionalEventData(
|
||||||
|
provisionalTriggers,
|
||||||
|
zipCode,
|
||||||
|
firstAvailableAppointmentDateString,
|
||||||
|
shopAppointmentType
|
||||||
|
) {
|
||||||
|
var numberOfDays = null;
|
||||||
|
if (firstAvailableAppointmentDateString)
|
||||||
|
numberOfDays = getDateDifferenceInDays(
|
||||||
|
new Date().toISOString().split("T")[0],
|
||||||
|
firstAvailableAppointmentDateString
|
||||||
|
);
|
||||||
|
|
||||||
|
if (shopAppointmentType)
|
||||||
|
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ShopAppointmentType:${shopAppointmentType},ProvisionalTriggers:${provisionalTriggers.join(
|
||||||
|
","
|
||||||
|
)}`;
|
||||||
|
else
|
||||||
|
return `FirstAvailableAppointment:${numberOfDays},Zip:${zipCode},ProvisionalTriggers:${provisionalTriggers.join(
|
||||||
|
","
|
||||||
|
)}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHasRecalibrationPart(state) {
|
||||||
|
return containsRecalParts(state.order.lineItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortArrayOfObjectsByPropertyValue(arrayOfObjects, propertyName) {
|
||||||
|
if (!arrayOfObjects) return null;
|
||||||
|
|
||||||
|
return arrayOfObjects.sort((a, b) => {
|
||||||
|
if (a[propertyName] < b[propertyName]) return -1;
|
||||||
|
else if (a[propertyName] > b[propertyName]) return 1;
|
||||||
|
else return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertGlassPieceNamingForApi(glassArray) {
|
||||||
|
if (!glassArray || glassArray.length === 0) return [];
|
||||||
|
|
||||||
|
// check if array already converted. (likely when a session has been saved previously and then reloaded)
|
||||||
|
if (glassArray[0].location !== undefined) {
|
||||||
|
return glassArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
const converted = [];
|
||||||
|
glassArray.forEach((glass) => {
|
||||||
|
converted.push({
|
||||||
|
location: glass.glassLocation,
|
||||||
|
name: glass.glassName,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertResultsForApi(resultsArray) {
|
||||||
|
if (!resultsArray) return [];
|
||||||
|
const converted = [];
|
||||||
|
resultsArray.forEach((answer) => {
|
||||||
|
converted.push({
|
||||||
|
location: answer.glassLocation,
|
||||||
|
name: answer.glassName,
|
||||||
|
result: answer.result,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return converted;
|
||||||
|
}
|
||||||
|
|
||||||
|
function convertGlassPieceNamingFromApi(glassArray) {
|
||||||
|
glassArray.forEach((glass) => {
|
||||||
|
glass.glassLocation = glass.glassPiece.location;
|
||||||
|
glass.glassName = glass.glassPiece.name;
|
||||||
|
delete glass.glassPiece;
|
||||||
|
return glass;
|
||||||
|
});
|
||||||
|
return glassArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
lineItem.salesTax = pricedLineItem.salesTax;
|
||||||
|
});
|
||||||
|
|
||||||
|
return lineItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addTaxesToPricedLineItems(pricedLineItems, taxingLineItems = []) {
|
||||||
|
pricedLineItems.forEach((pricedLineItem) => {
|
||||||
|
const lineItemIndex = taxingLineItems.findIndex(
|
||||||
|
(taxingLineItem) => taxingLineItem.partNumber === pricedLineItem.partNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
if (pricedLineItem.childParts) {
|
||||||
|
addTaxesToPricedLineItems(pricedLineItem.childParts, taxingLineItems);
|
||||||
|
}
|
||||||
|
|
||||||
|
const taxedLineItem = taxingLineItems.splice(lineItemIndex, 1)[0];
|
||||||
|
pricedLineItem.salesTax = taxedLineItem?.salesTax ?? 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return pricedLineItems;
|
||||||
|
}
|
||||||
|
|
||||||
function getFlattenedArrayOfLineItemsWithChildParts(lineItems, childPartRecursiveCall = false) {
|
function getFlattenedArrayOfLineItemsWithChildParts(lineItems, childPartRecursiveCall = false) {
|
||||||
let flattenedArray = [];
|
let flattenedArray = [];
|
||||||
lineItems?.forEach((lineItem) => {
|
lineItems?.forEach((lineItem) => {
|
||||||
|
|
@ -3966,3 +3988,8 @@ function getExternalParameterDefaultState() {
|
||||||
function saveExternalParameterState(externalParameterState) {
|
function saveExternalParameterState(externalParameterState) {
|
||||||
window.sessionStorage.setItem("externalParameterState", JSON.stringify(externalParameterState));
|
window.sessionStorage.setItem("externalParameterState", JSON.stringify(externalParameterState));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const timeSlotCallFlags = {
|
||||||
|
shop: false,
|
||||||
|
mobile: false,
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -121,8 +121,8 @@ $body-color: $gray-600;
|
||||||
|
|
||||||
//Fonts
|
//Fonts
|
||||||
$font-family-sans-serif: AvertaRegular, Arial, Helvetica, sans-serif;
|
$font-family-sans-serif: AvertaRegular, Arial, Helvetica, sans-serif;
|
||||||
$font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
|
$font-family-monospace:
|
||||||
monospace;
|
SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||||
// stylelint-enable value-keyword-case
|
// stylelint-enable value-keyword-case
|
||||||
$font-family-base: $font-family-sans-serif;
|
$font-family-base: $font-family-sans-serif;
|
||||||
$font-family-code: $font-family-monospace;
|
$font-family-code: $font-family-monospace;
|
||||||
|
|
@ -170,8 +170,7 @@ $spacers: (
|
||||||
/* 16px */ 5: $spacer * 1.5,
|
/* 16px */ 5: $spacer * 1.5,
|
||||||
/* 24px */ 6: $spacer * 2,
|
/* 24px */ 6: $spacer * 2,
|
||||||
/* 32px */ 7: $spacer * 2.5,
|
/* 32px */ 7: $spacer * 2.5,
|
||||||
/* 40px */ 8: $spacer * 3,
|
/* 40px */ 8: $spacer * 3 /* 48px */,
|
||||||
/* 48px */
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//Enable negative spacing (does NOT work on padding)
|
//Enable negative spacing (does NOT work on padding)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue