| Server IP : 65.108.144.40 / Your IP : 216.73.217.165 Web Server : Apache/2.4.52 (Ubuntu) System : Linux ubuntu-8gb-hel1-1 5.15.0-173-generic #183-Ubuntu SMP Fri Mar 6 13:29:34 UTC 2026 x86_64 User : dev ( 1000) PHP Version : 8.2.30 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /var/www/html/support/vue-app/src/components/ |
Upload File : |
<template>
<div class="tyre-size-finder" :class="fitmentString == '' ? '' : 'fitment-set'">
<div class="banner-fitment" v-if="fitmentString !== ''">
Your fitment has been set!
<div class="fitment-graphic">
<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" class="icon">
<path
d="M15.061 7.495c-4.154 0-7.531 3.375-7.531 7.525s3.377 7.525 7.531 7.525 7.531-3.375 7.531-7.525-3.377-7.525-7.53-7.525zm0 .94a6.58 6.58 0 016.59 6.585 6.58 6.58 0 01-6.59 6.585 6.58 6.58 0 01-6.59-6.585 6.58 6.58 0 016.59-6.584z">
</path>
<path
d="M15.061 18.402c-.849 0-1.595.635-2.105 1.656l-.67 1.337.843.42.669-1.337c.42-.838.893-1.135 1.263-1.135.37 0 .844.297 1.263 1.135l.67 1.338.842-.42-.67-1.338c-.51-1.02-1.256-1.656-2.105-1.656zM18.28 16.066c-.263.806.111 1.711.924 2.512l1.067 1.05.66-.671-1.066-1.05c-.668-.657-.805-1.199-.69-1.55.114-.352.543-.71 1.47-.85l1.48-.223-.14-.93-1.48.223c-1.128.17-1.963.682-2.226 1.489zM17.05 12.285c.687.499 1.664.423 2.677-.102l1.328-.69-.433-.834-1.329.689c-.832.432-1.39.394-1.69.176-.299-.217-.507-.735-.354-1.66l.246-1.475-.929-.154-.245 1.475c-.188 1.125.042 2.077.729 2.575zM13.072 12.285c.687-.498.916-1.45.73-2.575l-.246-1.475-.929.154.246 1.475c.153.925-.055 1.443-.354 1.66-.3.218-.858.256-1.69-.176l-1.328-.69-.434.836 1.328.689c1.013.525 1.99.6 2.677.102zM11.843 16.066c-.263-.807-1.098-1.32-2.226-1.49l-1.48-.222-.14.93 1.48.223c.927.14 1.356.498 1.47.85.115.351-.021.893-.69 1.55l-1.066 1.05.66.67 1.067-1.049c.813-.8 1.187-1.705.925-2.512z">
</path>
<path
d="M15.06 12.668a2.36 2.36 0 00-2.353 2.352 2.36 2.36 0 002.354 2.352 2.36 2.36 0 002.354-2.352 2.36 2.36 0 00-2.354-2.351zm0 .941c.786 0 1.413.626 1.413 1.411s-.627 1.41-1.412 1.41a1.404 1.404 0 01-1.412-1.41c0-.785.627-1.41 1.412-1.41zM15.442 11.77a.47.47 0 10-.76-.553.47.47 0 00.76.553zM12.085 13.655a.47.47 0 10-.762.553.47.47 0 00.762-.553zM12.843 17.426a.471.471 0 10.291.896.471.471 0 00-.29-.897zM16.668 17.873a.47.47 0 00.803.332.47.47 0 10-.803-.332zM18.278 14.375a.47.47 0 10.29-.894.47.47 0 00-.29.894z">
</path>
<path
d="M13.872 1.433C6.368 2.09.808 8.712 1.465 16.21c.656 7.498 7.282 13.053 14.786 12.397 7.504-.656 13.066-7.276 12.41-14.775C28.003 6.334 21.375.777 13.871 1.433zm.083.937c6.997-.611 13.155 4.552 13.768 11.543.612 6.992-4.555 13.145-11.553 13.757-6.997.612-13.155-4.551-13.767-11.543C1.79 9.135 6.957 2.982 13.955 2.37z">
</path>
<path
d="M14.565 1.391a.47.47 0 00-.373.718l.699 1.163a.47.47 0 10.807-.483l-.699-1.165a.47.47 0 00-.434-.233zM10.114 2.345a.47.47 0 00-.289.841l1.054.854a.472.472 0 00.594-.73l-1.056-.855a.471.471 0 00-.303-.11zM6.21 4.772a.47.47 0 00-.121.916l1.283.443a.471.471 0 10.307-.889l-1.283-.443a.471.471 0 00-.186-.028zM4.778 8.356l-1.359.021a.471.471 0 10.017.94l1.357-.02a.471.471 0 10-.015-.941zM3.287 12.238a.472.472 0 00-.17.032l-1.268.487a.47.47 0 10.337.878l1.267-.487a.471.471 0 00-.166-.911zM3.182 16.4a.471.471 0 00-.286.12l-1.025.89a.47.47 0 10.616.709l1.026-.89a.47.47 0 00-.33-.828zM4.554 20.34a.47.47 0 00-.412.248l-.658 1.185a.47.47 0 10.822.457l.66-1.187a.47.47 0 00-.412-.703zM7.144 23.58a.47.47 0 00-.437.403l-.214 1.34a.47.47 0 10.929.148l.213-1.34a.47.47 0 00-.49-.55zM14.848 26.534a.47.47 0 00-.42.719l.698 1.163a.47.47 0 00.653.175.47.47 0 00.154-.658l-.699-1.163a.47.47 0 00-.386-.235zM18.941 25.892a.47.47 0 00-.288.841l1.053.854a.473.473 0 00.749-.231.471.471 0 00-.155-.5l-1.056-.854a.471.471 0 00-.303-.11zM22.613 23.882a.471.471 0 00-.17.916l1.284.443a.472.472 0 00.631-.472.471.471 0 00-.324-.417l-1.283-.443a.471.471 0 00-.138-.028zM26.687 20.724l-1.357.021a.471.471 0 10.017.94l1.357-.02a.471.471 0 10-.017-.941zM28.109 16.373a.47.47 0 00-.17.032l-1.268.485a.468.468 0 00-.285.613.473.473 0 00.621.265l1.269-.485a.471.471 0 00-.167-.91zM27.97 11.803a.471.471 0 00-.334.12l-1.024.888a.47.47 0 10.616.711l1.026-.89a.47.47 0 00-.285-.83zM26.228 7.564a.471.471 0 00-.41.248l-.659 1.185a.47.47 0 10.822.457l.66-1.186a.47.47 0 00-.413-.704zM23.14 4.169a.471.471 0 00-.439.402l-.213 1.34a.47.47 0 10.93.147l.214-1.34a.47.47 0 00-.491-.549zM19.121 2.023a.471.471 0 00-.457.568l.257 1.332a.47.47 0 10.925-.18l-.258-1.332a.47.47 0 00-.467-.388zM10.735 25.732a.47.47 0 00-.458.566l.26 1.332a.471.471 0 10.923-.179l-.258-1.332a.47.47 0 00-.467-.387z">
</path>
</svg>
<div class="button-text-wrap">
<label class="display-block">Your Tyre Fit</label>
<label class="display-block">{{ this.fitmentString }}</label>
</div>
</div>
</div>
<div class="close-modal">
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" viewBox="0 0 100 100" class="icon">
<path
d="M100 80.47c0 2.24-.79 4.15-2.36 5.72L86.2 97.64c-1.57 1.57-3.48 2.36-5.72 2.36s-4.15-.79-5.72-2.36L50 72.9 25.25 97.64c-1.57 1.57-3.48 2.36-5.72 2.36s-4.15-.79-5.72-2.36L2.36 86.2C.79 84.62 0 82.72 0 80.47s.79-4.15 2.36-5.72L27.1 50 2.36 25.25C.79 23.68 0 21.77 0 19.53s.79-4.15 2.36-5.72L13.8 2.36C15.38.79 17.28 0 19.53 0s4.15.79 5.72 2.36L50 27.1 74.75 2.36C76.32.79 78.23 0 80.47 0s4.15.79 5.72 2.36L97.64 13.8c1.57 1.57 2.36 3.48 2.36 5.72s-.79 4.15-2.36 5.72L72.9 50l24.75 24.75c1.56 1.57 2.35 3.48 2.35 5.72z" />
</svg>
</div>
<div class="left">
<div class="background"></div>
<div class="label">
<span>Find your tyre fit</span>
</div>
</div>
<div class="right">
<div class="modal-fitment" v-if="fitmentString !== ''">
Your fitment has been set!
<div class="fitment-graphic">
<svg width="30" height="30" viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg" class="icon">
<path
d="M15.061 7.495c-4.154 0-7.531 3.375-7.531 7.525s3.377 7.525 7.531 7.525 7.531-3.375 7.531-7.525-3.377-7.525-7.53-7.525zm0 .94a6.58 6.58 0 016.59 6.585 6.58 6.58 0 01-6.59 6.585 6.58 6.58 0 01-6.59-6.585 6.58 6.58 0 016.59-6.584z">
</path>
<path
d="M15.061 18.402c-.849 0-1.595.635-2.105 1.656l-.67 1.337.843.42.669-1.337c.42-.838.893-1.135 1.263-1.135.37 0 .844.297 1.263 1.135l.67 1.338.842-.42-.67-1.338c-.51-1.02-1.256-1.656-2.105-1.656zM18.28 16.066c-.263.806.111 1.711.924 2.512l1.067 1.05.66-.671-1.066-1.05c-.668-.657-.805-1.199-.69-1.55.114-.352.543-.71 1.47-.85l1.48-.223-.14-.93-1.48.223c-1.128.17-1.963.682-2.226 1.489zM17.05 12.285c.687.499 1.664.423 2.677-.102l1.328-.69-.433-.834-1.329.689c-.832.432-1.39.394-1.69.176-.299-.217-.507-.735-.354-1.66l.246-1.475-.929-.154-.245 1.475c-.188 1.125.042 2.077.729 2.575zM13.072 12.285c.687-.498.916-1.45.73-2.575l-.246-1.475-.929.154.246 1.475c.153.925-.055 1.443-.354 1.66-.3.218-.858.256-1.69-.176l-1.328-.69-.434.836 1.328.689c1.013.525 1.99.6 2.677.102zM11.843 16.066c-.263-.807-1.098-1.32-2.226-1.49l-1.48-.222-.14.93 1.48.223c.927.14 1.356.498 1.47.85.115.351-.021.893-.69 1.55l-1.066 1.05.66.67 1.067-1.049c.813-.8 1.187-1.705.925-2.512z">
</path>
<path
d="M15.06 12.668a2.36 2.36 0 00-2.353 2.352 2.36 2.36 0 002.354 2.352 2.36 2.36 0 002.354-2.352 2.36 2.36 0 00-2.354-2.351zm0 .941c.786 0 1.413.626 1.413 1.411s-.627 1.41-1.412 1.41a1.404 1.404 0 01-1.412-1.41c0-.785.627-1.41 1.412-1.41zM15.442 11.77a.47.47 0 10-.76-.553.47.47 0 00.76.553zM12.085 13.655a.47.47 0 10-.762.553.47.47 0 00.762-.553zM12.843 17.426a.471.471 0 10.291.896.471.471 0 00-.29-.897zM16.668 17.873a.47.47 0 00.803.332.47.47 0 10-.803-.332zM18.278 14.375a.47.47 0 10.29-.894.47.47 0 00-.29.894z">
</path>
<path
d="M13.872 1.433C6.368 2.09.808 8.712 1.465 16.21c.656 7.498 7.282 13.053 14.786 12.397 7.504-.656 13.066-7.276 12.41-14.775C28.003 6.334 21.375.777 13.871 1.433zm.083.937c6.997-.611 13.155 4.552 13.768 11.543.612 6.992-4.555 13.145-11.553 13.757-6.997.612-13.155-4.551-13.767-11.543C1.79 9.135 6.957 2.982 13.955 2.37z">
</path>
<path
d="M14.565 1.391a.47.47 0 00-.373.718l.699 1.163a.47.47 0 10.807-.483l-.699-1.165a.47.47 0 00-.434-.233zM10.114 2.345a.47.47 0 00-.289.841l1.054.854a.472.472 0 00.594-.73l-1.056-.855a.471.471 0 00-.303-.11zM6.21 4.772a.47.47 0 00-.121.916l1.283.443a.471.471 0 10.307-.889l-1.283-.443a.471.471 0 00-.186-.028zM4.778 8.356l-1.359.021a.471.471 0 10.017.94l1.357-.02a.471.471 0 10-.015-.941zM3.287 12.238a.472.472 0 00-.17.032l-1.268.487a.47.47 0 10.337.878l1.267-.487a.471.471 0 00-.166-.911zM3.182 16.4a.471.471 0 00-.286.12l-1.025.89a.47.47 0 10.616.709l1.026-.89a.47.47 0 00-.33-.828zM4.554 20.34a.47.47 0 00-.412.248l-.658 1.185a.47.47 0 10.822.457l.66-1.187a.47.47 0 00-.412-.703zM7.144 23.58a.47.47 0 00-.437.403l-.214 1.34a.47.47 0 10.929.148l.213-1.34a.47.47 0 00-.49-.55zM14.848 26.534a.47.47 0 00-.42.719l.698 1.163a.47.47 0 00.653.175.47.47 0 00.154-.658l-.699-1.163a.47.47 0 00-.386-.235zM18.941 25.892a.47.47 0 00-.288.841l1.053.854a.473.473 0 00.749-.231.471.471 0 00-.155-.5l-1.056-.854a.471.471 0 00-.303-.11zM22.613 23.882a.471.471 0 00-.17.916l1.284.443a.472.472 0 00.631-.472.471.471 0 00-.324-.417l-1.283-.443a.471.471 0 00-.138-.028zM26.687 20.724l-1.357.021a.471.471 0 10.017.94l1.357-.02a.471.471 0 10-.017-.941zM28.109 16.373a.47.47 0 00-.17.032l-1.268.485a.468.468 0 00-.285.613.473.473 0 00.621.265l1.269-.485a.471.471 0 00-.167-.91zM27.97 11.803a.471.471 0 00-.334.12l-1.024.888a.47.47 0 10.616.711l1.026-.89a.47.47 0 00-.285-.83zM26.228 7.564a.471.471 0 00-.41.248l-.659 1.185a.47.47 0 10.822.457l.66-1.186a.47.47 0 00-.413-.704zM23.14 4.169a.471.471 0 00-.439.402l-.213 1.34a.47.47 0 10.93.147l.214-1.34a.47.47 0 00-.491-.549zM19.121 2.023a.471.471 0 00-.457.568l.257 1.332a.47.47 0 10.925-.18l-.258-1.332a.47.47 0 00-.467-.388zM10.735 25.732a.47.47 0 00-.458.566l.26 1.332a.471.471 0 10.923-.179l-.258-1.332a.47.47 0 00-.467-.387z">
</path>
</svg>
<div class="button-text-wrap">
<label class="display-block">
<!-- <i class="fa fa-search" aria-hidden="true"></i> -->
Your Tyre Fit</label>
<label class="display-block">{{ this.fitmentString }}</label>
</div>
</div>
</div>
<div class="controls" v-if="fitmentString == ''">
<!-- <span class="tab-label search-label">Search By</span> -->
<span class="tab-label" @click="currentTab = 'registration'"
:class="currentTab == 'registration' ? 'active' : ''">Rego</span>
<span class="tab-label" @click="currentTab = 'make'" :class="currentTab == 'make' ? 'active' : ''">Make</span>
<span class="tab-label" @click="currentTab = 'size'" :class="currentTab == 'size' ? 'active' : ''">Size</span>
</div>
<!-- Registration tab -->
<div class="size-finder-type rego-finder" :class="{ 'rego-section': currentTab == 'registration' }"
v-if="currentTab == 'registration'">
<div class="input-container" v-if="
loading === false &&
apiResponse == false &&
apiResponse.length == 0 &&
fitmentString == ''
">
<input id="rego" type="text" placeholder="Enter REGO" v-model="registration" />
<div v-if="validate" class="warning">
Please enter a License Plate
</div>
</div>
<div class="input-container" v-if="
loading === false &&
apiResponse == false &&
apiResponse.length == 0 &&
fitmentString == ''
">
<select id="state" v-model="state" :disabled="registration == ''">
<option disabled value="Select a state">STATE</option>
<option value="ACT">ACT</option>
<option value="NSW">NSW</option>
<option value="NT">NT</option>
<option value="QLD">QLD</option>
<option value="SA">SA</option>
<option value="TAS">TAS</option>
<option value="VIC">VIC</option>
<option value="WA">WA</option>
</select>
<div v-if="validate" class="warning">Please select a state</div>
</div>
<div class="api-error" v-if="
loading === false &&
apiResponse === false &&
currentTab == 'registration'
">
<p>
*Vehicle not found. Try using the <span>MAKE</span> selector to find
your fitment
</p>
</div>
<div class="response-container" v-if="loading">
<div v-if="loading" class="loading-container">
<div class="loading-container-spinner"></div>
</div>
</div>
<div class="findVehicleBox" v-if="
loading === false &&
apiResponse !== false &&
apiResponse.length !== 0 &&
currentTab == 'registration'
">
<label class="info">We've found your vehicle</label>
<div class="vehicle-name">
{{ apiResponse.Name }}
</div>
</div>
</div>
<div class="button-group button-group-margin-top webBtn align-center" :class="{ disabled: disabled }"
v-if="currentTab === 'registration' && !loading && !isNotResponse" @click="
apiResponse?.Id
? (vehicleLookup(apiResponse.Id), scrollScreen())
: registration !== '' && state !== 'Select a state'
? registrationLookup()
: ''
">
<span v-if="
!loading &&
apiResponse &&
apiResponse.length !== 0 &&
fitmentString === ''
" class="button theme-primary align-start" data-autoload-component="button" @click="
apiResponse?.Id
? vehicleLookup(apiResponse.Id)
: registration !== '' && state !== 'Select a state'
? registrationLookup()
: ''
">
<i class="fa fa-search" aria-hidden="true"></i>
FIND A FIT
</span>
<span v-if="
!loading &&
apiResponse.length === 0 &&
!isNotResponse &&
fitmentString === ''
" class="button theme-primary" id="find-your-fit" @click="
apiResponse?.Id
? (vehicleLookup(apiResponse.Id), scrollScreen())
: registration !== '' && state !== 'Select a state'
? registrationLookup()
: ''
" data-autoload-component="button" :class="{ disabled }">
<i class="fa fa-search" aria-hidden="true"></i>
FIND A FIT
</span>
</div>
<div class="button-group button-group-margin-top webBtn align-center"
:class="[!isNotResponse ? 'findBtn' : 'removeFindBtn']" v-if="
loading === false &&
// apiResponse === false &&
isGetResponse &&
currentTab == 'registration'
" @click="reset()">
<span v-if="loading === false && isGetResponse && fitmentString == ''" class="button theme-primary align-start"
target="" data-autoload-component="button" @click="reset()">TRY AGAIN</span>
</div>
<!-- Make/Model finder tab -->
<div class="size-finder-type" :class="{ 'make-finder': loading === false }" v-if="currentTab == 'make'">
<div class="make-step input-container" v-if="
loading === false &&
// apiResponse == false &&
// apiResponse.length == 0 &&
fitmentString == ''
">
<select id="manufacturer" v-model="selectedVehicleMake">
<option disabled value="Select a make">MANUFACTURER</option>
<option v-for="make in vehicleMakes" :key="make.id" :value="make.id">
{{ make.name }}
</option>
</select>
</div>
<div class="make-step input-container" :class="{ 'disable-dropdown': loading === false }" v-if="
loading === false &&
// apiResponse == false &&
// apiResponse.length == 0 &&
fitmentString == ''
">
<select id="model" v-model="selectedVehicleModel" :disabled="selectedVehicleMake === 'Select a make'">
<option disabled value="Select a model">MODEL</option>
<option v-for="model in makeModels" :key="model.modelId" :value="model.modelId">
{{ model.modelName }}
</option>
</select>
</div>
<div class="make-step input-container" v-if="
loading === false &&
// apiResponse == false &&
// apiResponse.length == 0 &&
fitmentString == ''
">
<select id="year" v-model="selectedVehicleYear" :disabled="!vehicleYears?.length">
<option disabled value="Select a year">YEAR</option>
<option v-for="year in vehicleYears" :key="year" :value="year">
{{ year }}
</option>
</select>
</div>
<div class="make-step input-container" v-if="
loading === false &&
// apiResponse == false &&
// apiResponse.length == 0 &&
fitmentString == ''
">
<select id="series" v-model="selectedVehicleSeries" :disabled="!vehicleSeries?.length">
<option disabled value="Select a series">SERIES</option>
<option v-for="vehicle in vehicleSeries" :key="vehicle.Id" :value="vehicle.Id">
{{ vehicle.Name }}
</option>
</select>
</div>
<div class="response-container" v-if="loading">
<div v-if="loading" class="loading-container">
<div class="loading-container-spinner"></div>
</div>
</div>
</div>
<div class="button-group button-group-margin-top webBtn align-center" :class="{ disabled }"
v-if="currentTab == 'make' && !loading" @click="disabled ? '' : setVehicleFitment()">
<span v-if="
loading === false &&
// apiResponse == false &&
// apiResponse.length == 0 &&
fitmentString == ''
" class="button theme-primary" target="" data-autoload-component="button"
@click="disabled ? '' : setVehicleFitment()" :class="{ disabled }">
<i class="fa fa-search" aria-hidden="true"></i>
FIND A FIT</span>
</div>
<!-- Size Input tab -->
<div class="size-finder-type size-finder" v-if="currentTab == 'size'">
<div class="input-container">
<!-- <label for="width" class="input-label">Width</label> -->
<input v-model="selectedWidth" id="width" type="text" placeholder="WIDTH (mm or in)" maxlength="5"
v-on:keydown="isNumber($event)" />
</div>
<div class="input-container">
<!-- <label for="profile" class="input-label">Profile</label> -->
<input v-model="selectedProfile" :disabled="selectedWidth == ''" id="profile" type="text"
placeholder="PROFILE (aspet ratio)" maxlength="5" v-on:keydown="isNumber($event)" />
</div>
<div class="input-container">
<!-- <label for="rim" class="input-label">Rim</label> -->
<input v-model="selectedRim" :disabled="selectedWidth == '' || selectedProfile == ''" id="rim" type="text"
placeholder="RIM (inches)" maxlength="5" v-on:keydown="isNumber($event)" />
</div>
</div>
<div class="button-group button-group-margin-top webBtn align-center" :class="{ disabled }"
v-if="currentTab == 'size'" @click="!disabled && setManualFitment()">
<span class="button theme-primary" @click="!disabled && setManualFitment()" :class="{ disabled }">
<i class="fa fa-search" aria-hidden="true"></i>
FIND A FIT
</span>
</div>
</div>
</div>
</template>
<script>
let baseUrl = "https://coopertiredev.demandtech.org/wp-json/cooper/v1/";
export default {
data: function () {
return {
loading: false,
currentTab: "registration",
registration: "",
state: "Select a state",
apiResponse: [],
makeIds: [],
vehicleMakes: [],
selectedVehicleMake: "Select a make",
vehicleModels: [],
selectedVehicleModel: "Select a model",
vehicleYears: [],
selectedVehicleYear: "Select a year",
vehicleSeries: [],
selectedVehicleSeries: "Select a series",
selectedWidth: "",
selectedProfile: "",
selectedRim: "",
vehicleFitment: {},
manualFitment: "",
validate: false,
body: "",
fitmentString: "",
isGetResponse: false,
isNotResponse: false,
filterAPi: "",
};
},
props: {
tyreWizard: Boolean,
},
methods: {
storeSize() { },
registrationLookup() {
this.validate = false;
this.loading = true;
this.fetch = Promise.all([
fetch(`${baseUrl}registration`, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
body: JSON.stringify({
state: this.state,
registration: this.registration,
}),
}).then((response) => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
return response.json();
}),
]).then((results) => {
this.loading = false;
this.apiResponse = results[0];
this.isGetResponse = true;
if (!this.apiResponse) {
this.isNotResponse = true;
} else {
this.isNotResponse = false;
}
});
},
vehicleLookup(id, filtered = false) {
this.loading = true; // Show the loader immediately
// Prepare request body based on the `filtered` flag
if (filtered) {
this.body = JSON.stringify({
modelId: id,
modelYear: this.selectedVehicleYear,
});
} else {
this.body = JSON.stringify({
vehicle: id,
});
}
// Fetch data with the API call
this.fetch = fetch(`${baseUrl}vehicle`, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
body: this.body,
})
.then((response) => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
return response.json();
})
.then((result) => {
this.loading = false; // Hide the loader immediately after response
// Process result
if (!filtered) {
this.vehicleFitment = result.OEFitmentData;
this.filterAPi = result?.OEFitmentData?.FrontTyres?.Description;
// Update the Vuex store
if (this.$store) {
window.scrollTo({
top: 0,
behavior: "smooth", // This makes the scroll smooth
});
this.$store.dispatch("updateFilterData", this.filterAPi);
} else {
console.error("Vuex store is not available.");
}
} else {
this.vehicleSeries = result.Items;
}
})
.catch((error) => {
this.loading = false; // Hide the loader in case of error
console.error("API error:", error);
});
},
scrollScreen() {
window.scrollTo({
top: 0,
behavior: "smooth", // This makes the scroll smooth
});
},
getVehicleMakes() {
this.loading = true; // Show the loader immediately
// Attempt to access our local data
const localMakes = localStorage.getItem("vehicleMakes");
// If the local Make data exists
if (localMakes !== null) {
this.vehicleMakes = JSON.parse(localMakes);
// If we don't have an array of makeIds to lookup, populate from our Makes
if (this.makeIds.length === 0) {
this.vehicleMakes.forEach((x) => {
this.makeIds.push(x.id);
});
// Remove duplicates from vehicleMakes
this.vehicleMakes = [...new Set(this.vehicleMakes)];
// Call getVehicleModels with makeIds
this.getVehicleModels(this.makeIds);
// Stop the loader since we've processed the data from local storage
this.loading = false;
return;
}
}
// If no local data, make the API request
this.fetch = fetch(`${baseUrl}vehicleMakes`, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
})
.then((response) => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
return response.json();
})
.then((result) => {
this.loading = false; // Stop the loader after the response
// Process API results and update vehicleMakes and makeIds
result.Items.forEach((x) => {
this.vehicleMakes.push({ id: x.Id, name: x.Name });
this.makeIds.push(x.Id);
});
// Store to avoid later API calls
localStorage.setItem("vehicleMakes", JSON.stringify(this.vehicleMakes));
// Fetch vehicle models with the updated makeIds
this.getVehicleModels(this.makeIds);
})
.catch((error) => {
this.loading = false; // Stop the loader in case of error
console.error("API error:", error);
});
},
getVehicleModels(makeIds) {
this.loading = true; // Show the loader immediately
// Attempt to access local data
const localModels = localStorage.getItem("vehicleModels");
// If the local Model data exists
if (localModels !== null) {
this.vehicleModels = JSON.parse(localModels);
// Remove duplicates in vehicleModels
this.vehicleModels = [...new Set(this.vehicleModels)];
// Stop the loader as the data was found in local storage
this.loading = false;
return;
}
// If no local data, make the API request
this.fetch = fetch(`${baseUrl}vehicleModels`, {
method: "POST",
credentials: "same-origin",
headers: {
"Content-Type": "application/json",
accept: "application/json",
},
body: JSON.stringify({ id: makeIds }),
})
.then((response) => {
if (!response.ok) {
throw new Error("HTTP status " + response.status);
}
return response.json();
})
.then((result) => {
this.loading = false; // Stop the loader after the response
// Process API results and update vehicleModels
result.Items.forEach((x) => {
if (x.YearRanges.length !== undefined) {
let startArray = [];
let endArray = [];
x.YearRanges.forEach((el) => {
startArray.push(el.Start);
endArray.push(el.End);
});
this.vehicleModels.push({
modelId: x.Id,
modelName: x.Name,
modelStart: startArray,
modelEnd: endArray,
makeId: x.Make.Id,
});
} else {
this.vehicleModels.push({
modelId: x.Id,
modelName: x.Name,
modelStart: x.YearRanges.Start,
modelEnd: x.YearRanges.End,
makeId: x.Make.Id,
});
}
});
// Store the data in localStorage to avoid later API calls
localStorage.setItem("vehicleModels", JSON.stringify(this.vehicleModels));
})
.catch((error) => {
this.loading = false; // Stop the loader in case of error
console.error("API error:", error);
});
},
setVehicleFitment() {
this.vehicleLookup(this.selectedVehicleSeries);
},
setManualFitment() {
window.scrollTo({
top: 0,
behavior: "smooth", // This makes the scroll smooth
});
const fitmentString =
parseFloat(this.selectedWidth) +
"/" +
parseFloat(this.selectedProfile) +
"R" +
parseFloat(this.selectedRim);
this.fitmentString = fitmentString;
document.cookie = "fitment=" + fitmentString + ";path=/;max-age=2678400";
// @TODO: Check intended same-page functionality
// this fix won't show the tyre fit in header if on same page as tyre wizard
if (this.tyreWizard !== true) {
document.querySelector("#tyre-sizer-fit").innerHTML = fitmentString;
document.querySelector("#tyre-sizer").classList.add("pulse");
}
if (this.$store) {
this.$store.dispatch("updateFilterData", this.fitmentString);
} else {
console.error("Vuex store is not available.");
}
this.maybeReload(fitmentString);
},
closeModal() {
(this.currentTab = "registration"),
(this.registration = ""),
(this.state = "Select a state"),
(this.selectedVehicleMake = "Select a make"),
(this.selectedVehicleModel = "Select a model"),
(this.selectedVehicleYear = "Select a year"),
(this.selectedVehicleSeries = "Select a series"),
(this.selectedWidth = ""),
(this.selectedProfile = ""),
(this.selectedRim = ""),
document.querySelector(".close-modal").click();
},
maybeReload(fitmentString) {
this.currentTab = "registration";
this.fitmentString = fitmentString;
if (this.tyreWizard !== true) {
if (
document
.querySelector("#tyre-sizer-fit")
.classList.contains("home-page")
) {
location.href = "/our-range/";
} else {
location.reload();
}
} else {
this.$emit("fitment-set", fitmentString);
}
},
clearData() {
document.querySelector("#tyre-sizer-fit").innerHTML = "START HERE";
document.cookie =
"fitment=;expires=Thu, 01 Jan 1970 00:00:01 GMT;path=/;";
document.querySelector("#tyre-sizer").classList.add("pulse-error");
this.maybeReload();
},
reset() {
this.apiResponse = "";
this.isGetResponse = false;
this.isNotResponse = false;
},
isNumber($event) {
const input = $event.keyCode ? $event.keyCode : $event.which;
// allowed keycodes: 0-9, backspace, tab, enter, period
const keyCodes = [
8, 9, 13, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 96, 97, 98, 99, 100,
101, 102, 103, 104, 105, 190,
];
if (!keyCodes.includes(input)) {
$event.preventDefault();
}
},
},
watch: {
vehicleFitment: function () {
const fitmentString =
parseFloat(this.vehicleFitment.FrontTyres.SectionWidth) +
"/" +
parseFloat(this.vehicleFitment.FrontTyres.AspectRatio) +
"R" +
parseFloat(this.vehicleFitment.FrontTyres.RimDiameter);
// Set path and max age of 1 month
document.cookie = "fitment=" + fitmentString + ";path=/;max-age=2678400";
// @TODO: Check intended same-page functionality
// this fix won't show the tyre fit in header if on same page as tyre wizard
if (this.tyreWizard !== true) {
document.querySelector("#tyre-sizer-fit").innerHTML = fitmentString;
document.querySelector("#tyre-sizer").classList.add("pulse");
}
this.maybeReload(fitmentString);
},
selectedVehicleMake: function () {
this.selectedVehicleModel = "Select a model";
this.selectedVehicleYear = "Select a year";
this.selectedVehicleSeries = "Select a series";
this.vehicleYears = [];
this.makeModels = [];
this.vehicleSeries = [];
},
selectedVehicleModel: function () {
this.vehicleYears = [];
let modelYears = [];
this.vehicleSeries = [];
this.selectedVehicleYear = "Select a year";
this.selectedVehicleSeries = "Select a series";
this.vehicleModels.map((x) => {
if (this.selectedVehicleModel === x.modelId) {
if (Array.isArray(x.modelStart)) {
// For each year bracket, calculate the model years
x.modelStart.forEach((el, index) => {
for (let i = x.modelStart[index]; i <= x.modelEnd[index]; i++) {
modelYears.push(i);
}
});
} else {
for (let i = x.modelStart; i <= x.modelEnd; i++) {
modelYears.push(i);
}
}
this.vehicleYears = modelYears;
}
});
},
selectedVehicleYear: function () {
this.vehicleSeries = [];
this.selectedVehicleSeries = "Select a series";
this.vehicleLookup(this.selectedVehicleModel, true);
},
},
computed: {
disabled: function () {
if (this.currentTab == "registration") {
if (this.registration == "" || this.state == "Select a state") {
return true;
} else {
return false;
}
}
if (this.currentTab == "make") {
if (
this.selectedVehicleMake == "Select a make" ||
this.selectedVehicleModel == "Select a model" ||
this.selectedVehicleYear == "Select a year" ||
this.selectedVehicleSeries == "Select a series"
) {
return true;
} else {
return false;
}
}
if (this.currentTab == "size") {
if (
this.selectedProfile == "" ||
this.selectedWidth == "" ||
this.selectedRim == ""
) {
return true;
} else {
return false;
}
}
},
makeModels: function () {
if (this.selectedVehicleMake) {
// filter our models via currently selected make
return this.vehicleModels.filter((x) => {
return this.selectedVehicleMake == x.makeId;
});
}
},
},
mounted() {
localStorage.clear();
this.getVehicleMakes();
},
};
</script>