From 8d095b097dca78fbb6496b4f6ba67f9fa5521a83 Mon Sep 17 00:00:00 2001 From: Eli <88557639+lishaduck@users.noreply.github.com> Date: Fri, 1 Mar 2024 12:23:21 -0600 Subject: [PATCH 1/8] feat: add solar pricing calculator * Add Tailwind form reset and the headlessui plugin * Add a new page for the solar pricing calculator * Add a new island for comboboxes * Add a TODO comment about testing ;) * Add a new utility for grabbing geo data from IP addresses Co-authored-by: Matthew Wasser <71449347+MattsAttack@users.noreply.github.com> --- deno.json | 1 + src/fresh.gen.ts | 4 + src/islands/StateSelector.tsx | 110 +++++++++ src/routes/about.test.ts | 13 +- src/routes/calculator.tsx | 128 ++++++++++ src/tailwind.config.ts | 10 +- src/utils/calc.ts | 435 ++++++++++++++++++++++++++++++++++ src/utils/headless.ts | 50 ++++ src/utils/icons.ts | 6 + src/utils/ip.ts | 62 +++++ src/utils/zod.ts | 3 + 11 files changed, 818 insertions(+), 4 deletions(-) create mode 100644 src/islands/StateSelector.tsx create mode 100644 src/routes/calculator.tsx create mode 100644 src/utils/calc.ts create mode 100644 src/utils/headless.ts create mode 100644 src/utils/ip.ts create mode 100644 src/utils/zod.ts diff --git a/deno.json b/deno.json index 0671ab03..03b9faff 100644 --- a/deno.json +++ b/deno.json @@ -39,6 +39,7 @@ "remark-mdx-frontmatter": "npm:remark-mdx-frontmatter@4.0.0", "remark-preset-lint-consistent": "npm:remark-preset-lint-consistent@5.1.2", "remark-preset-lint-recommended": "npm:remark-preset-lint-recommended@6.1.3", + "@tailwindcss/forms": "npm:@tailwindcss/forms@0.5.7", "@tailwindcss/typography": "npm:@tailwindcss/typography@0.5.10", "tailwindcss": "npm:tailwindcss@3.4.1", "tailwindcss/plugin": "npm:tailwindcss@3.4.1/plugin.js", diff --git a/src/fresh.gen.ts b/src/fresh.gen.ts index 2083a31f..7fa38fc8 100644 --- a/src/fresh.gen.ts +++ b/src/fresh.gen.ts @@ -7,10 +7,12 @@ import * as $_500 from "./routes/_500.tsx"; import * as $_app from "./routes/_app.tsx"; import * as $_layout from "./routes/_layout.tsx"; import * as $about from "./routes/about.tsx"; +import * as $calculator from "./routes/calculator.tsx"; import * as $index from "./routes/index.tsx"; import * as $solutions_category_slug_ from "./routes/solutions/[category]/[[slug]].tsx"; import * as $solutions_category_index from "./routes/solutions/[category]/index.tsx"; import * as $HeaderMenu from "./islands/HeaderMenu.tsx"; +import * as $StateSelector from "./islands/StateSelector.tsx"; import { type Manifest } from "$fresh/server.ts"; const manifest = { @@ -20,12 +22,14 @@ const manifest = { "./routes/_app.tsx": $_app, "./routes/_layout.tsx": $_layout, "./routes/about.tsx": $about, + "./routes/calculator.tsx": $calculator, "./routes/index.tsx": $index, "./routes/solutions/[category]/[[slug]].tsx": $solutions_category_slug_, "./routes/solutions/[category]/index.tsx": $solutions_category_index, }, islands: { "./islands/HeaderMenu.tsx": $HeaderMenu, + "./islands/StateSelector.tsx": $StateSelector, }, baseUrl: import.meta.url, } satisfies Manifest; diff --git a/src/islands/StateSelector.tsx b/src/islands/StateSelector.tsx new file mode 100644 index 00000000..e7d2fe1a --- /dev/null +++ b/src/islands/StateSelector.tsx @@ -0,0 +1,110 @@ +import { IS_BROWSER } from "$fresh/runtime.ts"; +import { Combobox, Transition } from "@headlessui/react"; +import { useSignal } from "@preact/signals"; +import { Fragment, type JSX } from "preact"; +import { type State, states } from "../utils/calc.ts"; +import { IconCheck, IconChevronDown } from "../utils/icons.ts"; +import { tw } from "../utils/tailwind.ts"; + +export interface StateSelectorProps { + currentState: State; +} + +export function StateSelector({ + currentState, +}: StateSelectorProps): JSX.Element { + const state = useSignal(currentState); + const query = useSignal(""); + + const filteredStates = + query.value === "" + ? states + : states.filter((state) => + state + .toLowerCase() + .replace(/\s+/g, "") + .includes(query.value.toLowerCase().replace(/\s+/g, "")), + ); + + return ( +
Energy Form | +Time to Payoff | +Savings per Month | +Install Cost | +Rebate | +Emissions per Month | +
---|---|---|---|---|---|
Solar | +{data.regionData.payoff.toFixed(2)} Years | +${data.regionData.savings.toFixed(2)} | +${data.regionData.install.toFixed(2)} | +${data.regionData.rebate.toFixed(2)} | +{data.regionData.emissions.toFixed(2)} lbs of Carbon per kWh | +