Skip to content

Commit

Permalink
feat(web): display previously entered data in urban project installat…
Browse files Browse the repository at this point in the history
…ion expenses form
  • Loading branch information
stephane-ruhlmann committed Jan 9, 2025
1 parent bfa2492 commit edcfe4e
Show file tree
Hide file tree
Showing 8 changed files with 153 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,17 @@ export const getUrbanProjectSpaceDistribution = createSelector(selectCreationDat
);
});

export const getDefaultInstallationCosts = createSelector(selectSiteData, (state) => {
export const selectDefaultInstallationCosts = createSelector(selectSiteData, (state) => {
if (!state?.surfaceArea) {
return undefined;
}
return computeDefaultInstallationCostsFromSiteSurfaceArea(state.surfaceArea);
});

export const selectInstallationCosts = createSelector(selectCreationData, (creationData) => {
return creationData.installationExpenses ?? undefined;
});

export const selectContaminatedSurfaceAreaPercentageToDecontaminate = createSelector(
[selectSelf, selectSiteData],
(state, siteData): number => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,11 @@ import { optionalNumericFieldRegisterOptions } from "@/shared/views/components/f
import WizardFormLayout from "@/shared/views/layout/WizardFormLayout/WizardFormLayout";

type Props = {
initialValues?: FormValues;
onSubmit: (data: FormValues) => void;
onBack: () => void;
title: ReactNode;
instructions?: ReactNode;
defaultValues?: {
works: number;
technicalStudy: number;
other: number;
};
};

export type FormValues = {
Expand All @@ -30,16 +26,12 @@ export type FormValues = {
const InstallationExpensesForm = ({
onSubmit,
onBack,
defaultValues,
initialValues,
title,
instructions,
}: Props) => {
const { handleSubmit, register, watch } = useForm<FormValues>({
defaultValues: {
worksAmount: defaultValues?.works,
technicalStudyAmount: defaultValues?.technicalStudy,
otherAmount: defaultValues?.other,
},
defaultValues: initialValues,
});

const allExpenses = watch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { mapFormValuesToReinstatementExpenses } from "./mappers";

describe("Reinstatement expenses form mappers", () => {
describe("convertFormValuesToExpenses", () => {
it("should return an empty when form values are empty", () => {
it("should return an empty array when form values are empty", () => {
const result = mapFormValuesToReinstatementExpenses({});
expect(result).toEqual([]);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,18 @@ const purposeMapKeys = {
technicalStudyAmount: "technical_studies",
worksAmount: "installation_works",
otherAmount: "other",
};
} as const;

function PhotovoltaicPanelsInstallationExpensesFormContainer() {
const dispatch = useAppDispatch();
const defaultValues = useAppSelector(getDefaultValuesForPhotovoltaicInstallationExpenses);

const initialValues = defaultValues && {
technicalStudyAmount: defaultValues.technicalStudy,
worksAmount: defaultValues.works,
otherAmount: defaultValues.other,
};

return (
<InstallationExpensesForm
title="Dépenses d'installation de la centrale photovoltaïque"
Expand All @@ -42,17 +48,14 @@ function PhotovoltaicPanelsInstallationExpensesFormContainer() {
<p>Vous pouvez modifier ces montants.</p>
</FormInfo>
}
defaultValues={defaultValues}
initialValues={initialValues}
onSubmit={(formData: FormValues) => {
const expenses = typedObjectEntries(formData)
const expenses: PhotovoltaicInstallationExpense[] = typedObjectEntries(formData)
.filter(([, amount]) => amount && amount > 0)
.map(
([purpose, amount]) =>
({
amount: amount,
purpose: purposeMapKeys[purpose],
}) as PhotovoltaicInstallationExpense,
);
.map(([purpose, amount]) => ({
amount: amount as number,
purpose: purposeMapKeys[purpose],
}));
dispatch(completePhotovoltaicPanelsInstallationExpenses(expenses));
}}
onBack={() => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import { typedObjectEntries, UrbanProjectDevelopmentExpense } from "shared";

import {
installationExpensesCompleted,
installationExpensesReverted,
} from "@/features/create-project/application/urban-project/urbanProject.actions";
import { getDefaultInstallationCosts } from "@/features/create-project/application/urban-project/urbanProject.selectors";
import {
selectDefaultInstallationCosts,
selectInstallationCosts,
} from "@/features/create-project/application/urban-project/urbanProject.selectors";
import InstallationExpensesForm, {
FormValues,
} from "@/features/create-project/views/common-views/costs/installation-costs/InstallationCostsForm";
import { useAppDispatch, useAppSelector } from "@/shared/views/hooks/store.hooks";
import FormInfo from "@/shared/views/layout/WizardFormLayout/FormInfo";

const purposeMapKeys = {
technicalStudyAmount: "technical_studies",
worksAmount: "development_works",
otherAmount: "other",
};
import { mapFormValuesToExpenses, mapInitialValues } from "./mappers";

function InstallationExpensesFormContainer() {
const dispatch = useAppDispatch();
const defaultValues = useAppSelector(getDefaultInstallationCosts);
const preEnteredValues = useAppSelector(selectInstallationCosts);
const defaultValues = useAppSelector(selectDefaultInstallationCosts);

const initialValues = mapInitialValues(preEnteredValues, defaultValues);

return (
<InstallationExpensesForm
Expand All @@ -34,26 +34,9 @@ function InstallationExpensesFormContainer() {
<p>Vous pouvez modifier ces montants.</p>
</FormInfo>
}
defaultValues={
defaultValues
? {
works: defaultValues.developmentWorks,
technicalStudy: defaultValues.technicalStudies,
other: defaultValues.other,
}
: undefined
}
initialValues={initialValues}
onSubmit={(formData: FormValues) => {
const expenses = typedObjectEntries(formData)
.filter(([, amount]) => amount && amount > 0)
.map(
([purpose, amount]) =>
({
amount: amount,
purpose: purposeMapKeys[purpose],
}) as UrbanProjectDevelopmentExpense,
);
dispatch(installationExpensesCompleted(expenses));
dispatch(installationExpensesCompleted(mapFormValuesToExpenses(formData)));
}}
onBack={() => {
dispatch(installationExpensesReverted());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { ComputedInstallationCosts, UrbanProjectDevelopmentExpense } from "shared";

import { mapFormValuesToReinstatementExpenses } from "@/features/create-project/views/common-views/costs/reinstatement-costs/mappers";

import { mapFormValuesToExpenses, mapInitialValues } from "./mappers";

describe("Urban project installation costs form mappers", () => {
describe("mapFormValuesToExpenses", () => {
it("should return an empty when form values are empty", () => {
const result = mapFormValuesToReinstatementExpenses({});
expect(result).toEqual([]);
});
it("should filter out undefined and zero values", () => {
const result = mapFormValuesToExpenses({
technicalStudyAmount: 0,
worksAmount: undefined,
otherAmount: 50,
});
expect(result).toEqual([{ purpose: "other", amount: 50 }]);
});
});
describe("mapInitialValues", () => {
it("should return mapped given pre-entered data over default values", () => {
const preEnteredData: UrbanProjectDevelopmentExpense[] = [
{ purpose: "technical_studies", amount: 100 },
{ purpose: "development_works", amount: 200 },
];
const defaultValues: ComputedInstallationCosts = {
technicalStudies: 430,
developmentWorks: 540,
other: 50,
};
const result = mapInitialValues(preEnteredData, defaultValues);
expect(result).toEqual({
technicalStudyAmount: 100,
worksAmount: 200,
});
});

it("should return mapped given default values when no pre-entered data", () => {
const defaultValues: ComputedInstallationCosts = {
technicalStudies: 430,
developmentWorks: 540,
other: 50,
};
const result = mapInitialValues(undefined, defaultValues);
expect(result).toEqual({
technicalStudyAmount: 430,
worksAmount: 540,
otherAmount: 50,
});
});
it("should return undefined when no pre-entered data nor default values", () => {
const result = mapInitialValues(undefined, undefined);
expect(result).toEqual(undefined);
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
ComputedInstallationCosts,
typedObjectEntries,
UrbanProjectDevelopmentExpense,
} from "shared";

import { FormValues } from "@/features/create-project/views/common-views/costs/installation-costs/InstallationCostsForm";

const purposeMapKeys = {
technicalStudyAmount: "technical_studies",
worksAmount: "development_works",
otherAmount: "other",
} as const satisfies Record<keyof FormValues, UrbanProjectDevelopmentExpense["purpose"]>;

const expensesToFormValuesMap = {
technical_studies: "technicalStudyAmount",
development_works: "worksAmount",
other: "otherAmount",
} as const satisfies Record<UrbanProjectDevelopmentExpense["purpose"], keyof FormValues>;

export const mapFormValuesToExpenses = (
formValues: FormValues,
): UrbanProjectDevelopmentExpense[] => {
return typedObjectEntries(formValues)
.filter(([, amount]) => amount && amount > 0)
.map(([purpose, amount]) => ({
amount: amount as number,
purpose: purposeMapKeys[purpose],
}));
};

const mapExpensesToFormValues = (expenses: UrbanProjectDevelopmentExpense[]): FormValues => {
return expenses.reduce<FormValues>((acc, cur) => {
return { ...acc, [expensesToFormValuesMap[cur.purpose]]: cur.amount };
}, {});
};

const mapDefaultValuesToFormValues = (defaultValues: ComputedInstallationCosts): FormValues => {
const { developmentWorks, technicalStudies, other } = defaultValues;
return {
worksAmount: developmentWorks && Math.round(developmentWorks),
technicalStudyAmount: technicalStudies && Math.round(technicalStudies),
otherAmount: other && Math.round(other),
};
};

export const mapInitialValues = (
preEnteredData: UrbanProjectDevelopmentExpense[] | undefined,
defaultValues: ComputedInstallationCosts | undefined,
): FormValues | undefined => {
if (preEnteredData) return mapExpensesToFormValues(preEnteredData);

if (defaultValues) return mapDefaultValuesToFormValues(defaultValues);

return undefined;
};
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export type ComputedInstallationCosts = {
technicalStudies: number;
developmentWorks: number;
other: number;
};

export const computeDefaultInstallationCostsFromSiteSurfaceArea = (
surfaceArea: number,
): { technicalStudies: number; developmentWorks: number; other: number } => {
Expand Down

0 comments on commit edcfe4e

Please sign in to comment.