diff --git a/src/calculator-form.ts b/src/calculator-form.ts index 4c1cbb6..5aea7c5 100644 --- a/src/calculator-form.ts +++ b/src/calculator-form.ts @@ -1,4 +1,4 @@ -import { html, css } from 'lit'; +import { html, css, nothing } from 'lit'; import { downIcon, questionIcon } from './icons'; import { select, selectStyles, OptionParam } from './select'; import { inputStyles } from './styles/input'; @@ -73,110 +73,146 @@ const HOUSEHOLD_SIZE_OPTIONS: OptionParam[] = [1, 2, 3, 4, 5, 6, 7, 8].map( ); export const formTemplate = ( - [zip, ownerStatus, householdIncome, taxFiling, householdSize]: Array, + [ + zip, + ownerStatus, + householdIncome, + taxFiling, + householdSize, + utility, + ]: Array, + showUtilityField: boolean, + utilityOptions: OptionParam[], onSubmit: (e: SubmitEvent) => void, -) => html` -
-
-
-
- -`; + + `; +}; diff --git a/src/calculator.ts b/src/calculator.ts index edaf7e5..06b766e 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -156,7 +156,10 @@ export class RewiringAmericaCalculator extends LitElement { this.taxFiling, this.householdSize, ], + false, + [], (event: SubmitEvent) => this.submit(event), + () => {}, )}
${this.hideResult diff --git a/src/state-calculator.ts b/src/state-calculator.ts index 1d6c050..a9bd150 100644 --- a/src/state-calculator.ts +++ b/src/state-calculator.ts @@ -11,6 +11,7 @@ import { stateIncentivesTemplate, stateIncentivesStyles, } from './state-incentive-details'; +import { OptionParam } from './select'; const loadingTemplate = () => html`
Loading...
@@ -26,6 +27,8 @@ const errorTemplate = (error: unknown) => html` const DEFAULT_CALCULATOR_API_HOST: string = 'https://api.rewiringamerica.org'; +const BLANK_UTILITY: OptionParam = { value: '', label: '' }; + @customElement('rewiring-america-state-calculator') export class RewiringAmericaStateCalculator extends LitElement { static override styles = [ @@ -70,6 +73,9 @@ export class RewiringAmericaStateCalculator extends LitElement { @property({ type: String, attribute: 'household-size' }) householdSize: string = '1'; + @property({ type: String, attribute: 'utility' }) + utility: string = ''; + submit(e: SubmitEvent) { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); @@ -78,6 +84,7 @@ export class RewiringAmericaStateCalculator extends LitElement { this.householdIncome = (formData.get('household_income') as string) || ''; this.taxFiling = (formData.get('tax_filing') as FilingStatus) || ''; this.householdSize = (formData.get('household_size') as string) || ''; + this.utility = (formData.get('utility') ?? '') as string; } get hideResult() { @@ -99,6 +106,7 @@ export class RewiringAmericaStateCalculator extends LitElement { household_income, tax_filing, household_size, + utility, ]) => { if (this.hideResult) { // this is a special response type provided by Task to keep it in the INITIAL state @@ -113,6 +121,10 @@ export class RewiringAmericaStateCalculator extends LitElement { }); query.append('authority_types', 'federal'); query.append('authority_types', 'state'); + if (utility?.length > 0) { + query.append('authority_types', 'utility'); + query.set('utility', utility); + } return await fetchApi( this.apiKey, @@ -128,9 +140,34 @@ export class RewiringAmericaStateCalculator extends LitElement { this.householdIncome, this.taxFiling, this.householdSize, + this.utility, ], }); + private _utilityOptionsTask = new Task(this, { + task: async ([zip]) => { + const query = new URLSearchParams({ + 'location[zip]': zip, + }); + const url = `${this.apiHost}/api/v1/utilities?${query}`; + const response = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${this.apiKey}`, + }, + }); + + const utilityMap = await response.json(); + return Object.keys(utilityMap) + .map(id => ({ + value: id, + label: utilityMap[id].name, + })) + .sort((a, b) => a.label.localeCompare(b.label)); + }, + args: () => [this.zip], + }); + override render() { return html`
@@ -145,8 +182,18 @@ export class RewiringAmericaStateCalculator extends LitElement { this.householdIncome, this.taxFiling, this.householdSize, + this.utility, ], + true, + this._utilityOptionsTask.render({ + initial: () => [BLANK_UTILITY], + pending: () => [BLANK_UTILITY], + complete: a => [BLANK_UTILITY, ...a], + error: () => [BLANK_UTILITY], + }) as OptionParam[], (event: SubmitEvent) => this.submit(event), + (event: InputEvent) => + (this.zip = (event.target as HTMLInputElement).value), )}
${this.hideResult