Merge branch 'develop' into feature/csr-1465
This commit is contained in:
commit
85417ce9f2
22 changed files with 595 additions and 367 deletions
|
|
@ -21,6 +21,10 @@ const applicationConfig = {
|
|||
"//" +
|
||||
location.host +
|
||||
"/fmg/?fmgPage=payment-method&src=concept-funnel",
|
||||
GOOGLE_CALENDAR: "https://www.google.com/calendar/render?action=TEMPLATE",
|
||||
YAHOO_CALENDAR: "https://calendar.yahoo.com/?v=60",
|
||||
OUTLOOK_CALENDAR:
|
||||
"https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent",
|
||||
};
|
||||
|
||||
export { applicationConfig };
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ const storeActions = {
|
|||
SAVE_PIA_ERROR_CODE: "savePiaErrorCode",
|
||||
SAVE_PIA_WORK_ORDER: "savePiaWorkOrder",
|
||||
SAVE_CCTOKEN: "saveCCToken",
|
||||
SAVE_PAYPAL_TOKEN: "savePaypalToken",
|
||||
};
|
||||
|
||||
export { storeActions };
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const storeMutations = {
|
|||
UPDATE_PIA_ERROR_CODE: "updatePiaErrorCode",
|
||||
UPDATE_PIA_WORK_ORDER: "updatePiaWorkOrder",
|
||||
UPDATE_CCTOKEN: "updateCCToken",
|
||||
UPDATE_PAYPAL_TOKEN: "updatePaypalToken",
|
||||
|
||||
// VEHICLE MUTATIONS
|
||||
UPDATE_YEAR: "updateYear",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
class="my-4 caption modal-sub-body"
|
||||
v-if="ModalSubBodyText"
|
||||
v-html="ModalSubBodyText"></p>
|
||||
<slot></slot>
|
||||
</modal>
|
||||
</template>
|
||||
|
||||
|
|
@ -22,6 +23,10 @@ export default {
|
|||
name: "content-group-modal",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
footerButtonActionName: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
ModalName() {
|
||||
|
|
@ -50,10 +55,16 @@ export default {
|
|||
openModal() {
|
||||
this.$refs[this.ModalName].openModal();
|
||||
},
|
||||
|
||||
footerButtonClick() {
|
||||
closeModal() {
|
||||
this.$refs[this.ModalName].closeModal();
|
||||
},
|
||||
footerButtonClick() {
|
||||
if (this.footerButtonActionName) {
|
||||
this.$emit(this.footerButtonActionName, this.ModalName);
|
||||
} else {
|
||||
this.closeModal();
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
modal,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
|
|
|
|||
|
|
@ -1,167 +0,0 @@
|
|||
<template>
|
||||
<div class="calendar-section">
|
||||
<div class="add-to-calendar">
|
||||
<button v-on:click="openCalendarModal">
|
||||
<span class="add-to-calendar-span">
|
||||
<img src="@/assets/img/icons/add-to-calendar.svg" class="add-to-calendar-img" />
|
||||
<span class="add-to-calendar-text">Add to calendar</span></span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<calendarModalQuestion
|
||||
ref="calendarModalQuestion"
|
||||
customComponentId="calendarModalQuestion"
|
||||
cmsWidgetName="CalendarModalQuestion"
|
||||
@calendar-modal-closed="calendarModalClosed"
|
||||
:calendarOptionsData="calendarValues"
|
||||
v-model="selectedCalendarOption">
|
||||
</calendarModalQuestion>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { calendarOptions } from "@/constants/calendar-options";
|
||||
import { calendarStatus } from "@/constants/calendar-status";
|
||||
import calendarModalQuestion from "@/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question";
|
||||
import { getDateFormat } from "@/helpers/date-helper";
|
||||
import { getCalendarFile, download } from "@/helpers/add-to-calendar-helper";
|
||||
|
||||
export default {
|
||||
name: "add-to-calendar",
|
||||
components: {
|
||||
calendarModalQuestion,
|
||||
},
|
||||
props: {
|
||||
appointment: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedCalendarOption: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
calendarValues: {
|
||||
get: function () {
|
||||
var obj = [];
|
||||
const options = Object.values(calendarOptions);
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
obj[i] = this.getCalendarData(options[i]);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedCalendarOption(newValue) {
|
||||
if (newValue) {
|
||||
this.setCalendarAppointment(newValue);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setCalendarAppointment(calendarOption) {
|
||||
if (
|
||||
calendarOption.name.includes(calendarOptions.ICAL) ||
|
||||
calendarOption.name.includes(calendarOptions.OUTLOOK)
|
||||
) {
|
||||
this.getAppointment();
|
||||
} else {
|
||||
window.open(calendarOption.url);
|
||||
}
|
||||
},
|
||||
calendarModalClosed() {
|
||||
// Clear the selectedOption if close the modal
|
||||
this.selectedCalendarOption = null;
|
||||
},
|
||||
openCalendarModal() {
|
||||
this.$refs["calendarModalQuestion"].openModal();
|
||||
},
|
||||
getCalendarData(type) {
|
||||
var URL = "";
|
||||
const dateFormat = "yyyyMMddTHHmmss";
|
||||
const outlookComTimeSpanFormat = "yyyy-MM-ddTHH:mm:ss";
|
||||
if (type == calendarOptions.OUTLOOKCOM) {
|
||||
URL = `https://outlook.office.com/calendar/deeplink/compose?path=/calendar/action/compose&rru=addevent&startdt=${encodeURIComponent(
|
||||
getDateFormat(this.appointment.StartDate, outlookComTimeSpanFormat)
|
||||
)}&enddt=${encodeURIComponent(
|
||||
getDateFormat(this.appointment.EndDate, outlookComTimeSpanFormat)
|
||||
)}&subject=${encodeURIComponent(
|
||||
this.appointment.Subject
|
||||
)}&body=${encodeURIComponent(this.appointment.Body)}&location=${encodeURIComponent(
|
||||
this.appointment.Location
|
||||
)}`;
|
||||
}
|
||||
if (type == calendarOptions.GOOGLE) {
|
||||
URL = `https://www.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(
|
||||
this.appointment.Subject
|
||||
)}&dates=${encodeURIComponent(
|
||||
getDateFormat(this.appointment.StartDate, dateFormat)
|
||||
)}/${encodeURIComponent(
|
||||
getDateFormat(this.appointment.EndDate, dateFormat)
|
||||
)}&details=${encodeURIComponent(
|
||||
this.appointment.Body
|
||||
)}&location=${encodeURIComponent(this.appointment.Location)}&sf=true&output=xml`;
|
||||
}
|
||||
if (type == calendarOptions.YAHOO) {
|
||||
URL = `https://calendar.yahoo.com/?v=60&TITLE=${encodeURIComponent(
|
||||
this.appointment.Subject
|
||||
)}&DESC=${encodeURIComponent(this.appointment.Body)}&ST=${encodeURIComponent(
|
||||
getDateFormat(this.appointment.StartDate, dateFormat)
|
||||
)}&DUR=${this.appointment.Duration}&in_loc=${encodeURIComponent(
|
||||
this.appointment.Location
|
||||
)}`;
|
||||
}
|
||||
return {
|
||||
url: URL,
|
||||
name: type,
|
||||
icon: require(`@/assets/img/icons/${type}.svg`),
|
||||
};
|
||||
},
|
||||
getAppointment() {
|
||||
let body = this.appointment.Body;
|
||||
body = body.replace("|", "<").replace("~", ">");
|
||||
|
||||
const calFile = {
|
||||
Location: this.appointment.Location,
|
||||
Body: body,
|
||||
IsHTML: this.appointment.IsHTML,
|
||||
UniqueId: this.appointment.RefrrlSeqNum,
|
||||
Subject: this.appointment.Subject,
|
||||
StartDate: this.appointment.StartDate,
|
||||
EndDate: this.appointment.EndDate,
|
||||
Status: calendarStatus.BUSY,
|
||||
};
|
||||
var calBody = getCalendarFile(calFile);
|
||||
download("SafeliteAppointment.ics", calBody);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.add-to-calendar-text {
|
||||
margin: 0 0 0 7px;
|
||||
color: #1574a1;
|
||||
vertical-align: middle;
|
||||
font-weight: 500;
|
||||
font-family: "Roboto";
|
||||
}
|
||||
.add-to-calendar button {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.calendar-section {
|
||||
display: table;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.calendar-section .add-to-calendar {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.calendar-section .add-to-calendar .add-to-calendar-span {
|
||||
cursor: pointer;
|
||||
}
|
||||
.calendar-section .add-to-calendar .add-to-calendar-img {
|
||||
display: inline;
|
||||
width: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Components
|
||||
import addToCalendar from "@/layouts/add-to-calendar/add-to-calendar.vue";
|
||||
import addToCalendar from "@/layouts/confirmation/add-to-calendar/add-to-calendar.vue";
|
||||
import { calendarOptions } from "@/constants/calendar-options";
|
||||
import { AppointmentTypeStrings, RouteCodeFlags } from "@/constants/schedule-constants";
|
||||
|
||||
|
|
@ -176,11 +176,20 @@ describe("Add-to-calendar methods...", () => {
|
|||
});
|
||||
});
|
||||
|
||||
var appointmentText = "Appointment content";
|
||||
function setupMocks({ customMountOptions }) {
|
||||
const mountOptions = getMountOptions({
|
||||
...customMountOptions,
|
||||
});
|
||||
|
||||
mountOptions.mixins = [
|
||||
{
|
||||
methods: {
|
||||
getCmsContent: jest.fn().mockImplementation(() => {
|
||||
return appointmentText;
|
||||
}),
|
||||
},
|
||||
},
|
||||
];
|
||||
const wrapper = shallowMount(addToCalendar, mountOptions);
|
||||
wrapper.vm.$refs.calendarModalQuestion.openModal = jest.fn();
|
||||
return { wrapper };
|
||||
314
src/layouts/confirmation/add-to-calendar/add-to-calendar.vue
Normal file
314
src/layouts/confirmation/add-to-calendar/add-to-calendar.vue
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
<template>
|
||||
<div class="calendar-section">
|
||||
<div class="add-to-calendar">
|
||||
<button v-on:click="openCalendarModal">
|
||||
<span class="add-to-calendar-span">
|
||||
<img src="@/assets/img/icons/add-to-calendar.svg" class="add-to-calendar-img" />
|
||||
<span class="add-to-calendar-text">Add to calendar</span></span
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<calendarModalQuestion
|
||||
ref="calendarModalQuestion"
|
||||
customComponentId="calendarModalQuestion"
|
||||
cmsWidgetName="CalendarModalQuestion"
|
||||
@calendar-modal-closed="calendarModalClosed"
|
||||
:calendarOptionsData="calendarValues"
|
||||
v-model="selectedCalendarOption">
|
||||
</calendarModalQuestion>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { calendarOptions } from "@/constants/calendar-options";
|
||||
import { calendarStatus } from "@/constants/calendar-status";
|
||||
import calendarModalQuestion from "@/layouts/confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question";
|
||||
import { getDateFormat } from "@/helpers/date-helper";
|
||||
import { AppointmentTypeStrings, RouteCodeFlags } from "@/constants/schedule-constants";
|
||||
import { getCalendarFile, download } from "@/helpers/add-to-calendar-helper";
|
||||
import {
|
||||
calculateDuration,
|
||||
combineDateAndTime,
|
||||
shortTimeString,
|
||||
addMinutes,
|
||||
} from "@/helpers/date-helper";
|
||||
import store from "@/store";
|
||||
import { serviceType } from "@/constants/service-type";
|
||||
import { applicationConfig } from "@/constants/application-config.js";
|
||||
export default {
|
||||
name: "add-to-calendar",
|
||||
components: {
|
||||
calendarModalQuestion,
|
||||
},
|
||||
props: {
|
||||
mobileWidgetName: String,
|
||||
inShopWidgetName: String,
|
||||
dropOffWidgetName: String,
|
||||
overnightDropOffWidgetName: String,
|
||||
allDayDropOffWidgetName: String,
|
||||
sameDayDropOffWidgetName: String,
|
||||
serviceLocationFullAddress: String,
|
||||
providerFullAddress: String,
|
||||
appointmentType: String,
|
||||
scheduleDate: String,
|
||||
scheduleStartTime: String,
|
||||
scheduleEndTime: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedCalendarOption: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
calendarValues: {
|
||||
get: function () {
|
||||
var obj = [];
|
||||
const options = Object.values(calendarOptions);
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
obj[i] = this.getCalendarData(options[i]);
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
},
|
||||
IsSameDayDropOff() {
|
||||
const todaysDate = new Date().toISOString().split("T")[0];
|
||||
return this.scheduleDate === todaysDate;
|
||||
},
|
||||
AddToCalendar_Mobile_Subject() {
|
||||
return this.getCmsContent(this.mobileWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_Mobile_Body() {
|
||||
return this.getCmsContent(this.mobileWidgetName, "BodyText");
|
||||
},
|
||||
AddToCalendar_InShop_Subject() {
|
||||
return this.getCmsContent(this.inShopWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_InShop_Body() {
|
||||
return this.getCmsContent(this.inShopWidgetName, "BodyText");
|
||||
},
|
||||
AddToCalendar_DropOff_Subject() {
|
||||
return this.getCmsContent(this.dropOffWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_DropOff_Body() {
|
||||
return this.getCmsContent(this.dropOffWidgetName, "BodyText");
|
||||
},
|
||||
AddToCalendar_OvernightDropOff_Subject() {
|
||||
return this.getCmsContent(this.overnightDropOffWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_OvernightDropOff_Body() {
|
||||
return this.getCmsContent(this.overnightDropOffWidgetName, "BodyText");
|
||||
},
|
||||
AddToCalendar_AllDayDropOff_Subject() {
|
||||
return this.getCmsContent(this.allDayDropOffWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_AllDayDropOff_Body() {
|
||||
return this.getCmsContent(this.allDayDropOffWidgetName, "BodyText");
|
||||
},
|
||||
AddToCalendar_SameDayDropOff_Subject() {
|
||||
return this.getCmsContent(this.sameDayDropOffWidgetName, "HeaderText");
|
||||
},
|
||||
AddToCalendar_SameDayDropOff_Body() {
|
||||
return this.getCmsContent(this.sameDayDropOffWidgetName, "BodyText");
|
||||
},
|
||||
UniqueId() {
|
||||
return store.getters.order.referralNumber?.toString();
|
||||
},
|
||||
ServiceType() {
|
||||
const isRepair = store.getters.order.damage.isRepair;
|
||||
const funnelHasRecalibrationPart = store.getters.funnelHasRecalibrationPart;
|
||||
if (!isRepair) {
|
||||
if (funnelHasRecalibrationPart) {
|
||||
return serviceType.REPLACEMENT_AND_RECALIBRATION;
|
||||
} else {
|
||||
return serviceType.REPLACEMENT;
|
||||
}
|
||||
}
|
||||
return serviceType.REPAIR;
|
||||
},
|
||||
RouteCode() {
|
||||
return store.getters.order.schedule.routeCode;
|
||||
},
|
||||
Appointment() {
|
||||
var subject = "";
|
||||
var location = "";
|
||||
var startDateTime = combineDateAndTime(this.scheduleDate, this.scheduleStartTime);
|
||||
var endDateTime = combineDateAndTime(this.scheduleDate, this.scheduleEndTime);
|
||||
var body = "";
|
||||
var isHTML = false;
|
||||
var duration = "";
|
||||
|
||||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||
location = this.serviceLocationFullAddress?.replace("<br/>", "");
|
||||
subject = this.AddToCalendar_Mobile_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.AddToCalendar_Mobile_Body;
|
||||
} else {
|
||||
location = this.providerFullAddress?.replace("<br/>", "");
|
||||
if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) {
|
||||
if (this.RouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
subject = this.AddToCalendar_OvernightDropOff_Subject;
|
||||
body = this.AddToCalendar_OvernightDropOff_Body;
|
||||
} else if (this.RouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
if (this.IsSameDayDropOff) {
|
||||
subject = this.AddToCalendar_SameDayDropOff_Subject;
|
||||
endDateTime = addMinutes(startDateTime, 120);
|
||||
body = this.AddToCalendar_SameDayDropOff_Body;
|
||||
} else {
|
||||
endDateTime = addMinutes(startDateTime, 120);
|
||||
subject = this.AddToCalendar_AllDayDropOff_Subject?.replace(
|
||||
"{custom:STARTDATETIME}",
|
||||
shortTimeString(startDateTime)
|
||||
).replace("{custom:ENDDATETIME}", shortTimeString(endDateTime));
|
||||
body = this.AddToCalendar_AllDayDropOff_Body?.replace(
|
||||
"{custom:ENDDATETIME}",
|
||||
shortTimeString(endDateTime)
|
||||
);
|
||||
}
|
||||
} //normal time slot
|
||||
else {
|
||||
subject = this.AddToCalendar_DropOff_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.AddToCalendar_DropOff_Body?.replace(
|
||||
"{custom:ADDRESS}",
|
||||
location
|
||||
);
|
||||
}
|
||||
} else {
|
||||
subject = this.AddToCalendar_InShop_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.AddToCalendar_InShop_Body?.replace("{custom:ADDRESS}", location);
|
||||
}
|
||||
duration = calculateDuration(startDateTime, endDateTime);
|
||||
}
|
||||
return {
|
||||
Subject: subject,
|
||||
Location: location,
|
||||
StartDate: startDateTime,
|
||||
EndDate: endDateTime,
|
||||
RefrrlSeqNum: this.UniqueId,
|
||||
Body: body,
|
||||
IsHTML: isHTML,
|
||||
Duration: duration,
|
||||
};
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
selectedCalendarOption(newValue) {
|
||||
if (newValue) {
|
||||
this.setCalendarAppointment(newValue);
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
setCalendarAppointment(calendarOption) {
|
||||
if (
|
||||
calendarOption.name == calendarOptions.ICAL ||
|
||||
calendarOption.name == calendarOptions.OUTLOOK
|
||||
) {
|
||||
this.getAppointment();
|
||||
} else {
|
||||
window.open(calendarOption.url);
|
||||
}
|
||||
},
|
||||
calendarModalClosed() {
|
||||
// Clear the selectedOption if close the modal
|
||||
this.selectedCalendarOption = null;
|
||||
},
|
||||
openCalendarModal() {
|
||||
this.$refs["calendarModalQuestion"].openModal();
|
||||
},
|
||||
getCalendarData(type) {
|
||||
var URL = "";
|
||||
const dateFormat = "yyyyMMddTHHmmss";
|
||||
const outlookComTimeSpanFormat = "yyyy-MM-ddTHH:mm:ss";
|
||||
if (type == calendarOptions.OUTLOOKCOM) {
|
||||
URL = `${applicationConfig.OUTLOOK_CALENDAR}&startdt=${encodeURIComponent(
|
||||
getDateFormat(this.Appointment.StartDate, outlookComTimeSpanFormat)
|
||||
)}&enddt=${encodeURIComponent(
|
||||
getDateFormat(this.Appointment.EndDate, outlookComTimeSpanFormat)
|
||||
)}&subject=${encodeURIComponent(
|
||||
this.Appointment.Subject
|
||||
)}&body=${encodeURIComponent(this.Appointment.Body)}&location=${encodeURIComponent(
|
||||
this.Appointment.Location
|
||||
)}`;
|
||||
}
|
||||
if (type == calendarOptions.GOOGLE) {
|
||||
URL = `${applicationConfig.GOOGLE_CALENDAR}&text=${encodeURIComponent(
|
||||
this.Appointment.Subject
|
||||
)}&dates=${encodeURIComponent(
|
||||
getDateFormat(this.Appointment.StartDate, dateFormat)
|
||||
)}/${encodeURIComponent(
|
||||
getDateFormat(this.Appointment.EndDate, dateFormat)
|
||||
)}&details=${encodeURIComponent(
|
||||
this.Appointment.Body
|
||||
)}&location=${encodeURIComponent(this.Appointment.Location)}&sf=true&output=xml`;
|
||||
}
|
||||
if (type == calendarOptions.YAHOO) {
|
||||
URL = `${applicationConfig.YAHOO_CALENDAR}&TITLE=${encodeURIComponent(
|
||||
this.Appointment.Subject
|
||||
)}&DESC=${encodeURIComponent(this.Appointment.Body)}&ST=${encodeURIComponent(
|
||||
getDateFormat(this.Appointment.StartDate, dateFormat)
|
||||
)}&DUR=${this.Appointment.Duration}&in_loc=${encodeURIComponent(
|
||||
this.Appointment.Location
|
||||
)}`;
|
||||
}
|
||||
return {
|
||||
url: URL,
|
||||
name: type,
|
||||
icon: require(`@/assets/img/icons/${type}.svg`),
|
||||
};
|
||||
},
|
||||
getAppointment() {
|
||||
let body = this.Appointment.Body;
|
||||
body = body?.replace("|", "<").replace("~", ">");
|
||||
|
||||
const calFile = {
|
||||
Location: this.Appointment.Location,
|
||||
Body: body,
|
||||
IsHTML: this.Appointment.IsHTML,
|
||||
UniqueId: this.Appointment.RefrrlSeqNum,
|
||||
Subject: this.Appointment.Subject,
|
||||
StartDate: this.Appointment.StartDate,
|
||||
EndDate: this.Appointment.EndDate,
|
||||
Status: calendarStatus.BUSY,
|
||||
};
|
||||
var calBody = getCalendarFile(calFile);
|
||||
download("SafeliteAppointment.ics", calBody);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.add-to-calendar-text {
|
||||
margin: 0 0 0 7px;
|
||||
color: #1574a1;
|
||||
vertical-align: middle;
|
||||
font-weight: 500;
|
||||
font-family: "Roboto";
|
||||
}
|
||||
.add-to-calendar button {
|
||||
border: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
.calendar-section {
|
||||
display: table;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.calendar-section .add-to-calendar {
|
||||
padding-top: 15px;
|
||||
}
|
||||
.calendar-section .add-to-calendar .add-to-calendar-span {
|
||||
cursor: pointer;
|
||||
}
|
||||
.calendar-section .add-to-calendar .add-to-calendar-img {
|
||||
display: inline;
|
||||
width: 20px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import calendarModalQuestion from "@/layouts/add-to-calendar/calendar-modal-question/calendar-modal-question.vue";
|
||||
import calendarModalQuestion from "@/layouts/confirmation/add-to-calendar/calendar-modal-question/calendar-modal-question.vue";
|
||||
|
||||
describe("calendar-modal-question.vue", () => {
|
||||
test("When selected calendar option is changed, a correctly selectedCalendarOption should be emitted", async () => {
|
||||
|
|
@ -20,7 +20,19 @@
|
|||
<p>{{ ScheduleDateFormatted }}</p>
|
||||
<p>{{ ScheduleTimeFormatted }}</p>
|
||||
</div>
|
||||
<addToCalendar :appointment="this.AppointmentData" />
|
||||
<addToCalendar
|
||||
mobileWidgetName="AddToCalendar_Mobile"
|
||||
inShopWidgetName="AddToCalendar_InShop"
|
||||
dropOffWidgetName="AddToCalendar_DropOff"
|
||||
overnightDropOffWidgetName="AddToCalendar_OvernightDropOff"
|
||||
allDayDropOffWidgetName="AddToCalendar_AllDayDropOff"
|
||||
sameDayDropOffWidgetName="AddToCalendar_SameDayDropOff"
|
||||
:serviceLocationFullAddress="ServiceLocationFullAddress"
|
||||
:providerFullAddress="ProviderFullAddress"
|
||||
:appointmentType="AppointmentType"
|
||||
:scheduleDate="ScheduleDate"
|
||||
:scheduleStartTime="ScheduleStartTime"
|
||||
:scheduleEndTime="ScheduleEndTime" />
|
||||
|
||||
<div class="appoinmenttext" v-html="AppointmentWordingText"></div>
|
||||
</div>
|
||||
|
|
@ -43,22 +55,17 @@
|
|||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
|
||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||
import addToCalendar from "@/layouts/add-to-calendar/add-to-calendar";
|
||||
import addToCalendar from "@/layouts/confirmation/add-to-calendar/add-to-calendar";
|
||||
//Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { AppointmentTypeStrings, RouteCodeFlags } from "@/constants/schedule-constants";
|
||||
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { applicationConfig } from "@/constants/application-config.js";
|
||||
import { convertDateStringToDate } from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import {
|
||||
calculateDuration,
|
||||
combineDateAndTime,
|
||||
shortTimeString,
|
||||
addMinutes,
|
||||
} from "@/helpers/date-helper";
|
||||
|
||||
import { Form } from "vee-validate";
|
||||
import store from "@/store";
|
||||
import { serviceType } from "@/constants/service-type";
|
||||
|
||||
import { get12HourTimeFormat, get12HourTimeMobileFormat } from "@/helpers/date-helper";
|
||||
export default {
|
||||
name: "confirmation",
|
||||
|
|
@ -190,138 +197,6 @@ export default {
|
|||
return `at ${get12HourTimeFormat(this.ScheduleStartTime)}`;
|
||||
}
|
||||
},
|
||||
IsSameDayDropOff() {
|
||||
const todaysDate = new Date().toISOString().split("T")[0];
|
||||
return this.ScheduleDate === todaysDate;
|
||||
},
|
||||
Mobile_Appointment_Subject() {
|
||||
return this.getCmsContent("Mobile_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
Mobile_Appointment_Body() {
|
||||
return this.getCmsContent("Mobile_Appointment_Widget", "BodyText");
|
||||
},
|
||||
InShop_Appointment_Subject() {
|
||||
return this.getCmsContent("InShop_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
InShop_Appointment_Body() {
|
||||
return this.getCmsContent("InShop_Appointment_Widget", "BodyText");
|
||||
},
|
||||
Drop_Off_Appointment_Subject() {
|
||||
return this.getCmsContent("Drop_Off_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
Drop_Off_Appointment_Body() {
|
||||
return this.getCmsContent("Drop_Off_Appointment_Widget", "BodyText");
|
||||
},
|
||||
Overnight_Drop_Off_Appointment_Subject() {
|
||||
return this.getCmsContent("Drop_Off_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
Overnight_Drop_Off_Appointment_Body() {
|
||||
return this.getCmsContent("Drop_Off_Appointment_Widget", "BodyText");
|
||||
},
|
||||
All_Day_Drop_Off_Appointment_Subject() {
|
||||
return this.getCmsContent("All_Day_Drop_Off_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
All_Day_Drop_Off_Appointment_Body() {
|
||||
return this.getCmsContent("All_Day_Drop_Off_Appointment_Widget", "BodyText");
|
||||
},
|
||||
Same_Day_Drop_Off_Appointment_Subject() {
|
||||
return this.getCmsContent("Same_Day_Drop_Off_Appointment_Widget", "HeaderText");
|
||||
},
|
||||
Same_Day_Drop_Off_Appointment_Body() {
|
||||
return this.getCmsContent("Same_Day_Drop_Off_Appointment_Widget", "BodyText");
|
||||
},
|
||||
UniqueId() {
|
||||
return store.getters.order.referralNumber?.toString();
|
||||
},
|
||||
ServiceType() {
|
||||
const isRepair = store.getters.order.damage.isRepair;
|
||||
const funnelHasRecalibrationPart = store.getters.funnelHasRecalibrationPart;
|
||||
if (!isRepair) {
|
||||
if (funnelHasRecalibrationPart) {
|
||||
return serviceType.REPLACEMENT_AND_RECALIBRATION;
|
||||
} else {
|
||||
return serviceType.REPLACEMENT;
|
||||
}
|
||||
}
|
||||
return serviceType.REPAIR;
|
||||
},
|
||||
RouteCode() {
|
||||
return store.getters.order.schedule.routeCode;
|
||||
},
|
||||
AppointmentData() {
|
||||
var subject = "";
|
||||
var location = "";
|
||||
var startDateTime = combineDateAndTime(this.ScheduleDate, this.ScheduleStartTime);
|
||||
var endDateTime = combineDateAndTime(this.ScheduleDate, this.ScheduleEndTime);
|
||||
var body = "";
|
||||
var isHTML = false;
|
||||
var duration = "";
|
||||
|
||||
if (this.AppointmentType === AppointmentTypeStrings.MOBILE) {
|
||||
location = this.ServiceLocationFullAddress?.replace("<br/>", "");
|
||||
subject = this.Mobile_Appointment_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.Mobile_Appointment_Body;
|
||||
} else {
|
||||
location = this.ProviderFullAddress?.replace("<br/>", "");
|
||||
if (this.AppointmentType === AppointmentTypeStrings.DROP_OFF) {
|
||||
if (this.RouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
subject = this.Overnight_Drop_Off_Appointment_Subject;
|
||||
body = this.Overnight_Drop_Off_Appointment_Body;
|
||||
} else if (this.RouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
if (this.IsSameDayDropOff) {
|
||||
subject = this.Same_Day_Drop_Off_Appointment_Subject;
|
||||
endDateTime = addMinutes(startDateTime, 120);
|
||||
body = this.Same_Day_Drop_Off_Appointment_Body;
|
||||
} else {
|
||||
endDateTime = addMinutes(startDateTime, 120);
|
||||
subject = this.All_Day_Drop_Off_Appointment_Subject?.replace(
|
||||
"{custom:STARTDATETIME}",
|
||||
shortTimeString(startDateTime)
|
||||
).replace("{custom:ENDDATETIME}", shortTimeString(endDateTime));
|
||||
body = this.All_Day_Drop_Off_Appointment_Body?.replace(
|
||||
"{custom:ENDDATETIME}",
|
||||
shortTimeString(endDateTime)
|
||||
);
|
||||
}
|
||||
} //normal time slot
|
||||
else {
|
||||
subject = this.Drop_Off_Appointment_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.Drop_Off_Appointment_Body?.replace(
|
||||
"{custom:ADDRESS}",
|
||||
location
|
||||
);
|
||||
}
|
||||
} else {
|
||||
subject = this.InShop_Appointment_Subject?.replace(
|
||||
"{custom:SERVICETYPE}",
|
||||
this.ServiceType
|
||||
);
|
||||
body = this.InShop_Appointment_Body?.replace("{custom:ADDRESS}", location);
|
||||
}
|
||||
duration = calculateDuration(startDateTime, endDateTime);
|
||||
}
|
||||
return {
|
||||
Subject: subject,
|
||||
Location: location,
|
||||
StartDate: startDateTime,
|
||||
EndDate: endDateTime,
|
||||
RefrrlSeqNum: this.UniqueId,
|
||||
Body: body,
|
||||
IsHTML: isHTML,
|
||||
Duration: duration,
|
||||
};
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
workOrderNumber: store.getters.order.workOrderNumber,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="add-vaps-buttons" aria-live="polite">
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
:answers="answersToDisplay"
|
||||
groupName="addVaps"
|
||||
v-model="answersToDisplay"
|
||||
buttonTypeString="addVapsButton"
|
||||
:buttonTypeObject="addVapsButton"
|
||||
:isWide="answersToDisplay.length > 1 ? false : true"
|
||||
@update:modelValue="openModal" />
|
||||
|
||||
<contentGroupModal
|
||||
ref="RainDefenseModal"
|
||||
cmsWidgetName="RainDefenseModal"
|
||||
v-if="rainDefenseItem"
|
||||
@footer-button-action="addToCart('RainDefenseModal', rainDefenseItem)"
|
||||
footerButtonActionName="footer-button-action">
|
||||
<p class="price">{{ rainDefenseItem.listPrice }}</p>
|
||||
</contentGroupModal>
|
||||
|
||||
<contentGroupModal
|
||||
ref="WipersModal"
|
||||
cmsWidgetName="WipersModal"
|
||||
v-if="wipersItem"
|
||||
@footer-button-action="addToCart('WipersModal', wipersItem)"
|
||||
footerButtonActionName="footer-button-action">
|
||||
<p class="price">{{ wipersItem.listPrice }}</p>
|
||||
</contentGroupModal>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||
import addVapsButton from "./add-vaps-button/add-vaps-button";
|
||||
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
|
||||
|
||||
export default {
|
||||
name: "add-vaps-modal-buttons",
|
||||
props: {
|
||||
vapsTilesCmsName: String,
|
||||
availableLineItems: Object,
|
||||
modelValue: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addVapsButton: addVapsButton,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
openModal(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
addToCart(modalName, part) {
|
||||
const vapsItems = this.currentCartItems.vaps;
|
||||
const alreadyInVaps = vapsItems.some((item) => {
|
||||
return item.partType === part.partType;
|
||||
});
|
||||
if (!alreadyInVaps) {
|
||||
if (part.subItems) {
|
||||
// for wipers, a "combined" part (w/ subItems)
|
||||
part.subItems.forEach((part) => {
|
||||
this.currentCartItems.vaps.push(part);
|
||||
});
|
||||
} else {
|
||||
// for rain defense, a "single" part (w/o subItems)
|
||||
this.currentCartItems.vaps.push(part);
|
||||
}
|
||||
}
|
||||
this.$refs[modalName].closeModal();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
currentCartItems() {
|
||||
return this.modelValue;
|
||||
},
|
||||
showAddRainDefense() {
|
||||
// show if not in cart
|
||||
return !this.currentCartItems.vaps?.some((vap) => {
|
||||
return vap?.partType === "RAIN DEFENSE";
|
||||
});
|
||||
},
|
||||
showAddWipers() {
|
||||
// show if not in cart
|
||||
if (this.currentCartItems && this.currentCartItems.vaps) {
|
||||
return !this.currentCartItems.vaps.some((vap) => {
|
||||
return vap?.partType?.includes(" WIPER");
|
||||
});
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
rainDefenseItem() {
|
||||
const lineItem = this.availableLineItems.find((item) => {
|
||||
return item.partType === "RAIN DEFENSE";
|
||||
});
|
||||
if (lineItem)
|
||||
lineItem.listPrice = parseFloat(
|
||||
lineItem?.laborAmount + lineItem?.sellingPrice + lineItem?.kitPrice
|
||||
).toFixed(2);
|
||||
return lineItem;
|
||||
},
|
||||
wipersItem() {
|
||||
const wiperLineItems = this.availableLineItems.filter((item) => {
|
||||
return item.partType.includes("WIPER");
|
||||
});
|
||||
let wiperLineItem;
|
||||
if (wiperLineItems.length === 1) {
|
||||
wiperLineItem = wiperLineItems[0];
|
||||
wiperLineItem.listPrice = parseFloat(
|
||||
wiperLineItem.laborAmount + wiperLineItem.sellingPrice + wiperLineItem.kitPrice
|
||||
).toFixed(2);
|
||||
return wiperLineItem;
|
||||
} else if (wiperLineItems.length > 1) {
|
||||
let combinedPrice = 0;
|
||||
wiperLineItems?.forEach((item) => {
|
||||
combinedPrice += item?.laborAmount + item?.sellingPrice + item?.kitPrice;
|
||||
});
|
||||
wiperLineItem = {
|
||||
description: "COMBINED ITEM",
|
||||
partType: "WIPERS",
|
||||
subItems: [],
|
||||
listPrice: parseFloat(combinedPrice).toFixed(2),
|
||||
};
|
||||
wiperLineItems?.forEach((item) => {
|
||||
wiperLineItem.subItems.push(item);
|
||||
});
|
||||
return wiperLineItem;
|
||||
}
|
||||
return [];
|
||||
},
|
||||
answersCmsData() {
|
||||
return this.getCmsContent(this.vapsTilesCmsName, "Answers");
|
||||
},
|
||||
answersToDisplay() {
|
||||
const answers = [];
|
||||
if (!this.answersCmsData) return answers;
|
||||
const getAnswer = (name, answers) => {
|
||||
const answerIndex = answers.findIndex((answer) => {
|
||||
return answer.Name === name;
|
||||
});
|
||||
return answers[answerIndex];
|
||||
};
|
||||
if (this.showAddWipers) {
|
||||
const answer = getAnswer("WipersModal", this.answersCmsData);
|
||||
answer.SubText = "+$" + this.wipersItem.listPrice;
|
||||
answers.push(answer);
|
||||
}
|
||||
if (this.showAddRainDefense) {
|
||||
const answer = getAnswer("RainDefenseModal", this.answersCmsData);
|
||||
answer.SubText = "+$" + this.rainDefenseItem.listPrice;
|
||||
answers.push(answer);
|
||||
}
|
||||
return answers;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
buttonQuestion,
|
||||
contentGroupModal,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -42,12 +42,10 @@
|
|||
</div>
|
||||
|
||||
<add-vaps-modal-buttons
|
||||
:cartItems="cartItems"
|
||||
v-model="lineItems"
|
||||
:availableLineItems="availableLineItems"
|
||||
vapsTilesCmsName="VapsProductTiles"
|
||||
v-on="{ 'buttonEvent.openModal': openModal }" />
|
||||
vapsTilesCmsName="VapsProductTiles" />
|
||||
|
||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||
<paymentMethodQuestion
|
||||
v-if="!isPiaDisabled"
|
||||
v-model="paymentMethodInternalModel"
|
||||
|
|
@ -74,11 +72,11 @@ import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-heade
|
|||
import paymentMethodQuestion from "@/layouts/payment-method/payment-method-question/payment-method-question";
|
||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||
import cart from "@/fmg-components/cart/cart";
|
||||
import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons";
|
||||
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
|
||||
import addVapsModalButtons from "./add-vaps-modal-buttons/add-vaps-modal-buttons";
|
||||
import { submitWorkOrder } from "@/helpers/heritage-integration/order-helper.js";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
|
||||
// Supporting Items
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
|
|
@ -252,9 +250,6 @@ export default {
|
|||
packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs
|
||||
);
|
||||
},
|
||||
openModal(modalName) {
|
||||
this.$refs[modalName].openModal();
|
||||
},
|
||||
getPiaAlert() {
|
||||
return store.getters.order.payment.piaErrorCode ? true : false;
|
||||
},
|
||||
|
|
@ -271,13 +266,6 @@ export default {
|
|||
return paymentMethods.LATER;
|
||||
}
|
||||
},
|
||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||
this.cartItems = vapsItemsSelected;
|
||||
},
|
||||
// TODO (as part of CSR-1384) enable adding to the cart
|
||||
// vapsItemsSelectedAction(vapsItemsSelected) {
|
||||
// this.cartItems = vapsItemsSelected;
|
||||
// },
|
||||
cartRemove(item) {
|
||||
const matchedIndices = [];
|
||||
this.cartItems.forEach((cartItem, i) => {
|
||||
|
|
@ -397,7 +385,6 @@ export default {
|
|||
cart,
|
||||
alert,
|
||||
addVapsModalButtons,
|
||||
contentGroupModal,
|
||||
paymentMethodQuestion,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,13 +18,7 @@ export default {
|
|||
name: "payment-pia-return",
|
||||
async mounted() {
|
||||
this.$refs.loadingModal.showModal();
|
||||
// from paypal
|
||||
const piaError = getQuerystringParameter(queryStrings.ERROR);
|
||||
const token = getQuerystringParameter(queryStrings.TOKEN);
|
||||
const payerId = getQuerystringParameter(queryStrings.PAYERID);
|
||||
|
||||
// from credit card
|
||||
const subscriptionID = getQuerystringParameter(queryStrings.SUBSCRIPTIONID);
|
||||
|
||||
if (piaError) {
|
||||
console.log("Error during payment: " + piaError);
|
||||
|
|
@ -35,15 +29,16 @@ export default {
|
|||
);
|
||||
this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_ERROR, this.$route);
|
||||
} else {
|
||||
if (token && payerId) {
|
||||
await this.processPaypalResponse();
|
||||
} else {
|
||||
if (subscriptionID) {
|
||||
await this.processCreditCardResponse(subscriptionID);
|
||||
} else {
|
||||
console.log(
|
||||
"Error during payment: " + token + " : " + payerId + " : " + subscriptionID
|
||||
);
|
||||
switch (store.getters.order.payment.piaType) {
|
||||
case "cc":
|
||||
case "ap":
|
||||
await this.processCreditCardResponse();
|
||||
break;
|
||||
case "pp":
|
||||
await this.processPaypalResponse();
|
||||
break;
|
||||
default:
|
||||
console.log("Unknown Pia type: " + store.getters.order.payment.piaType);
|
||||
baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.SAVE_PIA_ERROR_CODE,
|
||||
piaError,
|
||||
|
|
@ -53,7 +48,6 @@ export default {
|
|||
this.navigationScenarios.PIA_ERROR,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -62,12 +56,16 @@ export default {
|
|||
return true;
|
||||
},
|
||||
async processPaypalResponse() {
|
||||
const token = getQuerystringParameter(queryStrings.TOKEN);
|
||||
const payerId = getQuerystringParameter(queryStrings.PAYERID);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_WORK_ORDER_FLAG, true, false);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_PAYPAL_TOKEN, token, false);
|
||||
|
||||
await this.saveAndSubmitWorkOrder();
|
||||
},
|
||||
async processCreditCardResponse(subscriptionID) {
|
||||
async processCreditCardResponse() {
|
||||
const subscriptionID = getQuerystringParameter(queryStrings.SUBSCRIPTIONID);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
||||
baseMixin.methods.dispatchStoreAction(storeActions.SAVE_WORK_ORDER_FLAG, true, false);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-5" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-4" />
|
||||
<template v-if="ChangeShopLink.length">
|
||||
<textBlock
|
||||
cmsWidgetName="ChangeShopLink"
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<vehicleBanner
|
||||
ref="vehicleBanner"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
|
|
|
|||
|
|
@ -5,12 +5,19 @@ import vehicle from "@/layouts/vehicle/vehicle.vue";
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import { nextTick } from "vue";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import baseMixin from "../../mixins/base-mixin";
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
settleAllPromises: jest.fn(),
|
||||
}));
|
||||
|
||||
// Mock fetchCmsContentForPage
|
||||
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||
fetchCmsContentForPage: jest.fn(),
|
||||
}));
|
||||
|
||||
describe("vehicle.vue", () => {
|
||||
test("arePagePrerequisitesValid should be true ", async () => {
|
||||
//Arrange
|
||||
|
|
@ -40,17 +47,24 @@ describe("vehicle.vue", () => {
|
|||
});
|
||||
|
||||
function setupMocks() {
|
||||
const wrapper = shallowMount(
|
||||
vehicle,
|
||||
getMountOptions({
|
||||
router: {
|
||||
navigate: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
},
|
||||
})
|
||||
);
|
||||
const mountOptions = getMountOptions({
|
||||
router: {
|
||||
navigate: jest.fn(),
|
||||
navigate: jest.fn(),
|
||||
navigateWithSaving: jest.fn(),
|
||||
navigateWithoutSaving: jest.fn(),
|
||||
},
|
||||
});
|
||||
|
||||
//Mock props
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn(),
|
||||
},
|
||||
};
|
||||
|
||||
mountOptions.mixins = [mockMixin];
|
||||
const wrapper = shallowMount(vehicle, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
||||
<div
|
||||
cmsWidgetName="FindYourVehicleCopyWidget"
|
||||
v-html="this.findYourVehicleCopy"
|
||||
class="mt-2 mb-4 small"></div>
|
||||
<vehicleQuestion
|
||||
ref="vehicleYearQuestion"
|
||||
v-model="selectedYear"
|
||||
|
|
@ -294,6 +298,9 @@ export default {
|
|||
else if (this.imageUrl == null && this.carId !== null) return false;
|
||||
else return true;
|
||||
},
|
||||
findYourVehicleCopy() {
|
||||
return this.getCmsContent("FindYourVehicleCopyWidget", "QuestionText");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getVehicle(year, make, model, style) {
|
||||
|
|
@ -430,6 +437,6 @@ export default {
|
|||
}
|
||||
.siteSubHeader {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1.5rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ const getDefaultState = () => {
|
|||
piaType: null,
|
||||
piaErrorCode: null,
|
||||
inactivePromos: null,
|
||||
paypalToken: null,
|
||||
ccToken: {
|
||||
subscriptionId: null,
|
||||
expMonth: null,
|
||||
|
|
@ -270,6 +271,9 @@ export const mutations = {
|
|||
state.order.payment.ccToken.transactionId = ccToken.transactionId;
|
||||
state.order.payment.ccToken.transReferenceNumber = ccToken.transReferenceNumber;
|
||||
},
|
||||
updatePaypalToken(state, ppToken) {
|
||||
state.order.payment.paypalToken = ppToken;
|
||||
},
|
||||
updateInsuranceVerifiedStatus(state, isVerified) {
|
||||
state.order.payment.insuranceCoverage.isVerified = isVerified;
|
||||
},
|
||||
|
|
@ -1644,6 +1648,10 @@ export const actions = {
|
|||
isInsurance: order.payment.isInsurance,
|
||||
parentAccountNumber: order.payment.parentAccountNumber,
|
||||
inactivePromos: order.payment.inactivePromos,
|
||||
isCreditCard: order.payment.piaType == "cc" ? true : false,
|
||||
isPaypal: order.payment.piaType == "pp" ? true : false,
|
||||
isAfterPay: order.payment.piaType == "ap" ? true : false,
|
||||
paypalToken: order.payment.paypalToken,
|
||||
ccToken: {
|
||||
subscriptionId: order.payment.ccToken.subscriptionId,
|
||||
expMonth: order.payment.ccToken.expMonth,
|
||||
|
|
@ -1777,6 +1785,9 @@ export const actions = {
|
|||
saveCCToken(context, ccToken) {
|
||||
context.commit(storeMutations.UPDATE_CCTOKEN, ccToken);
|
||||
},
|
||||
savePaypalToken(context, ppToken) {
|
||||
context.commit(storeMutations.UPDATE_PAYPAL_TOKEN, ppToken);
|
||||
},
|
||||
|
||||
// Business domain actions
|
||||
|
||||
|
|
@ -2516,8 +2527,7 @@ function convertGlassPieceNamingFromApi(glassArray) {
|
|||
}
|
||||
|
||||
function addPricesToLineItems(lineItems, pricingLineItems) {
|
||||
const pricedLineItems = deepClone(lineItems);
|
||||
pricedLineItems.forEach((lineItem) => {
|
||||
lineItems.forEach((lineItem) => {
|
||||
let lineItemIndex = pricingLineItems.findIndex(
|
||||
(pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber
|
||||
);
|
||||
|
|
@ -2533,7 +2543,7 @@ function addPricesToLineItems(lineItems, pricingLineItems) {
|
|||
lineItem.salesTax = pricedLineItem.salesTax;
|
||||
});
|
||||
|
||||
return pricedLineItems;
|
||||
return lineItems;
|
||||
}
|
||||
|
||||
function addTaxesToPricedLineItems(lineItems, taxingLineItems) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div
|
||||
class="alert fade show text-center mb-0 py-2 px-4"
|
||||
class="alert fade show text-center mb-0 py-2 px-4 border-0"
|
||||
role="alert"
|
||||
:class="[
|
||||
isDismissible ? 'alert-dismissible' : '',
|
||||
|
|
|
|||
Loading…
Reference in a new issue