Last active
July 9, 2024 02:17
-
-
Save judge2020/fab78fee2fac4a033bb8fe12afc65b58 to your computer and use it in GitHub Desktop.
Tesla Calculator code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable camelcase */ | |
import React, { useState } from "react"; | |
import { | |
FormInputRange, | |
FormInputSelect, | |
FormItem, | |
FormLabelRange, | |
} from "@tesla/design-system-react"; | |
import { Form, Input } from "@tesla/informed-tds"; | |
import { arrayOf, func, number, shape, string } from "prop-types"; | |
import "./override.css"; | |
import "@tesla/design-system/dist/index.css"; | |
import styles from "./calculator.module.css"; | |
const defaultProps = { | |
copy: { chargeCost: "Charge Cost", cta: "", currency: "$", gasSavings: "Gas Savings", more: "" }, | |
}; | |
const propTypes = { | |
copy: shape({ | |
chargeCost: string, | |
cta: string, | |
currency: string, | |
gasSavings: string, | |
more: string, | |
rangeLabel: string, | |
}), | |
allVehicles: arrayOf(shape({ value: string, label: string, product: string, "img-code": string })) | |
.isRequired, | |
calculationData: shape({ | |
ms: shape({ | |
fuel_efficiency_imperial: number, | |
fuel_efficiency_metric: number, | |
kwh_consumption_100: number, | |
supercharger_kwh_price: number, | |
fuel_price: number, | |
kwh_price: number, | |
electricity_last_updated: string, | |
last_updated: string, | |
}), | |
}).isRequired, | |
selectVehicle: func.isRequired, | |
selectedVehicle: shape({ product: string, img: string }).isRequired, | |
timeInput: string.isRequired, | |
}; | |
const AVERAGE_NUM_DAY_MONTH = 30.437; | |
const DEFAULT_RANGE = "100"; | |
const costOfGas = (distanceInMiles, fuelEfficiencyInMilesPerGallon, costOfGasperGallon) => { | |
return (distanceInMiles / fuelEfficiencyInMilesPerGallon) * costOfGasperGallon; | |
}; | |
const round = (value, decimals) => { | |
const rounded = Number(`${Math.round(`${value}e${decimals}`)}e-${decimals}`); | |
return rounded.toFixed(2); | |
}; | |
const dailyChargeCostCalc = (distanceInKM, energyEfficiencyInKWHPer100KM, costPerHour) => { | |
return round((distanceInKM / 100) * energyEfficiencyInKWHPer100KM * costPerHour, 2); | |
}; | |
const Calculator = ({ | |
copy, | |
allVehicles, | |
calculationData, | |
selectVehicle, | |
selectedVehicle, | |
timeInput, | |
}) => { | |
const defaultVehicleCalcData = calculationData[selectedVehicle.product]; | |
const { fuel_efficiency_imperial, fuel_price, kwh_consumption_100, kwh_price } = | |
defaultVehicleCalcData; | |
const defaultRangeKM = DEFAULT_RANGE; | |
const defaultDailyChargeCost = dailyChargeCostCalc(DEFAULT_RANGE, kwh_consumption_100, kwh_price); | |
const defaultDailyGasCost = costOfGas(defaultRangeKM, fuel_efficiency_imperial, fuel_price); | |
const defaultMonthlyChargeCost = defaultDailyChargeCost * AVERAGE_NUM_DAY_MONTH; | |
const defaultMontlyGasCost = defaultDailyGasCost * AVERAGE_NUM_DAY_MONTH; | |
const [rangeValue, setRangeValue] = useState(DEFAULT_RANGE); | |
const [dailyChargeCost, setDailyChargeCost] = useState(defaultDailyChargeCost); | |
const [dailyGasSaving, setDailyGasSaving] = useState( | |
defaultDailyGasCost - defaultDailyChargeCost | |
); | |
const [monthlyChargeCost, setMonthlyChargeCost] = useState(defaultMonthlyChargeCost); | |
const [monthlyGasSaving, setMonthlyGasSaving] = useState( | |
defaultMontlyGasCost - defaultMonthlyChargeCost | |
); | |
const updateCalculation = (vehicle, vehicleUpdate = false, forceRange) => { | |
let updatedRangeValue; | |
if (!vehicleUpdate) { | |
updatedRangeValue = forceRange || 0; | |
} else { | |
updatedRangeValue = parseInt(rangeValue, 10) || 0; | |
} | |
const vehicleCalcData = calculationData[vehicle.product]; | |
/* eslint-disable */ | |
const { fuel_efficiency_imperial, fuel_price, kwh_consumption_100, kwh_price } = | |
vehicleCalcData; | |
const updatedDailyChargeCost = dailyChargeCostCalc( | |
updatedRangeValue, | |
kwh_consumption_100, | |
kwh_price | |
); | |
const updatedDailyCostOfGas = costOfGas( | |
updatedRangeValue, | |
fuel_efficiency_imperial, | |
fuel_price | |
); | |
const updatedDailyGasSaving = updatedDailyCostOfGas - updatedDailyChargeCost; | |
setDailyChargeCost(updatedDailyChargeCost); | |
setDailyGasSaving(updatedDailyGasSaving); | |
setMonthlyChargeCost(updatedDailyChargeCost * AVERAGE_NUM_DAY_MONTH); | |
setMonthlyGasSaving(updatedDailyGasSaving * AVERAGE_NUM_DAY_MONTH); | |
}; | |
const handleIncrement = (mileageValue) => { | |
let inputRangeValue = mileageValue; | |
if (typeof inputRangeValue === undefined) { | |
inputRangeValue = 0 | |
} | |
setRangeValue(inputRangeValue); | |
// Analytics | |
if (window.dataLayer) { | |
window.dataLayer.push({ | |
event: "configurator", | |
"cfg-type": "charging-calculator", | |
interaction: `miles-driven-${mileageValue}`, | |
}); | |
} | |
updateCalculation(selectedVehicle, false, inputRangeValue); | |
}; | |
const sendAnalyticEvent = (interactionKey) => { | |
// Analytics | |
if (window.dataLayer) { | |
window.dataLayer.push({ | |
event: "configurator", | |
"cfg-type": "charging-calculator", | |
interaction: interactionKey, | |
}); | |
} | |
} | |
const path = | |
typeof window.tesla !== "undefined" && | |
typeof window.tesla.App !== "undefined" && | |
typeof window.tesla.App.base_url !== "undefined" | |
? window.tesla.App.base_url | |
: 'https://www.tesla.com'; | |
return ( | |
<> | |
<div className={`tds--vertical_padding ${styles.CalculatorDisplaySection}`}> | |
<ol | |
className={`tds-list tds-list--horizontal ${styles.CalculatorDisplayWrapper}`} | |
aria-live="polite" | |
aria-atomic="true" | |
> | |
<li className="tds-list-item tds-o-list-item"> | |
<div | |
className="tds-text--h1 tds-list-item_title tds-text_color--black tds--no_padding" | |
data-id="range" | |
> | |
<span>{copy.currency}</span> | |
<span className="specs--value-label"> | |
{timeInput === "daily" ? round(dailyChargeCost, 2) : round(monthlyChargeCost, 2)} | |
</span> | |
</div> | |
<span className="tds-text--body" data-id="range-label"> | |
<span>{copy.chargeCost}</span> | |
</span> | |
</li> | |
<li className="tds-list-item tds-o-list-item"> | |
<div | |
className="tds-text--h1 tds-list-item_title tds-text_color--black tds--no_padding" | |
data-id="top-speed" | |
> | |
<span>{copy.currency}</span> | |
<span className="specs--value-label"> | |
{timeInput === "daily" ? round(dailyGasSaving, 2) : round(monthlyGasSaving, 2)} | |
</span> | |
</div> | |
<span className="tds-text--body" data-id="top-speed-label"> | |
{copy.gasSavings} | |
</span> | |
</li> | |
</ol> | |
</div> | |
<Form className={styles.CalculatorWrapper}> | |
{({ formApi }) => ( | |
<> | |
<FormItem className={styles.RangeInputWrapper}> | |
<FormLabelRange>{copy.rangeLabel}</FormLabelRange> | |
<FormInputRange | |
progress | |
value={rangeValue === "" ? "0" : rangeValue} | |
onChange={(e) => { formApi.setValue('mileage', parseInt(e.target.value, 10)); handleIncrement(parseInt(e.target.value, 10))}} | |
max="300" | |
/> | |
</FormItem> | |
<Input placeholder={0} name="mileage" type="number" defaultValue={0} initialValue={rangeValue} onChange={ | |
formState => { | |
let newValue = formState.value !== undefined ? formState.value : 0; | |
if (formApi && (newValue > 3300 || newValue < 0 )) { | |
formApi.setValue('mileage', rangeValue); | |
newValue = rangeValue; | |
}; | |
handleIncrement(newValue); | |
}} className={`${styles.NumberInputWrapper} ${styles.CalculatorNumberInput}`}/> | |
<FormItem className={styles.VehicleSelectWrapper}> | |
<FormInputSelect | |
className={styles.VehicleSelectWrapper} | |
id="select-1" | |
options={allVehicles} | |
onChange={(e) => { | |
selectVehicle(e, updateCalculation); | |
}} | |
/> | |
</FormItem> | |
</> | |
)} | |
</Form> | |
<div className={`tds-btn_group tds-btn_group--vertical ${styles.ButtonGroupWrapper}`}> | |
<a | |
className={`tds-btn ${styles.OrderButton}`} | |
href={`${path}/${selectedVehicle.product.replace('m', 'model')}/design#overview`} | |
onClick={sendAnalyticEvent.bind(null, 'order-now')} | |
> | |
{copy.cta} | |
</a> | |
<a href="/support/charging" className="tds-link" onClick={sendAnalyticEvent.bind(null, 'learn-more-about-charging')}> | |
{copy.more} | |
</a> | |
</div> | |
</> | |
); | |
}; | |
Calculator.propTypes = propTypes; | |
Calculator.defaultProps = defaultProps; | |
export default Calculator; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"copy": { | |
"chargeCost": "Charge Cost", | |
"cta": "order now", | |
"ctaLink": "https://shop.tesla.com/product/wall-connector", | |
"currency": "$", | |
"gasSavings": "Gas Savings", | |
"more": "Learn More About Charging", | |
"rangeLabel": "Miles driven daily" | |
}, | |
"allVehicles": [ | |
{ | |
"value": "ms", | |
"label": "Model S", | |
"data-product": "ms", | |
"data-img-code": "mslongrange" | |
}, | |
{ | |
"value": "m3", | |
"label": "Model 3", | |
"data-product": "m3", | |
"data-img-code": "m3standard" | |
}, | |
{ | |
"value": "mx", | |
"label": "Model X", | |
"data-product": "mx", | |
"data-img-code": "mxlongrange" | |
}, | |
{ | |
"value": "my", | |
"label": "Model Y", | |
"data-product": "my", | |
"data-img-code": "mylongrange" | |
} | |
], | |
"calculationData": { | |
"ms": { | |
"fuel_efficiency_imperial": 23, | |
"fuel_efficiency_metric": 0, | |
"kwh_consumption_100": 28, | |
"supercharger_kwh_price": 0.26, | |
"fuel_price": 3.9, | |
"kwh_price": 0.16, | |
"electricity_last_updated": "", | |
"last_updated": "2023-08-26" | |
}, | |
"m3": { | |
"fuel_efficiency_imperial": 28, | |
"fuel_efficiency_metric": 0, | |
"kwh_consumption_100": 25.4, | |
"supercharger_kwh_price": 0.26, | |
"fuel_price": 3.9, | |
"kwh_price": 0.161, | |
"electricity_last_updated": "", | |
"last_updated": "2023-08-26" | |
}, | |
"mx": { | |
"fuel_efficiency_imperial": 22, | |
"fuel_efficiency_metric": 0, | |
"kwh_consumption_100": 33, | |
"supercharger_kwh_price": 0.26, | |
"fuel_price": 3.9, | |
"kwh_price": 0.161, | |
"electricity_last_updated": "", | |
"last_updated": "2023-08-26" | |
}, | |
"my": { | |
"fuel_efficiency_imperial": 25, | |
"fuel_efficiency_metric": 0, | |
"kwh_consumption_100": 28, | |
"supercharger_kwh_price": 0.26, | |
"fuel_price": 3.9, | |
"kwh_price": 0.16, | |
"electricity_last_updated": "", | |
"last_updated": "2023-08-26" | |
} | |
}, | |
"selectedVehicle": { | |
"img": "mslongrange", | |
"product": "ms" | |
}, | |
"timeInput": "daily" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment