Cursor converted store/index.js to typescript file, compiles successfuly

This commit is contained in:
Matt Sykes 2026-03-09 13:55:11 -04:00
parent 7ae16a5610
commit 90f5022787
8 changed files with 853 additions and 105 deletions

View file

@ -1,3 +1,3 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
presets: ["@vue/cli-plugin-babel/preset", "@babel/preset-typescript"],
};

View file

@ -5,13 +5,14 @@ module.exports = {
coverageReporters: ["html", "text", "jest-junit", "cobertura"], reporters: ['default', 'jest-junit'],
testResultsProcessor: "jest-junit",
preset: "@vue/cli-plugin-unit-jest",
transform: { "^.+\\.vue$": "@vue/vue3-jest",
"^.+\\.mjs$": "babel-jest",
transform: {
"^.+\\.vue$": "@vue/vue3-jest",
"^.+\\.(js|jsx|ts|tsx|mjs)$": "babel-jest",
},
transformIgnorePatterns: ["'/node_modules/(?!vee-validate)"],
moduleFileExtensions: ["js", "vue"],
moduleFileExtensions: ["js", "ts", "vue"],
collectCoverageFrom: [
"src/**/*.{js,vue}",
"src/**/*.{js,ts,vue}",
"!src/main.js",
"!src/constants/*.js",
"!src/router/**/*.js",

666
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -14,6 +14,7 @@
"dependencies": {
"@adyen/adyen-web": "^6.27.0",
"@iframe-resizer/child": "^5.3.3",
"@popperjs/core": "^2.11.8",
"axios": "^0.30.2",
"bootstrap": "^5.3.3",
"core-js": "^3.38.1",
@ -32,8 +33,11 @@
},
"devDependencies": {
"@babel/eslint-parser": "^7.25.1",
"@babel/preset-typescript": "^7.28.5",
"@typescript-eslint/parser": "^5.62.0",
"@vue/cli-plugin-babel": "~5.0.8",
"@vue/cli-plugin-eslint": "~5.0.8",
"@vue/cli-plugin-typescript": "~5.0.8",
"@vue/cli-plugin-unit-jest": "~5.0.8",
"@vue/cli-service": "~5.0.8",
"@vue/compiler-sfc": "^3.4.38",
@ -64,6 +68,13 @@
"no-unused-vars": "off"
},
"overrides": [
{
"files": [
"**/*.ts",
"**/*.tsx"
],
"parser": "@typescript-eslint/parser"
},
{
"files": [
"**/__tests__/*.{j,t}s?(x)",

View file

@ -1,4 +1,5 @@
import { createStore } from "vuex";
import type { RootState } from "./types";
import { endpoints } from "@/constants/endpoints.js";
import { storeMutations } from "@/constants/store-mutations";
import { sessionStorageKeyConstants } from "@/constants/session-storage.js";
@ -1188,7 +1189,7 @@ export const actions = {
};
reader.readAsDataURL(image);
}).then((result) => {
const components = result.split(",");
const components = (result as string).split(",");
const contentType = image.type;
const imageBase64 = components[1];
@ -2231,7 +2232,9 @@ export const actions = {
// Only set handler if this is the very first call in this session
if (!hasCalled) {
options.additionalSuccessEventDataHandler = (response) =>
(options as Record<string, unknown>).additionalSuccessEventDataHandler = (response: {
data: { provisionalTriggers: unknown; days?: { date: string }[] };
}) =>
getTimeSlotsAdditionalEventData(
response.data.provisionalTriggers,
order.serviceLocation.zipCode,
@ -2299,11 +2302,14 @@ export const actions = {
// Only set handler if this is the very first call in this session
if (!hasCalled) {
options.additionalSuccessEventDataHandler = (response) =>
(options as Record<string, unknown>).additionalSuccessEventDataHandler = (response: {
data: { provisionalTriggers: unknown; days?: { date: string }[] };
}) =>
getTimeSlotsAdditionalEventData(
response.data.provisionalTriggers,
order.serviceLocation.zipCode,
response.data.days?.[0]?.date
response.data.days?.[0]?.date,
undefined
);
}
@ -3508,7 +3514,7 @@ export const actions = {
sessionStorageKeyConstants.SUBMITTED_STATE,
JSON.stringify(submittedState)
);
window.sessionStorage.setItem("createNewSessionForHeritage", true);
window.sessionStorage.setItem("createNewSessionForHeritage", "true");
// clear vuex
context.commit(storeMutations.RESET_STATE);
@ -3642,7 +3648,7 @@ export const actions = {
},
};
export default createStore({
export default createStore<RootState>({
plugins: [
createPersistedState(),
sharedMutations({
@ -3659,9 +3665,18 @@ export default createStore({
actions,
});
export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItems) {
interface LineItemWithTax {
partNumber?: string;
laborAmount?: string | number;
salesTax?: number;
}
export function mapTaxedLineItemsToStoreFormat(
availableLineItems: LineItemWithTax[],
storeLineItems: Record<string, LineItemWithTax[]>
) {
// clone the lineItems array because what we're passing in is referencing the store directly
const lineItems = deepClone(storeLineItems);
const lineItems = deepClone(storeLineItems) as Record<string, LineItemWithTax[]>;
for (let [category, lineItemsInCategory] of Object.entries(lineItems)) {
lineItemsInCategory = lineItemsInCategory ?? [];
@ -3682,7 +3697,7 @@ export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItem
(lineItem) => lineItem.partNumber == "WSREPAIR"
);
repairChipLineItems = repairChipLineItems.sort(
(a, b) => parseFloat(b.laborAmount) - parseFloat(a.laborAmount)
(a, b) => parseFloat(String(b.laborAmount)) - parseFloat(String(a.laborAmount))
);
// get the supporting items from the available line items (taxed) that ARE repair chips and sort them by descending labor amount
@ -3690,7 +3705,7 @@ export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItem
(lineItem) => lineItem.partNumber == "WSREPAIR"
);
availableRepairChipLineItems = availableRepairChipLineItems.sort(
(a, b) => parseFloat(b.laborAmount) - parseFloat(a.laborAmount)
(a, b) => parseFloat(String(b.laborAmount)) - parseFloat(String(a.laborAmount))
);
// go through each one of those mapping the taxes to the correct chip

210
src/store/types.ts Normal file
View file

@ -0,0 +1,210 @@
/**
* Vuex store state type definitions.
* Mirrors the structure from getDefaultState() in store/index.ts
*/
export interface VehicleRegistration {
licensePlate: string | null;
}
export interface VehicleState {
year: number | null;
make: string | null;
model: string | null;
style: string | null;
vehicleSubType: string | null;
vehicleSpecialClass: string | null;
isBigTruck: boolean;
carId: string | null;
category: string | null;
vin: string | null;
canSafeliteService: boolean | null;
imageUrl: string | null;
imageVifNumber: string | null;
imageColor: string | null;
registration: VehicleRegistration;
}
export interface ProviderAddress {
streetAddress: string | null;
city: string | null;
state: string | null;
zipCode: string | null;
zipCodeCtu: string | null;
}
export interface ServiceLocationProvider {
providerNumber: string | null;
address: ProviderAddress;
}
export interface ServiceLocationState {
address: string | null;
address2: string | null;
city: string | null;
state: string | null;
zipCode: string | null;
zipCodeCtu: string | null;
appointmentType: string | null;
isVehicleProtected: boolean | null;
provider: ServiceLocationProvider;
techNotes: string | null;
}
export interface CustomerState {
firstName: string | null;
lastName: string | null;
emailAddress: string | null;
phoneNumber: string | null;
isSmsOptIn: boolean | null;
waitListRequested: boolean | null;
}
export interface DamageState {
isRepair: boolean | null;
numberOfChips: number | null;
glassToReplace: string | null;
partQuestionAnswers: unknown[] | null;
moldingQuestionAnswers: unknown[] | null;
capabilityQuestionAnswers: unknown[] | null;
dateOfLoss: string | null;
damageCause: string | null;
installOemGlass: boolean | null;
}
export interface LineItemsState {
glassParts: unknown[] | null;
supportingItems: unknown[] | null;
vaps: unknown[] | null;
serverData: unknown | null;
promos: unknown[] | null;
}
export interface InsuranceCoverageState {
isVerified: boolean | null;
coverageStatus: string | null;
coverageSubStatus: string | null;
coverageType: string | null;
coverageVerificationType: string | null;
}
export interface CcTokenState {
subscriptionId: string | null;
expMonth: string | null;
expYear: string | null;
cardType: string | null;
billToPostalCode: string | null;
billToFirstName: string | null;
billToLastName: string | null;
referenceNumber: string | null;
authCode: string | null;
transactionId: string | null;
transReferenceNumber: string | null;
lastFour: string | null;
}
export interface PaymentState {
isInsurance: boolean | null;
insuranceCoverage: InsuranceCoverageState;
parentAccountNumber: number;
billToAccountNumber: string | null;
isPia: boolean | null;
piaType: string | null;
inactivePromos: unknown[] | null;
paypalToken: string | null;
nextGenSettledAmount: number;
ccToken: CcTokenState;
}
export interface PolicyState {
currentDeductible: number;
originalDeductible: number;
policyNumber: string | null;
isItac: boolean;
additionalAuthFlag: string | null;
isNoComp: boolean;
insuranceCompanyName: string | null;
}
export interface ScheduleState {
date: string | null;
startTime: string | null;
endTime: string | null;
routeCode: string | null;
jobMaxMinutes: number | null;
jobMinMinutes: number | null;
}
export interface OrderState {
vehicle: VehicleState;
serviceLocation: ServiceLocationState;
customer: CustomerState;
damage: DamageState;
lineItems: LineItemsState;
payment: PaymentState;
policy: PolicyState;
schedule: ScheduleState;
referralNumber: string | null;
referralSequenceNumber: string | null;
referralDate: string | null;
referralCorrelationId: string | null;
eon: string | null;
workOrderNumber: string | null;
workOrderId: string | null;
customerPortalLoginToken: string | null;
lockToken: string | null;
settledTenderAmount: number;
isRecalAckOptIn: boolean;
isRecalAcknowledgedForScheduling: string;
isMSRFeeApplicable: boolean;
}
export interface ApplicationUserState {
eventBus: unknown[];
pageData: Record<string, unknown>;
savedSessionTimeout: Date | null;
saveSessionPromise: Promise<unknown> | null;
savedSessionId: string | null;
crmCustomerId: string | null;
lastPageVisited: string | null;
experiments: unknown[];
triggeredSiteEntry: boolean;
affiliateCookies: unknown[];
loggingOption: boolean;
hasAlreadyTriggeredError: boolean;
}
export interface RootState {
order: OrderState;
applicationUser: ApplicationUserState;
}
/** External parameter state (stored in sessionStorage, not Vuex) */
export interface ExternalParameterState {
isExternalParameter: string;
qsStash: unknown;
vehicle: {
year: string | null;
make: string | null;
model: string | null;
style: string | null;
};
vehicleDamage: {
damageType: string | null;
isRepair: boolean | null;
numberOfChips: number | null;
};
estimate: {
vinSelection: string | null;
};
serviceZip: {
zipCode: string | null;
};
quote: {
isInsurance: boolean | null;
servicePackage: string | null;
};
customer: {
emailAddress: string | null;
};
}

21
tsconfig.json Normal file
View file

@ -0,0 +1,21 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"strict": false,
"noImplicitAny": false,
"strictNullChecks": false,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"resolveJsonModule": true,
"isolatedModules": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.vue"],
"exclude": ["node_modules", "dist", "playwright-tests"]
}

View file

@ -3,6 +3,10 @@ const { environmentVariablesWithDefaults } = require('./environment-variables.js
module.exports = {
outputDir: "dist/fmg",
chainWebpack: (config) => {
// Override Vue CLI TypeScript plugin's main.ts entry for gradual migration
config.entry("app").clear().add("./src/main.js");
},
publicPath: "/fmg",
css: {
loaderOptions: {