DEV Community

Cover image for Inflation Calculator with React & TypeScript
Radzion Chachura
Radzion Chachura

Posted on • Originally published at radzion.com

Inflation Calculator with React & TypeScript

Watch on YouTube | 🐙 GitHub | 🎮 Demo

Let's develop a straightforward application that illustrates the amount of money you are losing due to inflation. Inflation is currently substantial, and this app will serve as an incentive to take action with your money.

To set up the app, I utilize Next.js and components from the react-toolkit repository repository, which I typically copy to begin a new project. I prefer having most of the components in the codebase, so that I can directly make the necessary changes, rather than dealing with complex frameworks.

We begin by including the title and description in the head for SEO purposes. The root container will be a flexbox element with some padding and center alignment. The content will be inside another flexbox element with a maximum width and a gap between each element. By using the VStack/HStack components, we rarely need to use the margin attribute.

import { InflationReport } from "components/InflationReport"
import { InflationResourcePromotion } from "components/InflationResourcePromotion"
import { DollarIcon } from "lib/ui/icons/DollarIcon"
import { PercentIcon } from "lib/ui/icons/PercentIcon"
import { AmountTextInput } from "lib/ui/inputs/AmountTextInput"
import { VStack } from "lib/ui/Stack"
import { Text } from "lib/ui/Text"
import Head from "next/head"
import { useState } from "react"
import styled from "styled-components"

const Container = styled(VStack)`
  padding: 80px 20px 40px 20px;

  align-items: center;
`

const Content = styled(VStack)`
  max-width: 360px;
  gap: 20px;
`

export default function Home() {
  const [amount, setAmount] = useState<number | undefined>(100000)
  const [inflation, setInflation] = useState<number | undefined>(8)

  return (
    <>
      <Head>
        <title>Inflation Calculator | See how your savings lose value</title>
        <meta
          name="description"
          content="Calculate how much money you lose to inflation every year/month/day"
        />
      </Head>
      <Container>
        <Content>
          <Text
            style={{ textTransform: "uppercase" }}
            weight="semibold"
            as="h1"
          >
            How much do I lose to{" "}
            <Text as="span" color="alert">
              inflation?
            </Text>
          </Text>
          <VStack gap={4}>
            <AmountTextInput
              label="Savings"
              value={amount}
              onValueChange={setAmount}
              shouldBePositive
              shouldBeInteger
              unit={<DollarIcon />}
            />
            <AmountTextInput
              label="Inflation"
              value={inflation}
              onValueChange={setInflation}
              shouldBePositive
              unit={<PercentIcon />}
            />
          </VStack>
          {amount !== undefined && inflation !== undefined && (
            <InflationReport savings={amount} inflation={inflation} />
          )}
          <InflationResourcePromotion />
        </Content>
      </Container>
    </>
  )
}
Enter fullscreen mode Exit fullscreen mode

For both amount and inflation fields we use the same AmountTextInput component. It shows a unit of the input value at the beginning to make it's more intuitive for the user.

If both inputs contain valid values, we render the InflationReport component, which receives the amount and inflation values as props and displays basic calculations about the money lost due to inflation. To format the currency, we use Intl.NumberFormat.

const sharedFormatterConfig = {
  style: "currency",
  currency: "USD",
}

const intCurrencyFormatter = new Intl.NumberFormat("en-US", {
  ...sharedFormatterConfig,
  maximumFractionDigits: 0,
  minimumFractionDigits: 0,
})

const floatCurrencyFormatter = new Intl.NumberFormat("en-US", {
  ...sharedFormatterConfig,
  maximumFractionDigits: 2,
})

export const formatCurrencyAmount = (amount: number) => {
  const formatter = Number.isInteger(amount)
    ? intCurrencyFormatter
    : floatCurrencyFormatter

  return formatter.format(amount)
}
Enter fullscreen mode Exit fullscreen mode

Lastly, we display the InflationResourcePromotion component, which serves as a call to action to watch a video on YouTube with some investment ideas.

Top comments (0)