Skip to content

Commit

Permalink
feat(Compensations): display salary for selected location, degree and…
Browse files Browse the repository at this point in the history
… examination year
  • Loading branch information
mathiazom committed Sep 11, 2024
1 parent 6ca523d commit dbc3daf
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 83 deletions.
41 changes: 32 additions & 9 deletions src/compensations/Compensations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import { CompensationsPage } from "studio/lib/payloads/compensations";
import SalaryCalculator, {
Degree,
} from "./components/salaryCalculator/SalaryCalculator";
import { useState } from "react";
import { calculatePension, calculateSalary } from "./utils/calculateSalary";
import { useMemo, useState } from "react";
import {
calculatePension,
calculateSalary,
maxSalariesExaminationYear,
minSalariesExaminationYear,
salariesFromLocation,
} from "./utils/salary";
import { CompanyLocation } from "studio/lib/payloads/companyDetails";
import {
IOption,
Expand Down Expand Up @@ -34,6 +40,16 @@ const Compensations = ({ compensations, locations }: CompensationsProps) => {
selectedDegree: "bachelor",
});

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

const updateSelectedDegree = (newDegree: Degree) => {
setFormState((prevState) => ({
...prevState,
Expand All @@ -50,13 +66,14 @@ const Compensations = ({ compensations, locations }: CompensationsProps) => {

const handleSubmit = (event: React.FormEvent) => {
event.preventDefault();
setSalary(
calculateSalary(
currentYear,
formState.examinationYear,
formState.selectedDegree,
),
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) => ({
Expand All @@ -74,10 +91,16 @@ const Compensations = ({ compensations, locations }: CompensationsProps) => {
selectedId={selectedLocation}
onValueChange={(option) => setSelectedLocation(option.id)}
/>
{compensations.showSalaryCalculator && (
{compensations.showSalaryCalculator && currentYearSalariesResult.ok && (
<>
<SalaryCalculator
examinationYearValue={formState.examinationYear}
minExaminationYear={minSalariesExaminationYear(
currentYearSalariesResult.value,
)}
maxExaminationYear={
maxSalariesExaminationYear(currentYearSalariesResult.value) - 1
}
selectedDegree={formState.selectedDegree}
onDegreeChanged={updateSelectedDegree}
onExaminationYearChanged={updateExaminationYear}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
RadioButtonGroup,
} from "src/components/forms/radioButtonGroup/RadioButtonGroup";
import Button from "src/components/buttons/Button";
import { maxExperience } from "src/compensations/utils/calculateSalary";

export type Degree = "bachelor" | "master";

Expand All @@ -16,6 +15,8 @@ const degreeOptions: IOption[] = [

interface SalaryCalculatorProps {
examinationYearValue: number;
minExaminationYear: number;
maxExaminationYear: number;
selectedDegree: Degree;
onDegreeChanged: (degree: Degree) => void;
onExaminationYearChanged: (examinationYear: number) => void;
Expand All @@ -24,15 +25,13 @@ interface SalaryCalculatorProps {

export default function SalaryCalculator({
examinationYearValue: yearValue,
minExaminationYear,
maxExaminationYear,
selectedDegree,
onDegreeChanged,
onExaminationYearChanged,
onSubmit,
}: SalaryCalculatorProps) {
const currentYear = new Date().getFullYear();
const minExaminationYear = maxExperience(currentYear);
const maxExaminationYear = currentYear - 1;

return (
<form
//TODO: replace aria-label with static translation from Sanity
Expand Down
28 changes: 0 additions & 28 deletions src/compensations/utils/calculateSalary.ts

This file was deleted.

54 changes: 54 additions & 0 deletions src/compensations/utils/salary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import {
isSalariesType,
Salaries,
} from "studio/components/salariesInput/utils/parseSalaries";
import { SalariesByLocation } from "../../../studio/lib/payloads/compensations";
import { Result, ResultError, ResultOk } from "../../../studio/utils/result";

export function calculateSalary(
examinationYear: number,
degree: string,
salaries: Salaries,
): number | undefined {
const degreeValue = degree === "bachelor" ? 1 : 0;
const adjustedYear = examinationYear + degreeValue;
return salaries[adjustedYear];
}

export function calculatePension(salary: number): number {
return Math.round(salary * 0.07);
}

function examinationYearsFromSalaries(salaries: Salaries) {
return Object.keys(salaries).map(Number);
}

export function minSalariesExaminationYear(salaries: Salaries): number {
return Math.min(...examinationYearsFromSalaries(salaries));
}

export function maxSalariesExaminationYear(salaries: Salaries): number {
return Math.max(...examinationYearsFromSalaries(salaries));
}

export function salariesFromLocation(
year: number,
locationId: string,
salariesByLocation: SalariesByLocation[],
): Result<Salaries, string> {
const yearlySalaries = salariesByLocation.find(
(s) => s.location._ref === locationId,
)?.yearlySalaries;
if (yearlySalaries === undefined) {
return ResultError(`Could not find salaries for location '${locationId}'`);
}
const salariesData = yearlySalaries.find((s) => s.year === year);
if (salariesData === undefined) {
return ResultError(`Could not find salaries for year ${year}`);
}
const parsedSalaries = JSON.parse(salariesData.salaries);
if (!isSalariesType(parsedSalaries)) {
return ResultError("Parsed salaries data was not valid");
}
return ResultOk(parsedSalaries);
}
40 changes: 0 additions & 40 deletions src/compensations/utils/salaryData.ts

This file was deleted.

10 changes: 10 additions & 0 deletions studio/components/salariesInput/utils/parseSalaries.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ export interface Salaries {
[year: string]: number;
}

export function isSalariesType(o: unknown): o is Salaries {
return (
typeof o === "object" &&
o !== null &&
Object.entries(o).every(
([k, v]) => !isNaN(Number(k)) && typeof v === "number",
)
);
}

const NON_EMPTY_DIGITS_ONLY_REGEX = new RegExp(/^\d+$/);
export const VALID_SALARY_REGEX = NON_EMPTY_DIGITS_ONLY_REGEX;

Expand Down
10 changes: 9 additions & 1 deletion studio/lib/payloads/compensations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { PortableTextBlock } from "src/components/richText/RichText";
import { Slug } from "./global";
import { Reference, Slug } from "./global";

export interface Benefit {
_type: string;
Expand All @@ -21,6 +21,13 @@ export interface SalariesPage {
salaries: string;
}

export interface SalariesByLocation {
_key: string;
_type: string;
location: Reference;
yearlySalaries: SalariesPage[];
}

export interface CompensationsPage {
_createdAt: string;
_id: string;
Expand All @@ -31,5 +38,6 @@ export interface CompensationsPage {
page: string;
slug: Slug;
benefitsByLocation: BenefitsByLocation[];
salaries: SalariesByLocation[];
showSalaryCalculator: boolean;
}
5 changes: 5 additions & 0 deletions studio/lib/payloads/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ export interface Slug {
_type: string;
current: string;
}

export interface Reference {
_type: "reference";
_ref: string;
}

0 comments on commit dbc3daf

Please sign in to comment.