diff --git a/src/item-name.ts b/src/item-name.ts index 428f0ac..09c69f1 100644 --- a/src/item-name.ts +++ b/src/item-name.ts @@ -1,6 +1,6 @@ import { ItemType } from './api/calculator-types-v1'; import { MsgFn } from './i18n/use-translated'; -import { Project } from './projects'; +import { Project, PROJECTS } from './projects'; type ItemGroup = | 'air_source_heat_pump' @@ -15,8 +15,7 @@ type ItemGroup = | 'weatherization' | 'audit_and_weatherization' | 'water_heater' - | 'electric_outdoor_equipment' - | 'hear_projects'; + | 'electric_outdoor_equipment'; const ALL_INSULATION: ItemType[] = [ 'attic_or_roof_insulation', @@ -116,17 +115,13 @@ const ITEM_GROUPS: { group: ItemGroup; members: Set }[] = [ group: 'water_heater', members: new Set(['heat_pump_water_heater', 'non_heat_pump_water_heater']), }, - { - group: 'hear_projects', - members: new Set(['heat_pump_clothes_dryer', 'electric_stove']), - }, ]; const itemsBelongToGroup = (items: ItemType[], members: Set) => { return items.every(i => members.has(i)); }; -const multipleItemsName = (items: ItemType[], msg: MsgFn, project: Project) => { +const multipleItemsName = (items: ItemType[], msg: MsgFn) => { // For a multiple-items case, check whether all the items are in one of the // defined groups. for (const { group, members } of ITEM_GROUPS) { @@ -180,8 +175,6 @@ const multipleItemsName = (items: ItemType[], msg: MsgFn, project: Project) => { return msg('electric outdoor equipment', { desc: 'e.g. "$100 off [this string]"', }); - case 'hear_projects': - return hearName(items, msg, project); default: { // This will be a type error if the above switch is not exhaustive const unknownGroup: never = group; @@ -194,51 +187,27 @@ const multipleItemsName = (items: ItemType[], msg: MsgFn, project: Project) => { return null; }; -const hearName = (items: ItemType[], msg: MsgFn, project: Project) => { - const HEAR_INCENTIVE_PROJECT_MSG_LIST: { - item: ItemType; - project: Project; - msg: string; - }[] = [ - { - item: 'heat_pump_clothes_dryer', - project: 'clothes_dryer', - msg: msg('a heat pump clothes dryer', { - desc: 'e.g. "$100 off [this string]"', - }), - }, - - { - item: 'electric_stove', - project: 'cooking', - msg: msg('an electric/induction stove', { - desc: 'e.g. "$100 off [this string]"', - }), - }, - ]; - - const match = HEAR_INCENTIVE_PROJECT_MSG_LIST.find( - group => items.includes(group.item) && project === group.project, - ); - - if (!match) return null; - - return match.msg; -}; - /** * TODO this is an internationalization sin. Figure out something better! */ -export const itemName = (items: ItemType[], msg: MsgFn, project: Project) => { - if (items.length > 1) { - return multipleItemsName(items, msg, project); +export const itemName = ( + incentiveItems: ItemType[], + msg: MsgFn, + project: Project, +) => { + const itemsToRender = incentiveItems.filter(item => + PROJECTS[project].items.includes(item), + ); + + if (itemsToRender.length > 1) { + return multipleItemsName(itemsToRender, msg); } - if (items.length !== 1) { + if (itemsToRender.length !== 1) { return null; } - const item = items[0]; + const item = itemsToRender[0]; switch (item) { case 'air_sealing': return msg('air sealing', { desc: 'e.g. "$100 off [this string]"' }); diff --git a/src/project-icons.tsx b/src/project-icons.tsx new file mode 100644 index 0000000..591e06a --- /dev/null +++ b/src/project-icons.tsx @@ -0,0 +1,24 @@ +import BatteryIcon from 'jsx:../static/icons/battery.svg'; +import ClothesDryerIcon from 'jsx:../static/icons/clothes-dryer.svg'; +import CookingIcon from 'jsx:../static/icons/cooking.svg'; +import ElectricalWiringIcon from 'jsx:../static/icons/electrical-wiring.svg'; +import EvIcon from 'jsx:../static/icons/ev.svg'; +import HvacIcon from 'jsx:../static/icons/hvac.svg'; +import LawnMowerIcon from 'jsx:../static/icons/lawnmower.svg'; +import SolarIcon from 'jsx:../static/icons/solar.svg'; +import WaterHeaterIcon from 'jsx:../static/icons/water-heater.svg'; +import WeatherizationIcon from 'jsx:../static/icons/weatherization.svg'; +import { Project } from './projects'; + +export const PROJECT_ICONS: { [p in Project]: () => React.ReactElement } = { + clothes_dryer: () => , + hvac: () => , + ev: () => , + solar: () => , + battery: () => , + water_heater: () => , + cooking: () => , + wiring: () => , + weatherization_and_efficiency: () => , + lawn_care: () => , +}; diff --git a/src/projects.tsx b/src/projects.ts similarity index 67% rename from src/projects.tsx rename to src/projects.ts index 3741499..a43624d 100644 --- a/src/projects.tsx +++ b/src/projects.ts @@ -1,19 +1,8 @@ -import BatteryIcon from 'jsx:../static/icons/battery.svg'; -import ClothesDryerIcon from 'jsx:../static/icons/clothes-dryer.svg'; -import CookingIcon from 'jsx:../static/icons/cooking.svg'; -import ElectricalWiringIcon from 'jsx:../static/icons/electrical-wiring.svg'; -import EvIcon from 'jsx:../static/icons/ev.svg'; -import HvacIcon from 'jsx:../static/icons/hvac.svg'; -import LawnMowerIcon from 'jsx:../static/icons/lawnmower.svg'; -import SolarIcon from 'jsx:../static/icons/solar.svg'; -import WaterHeaterIcon from 'jsx:../static/icons/water-heater.svg'; -import WeatherizationIcon from 'jsx:../static/icons/weatherization.svg'; import { ItemType } from './api/calculator-types-v1'; import { MsgFn } from './i18n/use-translated'; type ProjectInfo = { label: (msg: MsgFn) => string; - getIcon: () => React.ReactElement; items: ItemType[]; }; @@ -39,7 +28,6 @@ export const PROJECTS: Record = { clothes_dryer: { items: ['heat_pump_clothes_dryer', 'non_heat_pump_clothes_dryer'], label: msg => msg('Clothes dryer'), - getIcon: () => , }, hvac: { items: [ @@ -51,7 +39,6 @@ export const PROJECTS: Record = { 'other_heat_pump', ], label: msg => msg('Heating, ventilation & cooling'), - getIcon: () => , }, ev: { items: [ @@ -63,32 +50,26 @@ export const PROJECTS: Record = { 'ebike', ], label: msg => msg('Electric transportation'), - getIcon: () => , }, solar: { items: ['rooftop_solar_installation'], label: msg => msg('Solar', { desc: 'i.e. rooftop solar' }), - getIcon: () => , }, battery: { items: ['battery_storage_installation'], label: msg => msg('Battery storage'), - getIcon: () => , }, water_heater: { items: ['heat_pump_water_heater', 'non_heat_pump_water_heater'], label: msg => msg('Water heater'), - getIcon: () => , }, cooking: { items: ['electric_stove'], label: msg => msg('Cooking stove/range'), - getIcon: () => , }, wiring: { items: ['electric_panel', 'electric_wiring'], label: msg => msg('Electrical panel & wiring'), - getIcon: () => , }, weatherization_and_efficiency: { items: [ @@ -108,11 +89,9 @@ export const PROJECTS: Record = { 'energy_audit', ], label: msg => msg('Weatherization & efficiency'), - getIcon: () => , }, lawn_care: { items: ['electric_outdoor_equipment'], label: msg => msg('Lawn Care'), - getIcon: () => , }, }; diff --git a/src/state-incentive-details.tsx b/src/state-incentive-details.tsx index 72811f7..823f7f2 100644 --- a/src/state-incentive-details.tsx +++ b/src/state-incentive-details.tsx @@ -15,6 +15,7 @@ import { IncentiveCard } from './incentive-card'; import { IRARebate, getRebatesFor } from './ira-rebates'; import { itemName } from './item-name'; import { PartnerLogos } from './partner-logos'; +import { PROJECT_ICONS } from './project-icons'; import { PROJECTS, Project } from './projects'; import { safeLocalStorage } from './safe-local-storage'; @@ -250,7 +251,7 @@ const IncentiveGrid = forwardRef( const options: Option[] = tabs.map(({ project, count }) => ({ value: project, label: PROJECTS[project].label(msg), - getIcon: PROJECTS[project].getIcon, + getIcon: PROJECT_ICONS[project], badge: count, disabled: count === 0, })); diff --git a/static/icons/lawnmower.svg b/static/icons/lawnmower.svg index a3b20ca..5243145 100644 --- a/static/icons/lawnmower.svg +++ b/static/icons/lawnmower.svg @@ -1,5 +1,5 @@ - +