Merge branch 'develop' into feature/CSR-1144
This commit is contained in:
commit
4e732d19a9
11 changed files with 120 additions and 88 deletions
|
|
@ -31,8 +31,8 @@
|
|||
<div class="grid-item caption"><span class="sr-only">Saturday</span>S</div>
|
||||
<div
|
||||
v-for="date in month.dates"
|
||||
:key="date.inputValue.dateString"
|
||||
:id="date.inputValue.dateString"
|
||||
:key="date.inputValue"
|
||||
:id="date.inputValue"
|
||||
class="grid-item radio-wrapper"
|
||||
:class="[
|
||||
date.dateNum === 1 ? 'first-day-' + month.startDateDayIndex : '',
|
||||
|
|
@ -193,6 +193,51 @@ export default {
|
|||
weekEndDate: weekEndDate,
|
||||
});
|
||||
}
|
||||
|
||||
// are any of these weeks split between two months?
|
||||
const hasSplitWeek = (week) => {
|
||||
return week.weekStartDate.getMonth() !== week.weekEndDate.getMonth() ? true : false;
|
||||
};
|
||||
const splitWeekIndex = weeks.findIndex(hasSplitWeek);
|
||||
|
||||
if (splitWeekIndex > -1) {
|
||||
const week1 = [];
|
||||
const week2 = [];
|
||||
let switchToWeek2 = false;
|
||||
|
||||
for (let j = 0; j < 7; j++) {
|
||||
const newDate = new Date(weeks[splitWeekIndex].weekStartDate);
|
||||
newDate.setDate(newDate.getDate() + j);
|
||||
if (newDate.getDate() === 1) switchToWeek2 = true;
|
||||
if (switchToWeek2) {
|
||||
week2.push(newDate);
|
||||
} else {
|
||||
week1.push(newDate);
|
||||
}
|
||||
}
|
||||
|
||||
const week1EndDate = week1[week1.length - 1];
|
||||
const week2StartDate = week2[0];
|
||||
|
||||
if (week1EndDate < today) {
|
||||
// replace week 1 with week 2
|
||||
weeks[splitWeekIndex].weekStartDate = week2StartDate;
|
||||
} else {
|
||||
const newWeek = {
|
||||
weekNum: weeks[splitWeekIndex].weekNum,
|
||||
weekStartDate: week2StartDate,
|
||||
weekEndDate: weeks[splitWeekIndex].weekEndDate,
|
||||
};
|
||||
weeks[splitWeekIndex].weekEndDate = week1EndDate;
|
||||
weeks.splice(splitWeekIndex + 1, 0, newWeek);
|
||||
weeks.pop();
|
||||
weeks.forEach((item, index) => {
|
||||
if (index > splitWeekIndex) {
|
||||
item.weekNum = item.weekNum + 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return weeks;
|
||||
},
|
||||
async loadInitialData(config) {
|
||||
|
|
@ -209,7 +254,7 @@ export default {
|
|||
const todayYearNum = todayDate.getFullYear();
|
||||
// TODO - set up currentMonthStart if direction is PAST:
|
||||
// let currentMonthStart = new Date(todayYearNum, todayMonthIndex - 1, 1);
|
||||
let currentMonthEnd = new Date(todayYearNum, todayMonthIndex, 0);
|
||||
const currentMonthEnd = new Date(todayYearNum, todayMonthIndex, 0);
|
||||
|
||||
let calendarViewDirection = "none";
|
||||
if (config.selectableDatesSetting === "past") calendarViewDirection = "past";
|
||||
|
|
@ -222,8 +267,8 @@ export default {
|
|||
|
||||
const initialViewStartDate = todayDate;
|
||||
const initialViewEndDate = initialViewWeeks[initialViewWeeks.length - 1].weekEndDate;
|
||||
const saturday1month = initialViewWeeks[0].weekEndDate.getMonth();
|
||||
const sunday5month =
|
||||
const firstSaturdayMonth = initialViewWeeks[0].weekEndDate.getMonth();
|
||||
const lastSundayMonth =
|
||||
initialViewWeeks[initialViewWeeks.length - 1].weekStartDate.getMonth();
|
||||
|
||||
let hideSomeDaysForInitialView = false;
|
||||
|
|
@ -231,10 +276,10 @@ export default {
|
|||
|
||||
// TODO - NEED TO CREATE OPPOSITE LOGIC FOR "past" DIRECTION LIKE BELOW vvvvv
|
||||
if (calendarViewDirection === "future") {
|
||||
if (saturday1month !== sunday5month) {
|
||||
if (firstSaturdayMonth !== lastSundayMonth) {
|
||||
hideSomeDaysForInitialView = true;
|
||||
}
|
||||
if (initialViewStartDate.getMonth() === sunday5month) {
|
||||
if (initialViewStartDate.getMonth() === lastSundayMonth) {
|
||||
hideSecondMonth = true;
|
||||
if (currentMonthEnd > initialViewEndDate) {
|
||||
// should part of 1st month be hidden?
|
||||
|
|
@ -243,7 +288,7 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
let myPromise = new Promise((resolve, reject) => {
|
||||
const myPromise = new Promise((resolve, reject) => {
|
||||
const response = config.customSelectableDatesCallback(
|
||||
initialViewStartDate.toISOString().split("T")[0],
|
||||
initialViewEndDate.toISOString().split("T")[0],
|
||||
|
|
@ -431,12 +476,6 @@ export default {
|
|||
"-" +
|
||||
forceTwoDigitString(i);
|
||||
|
||||
const thisDate = {
|
||||
year: yearNum,
|
||||
month: monthIndex,
|
||||
date: i,
|
||||
dateString: dateString,
|
||||
};
|
||||
if (offset === 0 && i === this.todayDateNum) {
|
||||
dayClasses += "current-day";
|
||||
}
|
||||
|
|
@ -457,11 +496,9 @@ export default {
|
|||
const dateObject = {
|
||||
dateNum: i,
|
||||
dayClasses: dayClasses,
|
||||
inputValue: thisDate,
|
||||
inputValue: dateString,
|
||||
isSelectable:
|
||||
this.selectableDatesData.findIndex(
|
||||
(date) => date.dateString === dateString
|
||||
) > -1
|
||||
this.selectableDatesData.findIndex((date) => date.date === dateString) > -1
|
||||
? true
|
||||
: false,
|
||||
};
|
||||
|
|
@ -510,8 +547,8 @@ export default {
|
|||
if (monthToShow) {
|
||||
// make new API call with this month's start and end dates
|
||||
await this.updateSelectableDates(
|
||||
monthToShow.dates[monthStartDateNum].inputValue.dateString,
|
||||
monthToShow.dates[monthToShow.dates.length - 1].inputValue.dateString
|
||||
monthToShow.dates[monthStartDateNum].inputValue,
|
||||
monthToShow.dates[monthToShow.dates.length - 1].inputValue
|
||||
);
|
||||
this.isLoading = false;
|
||||
this.hideSomeDaysForInitialView = false; // if hid days on initial partial view, this will reveal those days
|
||||
|
|
@ -531,13 +568,13 @@ export default {
|
|||
);
|
||||
moreSelectableDates.days.forEach((selectableDate) => {
|
||||
const index = this.selectableDatesData.findIndex(
|
||||
(obj) => obj.dateString === selectableDate.dateString
|
||||
(dateObj) => dateObj.date === selectableDate.date
|
||||
);
|
||||
if (index === -1) this.selectableDatesData.push(selectableDate);
|
||||
if (index === -1) this.selectableDatesData.push(selectableDate.date);
|
||||
this.months.forEach((month) => {
|
||||
// TODO: avoid checking all calendar date; maybe only ones between monthStart and monthEnd as defined above?
|
||||
// TODO: avoid checking all calendar dates; maybe only ones between monthStart and monthEnd as defined above?
|
||||
month.dates.forEach((date) => {
|
||||
if (date.inputValue.dateString === selectableDate.dateString) {
|
||||
if (date.inputValue === selectableDate.date) {
|
||||
date["isSelectable"] = true;
|
||||
}
|
||||
});
|
||||
|
|
@ -808,7 +845,6 @@ export default {
|
|||
.btn-link {
|
||||
font-weight: 500;
|
||||
text-underline-offset: 4px;
|
||||
box-shadow: none !important; // TODO: FIX THIS
|
||||
position: absolute;
|
||||
top: 90%;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ import {
|
|||
getRouterLinkRouteFromCopy,
|
||||
getRouterLinkDisplayTextFromCopy,
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "./constants/schedule-constants";
|
||||
import { AppointmentTypeStrings } from "./constants/schedule-constants";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { required } from "@/helpers/validation-rules";
|
||||
import store from "@/store";
|
||||
|
|
@ -107,20 +107,7 @@ const getAvailableDates = async (startDate, endDate, appointmentType, providerNu
|
|||
);
|
||||
}
|
||||
|
||||
const newShopTimeSlots = newTimeSlotsResponse.data;
|
||||
return convertApiResponse(newShopTimeSlots);
|
||||
};
|
||||
const convertApiResponse = (responseData) => {
|
||||
// DATA CONVERSION
|
||||
responseData?.days.forEach((date) => {
|
||||
const dateString = date.date;
|
||||
date.dateString = dateString;
|
||||
const dateStringPieces = dateString.split("-");
|
||||
date.year = Number(dateStringPieces[0]);
|
||||
date.month = Number(dateStringPieces[1]);
|
||||
date.date = Number(dateStringPieces[2]);
|
||||
});
|
||||
return responseData;
|
||||
return newTimeSlotsResponse.data;
|
||||
};
|
||||
|
||||
export default {
|
||||
|
|
@ -146,24 +133,24 @@ export default {
|
|||
customSelectableDatesCallback: getAvailableDates,
|
||||
});
|
||||
|
||||
// Price EARLY BIRD pre-emptively to allow for asynchronous call to pricing
|
||||
const pricingPromise = baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||
{
|
||||
availableLineItems: [
|
||||
{
|
||||
partNumber: PREMIUM_FEE_PART_TYPE,
|
||||
partType: PREMIUM_FEE_PART_TYPE,
|
||||
description: null,
|
||||
},
|
||||
],
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
const premiumFeePromise = baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.GET_MOBILE_PREMIUM_FEE
|
||||
);
|
||||
|
||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||
if (result.data) {
|
||||
return baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.PRICE_ORDER_ITEMS_AND_SAVE_SERVER_DATA,
|
||||
{
|
||||
availableLineItems: [result.data],
|
||||
},
|
||||
false
|
||||
);
|
||||
} else {
|
||||
return result.data;
|
||||
}
|
||||
});
|
||||
|
||||
const alertReasonsPromise = locationAlerts.methods.loadInitialData(
|
||||
store.getters.order.serviceLocation.zipCodeCtu
|
||||
);
|
||||
|
|
@ -182,12 +169,8 @@ export default {
|
|||
promise: datePickerInitialDataPromise,
|
||||
},
|
||||
{
|
||||
resultKey: "premiumFee",
|
||||
promise: premiumFeePromise,
|
||||
},
|
||||
{
|
||||
resultKey: "pricingResults",
|
||||
promise: pricingPromise,
|
||||
resultKey: "premiumFeeWithPrice",
|
||||
promise: premiumFeeWithPricePromise,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
@ -199,9 +182,10 @@ export default {
|
|||
vm.$refs.datePicker.initializeComponent(resultMap.datePickerInitialData);
|
||||
vm.$refs.locationAlerts.initializeComponent(resultMap.alertReasons);
|
||||
vm.selectableDatesData = resultMap.datePickerInitialData.initialShopTimeSlotsResponse;
|
||||
if (resultMap.premiumFee) {
|
||||
vm.mobilePremiumAppointmentFee = resultMap.pricingResults[0];
|
||||
}
|
||||
vm.mobilePremiumAppointmentFee = resultMap.premiumFeeWithPrice
|
||||
? resultMap.premiumFeeWithPrice[0]
|
||||
: null;
|
||||
vm.updateFooterButtonText(vm.selectedTimeSlotData);
|
||||
});
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -216,11 +200,11 @@ export default {
|
|||
return this.$store.getters.order.serviceLocation.appointmentType;
|
||||
},
|
||||
timeSlotsForSelectedDate() {
|
||||
if (this.selectedDate === null) {
|
||||
if (!this.selectedDate) {
|
||||
return null;
|
||||
}
|
||||
return this.selectableDatesData.days?.find(
|
||||
(selectableDate) => selectableDate.dateString === this.selectedDate.dateString
|
||||
(selectableDate) => selectableDate.date === this.selectedDate
|
||||
);
|
||||
},
|
||||
appointmentDateAndTime() {
|
||||
|
|
@ -230,10 +214,9 @@ export default {
|
|||
const timeSlotSelectedObject = this.getTimeSlotObjectFromTimeSlotId(
|
||||
this.selectedTimeSlotData.id
|
||||
);
|
||||
|
||||
if (timeSlotSelectedObject) {
|
||||
return {
|
||||
date: this.selectedDate.dateString,
|
||||
date: this.selectedDate,
|
||||
startTime: timeSlotSelectedObject.startTime,
|
||||
endTime: timeSlotSelectedObject.endTime,
|
||||
routeCode: this.selectedTimeSlotData.id,
|
||||
|
|
@ -275,7 +258,7 @@ export default {
|
|||
},
|
||||
getTimeSlotObjectFromTimeSlotId(timeSlotId) {
|
||||
const timeSlots = this.selectableDatesData.days.find(
|
||||
(selectableDate) => selectableDate.dateString === this.selectedDate.dateString
|
||||
(selectableDate) => selectableDate.date === this.selectedDate
|
||||
).timeSlots;
|
||||
return timeSlots.find((timeSlot) => timeSlot.id === timeSlotId);
|
||||
},
|
||||
|
|
@ -325,7 +308,7 @@ export default {
|
|||
},
|
||||
convertSelectedDateToShortMonthAndDay(selectedDate) {
|
||||
// This conversion ensures we don't get get GMT induced date changes
|
||||
const dateObject = new Date(`${selectedDate.dateString}T00:00:00`);
|
||||
const dateObject = new Date(`${selectedDate}T00:00:00`);
|
||||
// Ex: April 25
|
||||
return dateObject.toLocaleDateString("en-us", { month: "short", day: "numeric" });
|
||||
},
|
||||
|
|
@ -365,7 +348,7 @@ export default {
|
|||
};
|
||||
}
|
||||
},
|
||||
selectedTimeSlotData() {
|
||||
selectedTimeSlotData(newValue) {
|
||||
this.updateFooterButtonText(this.selectedTimeSlotData);
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -78,13 +78,14 @@ export default {
|
|||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTimeSlotId: null,
|
||||
selectedTimeSlotId: this.modelValue.id,
|
||||
timeSlotModalListButton: timeSlotModalListButton,
|
||||
};
|
||||
},
|
||||
setup(props) {
|
||||
const { handleChange } = useField("time-slot-modal-question", props.validationRules);
|
||||
|
||||
// Run validation on component load
|
||||
handleChange(props.modelValue.id);
|
||||
return {
|
||||
handleChange,
|
||||
};
|
||||
|
|
@ -92,6 +93,11 @@ export default {
|
|||
watch: {
|
||||
modelValue() {
|
||||
// Run component validation that is used at parent level
|
||||
if (this.modelValue.isPremiumAppointment) {
|
||||
this.selectedTimeSlotId = this.addPremiumFlagToInput(this.modelValue.id);
|
||||
} else {
|
||||
this.selectedTimeSlotId = this.modelValue.id;
|
||||
}
|
||||
this.handleChange(this.modelValue.id);
|
||||
},
|
||||
availableTimeSlots(newValue) {
|
||||
|
|
@ -162,7 +168,7 @@ export default {
|
|||
}
|
||||
|
||||
// This conversion ensures we don't get get GMT induced date changes
|
||||
const dateObject = new Date(`${this.dateAndTimeSlotData.dateString}T00:00:00`);
|
||||
const dateObject = new Date(`${this.dateAndTimeSlotData.date}T00:00:00`);
|
||||
// Ex: Tuesday, April 22
|
||||
return dateObject.toLocaleDateString("en-us", {
|
||||
weekday: "long",
|
||||
|
|
@ -203,12 +209,6 @@ export default {
|
|||
},
|
||||
// fires any time the modal is closed, AFTER "closeModal" fires if footer button is used
|
||||
onModalClosed() {
|
||||
// Reset component state to parent's state
|
||||
if (this.modelValue.isPremiumAppointment) {
|
||||
this.selectedTimeSlotId = this.addPremiumFlagToInput(this.modelValue.id);
|
||||
} else {
|
||||
this.selectedTimeSlotId = this.modelValue.id;
|
||||
}
|
||||
this.$emit("time-slot-modal-closed");
|
||||
},
|
||||
// Expected input: "HH:MM"
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ export default {
|
|||
city: this.getServiceCityFromStore(),
|
||||
state: this.getServiceStateFromStore(),
|
||||
zipCode: this.getServiceZipCodeFromStore(),
|
||||
isVehicleProtected: null,
|
||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||
isGlassServiceableInshop: null,
|
||||
isRecalibrationServiceableInshop: null,
|
||||
isGlassServiceableMobile: null,
|
||||
|
|
@ -348,6 +348,9 @@ export default {
|
|||
getServiceZipCodeFromStore() {
|
||||
return store.getters.order.serviceLocation.zipCode;
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return store.getters.order.serviceLocation.isVehicleProtected;
|
||||
},
|
||||
getSelectedAppointmentType() {
|
||||
return store.getters.order.serviceLocation.appointmentType;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ export default {
|
|||
.button-auxillary-copy {
|
||||
box-sizing: border-box;
|
||||
justify-content: right;
|
||||
line-height: 1.25rem !important;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
align-items: center;
|
||||
|
|
@ -205,7 +205,7 @@ export default {
|
|||
}
|
||||
|
||||
.loader:after {
|
||||
background-color: $gray-300 !important;
|
||||
background-color: $gray-300;
|
||||
height: 1rem;
|
||||
width: 1rem;
|
||||
}
|
||||
|
|
@ -221,7 +221,7 @@ export default {
|
|||
}
|
||||
|
||||
&.gray {
|
||||
color: $gray-600 !important;
|
||||
color: $gray-600;
|
||||
background-color: $gray-100;
|
||||
padding-left: 0.125rem;
|
||||
padding-right: 0.125rem;
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ export default {
|
|||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.5rem !important;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.5rem;
|
||||
gap: 0.25rem;
|
||||
|
||||
.alert-heading {
|
||||
|
|
|
|||
|
|
@ -39,11 +39,13 @@ const getDefaultState = () => {
|
|||
},
|
||||
serviceLocation: {
|
||||
address: null,
|
||||
address2: null,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCode: null,
|
||||
zipCodeCtu: null,
|
||||
appointmentType: null,
|
||||
isVehicleProtected: null,
|
||||
provider: {
|
||||
providerNumber: null,
|
||||
address: {
|
||||
|
|
@ -1190,7 +1192,6 @@ export const actions = {
|
|||
method: endpoints.GetShopTimeSlots.method,
|
||||
endpoint: endpoints.GetShopTimeSlots.url,
|
||||
payload: payload,
|
||||
logApiCall: false,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
@ -1242,7 +1243,6 @@ export const actions = {
|
|||
method: endpoints.GetMobileTimeSlots.method,
|
||||
endpoint: endpoints.GetMobileTimeSlots.url,
|
||||
payload: payload,
|
||||
logApiCall: false,
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -56,3 +56,9 @@ body {
|
|||
height: calc(100% - 72px);
|
||||
}
|
||||
}
|
||||
//Disable scroll of main container when modal is open
|
||||
.modal-open {
|
||||
.page-container-grouped-styles {
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
position: relative;
|
||||
z-index: 5;
|
||||
@include box-shadow-hover($blue-300);
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,3 +190,6 @@ $alert-color-scale: 40%;
|
|||
// This affects all [Bootstrap] modals
|
||||
$modal-fade-transform: translate(0, 100%);
|
||||
$modal-backdrop-opacity: 0;
|
||||
|
||||
//Disable default !important behavior
|
||||
$enable-important-utilities: false;
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ export default {
|
|||
|
||||
+ .list-card-content {
|
||||
outline: none;
|
||||
display: block;
|
||||
display: flex;
|
||||
position: relative;
|
||||
|
||||
p {
|
||||
|
|
|
|||
Loading…
Reference in a new issue