Skip to content

Commit

Permalink
simplify selectedValue and minor cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
christinaroise committed Aug 26, 2024
1 parent f4a868b commit 74a8148
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 108 deletions.
80 changes: 18 additions & 62 deletions src/components/forms/radioButtonGroup/RadioButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,27 @@ export interface IOption {
id: string;
label: string;
disabled?: boolean;
currentSelected: boolean;
}

interface RenderOptionsProps {
options: IOption[];
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
}

interface RadioButtonGroupProps {
id: string;
label: string;
options: IOption[];
selectedId: string;
onValueChange: (option: IOption) => void;
}

/**
* Important Note on RadioButtons:
*
* - The `RadioButton` component, defined in this code, should not be used in isolation.
* Radio buttons are designed to be part of a group where only one option can be selected at a time.
*
* - When used individually, a radio button loses its intended functionality of providing mutually exclusive choices
* and may confuse users or lead to unexpected behavior.
*
* - Instead, radio buttons should always be used within a group, typically managed by a parent component
* such as `RadioButtonGroup`, which ensures that only one radio button in the group can be selected at any given time.
*
* - The parent component should handle the state management and changes, ensuring that the user can only select
* one option from the group and that this selection is properly communicated back to the application.
*
* - Example of usage within a group:
*
* ```
* const options = [
* { id: 'radio1', label: 'Option 1', value: '1', currentSelected: false },
* { id: 'radio2', label: 'Option 2', value: '2', currentSelected: true },
* ];
*
* <RadioButtonGroup
* id="example-group"
* label="Choose an option"
* options={options}
* onValueChange={(name, value) => console.log(`Selected ${name}: ${value}`)}
* />
* ```
* - In this example, the `RadioButtonGroup` component renders multiple `RadioButton` components
* as part of a cohesive group, enabling proper radio button functionality.
*/

export const RadioButtonGroup = ({
id,
label,
options,
selectedId,
onValueChange,
}: RadioButtonGroupProps) => {
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedOption = options.find((option) => option.id === e.target.id);
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const selectedOption = options.find(
(option) => option.id === e.target.value
);
if (selectedOption) {
onValueChange(selectedOption);
}
Expand All @@ -73,27 +37,19 @@ export const RadioButtonGroup = ({
<fieldset className={styles.fieldset} id={id}>
<legend className={textStyles.h3}>{label}</legend>
<div className={styles.wrapper}>
<RenderOptions options={options} onChange={handleChange} />
{options.map(({ id, label, disabled }) => (
<RadioButton
key={id}
id={id}
label={label}
name="radio"
disabled={disabled}
value={id}
checked={id === selectedId}
onChange={onChange}
/>
))}
</div>
</fieldset>
);
};

const RenderOptions = ({ options, onChange }: RenderOptionsProps) => {
return (
<>
{options.map(({ id, label, disabled, currentSelected }) => (
<RadioButton
key={id}
id={id}
label={label}
name="radio"
disabled={disabled}
value={label}
defaultChecked={currentSelected}
onChange={onChange}
/>
))}
</>
);
};
47 changes: 20 additions & 27 deletions src/salaryAndBenefits/SalaryAndBenefits.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"use client";

import styles from "./salaryAndBenefits.module.css";
import Text from "src/components/text/Text";
import { SalaryAndBenefitsPage } from "studio/lib/payloads/salaryAndBenefits";
Expand All @@ -8,11 +7,7 @@ import SalaryCalculator, {
Degree,
} from "./components/salaryCalculator/SalaryCalculator";
import { useState } from "react";
import {
calculatePension,
calculateSalary,
maxExperience,
} from "./utils/calculateSalary";
import { calculatePension, calculateSalary } from "./utils/calculateSalary";

interface SalaryAndBenefitsProps {
salaryAndBenefits: SalaryAndBenefitsPage;
Expand All @@ -25,8 +20,6 @@ interface SalaryCalculatorFormState {

const SalaryAndBenefits = ({ salaryAndBenefits }: SalaryAndBenefitsProps) => {
const currentYear = new Date().getFullYear();
const minExaminationYear = maxExperience(currentYear);
const maxExaminationYear = currentYear - 1;

const [formState, setFormState] = useState<SalaryCalculatorFormState>({
examinationYear: currentYear - 1,
Expand Down Expand Up @@ -54,33 +47,33 @@ const SalaryAndBenefits = ({ salaryAndBenefits }: SalaryAndBenefitsProps) => {
calculateSalary(
currentYear,
formState.examinationYear,
formState.selectedDegree,
),
formState.selectedDegree
)
);
};

return (
<div className={styles.wrapper}>
<Text type="h1">{salaryAndBenefits.basicTitle}</Text>
{salaryAndBenefits.showSalaryCalculator && (
<SalaryCalculator
// TODO: should also take in degree state (this requires changes to IOption of RadioButtonGroup)
examinationYear={formState.examinationYear}
minExaminationYear={minExaminationYear}
maxExaminationYear={maxExaminationYear}
onDegreeChanged={updateSelectedDegree}
onExaminationYearChanged={updateExaminationYear}
onSubmit={handleSubmit}
/>
<>
<SalaryCalculator
examinationYearValue={formState.examinationYear}
selectedDegree={formState.selectedDegree}
onDegreeChanged={updateSelectedDegree}
onExaminationYearChanged={updateExaminationYear}
onSubmit={handleSubmit}
/>
{salary !== null ? (
<div aria-live="polite">
<Text> Du vil få en årlig lønn på {salary}</Text>
<Text>
Du vil få en årlig pensjon på omtrent {calculatePension(salary)}
</Text>
</div>
) : null}
</>
)}
{salary !== null ? (
<div aria-live="polite">
<Text> Du vil få en årlig lønn på {salary}</Text>
<Text>
Du vil få en årlig pensjon på omtrent {calculatePension(salary)}
</Text>
</div>
) : null}
<div className={styles.benefits}>
{salaryAndBenefits.benefits.map((benefit) => (
<div key={benefit._key} className={styles.benefitWrapper}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,34 @@ import {
RadioButtonGroup,
} from "src/components/forms/radioButtonGroup/RadioButtonGroup";
import Button from "src/components/buttons/Button";
import { maxExperience } from "src/salaryAndBenefits/utils/calculateSalary";

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

const degreeOptions: IOption[] = [
{
id: "bachelor",
label: "Bachelor",
currentSelected: true,
disabled: false,
},
{ id: "master", label: "Master", currentSelected: false, disabled: false },
{ id: "bachelor", label: "Bachelor" },
{ id: "master", label: "Master" },
];

interface SalaryCalculatorProps {
examinationYear: number;
minExaminationYear: number;
maxExaminationYear: number;
examinationYearValue: number;
selectedDegree: Degree;
onDegreeChanged: (degree: Degree) => void;
onExaminationYearChanged: (examinationYear: number) => void;
onSubmit: (event: React.FormEvent) => void;
}

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

return (
<form
aria-label="salary calculator"
Expand All @@ -45,18 +43,18 @@ export default function SalaryCalculator({
id="degree-group"
label="Choose your degree"
options={degreeOptions}
onValueChange={(value) =>
(value.id === "bachelor" || value.id === "master") &&
onDegreeChanged(value.id)
selectedId={selectedDegree}
onValueChange={(selectedOption) =>
onDegreeChanged(selectedOption.id as Degree)
}
/>
<InputField
label="year"
label="Year"
name="examinationYear"
type="number"
max={maxExaminationYear}
min={minExaminationYear}
value={examinationYear}
max={maxExaminationYear}
value={yearValue}
onChange={(_name, value) => onExaminationYearChanged(parseInt(value))}
required
/>
Expand Down

0 comments on commit 74a8148

Please sign in to comment.