{"version":3,"file":"js/219.396879b83943dfa1b3b1.chunk.js","mappings":"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","sources":["webpack://ti_west/./app/components/purchase-form/purchase-form.constants.ts","webpack://ti_west/./app/components/purchase-form/purchase-form.util.ts","webpack://ti_west/./app/utility/exam-transfer-window.ts"],"sourcesContent":["import { StringUnion } from '@app/interfaces/string-union';\n\nconst MATERIAL_TAB_ID = 'MATERIAL_TAB';\nconst EXAM_TAB_ID = 'EXAM_TAB';\n\nconst TabIds = StringUnion(MATERIAL_TAB_ID, EXAM_TAB_ID);\nexport type TabIdType = typeof TabIds.type;\n\nconst ONSITE = 'ONSITE';\nconst VIRTUAL = 'VIRTUAL';\nconst PROMETRIC = 'PROMETRIC';\n\nexport const TestingLocations = StringUnion(ONSITE, VIRTUAL, PROMETRIC);\nexport type TestingLocationType = typeof TestingLocations.type;\n\ntype PurchaseTab = {\n\tclassName: string;\n\tdescription: string;\n\telementId: string;\n\tformName: string;\n\tid: TabIdType;\n\tpanelName: string;\n\ttitle: string;\n};\n\nconst materialTab: PurchaseTab = {\n\tclassName: 'purchase-tabs__button--materials',\n\tdescription:\n\t\t'Select The Institutes Designations\\' exam window you are targeting as well as your materials package.',\n\telementId: 'tab-materials',\n\tformName: 'material-form',\n\tid: MATERIAL_TAB_ID,\n\tpanelName: 'panel-materials',\n\ttitle: 'Buy Materials',\n};\n\nconst examTab: PurchaseTab = {\n\tclassName: 'purchase-tabs__button--exam',\n\tdescription:\n\t\t'Save on The Institutes Designations\\' exams if you purchase before the window opens or purchase a retake in the same window. Discount is applied in the cart.',\n\telementId: 'tab-exam',\n\tformName: 'exam-form',\n\tid: EXAM_TAB_ID,\n\tpanelName: 'panel-exam',\n\ttitle: 'Buy Exam',\n};\n\nexport const PURCHASE_TAB_STRINGS: Record = Object.freeze({\n\t[MATERIAL_TAB_ID]: materialTab,\n\t[EXAM_TAB_ID]: examTab,\n});\n\nexport const LOCAL_STORAGE_ID = 'purchaseTabs';\nexport const LOCAL_STORAGE_FORM_ID = 'purchaseMaterialsForm';\n","/**\n * @file Utilities for purchase form components.\n */\nimport classNames from 'classnames';\nimport cookies from 'js-cookie';\nimport merge from 'lodash.merge';\nimport { DateTime } from 'luxon';\n\nimport { FormValues } from '@app/interfaces/form';\nimport {\n\tMarketing,\n\tMarketingExamWindow,\n} from '@app/interfaces/store/content/marketing';\nimport {\n\tExamWindow,\n\tProgramRule,\n} from '@app/interfaces/store/content/program-rule';\nimport { formatExamWindowLabel } from '@app/utility/exam-transfer-window';\nimport { getParameterByName } from '@app/utility/getParameterByName';\nimport {\n\tfindApplicablePrice,\n\tfindApplicableMaterialPrice,\n} from '@app/utility/price';\n\nimport {\n\tLOCAL_STORAGE_FORM_ID,\n\tLOCAL_STORAGE_ID,\n\tPURCHASE_TAB_STRINGS,\n\tTabIdType,\n} from './purchase-form.constants';\nimport {\n\tExamExamWindowOptions,\n\tExamFields,\n\tExamOption,\n\tGroupedExamOptions,\n\tMaterialExamWindowOptions,\n\tMaterialOption,\n\tMergedProduct,\n\tMergedProducts,\n\tPurchaseOptions,\n} from './purchase-form.types';\n\n/**\n * Determines if a product is an online course.\n *\n * @param {MergedProduct} mergedProduct Merged product.\n *\n * @returns {boolean} True if product is an online course.\n */\nconst isOnlineCourse = ({\n\tgradeForExam,\n\tpublished = true,\n}: MergedProduct): boolean => published && !gradeForExam;\n\n/**\n * Determines if a product is a virtual exam.\n *\n * @param {boolean} published published product.\n * @param {boolean=} gradeForExam Grade For Exam (determines if VE).\n * @returns {boolean} True if product is a virtual exam.\n */\nexport const isVirtualExam = (\n\tpublished: boolean | undefined = true,\n\tgradeForExam?: boolean,\n): boolean => published && gradeForExam === true;\n\n/**\n * Returns a callback function to map an ID to Product object.\n *\n * @param {MergedProducts} products\n * @returns {(id:number) => MergedProduct} Mapping of ID to product.\n */\nconst mapIdToProduct =\n\t(products: MergedProducts): ((id: number) => MergedProduct) =>\n\t(productId: number) =>\n\t\tproducts[productId];\n\n/**\n * Get virtual exams from online course ids and products.\n *\n * @param {number[]} onlineCourseIds Online course IDs.\n * @param {MergedProducts} products Product listing.\n *\n * @returns {MergedProduct[]} List of virtual exam products.\n */\nconst getVirtualExams = (\n\tonlineCourseIds: number[],\n\tproducts: MergedProducts,\n): MergedProduct[] =>\n\tonlineCourseIds\n\t\t.map(mapIdToProduct(products))\n\t\t.filter(({ gradeForExam, published }) =>\n\t\t\tisVirtualExam(published, gradeForExam),\n\t\t);\n\n/**\n * Checks if exam is available within an exam window based on input products.\n *\n * @param {MergedProducts} products Merged products.\n * @returns {(window:ExamWindow) => boolean} Check for any valid exams.\n */\nexport const isExamAvailable =\n\t(products: MergedProducts): ((window: ExamWindow) => boolean) =>\n\t({ examIds, onlineCourseIds }: ExamWindow) =>\n\t\t(examIds.length || getVirtualExams(onlineCourseIds, products).length) > 0;\n\n/**\n * Map exam window to exam window label-value, with nested material options per\n * exam window.\n *\n * @param {MergedProducts} products Merged products.\n * @returns {(window: ExamWindow) => MaterialExamWindowOptions} Options for materials\n */\nconst mapWindowToMaterial =\n\t(\n\t\tproducts: MergedProducts,\n\t): ((window: ExamWindow) => MaterialExamWindowOptions) =>\n\t({\n\t\tid: value = '',\n\t\tstartDate = '',\n\t\tendDate = '',\n\t\tpackageIds = [],\n\t\tprintedMaterialIds = [],\n\t\tonlineCourseIds = [],\n\t}: ExamWindow) => ({\n\t\tvalue,\n\t\tlabel: formatExamWindowLabel(startDate, endDate),\n\t\toptions: [\n\t\t\t...packageIds.map(mapIdToProduct(products)),\n\t\t\t...printedMaterialIds.map(mapIdToProduct(products)),\n\t\t\t...onlineCourseIds.map(mapIdToProduct(products)).filter(isOnlineCourse),\n\t\t].map(\n\t\t\t({\n\t\t\t\ttitle: label = '',\n\t\t\t\tid,\n\t\t\t\tdetailedInformation: description = '',\n\t\t\t\tprices,\n\t\t\t}) => ({\n\t\t\t\tlabel,\n\t\t\t\tvalue: id.toString(),\n\t\t\t\tdescription,\n\t\t\t\texamWindowStartDate: startDate,\n\t\t\t\t...findApplicableMaterialPrice(\n\t\t\t\t\tprices,\n\t\t\t\t\tstartDate ? DateTime.fromFormat(startDate, 'yyyy-MM-dd') : undefined,\n\t\t\t\t),\n\t\t\t}),\n\t\t),\n\t});\n\n/**\n * Map a product to an exam option.\n *\n * @param {MergedProduct} mergedProduct Merged product.\n * @returns {ExamOption} Exam option.\n */\nconst mapProductToExam = (\n\t{\n\t\tdetailedInformation: description = '',\n\t\texam,\n\t\tid,\n\t\tprices,\n\t\ttitle: label = '',\n\t}: MergedProduct,\n\tstartDate: string,\n\tendDate?: string,\n): ExamOption => ({\n\tdescription,\n\tlabel,\n\texamWindowStartDate: startDate,\n\t...findApplicablePrice(\n\t\tprices,\n\t\tstartDate ? DateTime.fromFormat(startDate, 'yyyy-MM-dd') : undefined,\n\t\tendDate ? DateTime.fromFormat(endDate, 'yyyy-MM-dd') : undefined,\n\t),\n\tvalue: id.toString(),\n\t...(exam?.courseCode && { courseCode: exam.courseCode }),\n\t...(exam?.beginning && { examDate: exam.beginning }),\n\t...(exam?.type && { examType: exam.type }),\n});\n\n/**\n * Group exams by their exam types.\n *\n * @param {ExamOption[]} exams List of exams with examType.\n * @returns {GroupedExamOptions} Grouped exams with examType as key.\n */\nconst groupExamByType = (exams: ExamOption[] = []): GroupedExamOptions =>\n\texams.reduce(\n\t\t(group: GroupedExamOptions, exam) => ({\n\t\t\t...group,\n\t\t\t...(exam.examType !== undefined &&\n\t\t\t\tgroup[exam.examType] && {\n\t\t\t\t\t[exam.examType]: [...group[exam.examType], exam],\n\t\t\t\t}),\n\t\t}),\n\t\t{ VIRTUAL: [], PROMETRIC: [], INTERNET: [] },\n\t);\n\n/**\n * Map exam window to exam window label-value, with nested exam options per\n * exam, grouped by exam-type.\n *\n * @param {MergedProducts} products Merged products.\n * @returns {(window: ExamWindow) => ExamExamWindowOptions} Options for exams.\n */\nconst mapWindowToExam =\n\t(products: MergedProducts): ((window: ExamWindow) => ExamExamWindowOptions) =>\n\t({\n\t\tid: value = '',\n\t\tstartDate = '',\n\t\tendDate = '',\n\t\tonlineCourseIds = [],\n\t\texamIds = [],\n\t}: ExamWindow) => {\n\t\tconst physicalExams = examIds.map(mapIdToProduct(products));\n\n\t\tconst virtualExams = getVirtualExams(onlineCourseIds, products);\n\n\t\tconst label = formatExamWindowLabel(startDate, endDate);\n\n\t\tconst options = {\n\t\t\t...groupExamByType(\n\t\t\t\tphysicalExams.map((p) => mapProductToExam(p, startDate, endDate)),\n\t\t\t),\n\t\t\t...(virtualExams.length && {\n\t\t\t\tVIRTUAL: virtualExams.map((p) =>\n\t\t\t\t\tmapProductToExam(p, startDate, endDate),\n\t\t\t\t),\n\t\t\t}),\n\t\t};\n\n\t\treturn {\n\t\t\tlabel,\n\t\t\tvalue,\n\t\t\toptions,\n\t\t};\n\t};\n\n/**\n * Checks if exam window is published on the CMS.\n *\n * @param {MarketingExamWindow[]} marketingExamWindows Exam windows from CMS.\n * @returns {(window:ExamWindow) => boolean | undefined} True if published.\n */\nexport const isExamWindowPublished =\n\t(\n\t\tmarketingExamWindows: MarketingExamWindow[],\n\t): ((window: ExamWindow) => boolean | undefined) =>\n\t(examWindow: ExamWindow) =>\n\t\t(marketingExamWindows.find(({ apiId }) => examWindow.id === apiId) || {})\n\t\t\t.isPublished;\n\n/**\n * Get purchase options based on course's exam windows and content store.\n *\n * @param {ExamWindow[]} examWindows Exam windows.\n * @param {ProgramRule} programRule Redux store for program rule content.\n * @param {Marketing} marketing Redux store for marketing content.\n * @param {TabIdType | undefined} tabId Specify tab ID to display one tab.\n * @returns {PurchaseOptions} Purchase options split by exam and material.\n */\nexport const getPurchaseOptions = (\n\texamWindows: ExamWindow[] = [],\n\tprogramRule: ProgramRule,\n\tmarketing: Marketing,\n\ttabId?: TabIdType,\n): PurchaseOptions => {\n\tconst products = merge(programRule.products, marketing.topicCourses || {});\n\tconst validExamWindows = examWindows.filter(\n\t\tisExamWindowPublished(marketing.examWindows || []),\n\t);\n\n\t// Get material options by mapping exam window products to a list of\n\t// materials, then filtering in non-empty lists.\n\tconst getMaterialOptions = () =>\n\t\tvalidExamWindows\n\t\t\t.map(mapWindowToMaterial(products))\n\t\t\t.filter(({ options }) => options.length);\n\n\t// Get exam options by filtering in exam windows that have exams within them,\n\t// then map exam window products to a list of exams, grouped by exam type.\n\tconst getExamOptions = () =>\n\t\tvalidExamWindows\n\t\t\t.filter(isExamAvailable(products))\n\t\t\t.map(mapWindowToExam(products));\n\n\treturn {\n\t\t...((tabId === 'MATERIAL_TAB' || !tabId) && {\n\t\t\tmaterialOptions: getMaterialOptions(),\n\t\t}),\n\t\t...((tabId === 'EXAM_TAB' || !tabId) && { examOptions: getExamOptions() }),\n\t};\n};\n\n/**\n * Returns material/exam price max and min.\n * @param options\n */\nexport const getMinMaxPriceFromOptions = (\n\toptions: MaterialOption[] | ExamOption[],\n) => {\n\tlet max;\n\tlet min;\n\n\tfor (const option of options) {\n\t\tif (!min || option.salePrice < min) {\n\t\t\tmin = option.salePrice;\n\t\t}\n\n\t\tif (!max || option.currentPrice > max) {\n\t\t\tmax = option.currentPrice;\n\t\t}\n\t}\n\n\treturn [min, max];\n};\n\n/**\n * Redirects to Gatekeeper login page.\n *\n * Takes in optional anchorId, to scroll to after redirect after log in.\n *\n * @param {string} loginUrl Gatekeeper login URL.\n * @param {string=} anchorId Anchor ID.\n */\nexport const redirectToLogin = (loginUrl: string, anchorId: string = '') => {\n\tlet url = loginUrl;\n\n\tconst returnUrlParam =\n\t\tgetParameterByName('returnUrl', loginUrl) || ''.split('?')[0].split('#')[0];\n\tconst cancelUrlParam =\n\t\tgetParameterByName('cancelUrl', loginUrl) || ''.split('?')[0].split('#')[0];\n\n\tconst anchor = anchorId ? `#${anchorId}` : '';\n\n\turl = url.replace(\n\t\t/returnUrl(=([^&#]*)|&|#|$)/,\n\t\t`returnUrl=${encodeURIComponent(`${returnUrlParam}${anchor}`)}`,\n\t);\n\turl = url.replace(\n\t\t/cancelUrl(=([^&#]*)|&|#|$)/,\n\t\t`cancelUrl=${encodeURIComponent(`${cancelUrlParam}${anchor}`)}`,\n\t);\n\n\twindow.location.assign(url);\n};\n\n/**\n * If user is not authenticated, create a CART_UPDATE cookie.\n *\n * @param {boolean} isAuthenticated True if user is authenticated via Gatekeeper\n */\nexport const setUpdateCookie = (isAuthenticated: boolean) => {\n\tif (!isAuthenticated && !cookies.get('WCSNUM')) {\n\t\tcookies.set('CART_UPDATE', 'true', { secure: true });\n\t}\n};\n\n/**\n * Get price range string from minimum and maximum values.\n *\n * @param {number} min Minimum value.\n * @param {number} max Maximum value.\n * @returns {string} Price range string.\n */\nexport const getPriceRange = (min: number = 0, max: number = 0): string => {\n\t// If min and max are empty, return nothing.\n\tif (!min && !max) {\n\t\treturn '';\n\t}\n\n\t// If min XOR max, return truthy choice.\n\tif (min ? !max : max) {\n\t\treturn `$${(min || max).toString()}`;\n\t}\n\n\t// If min and max are equal, return one.\n\tif (min === max) {\n\t\treturn `$${min.toString()}`;\n\t}\n\n\treturn `$${min}-$${max}`;\n};\n\n/**\n * Utility for local storage management.\n */\nexport const localStorageUtil = {\n\t/**\n\t * Sets local storage item with tab ID and course code for later consumption\n\t * by the load method.\n\t *\n\t * @param {TabIdType} tabId Tab ID.\n\t * @param {string} courseCode Course code.\n\t */\n\tsaveTab: (tabId: TabIdType, courseCode: string) => {\n\t\tlocalStorage.setItem(\n\t\t\tLOCAL_STORAGE_ID,\n\t\t\tJSON.stringify({ tab: tabId, courseCode }),\n\t\t);\n\t},\n\n\t/**\n\t * Loads from local storage to set current tab for course.\n\t *\n\t * @callback onLoad On load callback that takes in tab ID.\n\t * @param {string} courseCode Course code.\n\t */\n\tloadTab: (onLoad: (tabId: TabIdType) => void, courseCode: string) => {\n\t\tconst { tab = '', courseCode: code = '' } = JSON.parse(\n\t\t\tlocalStorage.getItem(LOCAL_STORAGE_ID) || '{}',\n\t\t);\n\t\tif (courseCode === code) {\n\t\t\tlocalStorage.removeItem(LOCAL_STORAGE_ID);\n\t\t\tonLoad(tab);\n\t\t}\n\t},\n\n\t/**\n\t * Loads from local storage to set overlay and title for form.\n\t *\n\t * @callback onLoad On load callback that takes in overlay and title.\n\t * @param {string} courseCode Course code.\n\t */\n\tloadForm: (\n\t\tonLoad: (isOpen: boolean, title: string) => void,\n\t\tcourseCode: string,\n\t) => {\n\t\tconst { openOverlayCode = '', storedTitle = '' } = JSON.parse(\n\t\t\tlocalStorage.getItem(LOCAL_STORAGE_FORM_ID) || '{}',\n\t\t);\n\n\t\tif (openOverlayCode === courseCode && storedTitle.length) {\n\t\t\tlocalStorage.removeItem(LOCAL_STORAGE_FORM_ID);\n\t\t\tonLoad(true, storedTitle);\n\t\t}\n\t},\n};\n\n/**\n * Form util methods.\n */\nexport const formUtil = {\n\tcreateFormName: (...strings: string[]) => strings.join('-'),\n\tcreateMaterialFields: (id: number) => ({\n\t\tEXAMWINDOW_FIELDNAME: `materials-${id.toString()}-select-exam-window`,\n\t\tMATERIAL_FIELDNAME: `materials-${id.toString()}-radio-group`,\n\t}),\n\tcreateExamFields: (id: number): ExamFields => ({\n\t\tEXAMWINDOW_FIELDNAME: `exam-${id.toString()}-select-exam-window`,\n\t\tTESTING_LOCATION_FIELDNAME: `exam-${id.toString()}-radio-group-testing-location`,\n\t\tTESTING_LOCATION_FIELDS: {\n\t\t\tPROMETRIC: {\n\t\t\t\tEXAM_FIELDNAME: `exam-${id.toString()}-select-prometric-exam`,\n\t\t\t\tPROGRAM_FIELDNAME: `exam-${id.toString()}-select-prometric-program`,\n\t\t\t},\n\t\t\tONSITE: {\n\t\t\t\tEXAM_FIELDNAME: `exam-${id.toString()}-select-on-site-exam`,\n\t\t\t\tCOUNTRY_FIELDNAME: `exam-${id.toString()}-select-on-site-country`,\n\t\t\t\tSTATE_FIELDNAME: `exam-${id.toString()}-select-on-site-state`,\n\t\t\t\tCENTER_FIELDNAME: `exam-${id.toString()}-select-on-site-center`,\n\t\t\t\tPROGRAM_FIELDNAME: `exam-${id.toString()}-select-on-site-program`,\n\t\t\t},\n\t\t\tVIRTUAL: {\n\t\t\t\tEXAM_FIELDNAME: `exam-${id.toString()}-select-virtual-exam`,\n\t\t\t\tPROGRAM_FIELDNAME: `exam-${id.toString()}-select-virtual-program`,\n\t\t\t},\n\t\t},\n\t}),\n\tselectValue: (\n\t\tformValues: FormValues | undefined,\n\t\tfieldName: string,\n\t): string => (formValues !== undefined ? formValues[fieldName] : ''),\n\tfieldExists: (formValues: FormValues, field?: string) =>\n\t\tfield !== undefined && field in formValues && formValues[field] !== null,\n};\n\n/**\n * Tab util methods.\n */\nexport const tabUtil = {\n\tsetId: (tabId: TabIdType, id: number): string =>\n\t\t`${PURCHASE_TAB_STRINGS[tabId].elementId}-${String(id)}`,\n\tsetPanelId: (tabId: TabIdType, id: number): string =>\n\t\t`${PURCHASE_TAB_STRINGS[tabId].panelName}-${String(id)}`,\n\tsetClassName: (tabId: TabIdType, activeTab: TabIdType): string =>\n\t\tclassNames(\n\t\t\t'purchase-tabs__button',\n\t\t\t`${PURCHASE_TAB_STRINGS[tabId].className}`,\n\t\t\t{\n\t\t\t\t'purchase-tabs__button--active': tabId === activeTab,\n\t\t\t},\n\t\t),\n\tsetTabIndex: (tabId: TabIdType, activeTab: TabIdType): number =>\n\t\ttabId === activeTab ? 0 : -1,\n};\n","import { DateTime } from 'luxon';\n\nimport { CartItem } from '@aicpcu/web-api-spec-model';\n\nimport { ProductFamily } from '@app/constants/product-family';\n\nimport { formatDateString } from './date';\n\n/**\n * Get exam window label with a formatted start and end date.\n *\n * @param {string} startDate Start date of exam window.\n * @param {string} endDate End date of exam window.\n *\n * @returns {string} Exam window label with formatted dates.\n */\nexport const formatExamWindowLabel = (\n\tstartDate: string | Date | DateTime,\n\tendDate: string | Date | DateTime,\n): string => {\n\tconst formattedStartDate = formatDateString(startDate, 'MMMM d');\n\tconst formattedEndDate = formatDateString(endDate, 'MMMM d');\n\tconst dateYear = formatDateString(endDate, 'yyyy');\n\n\treturn `${formattedStartDate} - ${formattedEndDate}, ${dateYear}`;\n};\n\n/**\n * Function to review if cart has more items apart from an exam transfer fee\n * @param cartItems items on cart\n * @returns boolean\n */\nexport const reviewIfHasExamTransferAndMoreItems = (cartItems: CartItem []) =>\n\tcartItems.length > 1 && cartItems.some(\n\t\t(cartItem) => cartItem.productFamily === ProductFamily.TRANS_FEE,\n\t);\n\n/**\n * Function to check if only item in cart is transfer fee\n * @param cartItems items on cart\n * @returns boolean\n */\nexport const isItemTransferFee = (cartItems: CartItem []) =>\n\tcartItems.length === 1 && cartItems[0].productFamily === ProductFamily.TRANS_FEE;\n\n/**\n * Function to filter items that are not exam transfer fee\n * @param cartItems items on cart\n * @returns cartItems filtered\n */\nexport const filterNotExamTransferItems = (cartItems: CartItem []) => cartItems.filter(\n\t\t(cartItem) => cartItem.productFamily !== ProductFamily.TRANS_FEE,\n\t);\n"],"names":["string_union_1","require","MATERIAL_TAB_ID","EXAM_TAB_ID","StringUnion","exports","materialTab","className","description","elementId","formName","id","panelName","title","examTab","Object","freeze","_a","classnames_1","__importDefault","js_cookie_1","lodash_merge_1","luxon_1","exam_transfer_window_1","getParameterByName_1","price_1","purchase_form_constants_1","isOnlineCourse","gradeForExam","_b","published","mapIdToProduct","products","productId","getVirtualExams","onlineCourseIds","map","filter","isVirtualExam","examIds","length","mapProductToExam","startDate","endDate","detailedInformation","exam","prices","_c","__assign","label","examWindowStartDate","findApplicablePrice","DateTime","fromFormat","undefined","value","toString","courseCode","beginning","examDate","type","examType","mapWindowToExam","exams","_d","_e","_f","physicalExams","virtualExams","formatExamWindowLabel","options","p","reduce","group","__spreadArray","VIRTUAL","PROMETRIC","INTERNET","marketingExamWindows","examWindow","find","apiId","isPublished","examWindows","programRule","marketing","tabId","topicCourses","validExamWindows","isExamWindowPublished","materialOptions","packageIds","printedMaterialIds","_g","findApplicableMaterialPrice","mapWindowToMaterial","examOptions","isExamAvailable","max","min","_i","options_1","option","salePrice","currentPrice","loginUrl","anchorId","url","returnUrlParam","getParameterByName","split","cancelUrlParam","anchor","concat","replace","encodeURIComponent","window","location","assign","isAuthenticated","get","set","secure","saveTab","localStorage","setItem","LOCAL_STORAGE_ID","JSON","stringify","tab","loadTab","onLoad","parse","getItem","removeItem","loadForm","LOCAL_STORAGE_FORM_ID","openOverlayCode","storedTitle","createFormName","strings","arguments","join","createMaterialFields","EXAMWINDOW_FIELDNAME","MATERIAL_FIELDNAME","createExamFields","TESTING_LOCATION_FIELDNAME","TESTING_LOCATION_FIELDS","EXAM_FIELDNAME","PROGRAM_FIELDNAME","ONSITE","COUNTRY_FIELDNAME","STATE_FIELDNAME","CENTER_FIELDNAME","selectValue","formValues","fieldName","fieldExists","field","setId","PURCHASE_TAB_STRINGS","String","setPanelId","setClassName","activeTab","setTabIndex","product_family_1","date_1","formattedStartDate","formatDateString","formattedEndDate","dateYear","cartItems","some","cartItem","productFamily","ProductFamily","TRANS_FEE"],"sourceRoot":""}