Last active
July 9, 2024 02:17
-
-
Save judge2020/fab78fee2fac4a033bb8fe12afc65b58 to your computer and use it in GitHub Desktop.
Revisions
-
judge2020 renamed this gist
Jul 9, 2024 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
judge2020 created this gist
Jul 9, 2024 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,84 @@ { "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" } This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,250 @@ /* 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;