diff --git a/src/pages/prescreen-1d.tsx b/src/pages/prescreen-1d.tsx index 8df059908..d262d9a84 100644 --- a/src/pages/prescreen-1d.tsx +++ b/src/pages/prescreen-1d.tsx @@ -65,15 +65,7 @@ const Link = styled.a` overflow-wrap: break-word; `; -/////// -/////// - -// TODO: Change te interface to a props object -interface Prescreen1dProps { - userState: UserState - userStateActions: UserStateActions -} -const Prescreen1d = ({ userState, userStateActions }: Prescreen1dProps) => { +const Prescreen1d = ({ userState, userStateActions }) => { const { setExpectedLastEarningYear, setAwiTrendOrManualPrediction, setAwiTrendSelection, @@ -247,8 +239,4 @@ const Prescreen1d = ({ userState, userStateActions }: Prescreen1dProps) => { ); }; -export default function Prescreen1dWrapper(): JSX.Element { - const userState = useUserState() - const userStateActions = useUserStateActions() - return -} +export default Prescreen1d; \ No newline at end of file diff --git a/src/pages/screen-2a.tsx b/src/pages/screen-2a.tsx index c13f54e20..56c4e8b7b 100644 --- a/src/pages/screen-2a.tsx +++ b/src/pages/screen-2a.tsx @@ -1,20 +1,41 @@ -import styled from "@emotion/styled"; -import SectionsCarousel from "react-slick"; -import { breakPoints, colors } from "../constants"; -import { H2, SEO } from "../components"; -import stepImg1 from "../images/step1.png"; -import stepImg2 from "../images/step2.png"; -import stepImg3 from "../images/step3.png"; -import finalImg from "../images/final.png"; - -const Screen2a = () => { - const Arrow = ({ className, onClick }: { - className?: string, - onClick?: () => void +import styled from '@emotion/styled'; +import SectionsCarousel from 'react-slick'; +import { breakPoints, colors } from '../constants'; +import { H2, SEO } from '../components'; +import { radii, spacing } from '../constants'; +import { FunctionComponent } from 'react'; +import { + UserState, + EarningsEnum, + useUserState, +} from '../library/user-state-context'; +import { + UserStateActions, + useUserStateActions, +} from '../library/user-state-actions-context'; +import { format } from 'd3-format'; + +interface Screen2aProps { + userState: UserState; + userStateActions: UserStateActions; +} + +export const Screen2a: FunctionComponent = () => { + // const { + // userState: { haveEarnings, haveSSAAccount, earningsFormat }, + // } = this.props; + + // debugger + const Arrow = ({ + className, + onClick, + }: { + className?: string; + onClick?: () => void; }) => ( ); @@ -22,41 +43,109 @@ const Screen2a = () => { return (

Benefit Formula

- - {renderSections()} - - } - pauseOnHover={true} - prevArrow={} - slidesToScroll={1} - slidesToShow={1} - speed={700} - > - {renderSections({ isInCarousel: true })} - + {SliderSections()} + } + pauseOnHover={true} + prevArrow={} + slidesToScroll={1} + slidesToShow={1} + speed={700} + > + {SliderSections({ isInCarousel: true })} +
- ) + ); +}; + +const BarChart = (bottomPercent: number) => { + // console.log('bottomPercent: ', bottomPercent.bottomPercent); + return ( +
+
+
+ {bottomPercent.bottomPercent * 100}% +
+
+ ); }; -const renderSections = ({ isInCarousel }: { isInCarousel?: boolean } = {}) => { - const key = `screen-2a-${isInCarousel ? "carousel" : "list"}-section-` +const SliderSections = ({ isInCarousel }: { isInCarousel?: boolean } = {}) => { + const userState = useUserState(); // react hook always on top of functional components + const key = `screen-2a-${isInCarousel ? 'carousel' : 'list'}-section-`; + const userStateTablePage1 = + userState && userState.userProfile && userState.userProfile.bendPoints; + const userStateYearOf62 = userState && userState.year62; + const userAIME = + userState && userState.userProfile && userState.userProfile.aime; + const beforeFirstBendPoint = + (userStateTablePage1 && + userStateTablePage1[0] && + userStateTablePage1[0].Amount) || + 805.5; + const beforeFirstBendPointPercent = + (userStateTablePage1 && + userStateTablePage1[0] && + userStateTablePage1[0].Percent) || + 0.9; + const afterFirstBendPoint = + (userStateTablePage1 && + userStateTablePage1[1] && + userStateTablePage1[1].Amount) ?? + 1440.64; + const afterFirstBendPointPercent = + (userStateTablePage1 && + userStateTablePage1[1] && + userStateTablePage1[1].Percent) || + 0.32; + const pastSecondBendPoint = + (userStateTablePage1 && + userStateTablePage1[2] && + userStateTablePage1[2].Amount) ?? + 90.45; + const pastSecondBendPointPercent = + (userStateTablePage1 && + userStateTablePage1[2] && + userStateTablePage1[2].Percent) || + 0.15; + var totalPrimaryInsuranceAmount = + beforeFirstBendPoint + afterFirstBendPoint + pastSecondBendPoint; + const formatValue = format('$,.1f'); + const formatPercent = format('.0%'); + const explanationAIME = ( + yearOf62: number | null, + aime: number | null + ): string => { + // For this // example, we are using the bend points for someone who turned 62 in 2018, + // and had AIME of $6,000. + if (yearOf62 === null || aime === null) { + return `For this example, we are using the bend points for someone who turned 62 in 2018, and had AIME of $6,000.`; + } else { + return `In your case, the bend points are for people who turned 62 in ${yearOf62} year and had an AIME of $${aime}`; + } + }; - return ([ -
+ return [ +

How does Social Security calculate my benefits?

Social Security uses three things to calculate your Primary Insurance Amount, or your basic benefit before adjusting for early or late - retirement. + retirement. {explanationAIME(userStateYearOf62, userAIME)}

The three inputs are: @@ -69,50 +158,358 @@ const renderSections = ({ isInCarousel }: { isInCarousel?: boolean } = {}) => {

We'll walk you through an example in the following steps.

, -
+

Step 1:

Social Security calculates how much of your Average Indexed Monthly Earnings (AIME) fall below your first bend point. Bend points - are set by law and correspond to the year of your birth. For this - example, we are using the bend points for someone who turned 62 in 2018, - and had AIME of $6,000. + are set by law and correspond to the year of your birth.

- You get 90% of what falls under this bend point. + You get {formatPercent(beforeFirstBendPointPercent)} of what falls under + this bend point. +

+ + + + 1st Bucket + 1st Bend Point = ${beforeFirstBendPoint} + + + + + + + + + + + + + + + + + + + + + + You get back {formatPercent(beforeFirstBendPointPercent)} of the + amount, or {formatValue(beforeFirstBendPoint)} + + + + + + + + + + + + + + Primary Insurance Amount Formula + + + + step 1 + step 2 + step 3 + PIA + + + {formatValue(beforeFirstBendPoint)} + + + + + + +

+ However, if you answered “Yes” to the first question in the “Employment + Status” section of this website, the amount you get back of this first + bucket will be different. To learn more, please see the + + Windfall Elimination Provision pamphlet +

-
, -
+

Step 2:

Social Security calculates how much of your AIME fall below your first and second bend points.

- + + + + 1st Bucket + 1st Bend Point = ${beforeFirstBendPoint} + + 2nd Bucket + 2nd Bend Point = ${afterFirstBendPoint} + + + + + + + + + + + + + + + + + + + + + You get back {formatPercent(beforeFirstBendPointPercent)} of the + amount, or {formatValue(beforeFirstBendPoint)} + + + + You get back {formatPercent(afterFirstBendPointPercent)} of the + amount, or {formatValue(afterFirstBendPoint)} + + + + + + + + + + + + AIME or Average Income Monthly Earnings + + + + step 1 + step 2 + step 3 + PIA + + + {formatValue(beforeFirstBendPoint)} + {formatValue(afterFirstBendPoint)} + + + +
, -
+

Step 3:

Social Security calculates how much of your AIME fall below your second bend point.

- + + + + 1st Bucket + 1st Bend Point = ${beforeFirstBendPoint} + + 2nd Bucket + 2nd Bend Point = ${afterFirstBendPoint} + + 3rd Bucket + + + + + + + + + + + + + + + + + + + + You get back {formatPercent(beforeFirstBendPointPercent)} of the + amount, or {formatValue(beforeFirstBendPoint)} + + + + You get back {formatPercent(afterFirstBendPointPercent)} of the + amount, or {formatValue(afterFirstBendPoint)} + + + + You get back {formatPercent(pastSecondBendPointPercent)} of the + amount, or {formatValue(pastSecondBendPoint)} + + + + + + + + AIME or Average Income Monthly Earnings + + + + step 1 + step 2 + step 3 + PIA + + + {formatValue(beforeFirstBendPoint)} + {formatValue(afterFirstBendPoint)} + {formatValue(pastSecondBendPoint)} + + +
, -
+

Final Calculation

Finally, Social Security adds the results of the three previous steps altogether.

- -
- ]) + + + + 1st Bucket + 1st Bend Point = ${beforeFirstBendPoint} + + 2nd Bucket + 2nd Bend Point = ${afterFirstBendPoint} + + 3rd Bucket + + + + + + + + + + + + + + + + + + + + You get back {formatPercent(beforeFirstBendPointPercent)} of the + amount, or {formatValue(beforeFirstBendPoint)} + + + + You get back {formatPercent(afterFirstBendPointPercent)} of the + amount, or {formatValue(afterFirstBendPoint)} + + + + You get back {formatPercent(pastSecondBendPointPercent)} of the + amount, or {formatValue(pastSecondBendPoint)} + + + + + + + + AIME or Average Income Monthly Earnings + + + + step 1 + step 2 + step 3 + PIA + + + {formatValue(beforeFirstBendPoint)} + {formatValue(afterFirstBendPoint)} + {formatValue(pastSecondBendPoint)} + {formatValue(totalPrimaryInsuranceAmount)} + + +

+ Remember: this is the basic amount you are paid before Social Security + adjusts your benefits lower for early retirement, or higher for delayed + retirement. +

+
, + +
+
+

Commonly Asked Questions

+ +

I currently have an overpayment, so what should I do?

+ + See the SSA document on Overpayments + + +

How can I work on changing this law?

+ + Find your Representative + + +

How can I talk with my representative about Social Security?

+ + Request for your Representative's staff to look at your case + +
+
, + ]; }; +const TableBarChart = styled.table` + font-size: 75%; + margin-bottom: 20px; + margin-top: 20px; + + td { + width: 12.5%; + } + + .barContainer { + height: 200px; + } + + .barTop { + background-color: #dddddd; + display: flex; + justify-content: center; + align-items: center; + } + + .barBottom { + background-color: #433a74; + justify-content: center; + display: flex; + align-items: center; + } +`; + const Wrapper = styled.div` width: 100%; .screen-2a-carousel-container { @@ -135,9 +532,9 @@ const SectionsList = styled.div` const Section = styled.section<{ isInCarousel?: boolean }>` box-sizing: border-box; - margin-top: ${props => !props.isInCarousel && "3rem"}; + margin-top: ${(props) => !props.isInCarousel && '3rem'}; outline: none; - padding: ${props => props.isInCarousel && "0 1rem"}; + padding: ${(props) => props.isInCarousel && '0 1rem'}; `; const Image = styled.img` @@ -148,8 +545,8 @@ const Image = styled.img` const ArrowElement = styled.div<{ isArrowLeft?: boolean }>` height: 2.5rem; - left: ${props => props.isArrowLeft && "-2.75rem"}; - right: ${props => !props.isArrowLeft && "-2.75rem"}; + left: ${(props) => props.isArrowLeft && '-2.75rem'}; + right: ${(props) => !props.isArrowLeft && '-2.75rem'}; width: 2.5rem; &:before { color: ${colors.purple}; @@ -157,4 +554,32 @@ const ArrowElement = styled.div<{ isArrowLeft?: boolean }>` } `; +const ChartTable = styled.table` + margin: auto; + width: 100%; + text-align: center; + vertical-align: bottom; + column-width: 33.3%; +`; + +export const DisplayTable = styled('table')` + table-layout: fixed; + border: 1px solid black; + border-radius: ${radii[0]}; + margin: auto; +`; + +export const TableHeader = styled('th')` + background-color: #dddddd; + border: 1px solid #888888; + text-align: left; + padding: 8px; +`; + +export const td = styled('tr')` + border: 1px solid #888888; + text-align: center; + padding: 8px; +`; + export default Screen2a;