Skip to content

Commit

Permalink
feat: adds calculator to compensation page for temp release (#977)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikaelbr authored Dec 10, 2024
1 parent 25a0955 commit c963b86
Show file tree
Hide file tree
Showing 12 changed files with 124 additions and 290 deletions.
10 changes: 2 additions & 8 deletions src/app/(main)/[locale]/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Metadata } from "next";
import { headers } from "next/headers";

import Compensations from "src/components/compensations/Compensations";
import CompensationsPreview from "src/components/compensations/CompensationsPreview";
import CustomerCase from "src/components/customerCases/customerCase/CustomerCase";
import CustomerCases from "src/components/customerCases/CustomerCases";
import CustomerCasesPreview from "src/components/customerCases/CustomerCasesPreview";
Expand Down Expand Up @@ -111,14 +110,9 @@ async function Page({ params }: Props) {
</>
);
case "compensations":
return isDraftMode ? (
<CompensationsPreview
initialCompensations={queryResponse.compensationsPage}
initialLocations={queryResponse.companyLocations}
initialLocale={queryResponse.locale}
/>
) : (
return isDraftMode ? null : (
<Compensations
language={locale}
compensations={queryResponse.compensationsPage.data}
locations={queryResponse.companyLocations.data}
locale={queryResponse.locale.data}
Expand Down
60 changes: 60 additions & 0 deletions src/components/compensations/CompensationSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
"use client";
import { useState } from "react";

import {
IOption,
RadioButtonGroup,
} from "src/components/forms/radioButtonGroup/RadioButtonGroup";
import { CompanyLocation } from "studio/lib/interfaces/companyDetails";
import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";

import BenefitsByLocation from "./components/benefitsByLocation/BenefitsByLocation";
import YearlyBonuses from "./components/yearlyBonuses/YearlyBonuses";

interface CompensationsProps {
compensations: CompensationsPage;
locations: CompanyLocation[];
locale: LocaleDocument;
}

export default function CompensationSelector({
compensations,
locations,
locale,
}: CompensationsProps) {
const [selectedLocation, setSelectedLocation] = useState<string>(
locations[0]._id,
);

const locationOptions: IOption[] = locations.map((companyLocation) => ({
id: companyLocation._id,
label: companyLocation.companyLocationName,
}));

const benefitsFilteredByLocation =
compensations.benefitsByLocation.find(
(benefit) => benefit.location._ref === selectedLocation,
)?.benefits || [];

const yearlyBonusesForLocation = compensations.bonusesByLocation.find(
(b) => b.location._ref === selectedLocation,
)?.yearlyBonuses;

return (
<>
{yearlyBonusesForLocation && (
<YearlyBonuses bonuses={yearlyBonusesForLocation} locale={locale} />
)}
<RadioButtonGroup
id="location-group"
label="Velg lokasjon"
options={locationOptions}
selectedId={selectedLocation}
onValueChange={(option) => setSelectedLocation(option.id)}
/>

<BenefitsByLocation benefits={benefitsFilteredByLocation} />
</>
);
}
151 changes: 17 additions & 134 deletions src/components/compensations/Compensations.tsx
Original file line number Diff line number Diff line change
@@ -1,156 +1,39 @@
"use client";
import { useMemo, useState } from "react";

import {
IOption,
RadioButtonGroup,
} from "src/components/forms/radioButtonGroup/RadioButtonGroup";
import CompensationCalculator from "src/components/sections/compensation-calculator/CompensationCalculator";
import Text from "src/components/text/Text";
import { formatAsCurrency } from "src/utils/i18n";
import { CompanyLocation } from "studio/lib/interfaces/companyDetails";
import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";

import styles from "./compensations.module.css";
import BenefitsByLocation from "./components/benefitsByLocation/BenefitsByLocation";
import SalaryCalculator, {
Degree,
} from "./components/salaryCalculator/SalaryCalculator";
import YearlyBonuses from "./components/yearlyBonuses/YearlyBonuses";
import {
calculatePension,
calculateSalary,
maxSalariesExaminationYear,
minSalariesExaminationYear,
salariesFromLocation,
} from "./utils/salary";
import CompensationSelector from "./CompensationSelector";

interface CompensationsProps {
compensations: CompensationsPage;
locations: CompanyLocation[];
locale: LocaleDocument;
language: string;
}

interface SalaryCalculatorFormState {
examinationYear: number;
selectedDegree: Degree;
}

const Compensations = ({
export default async function Compensations({
compensations,
locations,
locale,
}: CompensationsProps) => {
const [selectedLocation, setSelectedLocation] = useState<string>(
locations[0]._id,
);
const currentYear = new Date().getFullYear();
const [salary, setSalary] = useState<number | null>(null);
const [formState, setFormState] = useState<SalaryCalculatorFormState>({
examinationYear: currentYear - 1,
selectedDegree: "bachelor",
});

const currentYearSalariesResult = useMemo(
() =>
salariesFromLocation(
currentYear,
selectedLocation,
compensations.salariesByLocation,
),
[currentYear, selectedLocation, compensations.salariesByLocation],
);

const updateSelectedDegree = (newDegree: Degree) => {
setFormState((prevState) => ({
...prevState,
selectedDegree: newDegree,
}));
};

const updateExaminationYear = (newYear: number) => {
setFormState((prevState) => ({
...prevState,
examinationYear: newYear,
}));
};

const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
if (!currentYearSalariesResult.ok) return;
const salary = calculateSalary(
formState.examinationYear,
formState.selectedDegree,
currentYearSalariesResult.value,
);
if (salary === undefined) return;
setSalary(salary);
};

const locationOptions: IOption[] = locations.map((companyLocation) => ({
id: companyLocation._id,
label: companyLocation.companyLocationName,
}));

const benefitsFilteredByLocation =
compensations.benefitsByLocation.find(
(benefit) => benefit.location._ref === selectedLocation,
)?.benefits || [];

const yearlyBonusesForLocation = compensations.bonusesByLocation.find(
(b) => b.location._ref === selectedLocation,
)?.yearlyBonuses;

language,
}: CompensationsProps) {
return (
<div className={styles.wrapper}>
<Text type="h1">{compensations.basicTitle}</Text>
<RadioButtonGroup
id="location-group"
label="Velg lokasjon"
options={locationOptions}
selectedId={selectedLocation}
onValueChange={(option) => setSelectedLocation(option.id)}

<CompensationCalculator
section={compensations.compensationCalculator}
language={language}
/>

<CompensationSelector
compensations={compensations}
locations={locations}
locale={locale}
/>
{compensations.showSalaryCalculator && currentYearSalariesResult.ok && (
<>
<SalaryCalculator
examinationYearValue={formState.examinationYear}
minExaminationYear={minSalariesExaminationYear(
currentYearSalariesResult.value,
)}
maxExaminationYear={
maxSalariesExaminationYear(currentYearSalariesResult.value) - 1
}
selectedDegree={formState.selectedDegree}
onDegreeChanged={updateSelectedDegree}
onExaminationYearChanged={updateExaminationYear}
onSubmit={handleSubmit}
/>
{salary !== null ? (
<div aria-live="polite">
<Text>
{`Du vil få en årlig lønn på ${formatAsCurrency(salary, locale.locale, locale.currency)}`}
</Text>
{compensations.pensionPercent && (
<Text>
Du vil få en årlig pensjon på omtrent{" "}
{formatAsCurrency(
calculatePension(salary, compensations.pensionPercent),
locale.locale,
locale.currency,
)}
</Text>
)}
</div>
) : null}
</>
)}
{yearlyBonusesForLocation && (
<YearlyBonuses bonuses={yearlyBonusesForLocation} locale={locale} />
)}
<BenefitsByLocation benefits={benefitsFilteredByLocation} />
</div>
);
};

export default Compensations;
}
62 changes: 0 additions & 62 deletions src/components/compensations/CompensationsPreview.tsx

This file was deleted.

This file was deleted.

Loading

0 comments on commit c963b86

Please sign in to comment.