diff --git a/packages/webapp/.storybook/state.js b/packages/webapp/.storybook/state.js
index d3f40594d0..0a76d9e745 100755
--- a/packages/webapp/.storybook/state.js
+++ b/packages/webapp/.storybook/state.js
@@ -1383,96 +1383,6 @@ export default {
},
},
},
- barnReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- ceremonialReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- farmSiteBoundaryReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- fieldReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- gardenReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- greenhouseReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- surfaceWaterReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- naturalAreaReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- residenceReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- bufferZoneReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- watercourseReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- fenceReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- gateReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- waterValveReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
- soilSampleLocationReducer: {
- ids: [],
- entities: {},
- loading: false,
- loaded: false,
- },
showedSpotlightReducer: {
loaded: true,
loading: false,
@@ -1708,6 +1618,13 @@ export default {
loading: false,
loaded: false,
},
+ irrigationTaskReducer: {
+ ids: [],
+ entities: {},
+ loading: false,
+ error: null,
+ loaded: false,
+ },
irrigationTaskTypesReducer: {
irrigationTaskTypes: [
{
@@ -1746,6 +1663,20 @@ export default {
ids: [],
entities: {},
},
+ animalMovementTaskReducer: {
+ ids: [],
+ entities: {},
+ loading: false,
+ error: null,
+ loaded: false,
+ },
+ soilSampleTaskReducer: {
+ ids: [],
+ entities: {},
+ loading: false,
+ error: null,
+ loaded: false,
+ },
},
persistedStateReducer: {
userLogReducer: {
diff --git a/packages/webapp/public/locales/en/message.json b/packages/webapp/public/locales/en/message.json
index a774f971e1..07ce09cdb0 100644
--- a/packages/webapp/public/locales/en/message.json
+++ b/packages/webapp/public/locales/en/message.json
@@ -156,6 +156,7 @@
"MAP": {
"FAIL_PATCH": "Failed to update",
"FAIL_POST": "Failed to add new",
+ "FAIL_DELETE": "Failed to retire",
"SUCCESS_DELETE": "Successfully retired",
"SUCCESS_PATCH": "Successfully updated",
"SUCCESS_POST": "Successfully saved"
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/AreaDetails.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails.jsx
similarity index 66%
rename from packages/webapp/src/components/LocationDetailLayout/AreaDetails/AreaDetails.jsx
rename to packages/webapp/src/components/LocationDetailLayout/AreaDetails.jsx
index f56b6ff33e..07acace652 100644
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/AreaDetails.jsx
+++ b/packages/webapp/src/components/LocationDetailLayout/AreaDetails.jsx
@@ -1,18 +1,14 @@
-import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useFormContext } from 'react-hook-form';
-import Input from '../../Form/Input';
-import PureWarningBox from '../../WarningBox';
-import { Label } from '../../Typography';
-import Unit from '../../Form/Unit';
-import { fieldEnum as areaEnum } from '../../../containers/constants';
-import { area_perimeter, area_total_area } from '../../../util/convert-units/unit';
-import InputAutoSize from '../../Form/InputAutoSize';
+import Input from '../Form/Input';
+import Unit from '../Form/Unit';
+import { fieldEnum as areaEnum } from '../../containers/constants';
+import { area_perimeter, area_total_area } from '../../util/convert-units/unit';
+import InputAutoSize from '../Form/InputAutoSize';
export default function AreaDetails({
name,
showPerimeter,
- history,
children,
system,
isCreateLocationPage,
@@ -30,31 +26,9 @@ export default function AreaDetails({
control,
formState: { errors },
} = useFormContext();
- const [errorMessage, setErrorMessage] = useState();
- useEffect(() => {
- const handleOffline = () => setErrorMessage(t('FARM_MAP.AREA_DETAILS.NETWORK'));
- const handleOnline = () => setErrorMessage(null);
- window.addEventListener('offline', handleOffline);
- window.addEventListener('online', handleOnline);
- return () => {
- window.removeEventListener('offline', handleOffline);
- window.removeEventListener('online', handleOnline);
- };
- }, []);
-
- useEffect(() => {
- if (history?.location?.state?.error && !history?.location?.state?.error?.retire) {
- setErrorMessage(history?.location?.state?.error);
- }
- }, [history?.location?.state?.error]);
return (
<>
- {errorMessage && (
-
- {errorMessage}
-
- )}
-
-
- );
-}
-
-export function PureBarn({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const washPackSelection = data[barnEnum.wash_and_pack];
- const coldStorage = data[barnEnum.cold_storage];
- const usedForAnimals = data[barnEnum.used_for_animals];
- data[barnEnum.total_area_unit] = data[barnEnum.total_area_unit]?.value;
- data[barnEnum.perimeter_unit] = data[barnEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- type: 'barn',
- wash_and_pack: washPackSelection,
- cold_storage: coldStorage,
- used_for_animals: usedForAnimals,
- });
- submitForm({ formData });
- };
-
- return (
- }
- showPerimeter={false}
- />
- );
-}
-
-export function BarnDetailChildren({ isViewLocationPage }) {
- const { t } = useTranslation();
- const { control } = useFormContext();
- return (
- <>
-
-
- {t('FARM_MAP.BARN.WASH_PACK')}
- {t('common:OPTIONAL')}
-
-
-
-
-
-
-
- {t('FARM_MAP.BARN.COLD_STORAGE')}
- {t('common:OPTIONAL')}
-
-
-
-
-
-
-
- {t('FARM_MAP.BARN.ANIMALS')}
- {t('common:OPTIONAL')}
-
-
-
-
-
- >
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/CeremonialArea/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/CeremonialArea/index.jsx
deleted file mode 100644
index 416ecac23c..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/CeremonialArea/index.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import { ceremonialEnum } from '../../../../containers/constants';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureCeremonialAreaWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureCeremonialArea({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- data[ceremonialEnum.total_area_unit] = data[ceremonialEnum.total_area_unit]?.value;
- data[ceremonialEnum.perimeter_unit] = data[ceremonialEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- type: 'ceremonial_area',
- });
- submitForm({ formData });
- };
-
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/FarmSiteBoundary/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/FarmSiteBoundary/index.jsx
deleted file mode 100644
index d4df9d7579..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/FarmSiteBoundary/index.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import { farmSiteBoundaryEnum } from '../../../../containers/constants';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureFarmSiteBoundaryWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureFarmSiteBoundary({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- data[farmSiteBoundaryEnum.total_area_unit] = data[farmSiteBoundaryEnum.total_area_unit]?.value;
- data[farmSiteBoundaryEnum.perimeter_unit] = data[farmSiteBoundaryEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'farm_site_boundary',
- });
- submitForm({ formData });
- };
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Field/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Field/index.jsx
deleted file mode 100644
index d561a9ceb4..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Field/index.jsx
+++ /dev/null
@@ -1,132 +0,0 @@
-import { useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import Leaf from '../../../../assets/images/farmMapFilter/Leaf.svg';
-import Input from '../../../Form/Input';
-import { fieldEnum } from '../../../../containers/constants';
-import { Label } from '../../../Typography';
-import { getDateInputFormat } from '../../../../util/moment';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import RadioGroup from '../../../Form/RadioGroup';
-import {
- getFormDataWithoutNulls,
- getProcessedFormData,
-} from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureFieldWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureField({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- getProcessedFormData();
- const getDefaultValues = () => {
- return {
- [fieldEnum.organic_status]: 'Non-Organic',
- ...persistedFormData,
- [fieldEnum.transition_date]: getDateInputFormat(
- persistedFormData[fieldEnum.transition_date] || new Date(),
- ),
- };
- };
- const onSubmit = (data) => {
- data[fieldEnum.total_area_unit] = data[fieldEnum.total_area_unit]?.value;
- data[fieldEnum.perimeter_unit] = data[fieldEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'field',
- });
- submitForm({ formData });
- };
-
- return (
- }
- showPerimeter={true}
- />
- );
-}
-
-export function FieldDetailsChildren({ isViewLocationPage }) {
- const { t } = useTranslation();
- const { control, watch, register } = useFormContext();
- const fieldTypeSelection = watch(fieldEnum.organic_status);
- const [transitionalDate, setTransitionalDate] = useState(watch(fieldEnum.transition_date));
- return (
-
-
-
- {t('FARM_MAP.FIELD.FIELD_TYPE')}
-
-
-
-
-
-
-
- {fieldTypeSelection === 'Transitional' && (
- setTransitionalDate(e.target.value)}
- value={transitionalDate}
- />
- )}
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Garden/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Garden/index.jsx
deleted file mode 100644
index 906ab9d7b2..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Garden/index.jsx
+++ /dev/null
@@ -1,139 +0,0 @@
-import { useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import Leaf from '../../../../assets/images/farmMapFilter/Leaf.svg';
-import Input, { getInputErrors } from '../../../Form/Input';
-import { gardenEnum } from '../../../../containers/constants';
-import { Label } from '../../../Typography';
-import { getDateInputFormat } from '../../../../util/moment';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import RadioGroup from '../../../Form/RadioGroup';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureGardenWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureGarden({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const getDefaultValues = () => {
- return {
- [gardenEnum.organic_status]: 'Non-Organic',
- ...persistedFormData,
- [gardenEnum.transition_date]: getDateInputFormat(
- persistedFormData[gardenEnum.transition_date] || new Date(),
- ),
- };
- };
- const onSubmit = (data) => {
- data[gardenEnum.total_area_unit] = data[gardenEnum.total_area_unit]?.value;
- data[gardenEnum.perimeter_unit] = data[gardenEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'garden',
- });
- submitForm({ formData });
- };
-
- return (
- }
- showPerimeter={true}
- />
- );
-}
-
-export function GardenDetailsChildren({ isViewLocationPage }) {
- const { t } = useTranslation();
- const {
- control,
- watch,
- register,
- formState: { errors },
- } = useFormContext();
- const gardenTypeSelection = watch(gardenEnum.organic_status);
- const [transitionalDate, setTransitionalDate] = useState(watch(gardenEnum.transition_date));
- return (
-
-
-
- {t('FARM_MAP.GARDEN.GARDEN_TYPE')}
-
-
-
-
-
- {gardenTypeSelection === 'Transitional' && (
- setTransitionalDate(e.target.value)}
- value={transitionalDate}
- />
- )}
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Greenhouse/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Greenhouse/index.jsx
deleted file mode 100644
index af36b0029c..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Greenhouse/index.jsx
+++ /dev/null
@@ -1,198 +0,0 @@
-import { useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import Leaf from '../../../../assets/images/farmMapFilter/Leaf.svg';
-import Input from '../../../Form/Input';
-import { greenhouseEnum } from '../../../../containers/constants';
-import { Label } from '../../../Typography';
-import { getDateInputFormat } from '../../../../util/moment';
-import RadioGroup from '../../../Form/RadioGroup';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-import InputBaseLabel from '../../../Form/InputBase/InputBaseLabel';
-
-export default function PureGreenhouseWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureGreenhouse({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const getDefaultValues = () => {
- return {
- [greenhouseEnum.organic_status]: 'Non-Organic',
- ...persistedFormData,
- [greenhouseEnum.transition_date]: getDateInputFormat(
- persistedFormData[greenhouseEnum.transition_date] || new Date(),
- ),
- };
- };
- const onSubmit = (data) => {
- const supplementalLighting = data[greenhouseEnum.supplemental_lighting];
- const co2Enrichment = data[greenhouseEnum.co2_enrichment];
- const greenhouseHeated = data[greenhouseEnum.greenhouse_heated];
- data[greenhouseEnum.total_area_unit] = data[greenhouseEnum.total_area_unit]?.value;
- data[greenhouseEnum.perimeter_unit] = data[greenhouseEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'greenhouse',
- supplemental_lighting: supplementalLighting,
- co2_enrichment: co2Enrichment,
- greenhouse_heated: greenhouseHeated,
- });
- submitForm({ formData });
- };
-
- return (
- }
- showPerimeter={false}
- />
- );
-}
-
-export function GreenhouseDetailsChildren({ isViewLocationPage }) {
- const { t } = useTranslation();
- const { register, watch, control } = useFormContext();
- const greenhouseTypeSelection = watch(greenhouseEnum.organic_status);
- const [transitionalDate, setTransitionalDate] = useState(watch(greenhouseEnum.transition_date));
- return (
-
-
-
-
-
- {greenhouseTypeSelection === 'Transitional' && (
- setTransitionalDate(e.target.value)}
- value={transitionalDate}
- />
- )}
-
-
- {greenhouseTypeSelection === 'Organic' && (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- )}
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/NaturalArea/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/NaturalArea/index.jsx
deleted file mode 100644
index 865f7c75e2..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/NaturalArea/index.jsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { naturalAreaEnum } from '../../../../containers/constants';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureNaturalAreaWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureNaturalArea({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const { t } = useTranslation();
- const onSubmit = (data) => {
- data[naturalAreaEnum.total_area_unit] = data[naturalAreaEnum.total_area_unit]?.value;
- data[naturalAreaEnum.perimeter_unit] = data[naturalAreaEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'natural_area',
- });
- submitForm({ formData });
- };
-
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Residence/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Residence/index.jsx
deleted file mode 100644
index d883eab2fb..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/Residence/index.jsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import { residenceEnum } from '../../../../containers/constants';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureResidenceWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureResidence({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- data[residenceEnum.total_area_unit] = data[residenceEnum.total_area_unit]?.value;
-
- data[residenceEnum.perimeter_unit] = data[residenceEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
-
- type: 'residence',
- });
- submitForm({ formData });
- };
-
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/SurfaceWater/index.jsx b/packages/webapp/src/components/LocationDetailLayout/AreaDetails/SurfaceWater/index.jsx
deleted file mode 100644
index 38cd8c1714..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/AreaDetails/SurfaceWater/index.jsx
+++ /dev/null
@@ -1,86 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import locationDetailStyles from '../../styles.module.scss';
-import { surfaceWaterEnum } from '../../../../containers/constants';
-import { Label } from '../../../Typography';
-import RadioGroup from '../../../Form/RadioGroup';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureSurfaceWaterWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureSurfaceWater({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const usedForIrrigation = data[surfaceWaterEnum.used_for_irrigation];
- data[surfaceWaterEnum.total_area_unit] = data[surfaceWaterEnum.total_area_unit]?.value;
- data[surfaceWaterEnum.perimeter_unit] = data[surfaceWaterEnum.perimeter_unit]?.value;
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- type: 'surface_water',
- used_for_irrigation: usedForIrrigation,
- });
- submitForm({ formData });
- };
-
- return (
- }
- showPerimeter={true}
- />
- );
-}
-
-export function SurfaceWaterDetailsChildren({ isViewLocationPage }) {
- const { t } = useTranslation();
- const { control } = useFormContext();
- return (
-
-
- {t('FARM_MAP.BARN.ANIMALS')}
- {t('common:OPTIONAL')}
-
-
-
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/ExtraFormFieldsMap.jsx b/packages/webapp/src/components/LocationDetailLayout/ExtraFormFieldsMap.jsx
new file mode 100644
index 0000000000..752fae3793
--- /dev/null
+++ b/packages/webapp/src/components/LocationDetailLayout/ExtraFormFieldsMap.jsx
@@ -0,0 +1,678 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+import { useState } from 'react';
+import { useFormContext } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+import { Label } from '../Typography';
+import RadioGroup from '../Form/RadioGroup';
+import InputBaseLabel from '../Form/InputBase/InputBaseLabel';
+import Input, { getInputErrors } from '../Form/Input';
+import Unit from '../Form/Unit';
+import {
+ barnEnum,
+ bufferZoneEnum,
+ fenceEnum,
+ fieldEnum,
+ gardenEnum,
+ greenhouseEnum,
+ surfaceWaterEnum,
+ watercourseEnum,
+ waterValveEnum,
+} from '../../containers/constants';
+import styles from './styles.module.scss';
+import Leaf from '../../assets/images/farmMapFilter/Leaf.svg';
+import {
+ area_total_area,
+ line_length,
+ line_width,
+ water_valve_flow_rate,
+ watercourse_width,
+} from '../../util/convert-units/unit';
+import { buffer } from 'd3';
+
+// Areas Children
+
+function BarnDetailsChildren({ isViewLocationPage }) {
+ const { t } = useTranslation();
+ const { control } = useFormContext();
+ return (
+ <>
+
+
+ {t('FARM_MAP.BARN.WASH_PACK')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+
+
+ {t('FARM_MAP.BARN.COLD_STORAGE')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+
+
+ {t('FARM_MAP.BARN.ANIMALS')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+ >
+ );
+}
+
+function FieldDetailsChildren({ isViewLocationPage }) {
+ const { t } = useTranslation();
+ const { control, watch, register } = useFormContext();
+ const fieldTypeSelection = watch(fieldEnum.organic_status);
+ const [transitionalDate, setTransitionalDate] = useState(watch(fieldEnum.transition_date));
+ return (
+
+
+
+ {t('FARM_MAP.FIELD.FIELD_TYPE')}
+
+
+
+
+
+
+
+ {fieldTypeSelection === 'Transitional' && (
+ setTransitionalDate(e.target.value)}
+ value={transitionalDate}
+ />
+ )}
+
+
+ );
+}
+
+function GardenDetailsChildren({ isViewLocationPage }) {
+ const { t } = useTranslation();
+ const {
+ control,
+ watch,
+ register,
+ formState: { errors },
+ } = useFormContext();
+ const gardenTypeSelection = watch(gardenEnum.organic_status);
+ const [transitionalDate, setTransitionalDate] = useState(watch(gardenEnum.transition_date));
+ return (
+
+
+
+ {t('FARM_MAP.GARDEN.GARDEN_TYPE')}
+
+
+
+
+
+ {gardenTypeSelection === 'Transitional' && (
+ setTransitionalDate(e.target.value)}
+ value={transitionalDate}
+ />
+ )}
+
+
+ );
+}
+
+function GreenhouseDetailsChildren({ isViewLocationPage }) {
+ const { t } = useTranslation();
+ const { register, watch, control } = useFormContext();
+ const greenhouseTypeSelection = watch(greenhouseEnum.organic_status);
+ const [transitionalDate, setTransitionalDate] = useState(watch(greenhouseEnum.transition_date));
+ return (
+
+
+
+
+
+ {greenhouseTypeSelection === 'Transitional' && (
+ setTransitionalDate(e.target.value)}
+ value={transitionalDate}
+ />
+ )}
+
+
+ {greenhouseTypeSelection === 'Organic' && (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )}
+
+
+ );
+}
+
+function SurfaceWaterDetailsChildren({ isViewLocationPage }) {
+ const { t } = useTranslation();
+ const { control } = useFormContext();
+ return (
+
+
+ {t('FARM_MAP.BARN.ANIMALS')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+ );
+}
+
+// Lines Children
+function BufferZoneDetailsChildren({ system, isViewLocationPage, isEditLocationPage }) {
+ const { t } = useTranslation();
+ const {
+ register,
+ setValue,
+ getValues,
+ watch,
+ control,
+ formState: { errors },
+ } = useFormContext();
+ return (
+
+ );
+}
+
+function FenceDetailsChildren({ system, isViewLocationPage }) {
+ const { t } = useTranslation();
+ const {
+ register,
+ setValue,
+ getValues,
+ watch,
+ control,
+ formState: { errors },
+ } = useFormContext();
+ return (
+
+ );
+}
+
+function WatercourseDetailsChildren({ system, isViewLocationPage, isEditLocationPage }) {
+ const { t } = useTranslation();
+ const {
+ register,
+ setValue,
+ getValues,
+ watch,
+ control,
+ formState: { errors },
+ } = useFormContext();
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {t('FARM_MAP.WATERCOURSE.IRRIGATION')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+
+ );
+}
+
+// Points Children
+function WaterValveDetailsChildren({ system, isViewLocationPage }) {
+ const { t } = useTranslation();
+ const {
+ control,
+ register,
+ setValue,
+ getValues,
+ watch,
+ formState: { errors },
+ } = useFormContext();
+ return (
+
+
+ {t('FARM_MAP.WATER_VALVE.WATER_VALVE_TYPE')}
+ {t('common:OPTIONAL')}
+
+
+
+
+
+ );
+}
+
+function SoilSampleLocationDetailsChildren({ persistedFormData }) {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ );
+}
+
+const ExtraLocationFormFieldsMap = {
+ //areas
+ barn: BarnDetailsChildren,
+ ceremonial_area: null,
+ farm_site_boundary: null,
+ field: FieldDetailsChildren,
+ garden: GardenDetailsChildren,
+ greenhouse: GreenhouseDetailsChildren,
+ natural_area: null,
+ residence: null,
+ surface_water: SurfaceWaterDetailsChildren,
+ // lines
+ buffer_zone: BufferZoneDetailsChildren,
+ fence: FenceDetailsChildren,
+ watercourse: WatercourseDetailsChildren,
+ // points
+ gate: null,
+ soil_sample_location: SoilSampleLocationDetailsChildren,
+ water_valve: WaterValveDetailsChildren,
+};
+
+export default ExtraLocationFormFieldsMap;
diff --git a/packages/webapp/src/components/LocationDetailLayout/LineDetails.jsx b/packages/webapp/src/components/LocationDetailLayout/LineDetails.jsx
new file mode 100644
index 0000000000..905dbb6cea
--- /dev/null
+++ b/packages/webapp/src/components/LocationDetailLayout/LineDetails.jsx
@@ -0,0 +1,45 @@
+import { useTranslation } from 'react-i18next';
+import Input from '../Form/Input';
+import { fenceEnum as lineEnum } from '../../containers/constants';
+import InputAutoSize from '../Form/InputAutoSize';
+import { useFormContext } from 'react-hook-form';
+
+export default function LineDetails({
+ name,
+ children,
+ isCreateLocationPage,
+ isViewLocationPage,
+ isEditLocationPage,
+}) {
+ const { t } = useTranslation();
+ const {
+ register,
+ formState: { errors },
+ } = useFormContext();
+
+ return (
+ <>
+
+ {children}
+
+ >
+ );
+}
diff --git a/packages/webapp/src/components/LocationDetailLayout/LineDetails/BufferZone/index.jsx b/packages/webapp/src/components/LocationDetailLayout/LineDetails/BufferZone/index.jsx
deleted file mode 100644
index 497ca0c317..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/LineDetails/BufferZone/index.jsx
+++ /dev/null
@@ -1,128 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import { bufferZoneEnum } from '../../../../containers/constants';
-import Unit from '../../../Form/Unit';
-import { area_total_area, line_width } from '../../../../util/convert-units/unit';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureBufferZoneWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureBufferZone({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- type: 'buffer_zone',
- });
- formData[bufferZoneEnum.width_unit] = formData[bufferZoneEnum.width_unit]?.value;
- formData[bufferZoneEnum.length_unit] = formData[bufferZoneEnum.length_unit]?.value;
- formData[bufferZoneEnum.total_area_unit] = formData[bufferZoneEnum.total_area_unit]?.value;
- submitForm({ formData });
- };
-
- return (
-
- }
- />
- );
-}
-
-export function BufferZoneDetailsChildren({ isViewLocationPage, isEditLocationPage, system }) {
- const { t } = useTranslation();
- const {
- register,
- setValue,
- getValues,
- watch,
- control,
- formState: { errors },
- } = useFormContext();
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/LineDetails/Fence/index.jsx b/packages/webapp/src/components/LocationDetailLayout/LineDetails/Fence/index.jsx
deleted file mode 100644
index d2db03ae63..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/LineDetails/Fence/index.jsx
+++ /dev/null
@@ -1,125 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import Leaf from '../../../../assets/images/farmMapFilter/Leaf.svg';
-import { bufferZoneEnum, fenceEnum } from '../../../../containers/constants';
-import { Label } from '../../../Typography';
-import { line_length } from '../../../../util/convert-units/unit';
-import Unit from '../../../Form/Unit';
-import RadioGroup from '../../../Form/RadioGroup';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-import InputBaseLabel from '../../../Form/InputBase/InputBaseLabel';
-
-export default function PureFenceWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureFence({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const isPressureTreated = data[fenceEnum.pressure_treated];
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- pressure_treated: isPressureTreated,
- type: 'fence',
- });
- formData[fenceEnum.width] = 0;
- formData[fenceEnum.width_unit] = formData[fenceEnum.width_unit]?.value;
- formData[fenceEnum.length_unit] = formData[fenceEnum.length_unit]?.value;
- delete formData[bufferZoneEnum.total_area_unit];
- submitForm({ formData });
- };
-
- return (
-
- }
- />
- );
-}
-
-export function FenceDetailsChildren({ system, isViewLocationPage }) {
- const { t } = useTranslation();
- const {
- register,
- setValue,
- getValues,
- watch,
- control,
- formState: { errors },
- } = useFormContext();
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/LineDetails/LineDetails.jsx b/packages/webapp/src/components/LocationDetailLayout/LineDetails/LineDetails.jsx
deleted file mode 100644
index d69c9105c8..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/LineDetails/LineDetails.jsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import Input from '../../Form/Input';
-import { fenceEnum as lineEnum } from '../../../containers/constants';
-import PureWarningBox from '../../WarningBox';
-import { Label } from '../../Typography';
-import InputAutoSize from '../../Form/InputAutoSize';
-import { useFormContext } from 'react-hook-form';
-
-export default function LineDetails({
- name,
- history,
- children,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
-}) {
- const { t } = useTranslation();
- const {
- register,
- setValue,
- formState: { errors },
- } = useFormContext();
- const [errorMessage, setErrorMessage] = useState();
-
- useEffect(() => {
- const handleOffline = () => setErrorMessage(t('FARM_MAP.AREA_DETAILS.NETWORK'));
- const handleOnline = () => setErrorMessage(null);
- window.addEventListener('offline', handleOffline);
- window.addEventListener('online', handleOnline);
- return () => {
- window.removeEventListener('offline', handleOffline);
- window.removeEventListener('online', handleOnline);
- };
- }, []);
-
- useEffect(() => {
- if (history?.location?.state?.error && !history?.location?.state?.error?.retire) {
- setErrorMessage(history?.location?.state?.error);
- }
- }, [history?.location?.state?.error]);
-
- return (
- <>
- {errorMessage && !isViewLocationPage && (
-
- {errorMessage}
-
- )}
-
- {children}
-
- >
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/LineDetails/Watercourse/index.jsx b/packages/webapp/src/components/LocationDetailLayout/LineDetails/Watercourse/index.jsx
deleted file mode 100644
index 3dade95045..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/LineDetails/Watercourse/index.jsx
+++ /dev/null
@@ -1,191 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import { Label } from '../../../Typography';
-import locationDetailStyles from '../../styles.module.scss';
-import {
- area_total_area,
- line_length,
- line_width,
- watercourse_width,
-} from '../../../../util/convert-units/unit';
-import Unit from '../../../Form/Unit';
-import { watercourseEnum } from '../../../../containers/constants';
-import RadioGroup from '../../../Form/RadioGroup';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureWatercourseWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureWatercourse({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const usedForIrrigation = data[watercourseEnum.used_for_irrigation];
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- type: 'watercourse',
- used_for_irrigation: usedForIrrigation,
- });
- formData[watercourseEnum.length_unit] = formData[watercourseEnum.length_unit]?.value;
- formData[watercourseEnum.width_unit] = formData[watercourseEnum.width_unit]?.value;
- formData[watercourseEnum.buffer_width_unit] =
- formData[watercourseEnum.buffer_width_unit]?.value;
- formData[watercourseEnum.total_area_unit] = formData[watercourseEnum.total_area_unit]?.value;
- submitForm({ formData });
- };
-
- return (
-
- }
- />
- );
-}
-
-export function WatercourseDetailsChildren({ system, isViewLocationPage, isEditLocationPage }) {
- const { t } = useTranslation();
- const {
- register,
- setValue,
- getValues,
- watch,
- control,
- formState: { errors },
- } = useFormContext();
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {t('FARM_MAP.WATERCOURSE.IRRIGATION')}
- {t('common:OPTIONAL')}
-
-
-
-
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/LocationPageHeader.jsx b/packages/webapp/src/components/LocationDetailLayout/LocationPageHeader.jsx
index 53295ed855..f0b580282f 100644
--- a/packages/webapp/src/components/LocationDetailLayout/LocationPageHeader.jsx
+++ b/packages/webapp/src/components/LocationDetailLayout/LocationPageHeader.jsx
@@ -38,7 +38,7 @@ export default function LocationPageHeader({
return (
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails.jsx b/packages/webapp/src/components/LocationDetailLayout/PointDetails.jsx
new file mode 100644
index 0000000000..2dcb49fb7c
--- /dev/null
+++ b/packages/webapp/src/components/LocationDetailLayout/PointDetails.jsx
@@ -0,0 +1,45 @@
+import { useTranslation } from 'react-i18next';
+import Input from '../Form/Input';
+import { gateEnum as pointEnum } from '../../containers/constants';
+import InputAutoSize from '../Form/InputAutoSize';
+import { useFormContext } from 'react-hook-form';
+
+export default function PointDetails({
+ name,
+ children,
+ isCreateLocationPage,
+ isViewLocationPage,
+ isEditLocationPage,
+}) {
+ const { t } = useTranslation();
+ const {
+ register,
+ formState: { errors },
+ } = useFormContext();
+
+ return (
+ <>
+
+
+ {children}
+
+ >
+ );
+}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails/Gate/index.jsx b/packages/webapp/src/components/LocationDetailLayout/PointDetails/Gate/index.jsx
deleted file mode 100644
index 604d908b92..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/PointDetails/Gate/index.jsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureGateWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureGate({
- history,
- match,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- submitForm,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- });
- submitForm({ formData });
- };
- return (
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails/PointDetails.jsx b/packages/webapp/src/components/LocationDetailLayout/PointDetails/PointDetails.jsx
deleted file mode 100644
index 1d8d4dd51b..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/PointDetails/PointDetails.jsx
+++ /dev/null
@@ -1,73 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useTranslation } from 'react-i18next';
-import Input from '../../Form/Input';
-import { gateEnum as pointEnum } from '../../../containers/constants';
-import PureWarningBox from '../../WarningBox';
-import { Label } from '../../Typography';
-import InputAutoSize from '../../Form/InputAutoSize';
-import { useFormContext } from 'react-hook-form';
-
-export default function PointDetails({
- name,
- children,
- history,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
-}) {
- const { t } = useTranslation();
- const {
- register,
- setValue,
- formState: { errors },
- } = useFormContext();
- const [errorMessage, setErrorMessage] = useState();
-
- useEffect(() => {
- const handleOffline = () => setErrorMessage(t('FARM_MAP.AREA_DETAILS.NETWORK'));
- const handleOnline = () => setErrorMessage(null);
- window.addEventListener('offline', handleOffline);
- window.addEventListener('online', handleOnline);
- return () => {
- window.removeEventListener('offline', handleOffline);
- window.removeEventListener('online', handleOnline);
- };
- }, []);
-
- useEffect(() => {
- if (history?.location?.state?.error) {
- setErrorMessage(history?.location?.state?.error);
- }
- }, [history?.location?.state?.error]);
-
- return (
- <>
- {errorMessage && !isViewLocationPage && (
-
- {errorMessage}
-
- )}
-
-
- {children}
-
- >
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/index.jsx b/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/index.jsx
deleted file mode 100644
index 14aa508e3f..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/index.jsx
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-import { useTranslation } from 'react-i18next';
-import styles from './styles.module.scss';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import Input from '../../../Form/Input';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureSoilSampleLocationWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureSoilSampleLocation({
- history,
- match,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- submitForm,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- });
- submitForm({ formData });
- };
-
- return (
- }
- />
- );
-}
-
-export function SoilSampleLocationDetailsChildren({ persistedFormData }) {
- const { t } = useTranslation();
-
- return (
-
-
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/styles.module.scss b/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/styles.module.scss
deleted file mode 100644
index 440fbb113e..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/PointDetails/SoilSampleLocation/styles.module.scss
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-.latLngContainer {
- display: flex;
- flex-wrap: wrap;
- gap: 16px;
- margin-bottom: 40px;
-
- > div {
- flex-grow: 1;
- min-width: 240px;
- }
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PointDetails/WaterValve/index.jsx b/packages/webapp/src/components/LocationDetailLayout/PointDetails/WaterValve/index.jsx
deleted file mode 100644
index 058b7870a2..0000000000
--- a/packages/webapp/src/components/LocationDetailLayout/PointDetails/WaterValve/index.jsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import { useTranslation } from 'react-i18next';
-import { useFormContext } from 'react-hook-form';
-import locationDetailStyles from '../../styles.module.scss';
-import Unit from '../../../Form/Unit';
-import { waterValveEnum } from '../../../../containers/constants';
-import { water_valve_flow_rate } from '../../../../util/convert-units/unit';
-import { Label } from '../../../Typography';
-import { PersistedFormWrapper } from '../../PersistedFormWrapper';
-import RadioGroup from '../../../Form/RadioGroup';
-import { getFormDataWithoutNulls } from '../../../../containers/hooks/useHookFormPersist/utils';
-import { PureLocationDetailLayout } from '../../PureLocationDetailLayout';
-
-export default function PureWaterValveWrapper(props) {
- return (
-
-
-
- );
-}
-
-export function PureWaterValve({
- history,
- match,
- submitForm,
- system,
- isCreateLocationPage,
- isViewLocationPage,
- isEditLocationPage,
- persistedFormData,
- useHookFormPersist,
- handleRetire,
- isAdmin,
-}) {
- const onSubmit = (data) => {
- const formData = getFormDataWithoutNulls({
- ...persistedFormData,
- ...data,
- });
- formData[waterValveEnum.flow_rate_unit] = formData[waterValveEnum.flow_rate_unit]?.value;
- submitForm({ formData });
- };
- return (
-
- }
- />
- );
-}
-
-export function WaterValveDetailsChildren({ isViewLocationPage, system }) {
- const { t } = useTranslation();
- const {
- control,
- register,
- setValue,
- getValues,
- watch,
- formState: { errors },
- } = useFormContext();
- return (
-
-
- {t('FARM_MAP.WATER_VALVE.WATER_VALVE_TYPE')}
- {t('common:OPTIONAL')}
-
-
-
-
-
- );
-}
diff --git a/packages/webapp/src/components/LocationDetailLayout/PureLocationDetailLayout.jsx b/packages/webapp/src/components/LocationDetailLayout/PureLocationDetailLayout.jsx
index 4693f6b3d2..effea356a5 100644
--- a/packages/webapp/src/components/LocationDetailLayout/PureLocationDetailLayout.jsx
+++ b/packages/webapp/src/components/LocationDetailLayout/PureLocationDetailLayout.jsx
@@ -4,9 +4,9 @@ import { useForm, FormProvider } from 'react-hook-form';
import LocationButtons from './LocationButtons';
import LocationPageHeader from './LocationPageHeader';
import Form from '../Form';
-import AreaDetails from './AreaDetails/AreaDetails';
-import LineDetails from './LineDetails/LineDetails';
-import PointDetails from './PointDetails/PointDetails';
+import AreaDetails from './AreaDetails';
+import LineDetails from './LineDetails';
+import PointDetails from './PointDetails';
import RouterTab from '../RouterTab';
import useLocationRouterTabs from '../../containers/LocationDetails/useLocationRouterTabs';
import { Variant } from '../RouterTab/Tab';
@@ -60,7 +60,6 @@ export function PureLocationDetailLayout({
return (
.
+ */
+
+import { PersistedFormWrapper } from './PersistedFormWrapper';
+import { getFormDataWithoutNulls } from '../../containers/hooks/useHookFormPersist/utils';
+import { PureLocationDetailLayout } from './PureLocationDetailLayout';
+import ExtraLocationFormFieldsMap from './ExtraFormFieldsMap';
+import { getFigureType } from '../../containers/LocationDetails/utils';
+import { getDateInputFormat } from '../../util/moment';
+
+const getOrganicStatusDefaultValues = (persistedFormData) => {
+ return {
+ organic_status: 'Non-Organic',
+ ...persistedFormData,
+ transition_date: getDateInputFormat(persistedFormData['transition_date'] || new Date()),
+ };
+};
+
+const getAreaConfig = (persistedFormData) => ({
+ barn: {
+ showPerimeter: false,
+ defaultValues: persistedFormData,
+ },
+ ceremonial_area: {
+ showPerimeter: true,
+ defaultValues: persistedFormData,
+ },
+ farm_site_boundary: {
+ showPerimeter: true,
+ defaultValues: persistedFormData,
+ },
+ field: {
+ showPerimeter: true,
+ defaultValues: getOrganicStatusDefaultValues(persistedFormData),
+ },
+ garden: {
+ showPerimeter: true,
+ defaultValues: getOrganicStatusDefaultValues(persistedFormData),
+ },
+ greenhouse: {
+ showPerimeter: false,
+ defaultValues: getOrganicStatusDefaultValues(persistedFormData),
+ },
+ natural_area: {
+ showPerimeter: true,
+ defaultValues: persistedFormData,
+ },
+ residence: {
+ showPerimeter: false,
+ defaultValues: persistedFormData,
+ },
+ surface_water: {
+ showPerimeter: true,
+ defaultValues: persistedFormData,
+ },
+});
+
+export default function PureLocationFormWrapper({
+ history,
+ match,
+ submitForm,
+ system,
+ isCreateLocationPage = false,
+ isViewLocationPage = false,
+ isEditLocationPage = false,
+ persistedFormData,
+ useHookFormPersist = () => {},
+ handleRetire = () => {},
+ isAdmin = false,
+ locationType,
+}) {
+ const onSubmit = (data) => {
+ // area units lift value up to top level
+ if (getFigureType(locationType) === 'area') {
+ data[`total_area_unit`] = data[`total_area_unit`]?.value;
+ data[`perimeter_unit`] = data[`perimeter_unit`]?.value;
+ }
+ if (getFigureType(locationType) === 'line') {
+ data[`length_unit`] = data[`length_unit`]?.value;
+ data[`width_unit`] = data[`width_unit`]?.value;
+ data['total_area_unit'] = data['total_area_unit']?.value;
+ if (locationType === 'watercourse') {
+ data['buffer_width_unit'] = data['buffer_width_unit']?.value;
+ }
+ if (locationType === 'fence') {
+ data['width'] = 0;
+ delete data['total_area_unit'];
+ }
+ }
+ if (getFigureType(locationType) === 'point') {
+ if (locationType === 'water_valve') {
+ data['flow_rate_unit'] = data['flow_rate_unit']?.value;
+ }
+ }
+
+ const formData = getFormDataWithoutNulls({
+ ...persistedFormData,
+ ...data,
+ type: locationType,
+ });
+
+ submitForm({ formData });
+ };
+
+ const DetailsChildren = ExtraLocationFormFieldsMap[locationType] || undefined;
+ const areaConfig = getAreaConfig(persistedFormData)[locationType] || {};
+ const figureType = getFigureType(locationType);
+
+ return (
+
+
+ ) : undefined
+ }
+ showPerimeter={figureType === 'area' ? areaConfig.showPerimeter : undefined}
+ />
+
+ );
+}
diff --git a/packages/webapp/src/components/LocationDetailLayout/styles.module.scss b/packages/webapp/src/components/LocationDetailLayout/styles.module.scss
index 9a8b9a46ec..3ddcb227c9 100644
--- a/packages/webapp/src/components/LocationDetailLayout/styles.module.scss
+++ b/packages/webapp/src/components/LocationDetailLayout/styles.module.scss
@@ -24,3 +24,15 @@
font-size: 16px;
}
}
+
+.latLngContainer {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 16px;
+ margin-bottom: 40px;
+
+ > div {
+ flex-grow: 1;
+ min-width: 240px;
+ }
+}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/EditBarn.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/EditBarn.jsx
deleted file mode 100644
index 9221daa77e..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/EditBarn.jsx
+++ /dev/null
@@ -1,93 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureBarn from '../../../../components/LocationDetailLayout/AreaDetails/Barn';
-import { deleteBarnLocation, editBarnLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { barnSelector } from '../../../barnSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditBarnDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editBarnLocation({ ...data, ...match.params, figure_id: barn.figure_id }));
- };
- const barn = useSelector(barnSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
-
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteBarnLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditBarnDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/PostBarn.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/PostBarn.jsx
deleted file mode 100644
index 7a28d17671..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/PostBarn.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureBarn from '../../../../components/LocationDetailLayout/AreaDetails/Barn';
-import { postBarnLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostBarnDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postBarnLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostBarnDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/saga.js
deleted file mode 100644
index 6c00f0abcc..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/BarnDetailForm/saga.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteBarnSuccess,
- editBarnSuccess,
- getLocationObjectFromBarn,
- postBarnSuccess,
-} from '../../../barnSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postBarnLocation = createAction(`postBarnLocationSaga`);
-
-export function* postBarnLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromBarn(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postBarnSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BARN'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.BARN')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editBarnLocation = createAction(`editBarnLocationSaga`);
-
-export function* editBarnLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromBarn({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editBarnSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BARN'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.BARN')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteBarnLocation = createAction(`deleteBarnLocationSaga`);
-
-export function* deleteBarnLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteBarnSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BARN'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* barnLocationSaga() {
- yield takeLeading(postBarnLocation.type, postBarnLocationSaga);
- yield takeLeading(editBarnLocation.type, editBarnLocationSaga);
- yield takeLeading(deleteBarnLocation.type, deleteBarnLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/EditCeremonialArea.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/EditCeremonialArea.jsx
deleted file mode 100644
index 6d91bb3b11..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/EditCeremonialArea.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureCeremonial from '../../../../components/LocationDetailLayout/AreaDetails/CeremonialArea';
-import { deleteCeremonialLocation, editCeremonialLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { ceremonialSelector } from '../../../ceremonialSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditCeremonialDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editCeremonialLocation({
- ...data,
- ...match.params,
- figure_id: ceremonial.figure_id,
- }),
- );
- };
- const ceremonial = useSelector(ceremonialSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteCeremonialLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditCeremonialDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/PostCeremonialArea.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/PostCeremonialArea.jsx
deleted file mode 100644
index 5ea8f3d012..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/PostCeremonialArea.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureCeremonial from '../../../../components/LocationDetailLayout/AreaDetails/CeremonialArea';
-import { postCeremonialLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostCeremonialDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postCeremonialLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostCeremonialDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/saga.js
deleted file mode 100644
index 8812e21f8b..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/saga.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteCeremonialSuccess,
- editCeremonialSuccess,
- getLocationObjectFromCeremonial,
- postCeremonialSuccess,
-} from '../../../ceremonialSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postCeremonialLocation = createAction(`postCeremonialLocationSaga`);
-
-export function* postCeremonialLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromCeremonial(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postCeremonialSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.CA'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.CA')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editCeremonialLocation = createAction(`editCeremonialLocationSaga`);
-
-export function* editCeremonialLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromCeremonial({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editCeremonialSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.CA'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.CA')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteCeremonialLocation = createAction(`deleteCeremonialLocationSaga`);
-
-export function* deleteCeremonialLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteCeremonialSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.CA'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* ceremonialLocationSaga() {
- yield takeLeading(postCeremonialLocation.type, postCeremonialLocationSaga);
- yield takeLeading(editCeremonialLocation.type, editCeremonialLocationSaga);
- yield takeLeading(deleteCeremonialLocation.type, deleteCeremonialLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/EditFarmSiteBoundary.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/EditFarmSiteBoundary.jsx
deleted file mode 100644
index d82dd29296..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/EditFarmSiteBoundary.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureFarmSiteBoundary from '../../../../components/LocationDetailLayout/AreaDetails/FarmSiteBoundary';
-import { deleteFarmSiteBoundaryLocation, editFarmSiteBoundaryLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { farmSiteBoundarySelector } from '../../../farmSiteBoundarySlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditFarmSiteBoundaryDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editFarmSiteBoundaryLocation({
- ...data,
- ...match.params,
- figure_id: farmSiteBoundary.figure_id,
- }),
- );
- };
- const farmSiteBoundary = useSelector(farmSiteBoundarySelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteFarmSiteBoundaryLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditFarmSiteBoundaryDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/PostFarmSiteBoundary.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/PostFarmSiteBoundary.jsx
deleted file mode 100644
index cac2cf0496..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/PostFarmSiteBoundary.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureFarmSiteBoundary from '../../../../components/LocationDetailLayout/AreaDetails/FarmSiteBoundary';
-import { postFarmSiteBoundaryLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostFarmSiteBoundaryDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postFarmSiteBoundaryLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostFarmSiteBoundaryDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/saga.js
deleted file mode 100644
index 27981c4e64..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/saga.js
+++ /dev/null
@@ -1,135 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteFarmSiteBoundarySuccess,
- editFarmSiteBoundarySuccess,
- getLocationObjectFromFarmSiteBoundary,
- postFarmSiteBoundarySuccess,
-} from '../../../farmSiteBoundarySlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postFarmSiteBoundaryLocation = createAction(`postFarmSiteBoundaryLocationSaga`);
-
-export function* postFarmSiteBoundaryLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromFarmSiteBoundary(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postFarmSiteBoundarySuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FSB'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FSB')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editFarmSiteBoundaryLocation = createAction(`editFarmSiteBoundaryLocationSaga`);
-
-export function* editFarmSiteBoundaryLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromFarmSiteBoundary({
- ...formData,
- location_id,
- figure_id,
- });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editFarmSiteBoundarySuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FSB'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FSB')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteFarmSiteBoundaryLocation = createAction(`deleteFarmSiteBoundaryLocationSaga`);
-
-export function* deleteFarmSiteBoundaryLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteFarmSiteBoundarySuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FSB'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* farmSiteBoundaryLocationSaga() {
- yield takeLeading(postFarmSiteBoundaryLocation.type, postFarmSiteBoundaryLocationSaga);
- yield takeLeading(editFarmSiteBoundaryLocation.type, editFarmSiteBoundaryLocationSaga);
- yield takeLeading(deleteFarmSiteBoundaryLocation.type, deleteFarmSiteBoundaryLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/EditField.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/EditField.jsx
deleted file mode 100644
index f46816f616..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/EditField.jsx
+++ /dev/null
@@ -1,91 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useLocation, useHistory, useRouteMatch } from 'react-router-dom';
-import PureField from '../../../../components/LocationDetailLayout/AreaDetails/Field';
-import { deleteFieldLocation, editFieldLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { fieldSelector } from '../../../fieldSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditFieldDetailForm() {
- const history = useHistory();
- const location = useLocation();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editFieldLocation({ ...data, ...match.params, figure_id: field.figure_id }));
- };
- const field = useSelector(fieldSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteFieldLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditFieldDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/PostField.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/PostField.jsx
deleted file mode 100644
index 1193f1719b..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/PostField.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureField from '../../../../components/LocationDetailLayout/AreaDetails/Field';
-import { postFieldLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostFieldDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postFieldLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostFieldDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/saga.js
deleted file mode 100644
index 09ae593e52..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/FieldDetailForm/saga.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteFieldSuccess,
- editFieldSuccess,
- getLocationObjectFromField,
- postFieldSuccess,
-} from '../../../fieldSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postFieldLocation = createAction(`postFieldLocationSaga`);
-
-export function* postFieldLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromField(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postFieldSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FIELD'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FIELD')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editFieldLocation = createAction(`editFieldLocationSaga`);
-
-export function* editFieldLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromField({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editFieldSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FIELD'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FIELD')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteFieldLocation = createAction(`deleteFieldLocationSaga`);
-
-export function* deleteFieldLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteFieldSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.FIELD'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* fieldLocationSaga() {
- yield takeLeading(postFieldLocation.type, postFieldLocationSaga);
- yield takeLeading(editFieldLocation.type, editFieldLocationSaga);
- yield takeLeading(deleteFieldLocation.type, deleteFieldLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/EditGarden.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/EditGarden.jsx
deleted file mode 100644
index 792979437c..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/EditGarden.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureGarden from '../../../../components/LocationDetailLayout/AreaDetails/Garden';
-import { deleteGardenLocation, editGardenLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { gardenSelector } from '../../../gardenSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditGardenDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editGardenLocation({ ...data, ...match.params, figure_id: garden.figure_id }));
- };
- const garden = useSelector(gardenSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteGardenLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditGardenDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/PostGarden.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/PostGarden.jsx
deleted file mode 100644
index d864975213..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/PostGarden.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureGarden from '../../../../components/LocationDetailLayout/AreaDetails/Garden';
-import { postGardenLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostGardenDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postGardenLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostGardenDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/saga.js
deleted file mode 100644
index 7b135d4546..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GardenDetailForm/saga.js
+++ /dev/null
@@ -1,136 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteGardenSuccess,
- editGardenSuccess,
- getLocationObjectFromGarden,
- postGardenSuccess,
-} from '../../../gardenSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import history from '../../../../history';
-import i18n from '../../../../locales/i18n';
-
-export const postGardenLocation = createAction(`postGardenLocationSaga`);
-
-export function* postGardenLocationSaga({ payload: data }) {
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- data.formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGarden(data.formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postGardenSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.GARDEN'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GARDEN')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editGardenLocation = createAction(`editGardenLocationSaga`);
-
-export function* editGardenLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGarden({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editGardenSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.GARDEN'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GARDEN')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteGardenLocation = createAction(`deleteGardenLocationSaga`);
-
-export function* deleteGardenLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteGardenSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.GARDEN'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* gardenLocationSaga() {
- yield takeLeading(postGardenLocation.type, postGardenLocationSaga);
- yield takeLeading(editGardenLocation.type, editGardenLocationSaga);
- yield takeLeading(deleteGardenLocation.type, deleteGardenLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/EditGreenhouse.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/EditGreenhouse.jsx
deleted file mode 100644
index 74b601d9ff..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/EditGreenhouse.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureGreenhouse from '../../../../components/LocationDetailLayout/AreaDetails/Greenhouse';
-import { deleteGreenhouseLocation, editGreenhouseLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { greenhouseSelector } from '../../../greenhouseSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditGreenhouseDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editGreenhouseLocation({
- ...data,
- ...match.params,
- figure_id: greenhouse.figure_id,
- }),
- );
- };
- const greenhouse = useSelector(greenhouseSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteGreenhouseLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditGreenhouseDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/PostGreenhouse.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/PostGreenhouse.jsx
deleted file mode 100644
index bcb5a76e2e..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/PostGreenhouse.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureGreenhouse from '../../../../components/LocationDetailLayout/AreaDetails/Greenhouse';
-import { postGreenhouseLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostGreenhouseDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postGreenhouseLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostGreenhouseDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/saga.js
deleted file mode 100644
index 894090b0c4..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/GreenhouseDetailForm/saga.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteGreenhouseSuccess,
- editGreenhouseSuccess,
- getLocationObjectFromGreenHouse,
- postGreenhouseSuccess,
-} from '../../../greenhouseSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postGreenhouseLocation = createAction(`postGreenhouseLocationSaga`);
-
-export function* postGreenhouseLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGreenHouse(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postGreenhouseSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.GREENHOUSE'),
- i18n.t('message:MAP.SUCCESS_POST'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GREENHOUSE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editGreenhouseLocation = createAction(`editGreenhouseLocationSaga`);
-
-export function* editGreenhouseLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGreenHouse({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editGreenhouseSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.GREENHOUSE'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GREENHOUSE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteGreenhouseLocation = createAction(`deleteGreenhouseLocationSaga`);
-
-export function* deleteGreenhouseLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteGreenhouseSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.GREENHOUSE'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* greenhouseLocationSaga() {
- yield takeLeading(postGreenhouseLocation.type, postGreenhouseLocationSaga);
- yield takeLeading(editGreenhouseLocation.type, editGreenhouseLocationSaga);
- yield takeLeading(deleteGreenhouseLocation.type, deleteGreenhouseLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/EditNaturalArea.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/EditNaturalArea.jsx
deleted file mode 100644
index c92443c0f2..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/EditNaturalArea.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureNaturalArea from '../../../../components/LocationDetailLayout/AreaDetails/NaturalArea';
-import { deleteNaturalAreaLocation, editNaturalAreaLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { naturalAreaSelector } from '../../../naturalAreaSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditNaturalAreaDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editNaturalAreaLocation({
- ...data,
- ...match.params,
- figure_id: naturalArea.figure_id,
- }),
- );
- };
- const naturalArea = useSelector(naturalAreaSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteNaturalAreaLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditNaturalAreaDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/PostNaturalArea.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/PostNaturalArea.jsx
deleted file mode 100644
index c5d3962236..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/PostNaturalArea.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureNaturalArea from '../../../../components/LocationDetailLayout/AreaDetails/NaturalArea';
-import { postNaturalAreaLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostNaturalAreaDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postNaturalAreaLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostNaturalAreaDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/saga.js
deleted file mode 100644
index 63adeedc4a..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/saga.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteNaturalAreaSuccess,
- editNaturalAreaSuccess,
- getLocationObjectFromNaturalArea,
- postNaturalAreaSuccess,
-} from '../../../naturalAreaSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postNaturalAreaLocation = createAction(`postNaturalAreaLocationSaga`);
-
-export function* postNaturalAreaLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromNaturalArea(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postNaturalAreaSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.NA'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.NA')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editNaturalAreaLocation = createAction(`editNaturalAreaLocationSaga`);
-
-export function* editNaturalAreaLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromNaturalArea({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editNaturalAreaSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.NA'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.NA')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteNaturalAreaLocation = createAction(`deleteNaturalAreaLocationSaga`);
-
-export function* deleteNaturalAreaLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteNaturalAreaSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.NA'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* naturalAreaLocationSaga() {
- yield takeLeading(postNaturalAreaLocation.type, postNaturalAreaLocationSaga);
- yield takeLeading(editNaturalAreaLocation.type, editNaturalAreaLocationSaga);
- yield takeLeading(deleteNaturalAreaLocation.type, deleteNaturalAreaLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/EditResidence.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/EditResidence.jsx
deleted file mode 100644
index 5334c8d38c..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/EditResidence.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureResidence from '../../../../components/LocationDetailLayout/AreaDetails/Residence';
-import { deleteResidenceLocation, editResidenceLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { residenceSelector } from '../../../residenceSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditResidenceDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editResidenceLocation({ ...data, ...match.params, figure_id: residence.figure_id }));
- };
- const residence = useSelector(residenceSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteResidenceLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditResidenceDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/PostResidence.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/PostResidence.jsx
deleted file mode 100644
index f636b4c664..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/PostResidence.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureResidence from '../../../../components/LocationDetailLayout/AreaDetails/Residence';
-import { postResidenceLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostResidenceDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postResidenceLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostResidenceDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/saga.js
deleted file mode 100644
index 8092f634f9..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/ResidenceDetailForm/saga.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteResidenceSuccess,
- editResidenceSuccess,
- getLocationObjectFromResidence,
- postResidenceSuccess,
-} from '../../../residenceSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postResidenceLocation = createAction(`postResidenceLocationSaga`);
-
-export function* postResidenceLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromResidence(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postResidenceSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.RESIDENCE'),
- i18n.t('message:MAP.SUCCESS_POST'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.RESIDENCE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editResidenceLocation = createAction(`editResidenceLocationSaga`);
-
-export function* editResidenceLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromResidence({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editResidenceSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.RESIDENCE'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.RESIDENCE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteResidenceLocation = createAction(`deleteResidenceLocationSaga`);
-
-export function* deleteResidenceLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteResidenceSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.RESIDENCE'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* residenceLocationSaga() {
- yield takeLeading(postResidenceLocation.type, postResidenceLocationSaga);
- yield takeLeading(editResidenceLocation.type, editResidenceLocationSaga);
- yield takeLeading(deleteResidenceLocation.type, deleteResidenceLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/EditSurfaceWater.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/EditSurfaceWater.jsx
deleted file mode 100644
index 829de4c06b..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/EditSurfaceWater.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureSurfaceWater from '../../../../components/LocationDetailLayout/AreaDetails/SurfaceWater';
-import { deleteSurfaceWaterLocation, editSurfaceWaterLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { surfaceWaterSelector } from '../../../surfaceWaterSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditSurfaceWaterDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editSurfaceWaterLocation({
- ...data,
- ...match.params,
- figure_id: surfaceWater.figure_id,
- }),
- );
- };
- const surfaceWater = useSelector(surfaceWaterSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteSurfaceWaterLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditSurfaceWaterDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/PostSurfaceWater.jsx b/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/PostSurfaceWater.jsx
deleted file mode 100644
index b557f70fea..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/PostSurfaceWater.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureSurfaceWater from '../../../../components/LocationDetailLayout/AreaDetails/SurfaceWater';
-import { postSurfaceWaterLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostSurfaceWaterDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postSurfaceWaterLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostSurfaceWaterDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/saga.js
deleted file mode 100644
index eac9d6db98..0000000000
--- a/packages/webapp/src/containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/saga.js
+++ /dev/null
@@ -1,141 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteSurfaceWaterSuccess,
- editSurfaceWaterSuccess,
- getLocationObjectFromSurfaceWater,
- postSurfaceWaterSuccess,
-} from '../../../surfaceWaterSlice';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-import history from '../../../../history';
-
-export const postSurfaceWaterLocation = createAction(`postSurfaceWaterLocationSaga`);
-
-export function* postSurfaceWaterLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromSurfaceWater(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postSurfaceWaterSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SURFACE_WATER'),
- i18n.t('message:MAP.SUCCESS_POST'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
-
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.SURFACE_WATER')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editSurfaceWaterLocation = createAction(`editSurfaceWaterLocationSaga`);
-
-export function* editSurfaceWaterLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromSurfaceWater({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editSurfaceWaterSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SURFACE_WATER'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.SURFACE_WATER')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteSurfaceWaterLocation = createAction(`deleteSurfaceWaterLocationSaga`);
-
-export function* deleteSurfaceWaterLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteSurfaceWaterSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SURFACE_WATER'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* surfaceWaterLocationSaga() {
- yield takeLeading(postSurfaceWaterLocation.type, postSurfaceWaterLocationSaga);
- yield takeLeading(editSurfaceWaterLocation.type, editSurfaceWaterLocationSaga);
- yield takeLeading(deleteSurfaceWaterLocation.type, deleteSurfaceWaterLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/EditLocationDetailForm.tsx b/packages/webapp/src/containers/LocationDetails/EditLocationDetailForm.tsx
new file mode 100644
index 0000000000..8d7563a62d
--- /dev/null
+++ b/packages/webapp/src/containers/LocationDetails/EditLocationDetailForm.tsx
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+import { useEffect, useState } from 'react';
+import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
+import { useDispatch, useSelector } from 'react-redux';
+import { isAdminSelector, loginSelector, measurementSelector } from '../userFarmSlice';
+import {
+ useCheckDeleteLocationMutation,
+ useDeleteLocationMutation,
+ useUpdateLocationByTypeMutation,
+} from '../../store/api/locationApi';
+import useLocationsById from '../../hooks/location/useLocationsById';
+import UnableToRetireModal from '../../components/Modals/UnableToRetireModal';
+import RetireConfirmationModal from '../../components/Modals/RetireConfirmationModal';
+import { formatLocationTypeToLocationForDB, useLocationPageType } from './utils';
+import { FigureType, InternalMapLocation, InternalMapLocationType } from '../../store/api/types';
+import { enqueueErrorSnackbar, enqueueSuccessSnackbar } from '../Snackbar/snackbarSlice';
+import { useTranslation } from 'react-i18next';
+import { setMapCache } from '../Map/mapCacheSlice';
+import PureLocationFormWrapper from '../../components/LocationDetailLayout/PureLocationFormWrapper';
+
+function EditLocationDetailForm({ locationType }: { locationType: InternalMapLocationType }) {
+ const dispatch = useDispatch();
+ const { t } = useTranslation();
+ const location = useLocation();
+ const history = useHistory();
+ const match = useRouteMatch();
+ // @ts-expect-error match not typed
+ const { location_id } = match.params;
+ const isAdmin = useSelector(isAdminSelector);
+ const system = useSelector(measurementSelector);
+ const { farm_id } = useSelector(loginSelector);
+
+ const { locations: locationData } = useLocationsById(location_id);
+
+ const [updateLocationByType] = useUpdateLocationByTypeMutation();
+ const [deleteLocation] = useDeleteLocationMutation();
+ const [checkDeleteLocation] = useCheckDeleteLocationMutation();
+
+ const { isViewLocationPage, isEditLocationPage } = useLocationPageType();
+
+ const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
+ const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
+
+ const submitForm = async (data: { formData: any }) => {
+ if (!isEditLocationPage) return;
+ const { formData } = data;
+ formData.farm_id = farm_id;
+ try {
+ await updateLocationByType({
+ data: formatLocationTypeToLocationForDB(
+ {
+ ...formData,
+ ...match.params,
+ figure_id: locationData?.figure_id,
+ },
+ locationType,
+ ) as InternalMapLocation,
+ type: locationType,
+ location_id: location_id,
+ }).unwrap();
+ history.push({ pathname: '/map' });
+ dispatch(
+ enqueueSuccessSnackbar(
+ `${t(`FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`)} ${t(
+ 'message:MAP.SUCCESS_PATCH',
+ )
+ .toString()
+ ?.toLowerCase()}`,
+ ),
+ );
+ } catch (error) {
+ console.error(error);
+ dispatch(
+ enqueueErrorSnackbar(
+ `${t('message:MAP.FAIL_PATCH')} ${t(
+ `FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`,
+ ).toLowerCase()}`,
+ ),
+ );
+ }
+ };
+
+ const handleRetire = async () => {
+ try {
+ await checkDeleteLocation({ location_id }).unwrap();
+ setShowConfirmRetireModal(true);
+ } catch (_err) {
+ setShowCannotRetireModal(true);
+ }
+ };
+
+ const confirmRetire = async () => {
+ if (!isViewLocationPage) return;
+ try {
+ await deleteLocation({ location_id }).unwrap();
+ if (locationData?.figure_type === FigureType.POINT) {
+ dispatch(setMapCache({ maxZoom: undefined, farm_id }));
+ }
+ history.push({ pathname: '/map' });
+ dispatch(
+ enqueueSuccessSnackbar(
+ `${t(`FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`)} ${t(
+ 'message:MAP.SUCCESS_DELETE',
+ )
+ .toString()
+ ?.toLowerCase()}`,
+ ),
+ );
+ } catch (error) {
+ console.error(error);
+ dispatch(
+ enqueueErrorSnackbar(
+ `${t('message:MAP.FAIL_DELETE')} ${t(
+ `FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`,
+ ).toLowerCase()}`,
+ ),
+ );
+ }
+ setShowConfirmRetireModal(false);
+ };
+
+ return (
+ <>
+
+ {isViewLocationPage && showCannotRetireModal && (
+ setShowCannotRetireModal(false)} />
+ )}
+ {showConfirmRetireModal && (
+ setShowConfirmRetireModal(false)}
+ handleRetire={confirmRetire}
+ />
+ )}
+ >
+ );
+}
+
+export default EditLocationDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/EditBufferZone.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/EditBufferZone.jsx
deleted file mode 100644
index 9a231b79b8..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/EditBufferZone.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureBufferZone from '../../../../components/LocationDetailLayout/LineDetails/BufferZone';
-import { deleteBufferZoneLocation, editBufferZoneLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { bufferZoneSelector } from '../../../bufferZoneSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditBufferZoneDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const location = useLocation();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editBufferZoneLocation({
- ...data,
- ...match.params,
- figure_id: bufferZone.figure_id,
- }),
- );
- };
- const bufferZone = useSelector(bufferZoneSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteBufferZoneLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditBufferZoneDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/PostBufferZone.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/PostBufferZone.jsx
deleted file mode 100644
index dbb68bb18e..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/PostBufferZone.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureBufferZone from '../../../../components/LocationDetailLayout/LineDetails/BufferZone';
-import { postBufferZoneLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostBufferZoneDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postBufferZoneLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostBufferZoneDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/saga.js
deleted file mode 100644
index 07fbc0a582..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/BufferZoneDetailForm/saga.js
+++ /dev/null
@@ -1,131 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteBufferZoneSuccess,
- editBufferZoneSuccess,
- getLocationObjectFromBufferZone,
- postBufferZoneSuccess,
-} from '../../../bufferZoneSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postBufferZoneLocation = createAction(`postBufferZoneLocationSaga`);
-
-export function* postBufferZoneLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromBufferZone(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postBufferZoneSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BZ'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.BZ')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editBufferZoneLocation = createAction(`editBufferZoneLocationSaga`);
-
-export function* editBufferZoneLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromBufferZone({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editBufferZoneSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BZ'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.BZ')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteBufferZoneLocation = createAction(`deleteBufferZoneLocationSaga`);
-
-export function* deleteBufferZoneLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteBufferZoneSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.BZ'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* bufferZoneLocationSaga() {
- yield takeLeading(postBufferZoneLocation.type, postBufferZoneLocationSaga);
- yield takeLeading(editBufferZoneLocation.type, editBufferZoneLocationSaga);
- yield takeLeading(deleteBufferZoneLocation.type, deleteBufferZoneLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/EditFence.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/EditFence.jsx
deleted file mode 100644
index 808207e999..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/EditFence.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureFence from '../../../../components/LocationDetailLayout/LineDetails/Fence';
-import { deleteFenceLocation, editFenceLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { fenceSelector } from '../../../fenceSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditFenceDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const location = useLocation();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editFenceLocation({ ...data, ...match.params, figure_id: fence.figure_id }));
- };
- const fence = useSelector(fenceSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteFenceLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditFenceDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/PostFence.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/PostFence.jsx
deleted file mode 100644
index b897b43fa2..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/PostFence.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureFence from '../../../../components/LocationDetailLayout/LineDetails/Fence';
-import { postFenceLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostFenceDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postFenceLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostFenceDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/saga.js
deleted file mode 100644
index 24671d9cd9..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/FenceDetailForm/saga.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteFenceSuccess,
- editFenceSuccess,
- getLocationObjectFromFence,
- postFenceSuccess,
-} from '../../../fenceSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postFenceLocation = createAction(`postFenceLocationSaga`);
-
-export function* postFenceLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromFence(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postFenceSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FENCE'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FENCE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editFenceLocation = createAction(`editFenceLocationSaga`);
-
-export function* editFenceLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromFence({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editFenceSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.FENCE'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.FENCE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteFenceLocation = createAction(`deleteFenceLocationSaga`);
-
-export function* deleteFenceLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteFenceSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.FENCE'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* fenceLocationSaga() {
- yield takeLeading(postFenceLocation.type, postFenceLocationSaga);
- yield takeLeading(editFenceLocation.type, editFenceLocationSaga);
- yield takeLeading(deleteFenceLocation.type, deleteFenceLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/EditWatercourse.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/EditWatercourse.jsx
deleted file mode 100644
index e5eb910233..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/EditWatercourse.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureWatercourse from '../../../../components/LocationDetailLayout/LineDetails/Watercourse';
-import { deleteWatercourseLocation, editWatercourseLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { watercourseSelector } from '../../../watercourseSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditWatercourseDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const location = useLocation();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editWatercourseLocation({
- ...data,
- ...match.params,
- figure_id: watercourse.figure_id,
- }),
- );
- };
- const watercourse = useSelector(watercourseSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteWatercourseLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditWatercourseDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/PostWatercourse.jsx b/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/PostWatercourse.jsx
deleted file mode 100644
index 970a6df0a1..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/PostWatercourse.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureWatercourse from '../../../../components/LocationDetailLayout/LineDetails/Watercourse';
-import { postWatercourseLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostWatercourseDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postWatercourseLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostWatercourseDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/saga.js
deleted file mode 100644
index b2fd66afb7..0000000000
--- a/packages/webapp/src/containers/LocationDetails/LineDetails/WatercourseDetailForm/saga.js
+++ /dev/null
@@ -1,140 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteWatercourseSuccess,
- editWatercourseSuccess,
- getLocationObjectFromWatercourse,
- postWatercourseSuccess,
-} from '../../../watercourseSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postWatercourseLocation = createAction(`postWatercourseLocationSaga`);
-
-export function* postWatercourseLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromWatercourse(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(postWatercourseSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.WATERCOURSE'),
- i18n.t('message:MAP.SUCCESS_POST'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.WATERCOURSE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editWatercourseLocation = createAction(`editWatercourseLocationSaga`);
-
-export function* editWatercourseLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromWatercourse({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editWatercourseSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.WATERCOURSE'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.WATERCOURSE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteWatercourseLocation = createAction(`deleteWatercourseLocationSaga`);
-
-export function* deleteWatercourseLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(deleteWatercourseSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.WATERCOURSE'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* watercourseLocationSaga() {
- yield takeLeading(postWatercourseLocation.type, postWatercourseLocationSaga);
- yield takeLeading(editWatercourseLocation.type, editWatercourseLocationSaga);
- yield takeLeading(deleteWatercourseLocation.type, deleteWatercourseLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/EditGate.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/EditGate.jsx
deleted file mode 100644
index da347b88f8..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/EditGate.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureGate from '../../../../components/LocationDetailLayout/PointDetails/Gate';
-import { deleteGateLocation, editGateLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { gateSelector } from '../../../gateSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditGateDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(editGateLocation({ ...data, ...match.params, figure_id: gate.figure_id }));
- };
- const gate = useSelector(gateSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteGateLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditGateDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/PostGate.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/PostGate.jsx
deleted file mode 100644
index bd18374733..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/PostGate.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureGate from '../../../../components/LocationDetailLayout/PointDetails/Gate';
-import { postGateLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostGateDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postGateLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostGateDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/saga.js
deleted file mode 100644
index 0a173612f1..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/GateDetailForm/saga.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteGateSuccess,
- editGateSuccess,
- getLocationObjectFromGate,
- postGateSuccess,
-} from '../../../gateSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import { setMapCache } from '../../../Map/mapCacheSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postGateLocation = createAction(`postGateLocationSaga`);
-
-export function* postGateLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGate(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(postGateSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.GATE'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GATE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editGateLocation = createAction(`editGateLocationSaga`);
-
-export function* editGateLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromGate({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editGateSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.GATE'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.GATE')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteGateLocation = createAction(`deleteGateLocationSaga`);
-
-export function* deleteGateLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(deleteGateSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.GATE'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* gateLocationSaga() {
- yield takeLeading(postGateLocation.type, postGateLocationSaga);
- yield takeLeading(editGateLocation.type, editGateLocationSaga);
- yield takeLeading(deleteGateLocation.type, deleteGateLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/EditSoilSampleLocation.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/EditSoilSampleLocation.jsx
deleted file mode 100644
index 2b478ebf91..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/EditSoilSampleLocation.jsx
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-import { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureSoilSampleLocation from '../../../../components/LocationDetailLayout/PointDetails/SoilSampleLocation';
-import { deleteSoilSampleLocationLocation, editSoilSampleLocationLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { soilSampleLocationSelector } from '../../../soilSampleLocationSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-
-function EditSoilSampleLocationDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editSoilSampleLocationLocation({
- ...data,
- ...match.params,
- figure_id: soilSampleLocation.figure_id,
- }),
- );
- };
- const soilSampleLocation = useSelector(soilSampleLocationSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteSoilSampleLocationLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditSoilSampleLocationDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/PostSoilSampleLocation.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/PostSoilSampleLocation.jsx
deleted file mode 100644
index d59f84512d..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/PostSoilSampleLocation.jsx
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureSoilSampleLocation from '../../../../components/LocationDetailLayout/PointDetails/SoilSampleLocation';
-import { postSoilSampleLocationLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostSoilSampleLocationDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postSoilSampleLocationLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostSoilSampleLocationDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/saga.js
deleted file mode 100644
index a66449bc47..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/saga.js
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-import { createAction } from '@reduxjs/toolkit';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import i18n from '../../../../locales/i18n';
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { axios, getHeader } from '../../../saga';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import {
- deleteSoilSampleLocationSuccess,
- editSoilSampleLocationSuccess,
- getLocationObjectFromSoilSampleLocation,
- postSoilSampleLocationSuccess,
-} from '../../../soilSampleLocationSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import { setMapCache } from '../../../Map/mapCacheSlice';
-
-export const postSoilSampleLocationLocation = createAction(`postSoilSampleLocationLocationSaga`);
-
-export function* postSoilSampleLocationLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromSoilSampleLocation(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(postSoilSampleLocationSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SOIL_SAMPLE_LOCATION'),
- i18n.t('message:MAP.SUCCESS_POST'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.SOIL_SAMPLE_LOCATION')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editSoilSampleLocationLocation = createAction(`editSoilSampleLocationLocationSaga`);
-
-export function* editSoilSampleLocationLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromSoilSampleLocation({
- ...formData,
- location_id,
- figure_id,
- });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editSoilSampleLocationSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SOIL_SAMPLE_LOCATION'),
- i18n.t('message:MAP.SUCCESS_PATCH'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.SOIL_SAMPLE_LOCATION')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteSoilSampleLocationLocation = createAction(
- `deleteSoilSampleLocationLocationSaga`,
-);
-
-export function* deleteSoilSampleLocationLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(deleteSoilSampleLocationSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([
- i18n.t('FARM_MAP.MAP_FILTER.SOIL_SAMPLE_LOCATION'),
- i18n.t('message:MAP.SUCCESS_DELETE'),
- ]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* soilSampleLocationLocationSaga() {
- yield takeLeading(postSoilSampleLocationLocation.type, postSoilSampleLocationLocationSaga);
- yield takeLeading(editSoilSampleLocationLocation.type, editSoilSampleLocationLocationSaga);
- yield takeLeading(deleteSoilSampleLocationLocation.type, deleteSoilSampleLocationLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/EditWaterValve.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/EditWaterValve.jsx
deleted file mode 100644
index 38d1230cb7..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/EditWaterValve.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import { useHistory, useLocation, useRouteMatch } from 'react-router-dom';
-import PureWaterValve from '../../../../components/LocationDetailLayout/PointDetails/WaterValve';
-import { deleteWaterValveLocation, editWaterValveLocation } from './saga';
-import { useCheckDeleteLocationMutation } from '../../../../store/api/locationApi';
-import { useDispatch, useSelector } from 'react-redux';
-import { isAdminSelector, measurementSelector } from '../../../userFarmSlice';
-import { waterValveSelector } from '../../../waterValveSlice';
-import { useLocationPageType } from '../../utils';
-import UnableToRetireModal from '../../../../components/Modals/UnableToRetireModal';
-import RetireConfirmationModal from '../../../../components/Modals/RetireConfirmationModal';
-import {
- currentManagementPlansByLocationIdSelector,
- plannedManagementPlansByLocationIdSelector,
-} from '../../../Task/TaskCrops/managementPlansWithLocationSelector';
-
-function EditWaterValveDetailForm() {
- const location = useLocation();
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const isAdmin = useSelector(isAdminSelector);
- const system = useSelector(measurementSelector);
- const submitForm = (data) => {
- isEditLocationPage &&
- dispatch(
- editWaterValveLocation({
- ...data,
- ...match.params,
- figure_id: waterValve.figure_id,
- }),
- );
- };
- const waterValve = useSelector(waterValveSelector(match.params.location_id));
-
- useEffect(() => {
- if (location?.state?.error?.retire) {
- setShowCannotRetireModal(true);
- }
- }, [location?.state?.error]);
-
- const { isCreateLocationPage, isViewLocationPage, isEditLocationPage } = useLocationPageType();
-
- const [showCannotRetireModal, setShowCannotRetireModal] = useState(false);
- const [showConfirmRetireModal, setShowConfirmRetireModal] = useState(false);
- const { location_id } = match.params;
- const activeCrops = useSelector(currentManagementPlansByLocationIdSelector(location_id));
- const plannedCrops = useSelector(plannedManagementPlansByLocationIdSelector(location_id));
- const [checkDeleteLocation] = useCheckDeleteLocationMutation();
- const handleRetire = async () => {
- // approach 1: redux store check for dependencies
- // if (activeCrops.length === 0 && plannedCrops.length === 0) {
- // setShowConfirmRetireModal(true);
- // } else {
- // setShowCannotRetireModal(true);
- // }
-
- // approach 2: call backend for dependency check
- try {
- await checkDeleteLocation({ location_id }).unwrap();
- setShowConfirmRetireModal(true);
- } catch (_err) {
- setShowCannotRetireModal(true);
- }
- };
-
- const confirmRetire = () => {
- isViewLocationPage && dispatch(deleteWaterValveLocation({ location_id }));
- setShowConfirmRetireModal(false);
- };
-
- return (
- <>
-
- {isViewLocationPage && showCannotRetireModal && (
- setShowCannotRetireModal(false)} />
- )}
- {showConfirmRetireModal && (
- setShowConfirmRetireModal(false)}
- handleRetire={confirmRetire}
- />
- )}
- >
- );
-}
-
-export default EditWaterValveDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/PostWaterValve.jsx b/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/PostWaterValve.jsx
deleted file mode 100644
index 39eb836879..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/PostWaterValve.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useHistory, useRouteMatch } from 'react-router-dom';
-import PureWaterValve from '../../../../components/LocationDetailLayout/PointDetails/WaterValve';
-import { postWaterValveLocation } from './saga';
-import { useDispatch, useSelector } from 'react-redux';
-import { measurementSelector } from '../../../userFarmSlice';
-import useHookFormPersist from '../../../hooks/useHookFormPersist';
-import { hookFormPersistSelector } from '../../../hooks/useHookFormPersist/hookFormPersistSlice';
-
-function PostWaterValveDetailForm() {
- const history = useHistory();
- const match = useRouteMatch();
- const dispatch = useDispatch();
- const system = useSelector(measurementSelector);
- const persistedFormData = useSelector(hookFormPersistSelector);
-
- const submitForm = (data) => {
- dispatch(postWaterValveLocation(data));
- };
-
- return (
-
- );
-}
-
-export default PostWaterValveDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/saga.js b/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/saga.js
deleted file mode 100644
index ad9ea01678..0000000000
--- a/packages/webapp/src/containers/LocationDetails/PointDetails/WaterValveDetailForm/saga.js
+++ /dev/null
@@ -1,134 +0,0 @@
-import { call, put, select, takeLeading } from 'redux-saga/effects';
-import { invalidateTags } from '../../../../store/api/apiSlice';
-import apiConfig from '../../../../apiConfig';
-import { loginSelector } from '../../../userFarmSlice';
-import { axios, getHeader } from '../../../saga';
-import { createAction } from '@reduxjs/toolkit';
-import {
- deleteWaterValveSuccess,
- editWaterValveSuccess,
- getLocationObjectFromWaterValve,
- postWaterValveSuccess,
-} from '../../../waterValveSlice';
-import history from '../../../../history';
-import { canShowSuccessHeader, setSuccessMessage } from '../../../mapSlice';
-import { setMapCache } from '../../../Map/mapCacheSlice';
-import i18n from '../../../../locales/i18n';
-
-export const postWaterValveLocation = createAction(`postWaterValveLocationSaga`);
-
-export function* postWaterValveLocationSaga({ payload: data }) {
- const formData = data.formData;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromWaterValve(formData);
-
- try {
- const result = yield call(
- axios.post,
- `${locationURL}/${locationObject.figure.type}`,
- locationObject,
- header,
- );
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(postWaterValveSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.WV'), i18n.t('message:MAP.SUCCESS_POST')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push('/map');
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_POST')} ${i18n
- .t('FARM_MAP.MAP_FILTER.WV')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const editWaterValveLocation = createAction(`editWaterValveLocationSaga`);
-
-export function* editWaterValveLocationSaga({ payload: data }) {
- const { formData, location_id, figure_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- formData.farm_id = farm_id;
- const header = getHeader(user_id, farm_id);
- const locationObject = getLocationObjectFromWaterValve({ ...formData, location_id, figure_id });
-
- try {
- const result = yield call(
- axios.put,
- `${locationURL}/${locationObject.figure.type}/${location_id}`,
- locationObject,
- header,
- );
- yield put(editWaterValveSuccess(result.data));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.WV'), i18n.t('message:MAP.SUCCESS_PATCH')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: `${i18n.t('message:MAP.FAIL_PATCH')} ${i18n
- .t('FARM_MAP.MAP_FILTER.WV')
- .toLowerCase()}`,
- },
- );
- console.log(e);
- }
-}
-
-export const deleteWaterValveLocation = createAction(`deleteWaterValveLocationSaga`);
-
-export function* deleteWaterValveLocationSaga({ payload: data }) {
- const { location_id } = data;
- const { locationURL } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
-
- try {
- const result = yield call(axios.delete, `${locationURL}/${location_id}`, header);
- yield put(setMapCache({ maxZoom: undefined, farm_id }));
- yield put(deleteWaterValveSuccess(location_id));
- yield put(invalidateTags(['Locations']));
- yield put(
- setSuccessMessage([i18n.t('FARM_MAP.MAP_FILTER.WV'), i18n.t('message:MAP.SUCCESS_DELETE')]),
- );
- yield put(canShowSuccessHeader(true));
- history.push({ pathname: '/map' });
- } catch (e) {
- history.push(
- {
- pathname: history.location.pathname,
- },
- {
- error: {
- retire: true,
- },
- },
- );
- console.log(e);
- }
-}
-
-export default function* waterValveLocationSaga() {
- yield takeLeading(postWaterValveLocation.type, postWaterValveLocationSaga);
- yield takeLeading(editWaterValveLocation.type, editWaterValveLocationSaga);
- yield takeLeading(deleteWaterValveLocation.type, deleteWaterValveLocationSaga);
-}
diff --git a/packages/webapp/src/containers/LocationDetails/PostLocationDetailForm.tsx b/packages/webapp/src/containers/LocationDetails/PostLocationDetailForm.tsx
new file mode 100644
index 0000000000..9b6de5183d
--- /dev/null
+++ b/packages/webapp/src/containers/LocationDetails/PostLocationDetailForm.tsx
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+import { useHistory, useRouteMatch } from 'react-router-dom';
+import { useDispatch, useSelector } from 'react-redux';
+import { loginSelector, measurementSelector } from '../userFarmSlice';
+import { formatLocationTypeToLocationForDB } from './utils';
+import { InternalMapLocation, InternalMapLocationType } from '../../store/api/types';
+import { enqueueErrorSnackbar, enqueueSuccessSnackbar } from '../Snackbar/snackbarSlice';
+import useHookFormPersist from '../hooks/useHookFormPersist';
+import { hookFormPersistSelector } from '../hooks/useHookFormPersist/hookFormPersistSlice';
+import { setMapCache } from '../Map/mapCacheSlice';
+import { useAddLocationByTypeMutation } from '../../store/api/locationApi';
+import { useTranslation } from 'react-i18next';
+import PureLocationFormWrapper from '../../components/LocationDetailLayout/PureLocationFormWrapper';
+
+function PostLocationDetailForm({ locationType }: { locationType: InternalMapLocationType }) {
+ const history = useHistory();
+ const match = useRouteMatch();
+ const dispatch = useDispatch();
+ const { t } = useTranslation();
+ const system = useSelector(measurementSelector);
+ const persistedFormData = useSelector(hookFormPersistSelector);
+ const { farm_id } = useSelector(loginSelector);
+
+ const [addLocationByType] = useAddLocationByTypeMutation();
+
+ const submitForm = async (data: { formData: any }) => {
+ const { formData } = data;
+ formData.farm_id = farm_id;
+ const locationData = formatLocationTypeToLocationForDB(
+ formData,
+ locationType,
+ ) as InternalMapLocation;
+ try {
+ await addLocationByType({
+ data: locationData,
+ type: locationType,
+ }).unwrap();
+ if (locationData.figure.point) {
+ dispatch(setMapCache({ maxZoom: undefined, farm_id }));
+ }
+ history.push({ pathname: '/map' });
+ dispatch(
+ enqueueSuccessSnackbar(
+ `${t(`FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`)} ${t('message:MAP.SUCCESS_POST')
+ .toString()
+ ?.toLowerCase()}`,
+ ),
+ );
+ } catch (error) {
+ console.error(error);
+ dispatch(
+ enqueueErrorSnackbar(
+ `${t('message:MAP.FAIL_POST')} ${t(
+ `FARM_MAP.MAP_FILTER.${locationType.toUpperCase()}`,
+ ).toLowerCase()}`,
+ ),
+ );
+ }
+ };
+
+ return (
+
+ );
+}
+
+export default PostLocationDetailForm;
diff --git a/packages/webapp/src/containers/LocationDetails/utils.js b/packages/webapp/src/containers/LocationDetails/utils.js
index aace93794f..708f139087 100644
--- a/packages/webapp/src/containers/LocationDetails/utils.js
+++ b/packages/webapp/src/containers/LocationDetails/utils.js
@@ -1,7 +1,17 @@
import { useMemo } from 'react';
import { useRouteMatch } from 'react-router-dom';
-import { barnEnum, fenceEnum, fieldEnum, greenhouseEnum, surfaceWaterEnum } from '../constants';
+import {
+ areaProperties,
+ fieldEnum,
+ figureProperties,
+ lineProperties,
+ locationProperties,
+ pointProperties,
+} from '../constants';
import moment from 'moment';
+import { pick } from '../../util/pick';
+import { FigureType, InternalMapLocationType } from '../../store/api/types';
+import { getDateInputFormat } from '../../util/moment';
const isCreateLocationPage = (match) => match.path.includes('/create_location/');
const isViewLocationPage = (match) => /\w*\/:location_id\/details/.test(match.path);
@@ -18,12 +28,6 @@ export const useLocationPageType = () => {
);
};
-const boolToString = (bool) => {
- if (bool === true) return 'true';
- else if (bool === false) return 'false';
- else return undefined;
-};
-
export const getFormData = (location) => {
const result = { ...location };
result[fieldEnum.transition_date] &&
@@ -33,3 +37,96 @@ export const getFormData = (location) => {
return result;
};
+
+const propertiesToPick = {
+ // areas
+ barn: ['wash_and_pack', 'cold_storage', 'used_for_animals'],
+ ceremonial_area: [],
+ farm_site_boundary: [],
+ field: ['station_id', 'organic_status', 'transition_date'],
+ garden: ['station_id', 'organic_status', 'transition_date'],
+ greenhouse: [
+ 'organic_status',
+ 'transition_date',
+ 'supplemental_lighting',
+ 'co2_enrichment',
+ 'greenhouse_heated',
+ ],
+ natural_area: [],
+ residence: [],
+ surface_water: ['used_for_irrigation'],
+ // lines
+ buffer_zone: [],
+ fence: ['pressure_treated'],
+ watercourse: [
+ 'used_for_irrigation',
+ 'includes_riparian_buffer',
+ 'buffer_width',
+ 'buffer_width_unit',
+ ],
+ // points
+ gate: [],
+ soil_sample_location: [],
+ water_valve: ['source', 'flow_rate', 'flow_rate_unit'],
+};
+
+export const getFigureType = (locationType) => {
+ switch (locationType) {
+ case InternalMapLocationType.BARN:
+ case InternalMapLocationType.CEREMONIAL_AREA:
+ case InternalMapLocationType.FARM_SITE_BOUNDARY:
+ case InternalMapLocationType.FIELD:
+ case InternalMapLocationType.GARDEN:
+ case InternalMapLocationType.GREENHOUSE:
+ case InternalMapLocationType.NATURAL_AREA:
+ case InternalMapLocationType.RESIDENCE:
+ case InternalMapLocationType.SURFACE_WATER:
+ return 'area';
+ case InternalMapLocationType.BUFFER_ZONE:
+ case InternalMapLocationType.FENCE:
+ case InternalMapLocationType.WATERCOURSE:
+ return 'line';
+ case InternalMapLocationType.GATE:
+ case InternalMapLocationType.SOIL_SAMPLE_LOCATION:
+ case InternalMapLocationType.WATER_VALVE:
+ return 'point';
+ default:
+ throw new Error(`Unknown location type ${locationType}`);
+ }
+};
+
+const getFigureTypeProperties = (data, locationType) => {
+ const figureType = getFigureType(locationType);
+ const properties = { area: areaProperties, line: lineProperties, point: pointProperties };
+ return { [figureType]: pick(data, properties[figureType]) };
+};
+
+const getOrganicHistoryProperties = (data, locationType) => {
+ switch (locationType) {
+ case InternalMapLocationType.FIELD:
+ case InternalMapLocationType.GARDEN:
+ case InternalMapLocationType.GREENHOUSE:
+ return {
+ organic_history: {
+ effective_date: getDateInputFormat(),
+ organic_status: data.organic_status,
+ },
+ };
+ default:
+ return {};
+ }
+};
+
+export const formatLocationTypeToLocationForDB = (data, locationType) => {
+ return {
+ figure: {
+ ...pick(data, figureProperties),
+ ...getFigureTypeProperties(data, locationType),
+ },
+ [locationType]: {
+ ...pick(data, ['location_id', ...propertiesToPick[locationType]]),
+ ...getOrganicHistoryProperties(data, locationType),
+ },
+ ...pick(data, locationProperties),
+ };
+};
diff --git a/packages/webapp/src/containers/Map/index.jsx b/packages/webapp/src/containers/Map/index.jsx
index 836a8be3f4..d73e3b1059 100644
--- a/packages/webapp/src/containers/Map/index.jsx
+++ b/packages/webapp/src/containers/Map/index.jsx
@@ -34,7 +34,6 @@ import useDrawingManager from './useDrawingManager';
import { createShapeCapture } from './createShapeCapture';
import useMapAssetRenderer from './useMapAssetRenderer';
-import { getLocations } from '../saga';
import {
mapFilterSettingSelector,
setMapFilterHideAll,
@@ -146,10 +145,6 @@ export default function Map({ isCompactSideMenu }) {
if (drawingState.pointChanged) dispatch(setIsRedrawing(true));
}, [drawingState.pointChanged]);
- useEffect(() => {
- dispatch(getLocations());
- }, []);
-
useEffect(() => {
if (showHeader) setShowSuccessHeader(true);
}, [showHeader]);
diff --git a/packages/webapp/src/containers/Map/useMapAssetRenderer.js b/packages/webapp/src/containers/Map/useMapAssetRenderer.js
index 29eecf5da6..c5a0d133ee 100644
--- a/packages/webapp/src/containers/Map/useMapAssetRenderer.js
+++ b/packages/webapp/src/containers/Map/useMapAssetRenderer.js
@@ -149,8 +149,8 @@ const useMapAssetRenderer = ({ isClickable, showingConfirmButtons, drawingState
? drawNoFillArea
: drawArea
: isLine(assetType)
- ? drawLine
- : drawPoint;
+ ? drawLine
+ : drawPoint;
};
const { maxZoomRef } = useMaxZoom();
diff --git a/packages/webapp/src/containers/Task/TaskLocations/index.jsx b/packages/webapp/src/containers/Task/TaskLocations/index.jsx
index 8262613dbe..d789f57ada 100644
--- a/packages/webapp/src/containers/Task/TaskLocations/index.jsx
+++ b/packages/webapp/src/containers/Task/TaskLocations/index.jsx
@@ -19,11 +19,11 @@ import { useMaxZoom } from '../../Map/useMaxZoom';
import { managementPlanSelector } from '../../managementPlanSlice';
import { getProgress } from '../util';
import useAnimalsExist from '../../Animals/Inventory/useAnimalsExist';
-import { soilSampleLocationsSelector } from '../../soilSampleLocationSlice';
import useLocations from '../../../hooks/location/useLocations';
import useCropLocations from '../../../hooks/location/useCropLocations';
import useAnimalLocations from '../../../hooks/location/useAnimalLocations';
import useLocationsById from '../../../hooks/location/useLocationsById';
+import { InternalMapLocationType } from '../../../store/api/types';
export default function TaskLocationsSwitch() {
const location = useLocation();
@@ -176,7 +176,9 @@ function TaskAnimalLocations({ history, location }) {
function TaskSoilSampleLocations({ history, location }) {
const { t } = useTranslation();
- const soilSampleLocations = useSelector(soilSampleLocationsSelector);
+ const { locations: soilSampleLocations } = useLocations({
+ filterBy: InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ });
const onContinue = () => {
history.push('/add_task/task_details', location.state);
};
diff --git a/packages/webapp/src/containers/Task/TaskTypeSelection/index.jsx b/packages/webapp/src/containers/Task/TaskTypeSelection/index.jsx
index b5c5c3a8b6..3a0ec3098a 100644
--- a/packages/webapp/src/containers/Task/TaskTypeSelection/index.jsx
+++ b/packages/webapp/src/containers/Task/TaskTypeSelection/index.jsx
@@ -10,12 +10,13 @@ import { showedSpotlightSelector } from '../../showedSpotlightSlice';
import { setSpotlightToShown } from '../../Map/saga';
import { currentAndPlannedManagementPlansSelector } from '../../managementPlanSlice';
import useAnimalsExist from '../../Animals/Inventory/useAnimalsExist';
-import { soilSampleLocationsSelector } from '../../soilSampleLocationSlice';
import { hasAvailableProductsSelector } from '../../productSlice';
import { TASK_TYPES } from '../constants';
import { useIsOffline } from '../../hooks/useOfflineDetector/useIsOffline';
import useCropLocations from '../../../hooks/location/useCropLocations';
import useAnimalLocations from '../../../hooks/location/useAnimalLocations';
+import { InternalMapLocationType } from '../../../store/api/types';
+import useLocations from '../../../hooks/location/useLocations';
function TaskTypeSelection() {
const location = useLocation();
@@ -54,7 +55,10 @@ function TaskTypeSelection() {
useSelector(currentAndPlannedManagementPlansSelector)?.length > 0;
const { locations: animalLocations } = useAnimalLocations();
const hasAnimalMovementLocations = animalLocations?.length > 0;
- const hasSoilSampleLocations = useSelector(soilSampleLocationsSelector)?.length > 0;
+ const { locations: soilSampleLocations } = useLocations({
+ filterBy: InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ });
+ const hasSoilSampleLocations = soilSampleLocations?.length > 0;
const hasSoilAmendmentProducts = useSelector((state) =>
hasAvailableProductsSelector(state, TASK_TYPES.SOIL_AMENDMENT),
);
diff --git a/packages/webapp/src/containers/barnSlice.js b/packages/webapp/src/containers/barnSlice.js
deleted file mode 100644
index 62c497d07c..0000000000
--- a/packages/webapp/src/containers/barnSlice.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const barnProperties = ['wash_and_pack', 'cold_storage', 'used_for_animals', 'location_id'];
-export const getLocationObjectFromBarn = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- barn: pick(data, barnProperties),
- ...pick(data, locationProperties),
- };
-};
-const getBarnFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.barn, barnProperties),
- };
-};
-
-const upsertOneBarnWithLocation = (state, { payload: location }) => {
- barnAdapter.upsertOne(state, getBarnFromLocationObject(location));
-};
-const upsertManyBarnWithLocation = (state, { payload: locations }) => {
- barnAdapter.upsertMany(
- state,
- locations.map((location) => getBarnFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteBarn = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- barnAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const barnAdapter = createEntityAdapter({
- selectId: (barn) => barn.location_id,
-});
-
-const barnSlice = createSlice({
- name: 'barnReducer',
- initialState: barnAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingBarnStart: onLoadingStart,
- onLoadingBarnFail: onLoadingFail,
- getBarnsSuccess: upsertManyBarnWithLocation,
- postBarnSuccess: upsertOneBarnWithLocation,
- editBarnSuccess: upsertOneBarnWithLocation,
- deleteBarnSuccess: softDeleteBarn,
- },
-});
-export const {
- getBarnsSuccess,
- postBarnSuccess,
- editBarnSuccess,
- onLoadingBarnStart,
- onLoadingBarnFail,
- deleteBarnSuccess,
-} = barnSlice.actions;
-export default barnSlice.reducer;
-
-export const barnReducerSelector = (state) => state.entitiesReducer[barnSlice.name];
-
-const barnSelectors = barnAdapter.getSelectors((state) => state.entitiesReducer[barnSlice.name]);
-
-export const barnEntitiesSelector = barnSelectors.selectEntities;
-export const barnsSelector = createSelector(
- [barnSelectors.selectAll, loginSelector],
- (barns, { farm_id }) => {
- return barns.filter((barn) => barn.farm_id === farm_id && !barn.deleted);
- },
-);
-
-export const barnSelector = (location_id) =>
- createSelector(barnEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/bufferZoneSlice.js b/packages/webapp/src/containers/bufferZoneSlice.js
deleted file mode 100644
index 40c728b341..0000000000
--- a/packages/webapp/src/containers/bufferZoneSlice.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, lineProperties, locationProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-const bufferZoneProperties = ['location_id'];
-export const getLocationObjectFromBufferZone = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- line: pick(data, lineProperties),
- },
- buffer_zone: pick(data, bufferZoneProperties),
- ...pick(data, locationProperties),
- };
-};
-const getBufferZoneFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
-
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.line, lineProperties),
- ...pick(location.buffer_zone, bufferZoneProperties),
- };
-};
-
-const upsertOneBufferZoneWithLocation = (state, { payload: location }) => {
- bufferZoneAdapter.upsertOne(state, getBufferZoneFromLocationObject(location));
-};
-const upsertManyBufferZoneWithLocation = (state, { payload: locations }) => {
- bufferZoneAdapter.upsertMany(
- state,
- locations.map((location) => getBufferZoneFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteBufferZone = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- bufferZoneAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const bufferZoneAdapter = createEntityAdapter({
- selectId: (bufferZone) => bufferZone.location_id,
-});
-
-const bufferZoneSlice = createSlice({
- name: 'bufferZoneReducer',
- initialState: bufferZoneAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingBufferZoneStart: onLoadingStart,
- onLoadingBufferZoneFail: onLoadingFail,
- getBufferZonesSuccess: upsertManyBufferZoneWithLocation,
- postBufferZoneSuccess: upsertOneBufferZoneWithLocation,
- editBufferZoneSuccess: upsertOneBufferZoneWithLocation,
- deleteBufferZoneSuccess: softDeleteBufferZone,
- },
-});
-export const {
- getBufferZonesSuccess,
- postBufferZoneSuccess,
- editBufferZoneSuccess,
- onLoadingBufferZoneStart,
- onLoadingBufferZoneFail,
- deleteBufferZoneSuccess,
-} = bufferZoneSlice.actions;
-export default bufferZoneSlice.reducer;
-
-export const bufferZoneReducerSelector = (state) => state.entitiesReducer[bufferZoneSlice.name];
-
-const bufferZoneSelectors = bufferZoneAdapter.getSelectors(
- (state) => state.entitiesReducer[bufferZoneSlice.name],
-);
-
-export const bufferZoneEntitiesSelector = bufferZoneSelectors.selectEntities;
-export const bufferZonesSelector = createSelector(
- [bufferZoneSelectors.selectAll, loginSelector],
- (bufferZones, { farm_id }) => {
- return bufferZones.filter(
- (bufferZone) => bufferZone.farm_id === farm_id && !bufferZone.deleted,
- );
- },
-);
-
-export const bufferZoneSelector = (location_id) =>
- createSelector(bufferZoneEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/ceremonialSlice.js b/packages/webapp/src/containers/ceremonialSlice.js
deleted file mode 100644
index 3d77b10bfe..0000000000
--- a/packages/webapp/src/containers/ceremonialSlice.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const ceremonialProperties = ['location_id'];
-export const getLocationObjectFromCeremonial = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- ceremonial_area: pick(data, ceremonialProperties),
- ...pick(data, locationProperties),
- };
-};
-const getCeremonialFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
-
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.ceremonial_area, ceremonialProperties),
- };
-};
-
-const upsertOneCeremonialWithLocation = (state, { payload: location }) => {
- ceremonialAdapter.upsertOne(state, getCeremonialFromLocationObject(location));
-};
-const upsertManyCeremonialWithLocation = (state, { payload: locations }) => {
- ceremonialAdapter.upsertMany(
- state,
- locations.map((location) => getCeremonialFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteCeremonial = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- ceremonialAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const ceremonialAdapter = createEntityAdapter({
- selectId: (ceremonial) => ceremonial.location_id,
-});
-
-const ceremonialSlice = createSlice({
- name: 'ceremonialReducer',
- initialState: ceremonialAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingCeremonialStart: onLoadingStart,
- onLoadingCeremonialFail: onLoadingFail,
- getCeremonialsSuccess: upsertManyCeremonialWithLocation,
- postCeremonialSuccess: upsertOneCeremonialWithLocation,
- editCeremonialSuccess: upsertOneCeremonialWithLocation,
- deleteCeremonialSuccess: softDeleteCeremonial,
- },
-});
-export const {
- getCeremonialsSuccess,
- postCeremonialSuccess,
- editCeremonialSuccess,
- onLoadingCeremonialStart,
- onLoadingCeremonialFail,
- deleteCeremonialSuccess,
-} = ceremonialSlice.actions;
-export default ceremonialSlice.reducer;
-
-export const ceremonialReducerSelector = (state) => state.entitiesReducer[ceremonialSlice.name];
-
-const ceremonialSelectors = ceremonialAdapter.getSelectors(
- (state) => state.entitiesReducer[ceremonialSlice.name],
-);
-
-export const ceremonialEntitiesSelector = ceremonialSelectors.selectEntities;
-export const ceremonialsSelector = createSelector(
- [ceremonialSelectors.selectAll, loginSelector],
- (ceremonials, { farm_id }) => {
- return ceremonials.filter(
- (ceremonial) => ceremonial.farm_id === farm_id && !ceremonial.deleted,
- );
- },
-);
-
-export const ceremonialSelector = (location_id) =>
- createSelector(ceremonialEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/farmSiteBoundarySlice.js b/packages/webapp/src/containers/farmSiteBoundarySlice.js
deleted file mode 100644
index e4314e9bba..0000000000
--- a/packages/webapp/src/containers/farmSiteBoundarySlice.js
+++ /dev/null
@@ -1,94 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const farmSiteBoundaryProperties = ['location_id'];
-export const getLocationObjectFromFarmSiteBoundary = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- farm_site_boundary: pick(data, farmSiteBoundaryProperties),
- ...pick(data, locationProperties),
- };
-};
-const getFarmSiteBoundaryFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
-
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.farm_site_boundary, farmSiteBoundaryProperties),
- };
-};
-
-const upsertOneFarmSiteBoundaryWithLocation = (state, { payload: location }) => {
- farmSiteBoundaryAdapter.upsertOne(state, getFarmSiteBoundaryFromLocationObject(location));
-};
-const upsertManyFarmSiteBoundaryWithLocation = (state, { payload: locations }) => {
- farmSiteBoundaryAdapter.upsertMany(
- state,
- locations.map((location) => getFarmSiteBoundaryFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteFarmSiteBoundary = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- farmSiteBoundaryAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const farmSiteBoundaryAdapter = createEntityAdapter({
- selectId: (farmSiteBoundary) => farmSiteBoundary.location_id,
-});
-
-const farmSiteBoundarySlice = createSlice({
- name: 'farmSiteBoundaryReducer',
- initialState: farmSiteBoundaryAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingFarmSiteBoundaryStart: onLoadingStart,
- onLoadingFarmSiteBoundaryFail: onLoadingFail,
- getFarmSiteBoundarysSuccess: upsertManyFarmSiteBoundaryWithLocation,
- postFarmSiteBoundarySuccess: upsertOneFarmSiteBoundaryWithLocation,
- editFarmSiteBoundarySuccess: upsertOneFarmSiteBoundaryWithLocation,
- deleteFarmSiteBoundarySuccess: softDeleteFarmSiteBoundary,
- },
-});
-export const {
- getFarmSiteBoundarysSuccess,
- postFarmSiteBoundarySuccess,
- editFarmSiteBoundarySuccess,
- onLoadingFarmSiteBoundaryStart,
- onLoadingFarmSiteBoundaryFail,
- deleteFarmSiteBoundarySuccess,
-} = farmSiteBoundarySlice.actions;
-export default farmSiteBoundarySlice.reducer;
-
-export const farmSiteBoundaryReducerSelector = (state) =>
- state.entitiesReducer[farmSiteBoundarySlice.name];
-
-const farmSiteBoundarySelectors = farmSiteBoundaryAdapter.getSelectors(
- (state) => state.entitiesReducer[farmSiteBoundarySlice.name],
-);
-
-export const farmSiteBoundaryEntitiesSelector = farmSiteBoundarySelectors.selectEntities;
-export const farmSiteBoundarysSelector = createSelector(
- [farmSiteBoundarySelectors.selectAll, loginSelector],
- (farmSiteBoundarys, { farm_id }) => {
- return farmSiteBoundarys.filter(
- (farmSiteBoundary) => farmSiteBoundary.farm_id === farm_id && !farmSiteBoundary.deleted,
- );
- },
-);
-
-export const farmSiteBoundarySelector = (location_id) =>
- createSelector(farmSiteBoundaryEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/fenceSlice.js b/packages/webapp/src/containers/fenceSlice.js
deleted file mode 100644
index 9e07c2b1fd..0000000000
--- a/packages/webapp/src/containers/fenceSlice.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, lineProperties, locationProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-const fenceProperties = ['pressure_treated', 'location_id'];
-export const getLocationObjectFromFence = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- line: pick(data, lineProperties),
- },
- fence: pick(data, fenceProperties),
- ...pick(data, locationProperties),
- };
-};
-const getFenceFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.line, lineProperties),
- ...pick(location.fence, fenceProperties),
- };
-};
-
-const upsertOneFenceWithLocation = (state, { payload: location }) => {
- fenceAdapter.upsertOne(state, getFenceFromLocationObject(location));
-};
-const upsertManyFenceWithLocation = (state, { payload: locations }) => {
- fenceAdapter.upsertMany(
- state,
- locations.map((location) => getFenceFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteFence = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- fenceAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const fenceAdapter = createEntityAdapter({
- selectId: (fence) => fence.location_id,
-});
-
-const fenceSlice = createSlice({
- name: 'fenceReducer',
- initialState: fenceAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingFenceStart: onLoadingStart,
- onLoadingFenceFail: onLoadingFail,
- getFencesSuccess: upsertManyFenceWithLocation,
- postFenceSuccess: upsertOneFenceWithLocation,
- editFenceSuccess: upsertOneFenceWithLocation,
- deleteFenceSuccess: softDeleteFence,
- },
-});
-export const {
- getFencesSuccess,
- postFenceSuccess,
- editFenceSuccess,
- onLoadingFenceStart,
- onLoadingFenceFail,
- deleteFenceSuccess,
-} = fenceSlice.actions;
-export default fenceSlice.reducer;
-
-export const fenceReducerSelector = (state) => state.entitiesReducer[fenceSlice.name];
-
-const fenceSelectors = fenceAdapter.getSelectors((state) => state.entitiesReducer[fenceSlice.name]);
-
-export const fenceEntitiesSelector = fenceSelectors.selectEntities;
-export const fencesSelector = createSelector(
- [fenceSelectors.selectAll, loginSelector],
- (fences, { farm_id }) => {
- return fences.filter((fence) => fence.farm_id === farm_id && !fence.deleted);
- },
-);
-
-export const fenceSelector = (location_id) =>
- createSelector(fenceEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/fieldSlice.js b/packages/webapp/src/containers/fieldSlice.js
deleted file mode 100644
index a0f6fb587f..0000000000
--- a/packages/webapp/src/containers/fieldSlice.js
+++ /dev/null
@@ -1,95 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-import { getDateInputFormat } from '../util/moment';
-
-const fieldProperties = ['station_id', 'organic_status', 'transition_date', 'location_id'];
-export const getLocationObjectFromField = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- field: {
- ...pick(data, fieldProperties),
- organic_history: {
- effective_date: getDateInputFormat(),
- organic_status: data.organic_status,
- },
- },
- ...pick(data, locationProperties),
- };
-};
-const getFieldFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.field, fieldProperties),
- };
-};
-
-const upsertOneFieldWithLocation = (state, { payload: location }) => {
- fieldAdapter.upsertOne(state, getFieldFromLocationObject(location));
-};
-const upsertManyFieldWithLocation = (state, { payload: locations }) => {
- fieldAdapter.upsertMany(
- state,
- locations.map((location) => getFieldFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteField = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- fieldAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const fieldAdapter = createEntityAdapter({
- selectId: (field) => field.location_id,
-});
-
-const fieldSlice = createSlice({
- name: 'fieldReducer',
- initialState: fieldAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingFieldStart: onLoadingStart,
- onLoadingFieldFail: onLoadingFail,
- getFieldsSuccess: upsertManyFieldWithLocation,
- postFieldSuccess: upsertOneFieldWithLocation,
- editFieldSuccess: upsertOneFieldWithLocation,
- deleteFieldSuccess: softDeleteField,
- },
-});
-export const {
- getFieldsSuccess,
- postFieldSuccess,
- editFieldSuccess,
- onLoadingFieldStart,
- onLoadingFieldFail,
- deleteFieldSuccess,
-} = fieldSlice.actions;
-export default fieldSlice.reducer;
-
-export const fieldReducerSelector = (state) => state.entitiesReducer[fieldSlice.name];
-
-const fieldSelectors = fieldAdapter.getSelectors((state) => state.entitiesReducer[fieldSlice.name]);
-
-export const fieldEntitiesSelector = fieldSelectors.selectEntities;
-export const fieldsSelector = createSelector(
- [fieldSelectors.selectAll, loginSelector],
- (fields, { farm_id }) => {
- return fields.filter((field) => field.farm_id === farm_id && !field.deleted);
- },
-);
-
-export const fieldSelector = (location_id) =>
- createSelector(fieldEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/gardenSlice.js b/packages/webapp/src/containers/gardenSlice.js
deleted file mode 100644
index 0088227f7c..0000000000
--- a/packages/webapp/src/containers/gardenSlice.js
+++ /dev/null
@@ -1,97 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-import { getDateInputFormat } from '../util/moment';
-
-const gardenProperties = ['station_id', 'organic_status', 'transition_date', 'location_id'];
-export const getLocationObjectFromGarden = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- garden: {
- ...pick(data, gardenProperties),
- organic_history: {
- effective_date: getDateInputFormat(),
- organic_status: data.organic_status,
- },
- },
- ...pick(data, locationProperties),
- };
-};
-const getGardenFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.garden, gardenProperties),
- };
-};
-
-const upsertOneGardenWithLocation = (state, { payload: location }) => {
- gardenAdapter.upsertOne(state, getGardenFromLocationObject(location));
-};
-const upsertManyGardenWithLocation = (state, { payload: locations }) => {
- gardenAdapter.upsertMany(
- state,
- locations.map((location) => getGardenFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteGarden = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- gardenAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const gardenAdapter = createEntityAdapter({
- selectId: (garden) => garden.location_id,
-});
-
-const gardenSlice = createSlice({
- name: 'gardenReducer',
- initialState: gardenAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingGardenStart: onLoadingStart,
- onLoadingGardenFail: onLoadingFail,
- getGardensSuccess: upsertManyGardenWithLocation,
- postGardenSuccess: upsertOneGardenWithLocation,
- editGardenSuccess: upsertOneGardenWithLocation,
- deleteGardenSuccess: softDeleteGarden,
- },
-});
-export const {
- getGardensSuccess,
- postGardenSuccess,
- editGardenSuccess,
- onLoadingGardenStart,
- onLoadingGardenFail,
- deleteGardenSuccess,
-} = gardenSlice.actions;
-export default gardenSlice.reducer;
-
-export const gardenReducerSelector = (state) => state.entitiesReducer[gardenSlice.name];
-
-const gardenSelectors = gardenAdapter.getSelectors(
- (state) => state.entitiesReducer[gardenSlice.name],
-);
-
-export const gardenEntitiesSelector = gardenSelectors.selectEntities;
-export const gardensSelector = createSelector(
- [gardenSelectors.selectAll, loginSelector],
- (gardens, { farm_id }) => {
- return gardens.filter((garden) => garden.farm_id === farm_id && !garden.deleted);
- },
-);
-
-export const gardenSelector = (location_id) =>
- createSelector(gardenEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/gateSlice.js b/packages/webapp/src/containers/gateSlice.js
deleted file mode 100644
index 5543b1a10b..0000000000
--- a/packages/webapp/src/containers/gateSlice.js
+++ /dev/null
@@ -1,88 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, locationProperties, pointProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-const gateProperties = ['location_id'];
-export const getLocationObjectFromGate = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- point: pick(data, pointProperties),
- },
- gate: pick(data, gateProperties),
- ...pick(data, locationProperties),
- };
-};
-const getGateFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.point, pointProperties),
- ...pick(location.gate, gateProperties),
- };
-};
-
-const upsertOneGateWithLocation = (state, { payload: location }) => {
- gateAdapter.upsertOne(state, getGateFromLocationObject(location));
-};
-const upsertManyGateWithLocation = (state, { payload: locations }) => {
- gateAdapter.upsertMany(
- state,
- locations.map((location) => getGateFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteGate = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- gateAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const gateAdapter = createEntityAdapter({
- selectId: (gate) => gate.location_id,
-});
-
-const gateSlice = createSlice({
- name: 'gateReducer',
- initialState: gateAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingGateStart: onLoadingStart,
- onLoadingGateFail: onLoadingFail,
- getGatesSuccess: upsertManyGateWithLocation,
- postGateSuccess: upsertOneGateWithLocation,
- editGateSuccess: upsertOneGateWithLocation,
- deleteGateSuccess: softDeleteGate,
- },
-});
-export const {
- getGatesSuccess,
- postGateSuccess,
- editGateSuccess,
- onLoadingGateStart,
- onLoadingGateFail,
- deleteGateSuccess,
-} = gateSlice.actions;
-export default gateSlice.reducer;
-
-export const gateReducerSelector = (state) => state.entitiesReducer[gateSlice.name];
-
-const gateSelectors = gateAdapter.getSelectors((state) => state.entitiesReducer[gateSlice.name]);
-
-export const gateEntitiesSelector = gateSelectors.selectEntities;
-export const gatesSelector = createSelector(
- [gateSelectors.selectAll, loginSelector],
- (gates, { farm_id }) => {
- return gates.filter((gate) => gate.farm_id === farm_id && !gate.deleted);
- },
-);
-
-export const gateSelector = (location_id) =>
- createSelector(gateEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/greenhouseSlice.js b/packages/webapp/src/containers/greenhouseSlice.js
deleted file mode 100644
index d1f1cb5248..0000000000
--- a/packages/webapp/src/containers/greenhouseSlice.js
+++ /dev/null
@@ -1,106 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-import { getDateInputFormat } from '../util/moment';
-
-const greenHouseProperties = [
- 'organic_status',
- 'transition_date',
- 'supplemental_lighting',
- 'co2_enrichment',
- 'greenhouse_heated',
- 'location_id',
-];
-export const getLocationObjectFromGreenHouse = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- greenhouse: {
- ...pick(data, greenHouseProperties),
- organic_history: {
- effective_date: getDateInputFormat(),
- organic_status: data.organic_status,
- },
- },
- ...pick(data, locationProperties),
- };
-};
-const getGreenhouseFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.greenhouse, greenHouseProperties),
- };
-};
-
-const upsertOneGreenhouseWithLocation = (state, { payload: location }) => {
- greenhouseAdapter.upsertOne(state, getGreenhouseFromLocationObject(location));
-};
-const upsertManyGreenhouseWithLocation = (state, { payload: locations }) => {
- greenhouseAdapter.upsertMany(
- state,
- locations.map((location) => getGreenhouseFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteGreenhouse = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- greenhouseAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const greenhouseAdapter = createEntityAdapter({
- selectId: (greenhouse) => greenhouse.location_id,
-});
-
-const greenhouseSlice = createSlice({
- name: 'greenhouseReducer',
- initialState: greenhouseAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingGreenhouseStart: onLoadingStart,
- onLoadingGreenhouseFail: onLoadingFail,
- getGreenhousesSuccess: upsertManyGreenhouseWithLocation,
- postGreenhouseSuccess: upsertOneGreenhouseWithLocation,
- editGreenhouseSuccess: upsertOneGreenhouseWithLocation,
- deleteGreenhouseSuccess: softDeleteGreenhouse,
- },
-});
-export const {
- getGreenhousesSuccess,
- postGreenhouseSuccess,
- editGreenhouseSuccess,
- onLoadingGreenhouseStart,
- onLoadingGreenhouseFail,
- deleteGreenhouseSuccess,
-} = greenhouseSlice.actions;
-export default greenhouseSlice.reducer;
-
-export const greenhouseReducerSelector = (state) => state.entitiesReducer[greenhouseSlice.name];
-
-const greenhouseSelectors = greenhouseAdapter.getSelectors(
- (state) => state.entitiesReducer[greenhouseSlice.name],
-);
-
-export const greenhouseEntitiesSelector = greenhouseSelectors.selectEntities;
-export const greenhousesSelector = createSelector(
- [greenhouseSelectors.selectAll, loginSelector],
- (greenhouses, { farm_id }) => {
- return greenhouses.filter(
- (greenhouse) => greenhouse.farm_id === farm_id && !greenhouse.deleted,
- );
- },
-);
-
-export const greenhouseSelector = (location_id) =>
- createSelector(greenhouseEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/naturalAreaSlice.js b/packages/webapp/src/containers/naturalAreaSlice.js
deleted file mode 100644
index d77ea2a320..0000000000
--- a/packages/webapp/src/containers/naturalAreaSlice.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const naturalAreaProperties = ['location_id'];
-export const getLocationObjectFromNaturalArea = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- natural_area: pick(data, naturalAreaProperties),
- ...pick(data, locationProperties),
- };
-};
-const getNaturalAreaFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.natural_area, naturalAreaProperties),
- };
-};
-
-const upsertOneNaturalAreaWithLocation = (state, { payload: location }) => {
- naturalAreaAdapter.upsertOne(state, getNaturalAreaFromLocationObject(location));
-};
-const upsertManyNaturalAreaWithLocation = (state, { payload: locations }) => {
- naturalAreaAdapter.upsertMany(
- state,
- locations.map((location) => getNaturalAreaFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteNaturalArea = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- naturalAreaAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const naturalAreaAdapter = createEntityAdapter({
- selectId: (naturalArea) => naturalArea.location_id,
-});
-
-const naturalAreaSlice = createSlice({
- name: 'naturalAreaReducer',
- initialState: naturalAreaAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingNaturalAreaStart: onLoadingStart,
- onLoadingNaturalAreaFail: onLoadingFail,
- getNaturalAreasSuccess: upsertManyNaturalAreaWithLocation,
- postNaturalAreaSuccess: upsertOneNaturalAreaWithLocation,
- editNaturalAreaSuccess: upsertOneNaturalAreaWithLocation,
- deleteNaturalAreaSuccess: softDeleteNaturalArea,
- },
-});
-export const {
- getNaturalAreasSuccess,
- postNaturalAreaSuccess,
- editNaturalAreaSuccess,
- onLoadingNaturalAreaStart,
- onLoadingNaturalAreaFail,
- deleteNaturalAreaSuccess,
-} = naturalAreaSlice.actions;
-export default naturalAreaSlice.reducer;
-
-export const naturalAreaReducerSelector = (state) => state.entitiesReducer[naturalAreaSlice.name];
-
-const naturalAreaSelectors = naturalAreaAdapter.getSelectors(
- (state) => state.entitiesReducer[naturalAreaSlice.name],
-);
-
-export const naturalAreaEntitiesSelector = naturalAreaSelectors.selectEntities;
-export const naturalAreasSelector = createSelector(
- [naturalAreaSelectors.selectAll, loginSelector],
- (naturalAreas, { farm_id }) => {
- return naturalAreas.filter(
- (naturalArea) => naturalArea.farm_id === farm_id && !naturalArea.deleted,
- );
- },
-);
-
-export const naturalAreaSelector = (location_id) =>
- createSelector(naturalAreaEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/residenceSlice.js b/packages/webapp/src/containers/residenceSlice.js
deleted file mode 100644
index a2b32bbaf1..0000000000
--- a/packages/webapp/src/containers/residenceSlice.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const residenceProperties = ['location_id'];
-export const getLocationObjectFromResidence = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- residence: pick(data, residenceProperties),
- ...pick(data, locationProperties),
- };
-};
-const getResidenceFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.residence, residenceProperties),
- };
-};
-
-const upsertOneResidenceWithLocation = (state, { payload: location }) => {
- residenceAdapter.upsertOne(state, getResidenceFromLocationObject(location));
-};
-const upsertManyResidenceWithLocation = (state, { payload: locations }) => {
- residenceAdapter.upsertMany(
- state,
- locations.map((location) => getResidenceFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteResidence = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- residenceAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const residenceAdapter = createEntityAdapter({
- selectId: (residence) => residence.location_id,
-});
-
-const residenceSlice = createSlice({
- name: 'residenceReducer',
- initialState: residenceAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingResidenceStart: onLoadingStart,
- onLoadingResidenceFail: onLoadingFail,
- getResidencesSuccess: upsertManyResidenceWithLocation,
- postResidenceSuccess: upsertOneResidenceWithLocation,
- editResidenceSuccess: upsertOneResidenceWithLocation,
- deleteResidenceSuccess: softDeleteResidence,
- },
-});
-export const {
- getResidencesSuccess,
- postResidenceSuccess,
- editResidenceSuccess,
- onLoadingResidenceStart,
- onLoadingResidenceFail,
- deleteResidenceSuccess,
-} = residenceSlice.actions;
-export default residenceSlice.reducer;
-
-export const residenceReducerSelector = (state) => state.entitiesReducer[residenceSlice.name];
-
-const residenceSelectors = residenceAdapter.getSelectors(
- (state) => state.entitiesReducer[residenceSlice.name],
-);
-
-export const residenceEntitiesSelector = residenceSelectors.selectEntities;
-export const residencesSelector = createSelector(
- [residenceSelectors.selectAll, loginSelector],
- (residences, { farm_id }) => {
- return residences.filter((residence) => residence.farm_id === farm_id && !residence.deleted);
- },
-);
-
-export const residenceSelector = (location_id) =>
- createSelector(residenceEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/saga.js b/packages/webapp/src/containers/saga.js
index fe0b8ebf56..a15f85c3b1 100644
--- a/packages/webapp/src/containers/saga.js
+++ b/packages/webapp/src/containers/saga.js
@@ -40,7 +40,6 @@ import {
getTasksSaga,
} from './Task/saga';
import { appVersionSelector, setAppVersion } from './appSettingSlice';
-import { getBarnsSuccess, onLoadingBarnFail, onLoadingBarnStart } from './barnSlice';
import {
getBedMethodsSuccess,
onLoadingBedMethodFail,
@@ -51,16 +50,6 @@ import {
onLoadingBroadcastMethodFail,
onLoadingBroadcastMethodStart,
} from './broadcastMethodSlice';
-import {
- getBufferZonesSuccess,
- onLoadingBufferZoneFail,
- onLoadingBufferZoneStart,
-} from './bufferZoneSlice';
-import {
- getCeremonialsSuccess,
- onLoadingCeremonialFail,
- onLoadingCeremonialStart,
-} from './ceremonialSlice';
import {
getContainerMethodsSuccess,
onLoadingContainerMethodFail,
@@ -82,54 +71,25 @@ import {
onLoadingDocumentFail,
onLoadingDocumentStart,
} from './documentSlice';
-import {
- getFarmSiteBoundarysSuccess,
- onLoadingFarmSiteBoundaryFail,
- onLoadingFarmSiteBoundaryStart,
-} from './farmSiteBoundarySlice';
-import { getFencesSuccess, onLoadingFenceFail, onLoadingFenceStart } from './fenceSlice';
-import { getFieldsSuccess, onLoadingFieldFail, onLoadingFieldStart } from './fieldSlice';
import { resetTasksFilter } from './filterSlice';
import { resetDateRange, setIsFetchingData } from './Finances/actions.js';
import { fetchAllData as fetchAllFinanceData } from './Finances/saga';
-import { getGardensSuccess, onLoadingGardenFail, onLoadingGardenStart } from './gardenSlice';
-import { getGatesSuccess, onLoadingGateFail, onLoadingGateStart } from './gateSlice';
-import {
- getGreenhousesSuccess,
- onLoadingGreenhouseFail,
- onLoadingGreenhouseStart,
-} from './greenhouseSlice';
import {
getAllManagementPlansSuccess,
getManagementPlansSuccess,
onLoadingManagementPlanFail,
onLoadingManagementPlanStart,
} from './managementPlanSlice';
-import {
- getNaturalAreasSuccess,
- onLoadingNaturalAreaFail,
- onLoadingNaturalAreaStart,
-} from './naturalAreaSlice';
import {
getPlantingManagementPlansSuccess,
onLoadingPlantingManagementPlanFail,
onLoadingPlantingManagementPlanStart,
} from './plantingManagementPlanSlice';
-import {
- getResidencesSuccess,
- onLoadingResidenceFail,
- onLoadingResidenceStart,
-} from './residenceSlice';
import {
getRowMethodsSuccess,
onLoadingRowMethodFail,
onLoadingRowMethodStart,
} from './rowMethodSlice';
-import {
- getSurfaceWatersSuccess,
- onLoadingSurfaceWaterFail,
- onLoadingSurfaceWaterStart,
-} from './surfaceWaterSlice';
import { resetTasks } from './taskSlice';
import {
isAdminSelector,
@@ -141,23 +101,9 @@ import {
userFarmsByFarmSelector,
} from './userFarmSlice';
import { logUserInfoSuccess, userLogReducerSelector } from './userLogSlice';
-import {
- getWaterValvesSuccess,
- onLoadingWaterValveFail,
- onLoadingWaterValveStart,
-} from './waterValveSlice';
-import {
- getWatercoursesSuccess,
- onLoadingWatercourseFail,
- onLoadingWatercourseStart,
-} from './watercourseSlice';
import { api, invalidateTags } from '../store/api/apiSlice';
import { locationApi } from '../store/api/locationApi';
import { FarmLibraryTags, FarmTags } from '../store/api/apiTags';
-import {
- getSoilSampleLocationsSuccess,
- onLoadingSoilSampleLocationFail,
-} from './soilSampleLocationSlice';
import { getFieldWorkTypes } from './Task/FieldWorkTask/saga';
import { getIrrigationTaskTypes } from './Task/IrrigationTaskTypes/saga';
@@ -281,7 +227,7 @@ export function* getFarmInfoSaga() {
return;
}
localStorage.setItem('role_id', userFarm.role_id);
- yield put(getLocations());
+ yield put(locationApi.endpoints.getLocations.initiate());
yield put(getManagementPlans());
} catch (e) {
console.log(e);
@@ -325,81 +271,6 @@ export function* putFarmSaga({ payload: farm }) {
}
}
-export const onLoadingLocationStart = createAction('onLoadingLocationStartSaga');
-
-export function* onLoadingLocationStartSaga() {
- yield put(onLoadingFieldStart());
- yield put(onLoadingGardenStart());
- yield put(onLoadingCeremonialStart());
- yield put(onLoadingBarnStart());
- yield put(onLoadingFarmSiteBoundaryStart());
- yield put(onLoadingGreenhouseStart());
- yield put(onLoadingSurfaceWaterStart());
- yield put(onLoadingNaturalAreaStart());
- yield put(onLoadingResidenceStart());
- yield put(onLoadingBufferZoneStart());
- yield put(onLoadingWatercourseStart());
- yield put(onLoadingFenceStart());
- yield put(onLoadingGateStart());
- yield put(onLoadingWaterValveStart());
-}
-
-export const getLocations = createAction('getLocationsSaga');
-
-export function* getLocationsSaga() {
- const { getLocationsByFarmIdUrl } = apiConfig;
- let { user_id, farm_id } = yield select(loginSelector);
- const header = getHeader(user_id, farm_id);
- try {
- yield put(onLoadingLocationStart());
- const result = yield call(axios.get, getLocationsByFarmIdUrl(farm_id), header);
- yield put(getLocationsSuccess(result.data));
- } catch (e) {
- console.log('failed to fetch fields from database');
- }
-}
-
-export const getLocationsSuccess = createAction('getLocationsSuccessSaga');
-
-export function* getLocationsSuccessSaga({ payload: locations }) {
- const locations_by_figure_type = Object.keys(figureTypeActionMap).reduce(
- (map, locationType) => Object.assign(map, { [locationType]: [] }),
- {},
- );
- for (const location of locations) {
- locations_by_figure_type[location.figure.type].push(location);
- }
- for (const figure_type in figureTypeActionMap) {
- try {
- yield put(figureTypeActionMap[figure_type].success(locations_by_figure_type[figure_type]));
- } catch (e) {
- yield put(figureTypeActionMap[figure_type].fail(e));
- console.log(e);
- }
- }
-}
-
-const figureTypeActionMap = {
- field: { success: getFieldsSuccess, fail: onLoadingFieldFail },
- garden: { success: getGardensSuccess, fail: onLoadingGardenFail },
- barn: { success: getBarnsSuccess, fail: onLoadingBarnFail },
- ceremonial_area: { success: getCeremonialsSuccess, fail: onLoadingCeremonialFail },
- farm_site_boundary: { success: getFarmSiteBoundarysSuccess, fail: onLoadingFarmSiteBoundaryFail },
- greenhouse: { success: getGreenhousesSuccess, fail: onLoadingGreenhouseFail },
- surface_water: { success: getSurfaceWatersSuccess, fail: onLoadingSurfaceWaterFail },
- natural_area: { success: getNaturalAreasSuccess, fail: onLoadingNaturalAreaFail },
- residence: { success: getResidencesSuccess, fail: onLoadingResidenceFail },
- buffer_zone: { success: getBufferZonesSuccess, fail: onLoadingBufferZoneFail },
- watercourse: { success: getWatercoursesSuccess, fail: onLoadingWatercourseFail },
- fence: { success: getFencesSuccess, fail: onLoadingFenceFail },
- gate: { success: getGatesSuccess, fail: onLoadingGateFail },
- water_valve: { success: getWaterValvesSuccess, fail: onLoadingWaterValveFail },
- soil_sample_location: {
- success: getSoilSampleLocationsSuccess,
- fail: onLoadingSoilSampleLocationFail,
- },
-};
-
export function* onLoadingManagementPlanAndPlantingMethodStartSaga() {
yield put(onLoadingBroadcastMethodStart());
yield put(onLoadingBedMethodStart());
@@ -550,7 +421,7 @@ export const getCropsAndManagementPlans = createAction('getCropsAndManagementPla
export function* getCropsAndManagementPlansSaga() {
try {
- yield all([call(getLocationsSaga), call(getCropsSaga)]);
+ yield all([put(locationApi.endpoints.getLocations.initiate()), call(getCropsSaga)]);
yield call(getCropVarietiesSaga);
yield call(getManagementPlansSaga);
} catch (e) {
@@ -731,15 +602,12 @@ export default function* getFarmIdSaga() {
yield takeLeading(updateUser.type, updateUserSaga);
yield takeLatest(getFarmInfo.type, getFarmInfoSaga);
yield takeLeading(putFarm.type, putFarmSaga);
- yield takeLatest(getLocations.type, getLocationsSaga);
yield takeLatest(getManagementPlansByDate.type, getManagementPlansSaga);
yield takeLatest(getManagementPlans.type, getManagementPlansSaga);
yield takeLatest(getCrops.type, getCropsSaga);
yield takeLatest(getCropVarieties.type, getCropVarietiesSaga);
yield takeLatest(selectFarm.type, selectFarmSaga);
yield takeLeading(selectFarmAndFetchAll.type, selectFarmAndFetchAllSaga);
- yield takeLatest(onLoadingLocationStart.type, onLoadingLocationStartSaga);
- yield takeLatest(getLocationsSuccess.type, getLocationsSuccessSaga);
yield takeLatest(getDocuments.type, getDocumentsSaga);
yield takeLatest(
getManagementPlanAndPlantingMethodSuccess.type,
diff --git a/packages/webapp/src/containers/soilSampleLocationSlice.js b/packages/webapp/src/containers/soilSampleLocationSlice.js
deleted file mode 100644
index e82619088c..0000000000
--- a/packages/webapp/src/containers/soilSampleLocationSlice.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, locationProperties, pointProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-const soilSampleLocationProperties = ['location_id'];
-export const getLocationObjectFromSoilSampleLocation = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- point: pick(data, pointProperties),
- },
- soil_sample_location: pick(data, soilSampleLocationProperties),
- ...pick(data, locationProperties),
- };
-};
-const getSoilSampleLocationFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.point, pointProperties),
- ...pick(location.soil_sample_location, soilSampleLocationProperties),
- };
-};
-
-const upsertOneSoilSampleLocationWithLocation = (state, { payload: location }) => {
- soilSampleLocationAdapter.upsertOne(state, getSoilSampleLocationFromLocationObject(location));
-};
-const upsertManySoilSampleLocationWithLocation = (state, { payload: locations }) => {
- soilSampleLocationAdapter.upsertMany(
- state,
- locations.map((location) => getSoilSampleLocationFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteSoilSampleLocation = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- soilSampleLocationAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const soilSampleLocationAdapter = createEntityAdapter({
- selectId: (soil_sample_location) => soil_sample_location.location_id,
-});
-
-const soilSampleLocationSlice = createSlice({
- name: 'soilSampleLocationReducer',
- initialState: soilSampleLocationAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingSoilSampleLocationStart: onLoadingStart,
- onLoadingSoilSampleLocationFail: onLoadingFail,
- getSoilSampleLocationsSuccess: upsertManySoilSampleLocationWithLocation,
- postSoilSampleLocationSuccess: upsertOneSoilSampleLocationWithLocation,
- editSoilSampleLocationSuccess: upsertOneSoilSampleLocationWithLocation,
- deleteSoilSampleLocationSuccess: softDeleteSoilSampleLocation,
- },
-});
-export const {
- getSoilSampleLocationsSuccess,
- postSoilSampleLocationSuccess,
- editSoilSampleLocationSuccess,
- onLoadingSoilSampleLocationStart,
- onLoadingSoilSampleLocationFail,
- deleteSoilSampleLocationSuccess,
-} = soilSampleLocationSlice.actions;
-export default soilSampleLocationSlice.reducer;
-
-export const soilSampleLocationReducerSelector = (state) =>
- state.entitiesReducer[soilSampleLocationSlice.name];
-
-const soilSampleLocationSelectors = soilSampleLocationAdapter.getSelectors(
- (state) => state.entitiesReducer[soilSampleLocationSlice.name],
-);
-
-export const soilSampleLocationEntitiesSelector = soilSampleLocationSelectors.selectEntities;
-export const soilSampleLocationsSelector = createSelector(
- [soilSampleLocationSelectors.selectAll, loginSelector],
- (soilSampleLocations, { farm_id }) => {
- return soilSampleLocations.filter(
- (soil_sample_location) =>
- soil_sample_location.farm_id === farm_id && !soil_sample_location.deleted,
- );
- },
-);
-
-export const soilSampleLocationSelector = (location_id) =>
- createSelector(soilSampleLocationEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/surfaceWaterSlice.js b/packages/webapp/src/containers/surfaceWaterSlice.js
deleted file mode 100644
index d0840c16f3..0000000000
--- a/packages/webapp/src/containers/surfaceWaterSlice.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { areaProperties, figureProperties, locationProperties } from './constants';
-import { pick } from '../util/pick';
-
-const surfaceWaterProperties = ['used_for_irrigation', 'location_id'];
-export const getLocationObjectFromSurfaceWater = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- area: pick(data, areaProperties),
- },
- surface_water: pick(data, surfaceWaterProperties),
- ...pick(data, locationProperties),
- };
-};
-const getSurfaceWaterFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.area, areaProperties),
- ...pick(location.surface_water, surfaceWaterProperties),
- };
-};
-
-const upsertOneSurfaceWaterWithLocation = (state, { payload: location }) => {
- surfaceWaterAdapter.upsertOne(state, getSurfaceWaterFromLocationObject(location));
-};
-const upsertManySurfaceWaterWithLocation = (state, { payload: locations }) => {
- surfaceWaterAdapter.upsertMany(
- state,
- locations.map((location) => getSurfaceWaterFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteSurfaceWater = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- surfaceWaterAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const surfaceWaterAdapter = createEntityAdapter({
- selectId: (surfaceWater) => surfaceWater.location_id,
-});
-
-const surfaceWaterSlice = createSlice({
- name: 'surfaceWaterReducer',
- initialState: surfaceWaterAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingSurfaceWaterStart: onLoadingStart,
- onLoadingSurfaceWaterFail: onLoadingFail,
- getSurfaceWatersSuccess: upsertManySurfaceWaterWithLocation,
- postSurfaceWaterSuccess: upsertOneSurfaceWaterWithLocation,
- editSurfaceWaterSuccess: upsertOneSurfaceWaterWithLocation,
- deleteSurfaceWaterSuccess: softDeleteSurfaceWater,
- },
-});
-export const {
- getSurfaceWatersSuccess,
- postSurfaceWaterSuccess,
- editSurfaceWaterSuccess,
- onLoadingSurfaceWaterStart,
- onLoadingSurfaceWaterFail,
- deleteSurfaceWaterSuccess,
-} = surfaceWaterSlice.actions;
-export default surfaceWaterSlice.reducer;
-
-export const surfaceWaterReducerSelector = (state) => state.entitiesReducer[surfaceWaterSlice.name];
-
-const surfaceWaterSelectors = surfaceWaterAdapter.getSelectors(
- (state) => state.entitiesReducer[surfaceWaterSlice.name],
-);
-
-export const surfaceWaterEntitiesSelector = surfaceWaterSelectors.selectEntities;
-export const surfaceWatersSelector = createSelector(
- [surfaceWaterSelectors.selectAll, loginSelector],
- (surfaceWaters, { farm_id }) => {
- return surfaceWaters.filter(
- (surfaceWater) => surfaceWater.farm_id === farm_id && !surfaceWater.deleted,
- );
- },
-);
-
-export const surfaceWaterSelector = (location_id) =>
- createSelector(surfaceWaterEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/waterValveSlice.js b/packages/webapp/src/containers/waterValveSlice.js
deleted file mode 100644
index 44b057e966..0000000000
--- a/packages/webapp/src/containers/waterValveSlice.js
+++ /dev/null
@@ -1,92 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, locationProperties, pointProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-const waterValveProperties = ['source', 'flow_rate', 'flow_rate_unit', 'location_id'];
-export const getLocationObjectFromWaterValve = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- point: pick(data, pointProperties),
- },
- water_valve: pick(data, waterValveProperties),
- ...pick(data, locationProperties),
- };
-};
-const getWaterValveFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.point, pointProperties),
- ...pick(location.water_valve, waterValveProperties),
- };
-};
-
-const upsertOneWaterValveWithLocation = (state, { payload: location }) => {
- waterValveAdapter.upsertOne(state, getWaterValveFromLocationObject(location));
-};
-const upsertManyWaterValveWithLocation = (state, { payload: locations }) => {
- waterValveAdapter.upsertMany(
- state,
- locations.map((location) => getWaterValveFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteWaterValve = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- waterValveAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const waterValveAdapter = createEntityAdapter({
- selectId: (waterValve) => waterValve.location_id,
-});
-
-const waterValveSlice = createSlice({
- name: 'waterValveReducer',
- initialState: waterValveAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingWaterValveStart: onLoadingStart,
- onLoadingWaterValveFail: onLoadingFail,
- getWaterValvesSuccess: upsertManyWaterValveWithLocation,
- postWaterValveSuccess: upsertOneWaterValveWithLocation,
- editWaterValveSuccess: upsertOneWaterValveWithLocation,
- deleteWaterValveSuccess: softDeleteWaterValve,
- },
-});
-export const {
- getWaterValvesSuccess,
- postWaterValveSuccess,
- editWaterValveSuccess,
- onLoadingWaterValveStart,
- onLoadingWaterValveFail,
- deleteWaterValveSuccess,
-} = waterValveSlice.actions;
-export default waterValveSlice.reducer;
-
-export const waterValveReducerSelector = (state) => state.entitiesReducer[waterValveSlice.name];
-
-const waterValveSelectors = waterValveAdapter.getSelectors(
- (state) => state.entitiesReducer[waterValveSlice.name],
-);
-
-export const waterValveEntitiesSelector = waterValveSelectors.selectEntities;
-export const waterValvesSelector = createSelector(
- [waterValveSelectors.selectAll, loginSelector],
- (waterValves, { farm_id }) => {
- return waterValves.filter(
- (waterValve) => waterValve.farm_id === farm_id && !waterValve.deleted,
- );
- },
-);
-
-export const waterValveSelector = (location_id) =>
- createSelector(waterValveEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/containers/watercourseSlice.js b/packages/webapp/src/containers/watercourseSlice.js
deleted file mode 100644
index 73db123465..0000000000
--- a/packages/webapp/src/containers/watercourseSlice.js
+++ /dev/null
@@ -1,116 +0,0 @@
-import { createEntityAdapter, createSlice } from '@reduxjs/toolkit';
-import { figureProperties, lineProperties, locationProperties } from './constants';
-import { loginSelector, onLoadingFail, onLoadingStart, onLoadingSuccess } from './userFarmSlice';
-import { createSelector } from 'reselect';
-import { pick } from '../util/pick';
-
-export const watercourseEnum = {
- farm_id: 'farm_id',
- name: 'name',
- figure_id: 'figure_id',
- type: 'type',
- location_id: 'location_id',
- notes: 'notes',
- length: 'length',
- width: 'width',
- line_points: 'line_points',
- length_unit: 'length_unit',
- width_unit: 'width_unit',
- includes_riparian_buffer: 'includes_riparian_buffer',
- used_for_irrigation: 'used_for_irrigation',
- buffer_width: 'buffer_width',
- buffer_width_unit: 'buffer_width_unit',
-};
-
-const watercourseProperties = [
- 'used_for_irrigation',
- 'includes_riparian_buffer',
- 'buffer_width',
- 'buffer_width_unit',
- 'location_id',
-];
-export const getLocationObjectFromWatercourse = (data) => {
- return {
- figure: {
- ...pick(data, figureProperties),
- line: pick(data, lineProperties),
- },
- watercourse: pick(data, watercourseProperties),
- ...pick(data, locationProperties),
- };
-};
-const getWatercourseFromLocationObject = (location) => {
- return {
- ...pick(location, locationProperties),
- ...pick(location.figure, figureProperties),
- ...pick(location.figure.line, lineProperties),
- ...pick(location.watercourse, watercourseProperties),
- };
-};
-
-const upsertOneWatercourseWithLocation = (state, { payload: location }) => {
- watercourseAdapter.upsertOne(state, getWatercourseFromLocationObject(location));
-};
-const upsertManyWatercourseWithLocation = (state, { payload: locations }) => {
- watercourseAdapter.upsertMany(
- state,
- locations.map((location) => getWatercourseFromLocationObject(location)),
- );
- onLoadingSuccess(state);
-};
-const softDeleteWatercourse = (state, { payload: location_id }) => {
- state.loading = false;
- state.error = null;
- state.loaded = true;
- watercourseAdapter.updateOne(state, { id: location_id, changes: { deleted: true } });
-};
-
-const watercourseAdapter = createEntityAdapter({
- selectId: (watercourse) => watercourse.location_id,
-});
-
-const watercourseSlice = createSlice({
- name: 'watercourseReducer',
- initialState: watercourseAdapter.getInitialState({
- loading: false,
- error: undefined,
- location_id: undefined,
- loaded: false,
- }),
- reducers: {
- onLoadingWatercourseStart: onLoadingStart,
- onLoadingWatercourseFail: onLoadingFail,
- getWatercoursesSuccess: upsertManyWatercourseWithLocation,
- postWatercourseSuccess: upsertOneWatercourseWithLocation,
- editWatercourseSuccess: upsertOneWatercourseWithLocation,
- deleteWatercourseSuccess: softDeleteWatercourse,
- },
-});
-export const {
- getWatercoursesSuccess,
- postWatercourseSuccess,
- editWatercourseSuccess,
- onLoadingWatercourseStart,
- onLoadingWatercourseFail,
- deleteWatercourseSuccess,
-} = watercourseSlice.actions;
-export default watercourseSlice.reducer;
-
-export const watercourseReducerSelector = (state) => state.entitiesReducer[watercourseSlice.name];
-
-const watercourseSelectors = watercourseAdapter.getSelectors(
- (state) => state.entitiesReducer[watercourseSlice.name],
-);
-
-export const watercourseEntitiesSelector = watercourseSelectors.selectEntities;
-export const watercoursesSelector = createSelector(
- [watercourseSelectors.selectAll, loginSelector],
- (watercourses, { farm_id }) => {
- return watercourses.filter(
- (watercourse) => watercourse.farm_id === farm_id && !watercourse.deleted,
- );
- },
-);
-
-export const watercourseSelector = (location_id) =>
- createSelector(watercourseEntitiesSelector, (entities) => entities[location_id]);
diff --git a/packages/webapp/src/main.jsx b/packages/webapp/src/main.jsx
index c0564e7156..7ef6cacaea 100644
--- a/packages/webapp/src/main.jsx
+++ b/packages/webapp/src/main.jsx
@@ -26,23 +26,8 @@ import peopleSaga from './containers/Profile/People/saga';
import signUpSaga from './containers/CustomSignUp/saga';
import resetUserPasswordSaga from './containers/PasswordResetAccount/saga';
import outroSaga from './containers/Outro/saga';
-import fieldLocationSaga from './containers/LocationDetails/AreaDetails/FieldDetailForm/saga';
import documentSaga from './containers/Documents/saga';
import managementPlanSaga from './containers/Crop/saga';
-import gardenSaga from './containers/LocationDetails/AreaDetails/GardenDetailForm/saga';
-import gateSaga from './containers/LocationDetails/PointDetails/GateDetailForm/saga';
-import waterValveSaga from './containers/LocationDetails/PointDetails/WaterValveDetailForm/saga';
-import naturalAreaSaga from './containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/saga';
-import barnSaga from './containers/LocationDetails/AreaDetails/BarnDetailForm/saga';
-import surfaceWaterSaga from './containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/saga';
-import greenhouseSaga from './containers/LocationDetails/AreaDetails/GreenhouseDetailForm/saga';
-import ceremonialSaga from './containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/saga';
-import residenceSaga from './containers/LocationDetails/AreaDetails/ResidenceDetailForm/saga';
-import farmSiteBoundarySaga from './containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/saga';
-import fenceSaga from './containers/LocationDetails/LineDetails/FenceDetailForm/saga';
-import bufferZoneSaga from './containers/LocationDetails/LineDetails/BufferZoneDetailForm/saga';
-import watercourseSaga from './containers/LocationDetails/LineDetails/WatercourseDetailForm/saga';
-import soilSampleLocationLocationSaga from './containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/saga';
import financeSaga from './containers/Finances/saga';
import varietalSaga from './containers/AddCropVariety/saga';
import insightSaga from './containers/Insights/saga';
@@ -99,22 +84,7 @@ sagaMiddleware.run(peopleSaga);
sagaMiddleware.run(signUpSaga);
sagaMiddleware.run(resetUserPasswordSaga);
sagaMiddleware.run(outroSaga);
-sagaMiddleware.run(fieldLocationSaga);
sagaMiddleware.run(managementPlanSaga);
-sagaMiddleware.run(gardenSaga);
-sagaMiddleware.run(gateSaga);
-sagaMiddleware.run(barnSaga);
-sagaMiddleware.run(surfaceWaterSaga);
-sagaMiddleware.run(bufferZoneSaga);
-sagaMiddleware.run(naturalAreaSaga);
-sagaMiddleware.run(greenhouseSaga);
-sagaMiddleware.run(residenceSaga);
-sagaMiddleware.run(ceremonialSaga);
-sagaMiddleware.run(waterValveSaga);
-sagaMiddleware.run(farmSiteBoundarySaga);
-sagaMiddleware.run(fenceSaga);
-sagaMiddleware.run(watercourseSaga);
-sagaMiddleware.run(soilSampleLocationLocationSaga);
sagaMiddleware.run(financeSaga);
sagaMiddleware.run(varietalSaga);
sagaMiddleware.run(insightSaga);
diff --git a/packages/webapp/src/routes/BarnDetailsRoutes.jsx b/packages/webapp/src/routes/BarnDetailsRoutes.jsx
deleted file mode 100644
index 76504ff12f..0000000000
--- a/packages/webapp/src/routes/BarnDetailsRoutes.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditBarnDetailForm from '../containers/LocationDetails/AreaDetails/BarnDetailForm/EditBarn';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function BarnDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && } />}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/BufferZoneDetailsRoutes.jsx b/packages/webapp/src/routes/BufferZoneDetailsRoutes.jsx
deleted file mode 100644
index 473865174c..0000000000
--- a/packages/webapp/src/routes/BufferZoneDetailsRoutes.jsx
+++ /dev/null
@@ -1,37 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditBufferZoneDetailForm from '../containers/LocationDetails/LineDetails/BufferZoneDetailForm/EditBufferZone';
-import LocationManagementPlan from '../containers/LocationDetails/LocationManagementPlan';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
-import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
-
-export default function BufferZoneDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- } />
- }
- />
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/CeremonialAreaDetailsRoutes.jsx b/packages/webapp/src/routes/CeremonialAreaDetailsRoutes.jsx
deleted file mode 100644
index 5c8fde635a..0000000000
--- a/packages/webapp/src/routes/CeremonialAreaDetailsRoutes.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditCeremonialAreaForm from '../containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/EditCeremonialArea';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function CeremonialAreaDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/FarmSiteBoundaryDetailsRoutes.jsx b/packages/webapp/src/routes/FarmSiteBoundaryDetailsRoutes.jsx
deleted file mode 100644
index 29d2f74463..0000000000
--- a/packages/webapp/src/routes/FarmSiteBoundaryDetailsRoutes.jsx
+++ /dev/null
@@ -1,39 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditFarmSiteBoundaryDetailForm from '../containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/EditFarmSiteBoundary';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
-import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
-
-export default function FarmSiteBoundaryDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- }
- />
- }
- />
- >
- );
-}
diff --git a/packages/webapp/src/routes/FenceDetailsRoutes.jsx b/packages/webapp/src/routes/FenceDetailsRoutes.jsx
deleted file mode 100644
index bc8f5d8d99..0000000000
--- a/packages/webapp/src/routes/FenceDetailsRoutes.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditFenceDetailForm from '../containers/LocationDetails/LineDetails/FenceDetailForm/EditFence';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function FenceDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && (
- } />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/FieldDetailsRoutes.jsx b/packages/webapp/src/routes/FieldDetailsRoutes.jsx
deleted file mode 100644
index 7c493417bb..0000000000
--- a/packages/webapp/src/routes/FieldDetailsRoutes.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditFieldDetailForm from '../containers/LocationDetails/AreaDetails/FieldDetailForm/EditField';
-import LocationManagementPlan from '../containers/LocationDetails/LocationManagementPlan';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
-import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
-
-export default function FieldDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && (
- } />
- )}
- } />
- } />
- }
- />
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/GardenDetailsRoutes.jsx b/packages/webapp/src/routes/GardenDetailsRoutes.jsx
deleted file mode 100644
index 810493aa7f..0000000000
--- a/packages/webapp/src/routes/GardenDetailsRoutes.jsx
+++ /dev/null
@@ -1,29 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditGardenDetailForm from '../containers/LocationDetails/AreaDetails/GardenDetailForm/EditGarden';
-import LocationManagementPlan from '../containers/LocationDetails/LocationManagementPlan';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
-import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
-
-export default function GardenDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && (
- } />
- )}
- } />
- } />
- }
- />
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/GateDetailsRoutes.jsx b/packages/webapp/src/routes/GateDetailsRoutes.jsx
deleted file mode 100644
index 6e6ace1955..0000000000
--- a/packages/webapp/src/routes/GateDetailsRoutes.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditGateDetailForm from '../containers/LocationDetails/PointDetails/GateDetailForm/EditGate';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function GateDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && } />}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/GreenhouseDetailsRoutes.jsx b/packages/webapp/src/routes/GreenhouseDetailsRoutes.jsx
deleted file mode 100644
index d30c16ecc6..0000000000
--- a/packages/webapp/src/routes/GreenhouseDetailsRoutes.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditGreenhouseDetailForm from '../containers/LocationDetails/AreaDetails/GreenhouseDetailForm/EditGreenhouse';
-import LocationManagementPlan from '../containers/LocationDetails/LocationManagementPlan';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
-import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
-
-export default function GreenhouseDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- } />
- )}
- } />
- } />
- }
- />
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/LocationDetailsRoutes.jsx b/packages/webapp/src/routes/LocationDetailsRoutes.jsx
new file mode 100644
index 0000000000..f09d0a2711
--- /dev/null
+++ b/packages/webapp/src/routes/LocationDetailsRoutes.jsx
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+/* eslint-disable react/no-children-prop */
+import { Route } from 'react-router-dom';
+import { useSelector } from 'react-redux';
+import { isAdminSelector } from '../containers/userFarmSlice';
+import LocationTasks from '../containers/LocationDetails/LocationTasks';
+import LocationManagementPlan from '../containers/LocationDetails/LocationManagementPlan';
+import LocationFieldTechnology from '../containers/LocationDetails/LocationFieldTechnology';
+import LocationIrrigation from '../containers/LocationDetails/LocationIrrigation';
+import EditLocationDetailForm from '../containers/LocationDetails/EditLocationDetailForm';
+
+// Location route configuration - maps location type to enabled tabs
+export const locationRouteConfig = {
+ field: {
+ enabledTabs: ['details', 'crops', 'tasks', 'field_technology', 'irrigation'],
+ },
+ garden: {
+ enabledTabs: ['details', 'crops', 'tasks', 'field_technology', 'irrigation'],
+ },
+ greenhouse: {
+ enabledTabs: ['details', 'crops', 'tasks', 'field_technology', 'irrigation'],
+ },
+ barn: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ gate: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ water_valve: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ soil_sample_location: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ buffer_zone: {
+ enabledTabs: ['details', 'crops', 'tasks', 'field_technology', 'irrigation'],
+ },
+ watercourse: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ fence: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ natural_area: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ residence: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ surface_water: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ ceremonial_area: {
+ enabledTabs: ['details', 'tasks'],
+ },
+ farm_site_boundary: {
+ enabledTabs: ['details', 'tasks', 'field_technology', 'irrigation'],
+ },
+};
+
+export const allLocationTypes = Object.keys(locationRouteConfig);
+
+export default function LocationDetailsRoutes({ locationType }) {
+ const isAdmin = useSelector(isAdminSelector);
+ const config = locationRouteConfig[locationType];
+
+ if (!config) {
+ return null;
+ }
+
+ const prefix = `/${locationType}/:location_id`;
+
+ return (
+ <>
+ }
+ />
+ {isAdmin && (
+ }
+ />
+ )}
+
+ {config.enabledTabs.includes('tasks') && (
+ } />
+ )}
+
+ {config.enabledTabs.includes('crops') && (
+ } />
+ )}
+
+ {config.enabledTabs.includes('field_technology') && (
+ } />
+ )}
+
+ {config.enabledTabs.includes('irrigation') && (
+ } />
+ )}
+ >
+ );
+}
diff --git a/packages/webapp/src/routes/NaturalAreaDetailsRoutes.jsx b/packages/webapp/src/routes/NaturalAreaDetailsRoutes.jsx
deleted file mode 100644
index 50a9152a22..0000000000
--- a/packages/webapp/src/routes/NaturalAreaDetailsRoutes.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditNaturalAreaDetailForm from '../containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/EditNaturalArea';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function NaturalAreaDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/ResidenceDetailsRoutes.jsx b/packages/webapp/src/routes/ResidenceDetailsRoutes.jsx
deleted file mode 100644
index c339a08516..0000000000
--- a/packages/webapp/src/routes/ResidenceDetailsRoutes.jsx
+++ /dev/null
@@ -1,19 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditResidenceDetailForm from '../containers/LocationDetails/AreaDetails/ResidenceDetailForm/EditResidence';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function ResidenceDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- } />
- {isAdmin && (
- } />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/SoilSampleLocationDetailsRoutes.jsx b/packages/webapp/src/routes/SoilSampleLocationDetailsRoutes.jsx
deleted file mode 100644
index b88fa8dd95..0000000000
--- a/packages/webapp/src/routes/SoilSampleLocationDetailsRoutes.jsx
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2025 LiteFarm.org
- * This file is part of LiteFarm.
- *
- * LiteFarm is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * LiteFarm is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details, see .
- */
-
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditSoilSampleLocationDetailForm from '../containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/EditSoilSampleLocation';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function SoilSampleLocationDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/SurfaceWaterDetailsRoutes.jsx b/packages/webapp/src/routes/SurfaceWaterDetailsRoutes.jsx
deleted file mode 100644
index 670b383d54..0000000000
--- a/packages/webapp/src/routes/SurfaceWaterDetailsRoutes.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditSurfaceWaterDetailForm from '../containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/EditSurfaceWater';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function SurfaceWaterDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/WaterValveDetailsRoutes.jsx b/packages/webapp/src/routes/WaterValveDetailsRoutes.jsx
deleted file mode 100644
index 018ebf333b..0000000000
--- a/packages/webapp/src/routes/WaterValveDetailsRoutes.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditWaterValveDetailForm from '../containers/LocationDetails/PointDetails/WaterValveDetailForm/EditWaterValve';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function WaterValveDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/WatercourseDetailsRoutes.jsx b/packages/webapp/src/routes/WatercourseDetailsRoutes.jsx
deleted file mode 100644
index 7387aea16f..0000000000
--- a/packages/webapp/src/routes/WatercourseDetailsRoutes.jsx
+++ /dev/null
@@ -1,27 +0,0 @@
-/* eslint-disable react/no-children-prop */
-import { Route } from 'react-router-dom';
-import EditWatercourseDetailForm from '../containers/LocationDetails/LineDetails/WatercourseDetailForm/EditWatercourse';
-import { useSelector } from 'react-redux';
-import { isAdminSelector } from '../containers/userFarmSlice';
-import LocationTasks from '../containers/LocationDetails/LocationTasks';
-
-export default function WatercourseDetailsRoutes() {
- const isAdmin = useSelector(isAdminSelector);
- return (
- <>
- }
- />
- {isAdmin && (
- }
- />
- )}
- } />
- >
- );
-}
diff --git a/packages/webapp/src/routes/index.jsx b/packages/webapp/src/routes/index.jsx
index 803755d1a0..2e85091412 100644
--- a/packages/webapp/src/routes/index.jsx
+++ b/packages/webapp/src/routes/index.jsx
@@ -63,88 +63,20 @@ const Prices = React.lazy(() => import('../containers/Insights/Prices'));
const TapeRoutes = React.lazy(() => import('./TapeRoutes'));
const ExpiredTokenScreen = React.lazy(() => import('../containers/ExpiredTokenScreen'));
const Map = React.lazy(() => import('../containers/Map'));
-const PostFarmSiteBoundaryForm = React.lazy(() =>
- import(
- '../containers/LocationDetails/AreaDetails/FarmSiteBoundaryDetailForm/PostFarmSiteBoundary'
- ),
-);
-const FarmSiteBoundaryDetails = React.lazy(() => import('./FarmSiteBoundaryDetailsRoutes'));
-
-const PostFieldForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/FieldDetailForm/PostField'),
-);
-const FieldDetails = React.lazy(() => import('./FieldDetailsRoutes'));
-
-const PostGardenForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/GardenDetailForm/PostGarden'),
-);
-const GardenDetails = React.lazy(() => import('./GardenDetailsRoutes'));
-
-const PostGateForm = React.lazy(() =>
- import('../containers/LocationDetails/PointDetails/GateDetailForm/PostGate'),
-);
-const GateDetails = React.lazy(() => import('./GateDetailsRoutes'));
-
-const PostWaterValveForm = React.lazy(() =>
- import('../containers/LocationDetails/PointDetails/WaterValveDetailForm/PostWaterValve'),
-);
-const WaterValveDetails = React.lazy(() => import('./WaterValveDetailsRoutes'));
-
-const PostSoilSampleLocationForm = React.lazy(() =>
- import(
- '../containers/LocationDetails/PointDetails/SoilSampleLocationDetailForm/PostSoilSampleLocation'
- ),
-);
-
-const SoilSampleLocationDetails = React.lazy(() => import('./SoilSampleLocationDetailsRoutes'));
-
-const PostBarnForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/BarnDetailForm/PostBarn'),
-);
-const BarnDetails = React.lazy(() => import('./BarnDetailsRoutes'));
-
-const PostNaturalAreaForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/NaturalAreaDetailForm/PostNaturalArea'),
-);
-const NaturalAreaDetails = React.lazy(() => import('./NaturalAreaDetailsRoutes'));
-const PostSurfaceWaterForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/SurfaceWaterDetailForm/PostSurfaceWater'),
-);
-const SurfaceWaterDetails = React.lazy(() => import('./SurfaceWaterDetailsRoutes'));
+const LocationDetailsRoutes = React.lazy(() => import('./LocationDetailsRoutes'));
-const PostResidenceForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/ResidenceDetailForm/PostResidence'),
-);
-const ResidenceDetails = React.lazy(() => import('./ResidenceDetailsRoutes'));
-
-const PostCeremonialForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/CeremonialAreaDetailForm/PostCeremonialArea'),
-);
-const CeremonialAreaDetails = React.lazy(() => import('./CeremonialAreaDetailsRoutes'));
+// Import config separately to access allLocationTypes at render time
+import { allLocationTypes as allLocationTypesConfig } from './LocationDetailsRoutes.jsx';
+const allLocationTypes = allLocationTypesConfig;
-const PostGreenhouseForm = React.lazy(() =>
- import('../containers/LocationDetails/AreaDetails/GreenhouseDetailForm/PostGreenhouse'),
+const PostLocationDetailForm = React.lazy(
+ () => import('../containers/LocationDetails/PostLocationDetailForm'),
);
-const GreenhouseDetails = React.lazy(() => import('./GreenhouseDetailsRoutes'));
const CropManagement = React.lazy(() => import('../containers/Crop/CropManagement'));
const CropDetail = React.lazy(() => import('../containers/Crop/CropDetail/index'));
-const PostFenceForm = React.lazy(() =>
- import('../containers/LocationDetails/LineDetails/FenceDetailForm/PostFence'),
-);
-const FenceDetails = React.lazy(() => import('./FenceDetailsRoutes'));
-
-const PostBufferZoneForm = React.lazy(() =>
- import('../containers/LocationDetails/LineDetails/BufferZoneDetailForm/PostBufferZone'),
-);
-const BufferZoneDetails = React.lazy(() => import('./BufferZoneDetailsRoutes'));
-
-const PostWatercourseForm = React.lazy(() =>
- import('../containers/LocationDetails/LineDetails/WatercourseDetailForm/PostWatercourse'),
-);
-const WatercourseDetails = React.lazy(() => import('./WatercourseDetailsRoutes'));
const AddSensorsForm = React.lazy(() => import('../containers/AddSensors'));
const CropCatalogue = React.lazy(() => import('../containers/CropCatalogue'));
@@ -153,34 +85,34 @@ const AddCrop = React.lazy(() => import('../containers/AddCropVariety/AddCropVar
const EditCrop = React.lazy(() => import('../containers/EditCropVariety'));
const ComplianceInfo = React.lazy(() => import('../containers/AddCropVariety/ComplianceInfo'));
const AddNewCrop = React.lazy(() => import('../containers/AddNewCrop'));
-const PlantingLocation = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/PlantingLocation'),
+const PlantingLocation = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/PlantingLocation'),
);
const Transplant = React.lazy(() => import('../containers/Crop/AddManagementPlan/Transplant'));
const PlantingDate = React.lazy(() => import('../containers/Crop/AddManagementPlan/PlantingDate'));
-const PlantingMethod = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/PlantingMethod'),
+const PlantingMethod = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/PlantingMethod'),
);
-const PlantInContainer = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/PlantInContainer'),
+const PlantInContainer = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/PlantInContainer'),
);
-const PlantBroadcast = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/BroadcastPlan'),
+const PlantBroadcast = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/BroadcastPlan'),
);
const BedPlan = React.lazy(() => import('../containers/Crop/AddManagementPlan/BedPlan/BedPlan'));
-const BedPlanGuidance = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/BedPlan/BedPlanGuidance'),
+const BedPlanGuidance = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/BedPlan/BedPlanGuidance'),
);
-const ManagementPlanName = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/ManagementPlanName'),
+const ManagementPlanName = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/ManagementPlanName'),
);
const RowMethod = React.lazy(() => import('../containers/Crop/AddManagementPlan/RowMethod'));
-const RowMethodGuidance = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/RowMethod/RowGuidance'),
+const RowMethodGuidance = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/RowMethod/RowGuidance'),
);
-const PlantedAlready = React.lazy(() =>
- import('../containers/Crop/AddManagementPlan/PlantedAlready'),
+const PlantedAlready = React.lazy(
+ () => import('../containers/Crop/AddManagementPlan/PlantedAlready'),
);
const Documents = React.lazy(() => import('../containers/Documents'));
@@ -189,60 +121,63 @@ const EditDocument = React.lazy(() => import('../containers/Documents/Edit'));
const AddDocument = React.lazy(() => import('../containers/Documents/Add'));
const MainDocument = React.lazy(() => import('../containers/Documents/Main'));
-const CertificationReportingPeriod = React.lazy(() =>
- import('../containers/Certifications/ReportingPeriod'),
+const CertificationReportingPeriod = React.lazy(
+ () => import('../containers/Certifications/ReportingPeriod'),
);
const CertificationSurvey = React.lazy(() => import('../containers/Certifications/Survey'));
-const InterestedOrganic = React.lazy(() =>
- import('../containers/OrganicCertifierSurvey/InterestedOrganic/UpdateInterestedOrganic'),
+const InterestedOrganic = React.lazy(
+ () => import('../containers/OrganicCertifierSurvey/InterestedOrganic/UpdateInterestedOrganic'),
);
-const CertificationSelection = React.lazy(() =>
- import(
- '../containers/OrganicCertifierSurvey/CertificationSelection/UpdateCertificationSelection'
- ),
+const CertificationSelection = React.lazy(
+ () =>
+ import(
+ '../containers/OrganicCertifierSurvey/CertificationSelection/UpdateCertificationSelection'
+ ),
);
-const CertifierSelectionMenu = React.lazy(() =>
- import(
- '../containers/OrganicCertifierSurvey/CertifierSelectionMenu/UpdateCertifierSelectionMenu'
- ),
+const CertifierSelectionMenu = React.lazy(
+ () =>
+ import(
+ '../containers/OrganicCertifierSurvey/CertifierSelectionMenu/UpdateCertifierSelectionMenu'
+ ),
);
-const SetCertificationSummary = React.lazy(() =>
- import(
- '../containers/OrganicCertifierSurvey/SetCertificationSummary/UpdateSetCertificationSummary'
- ),
+const SetCertificationSummary = React.lazy(
+ () =>
+ import(
+ '../containers/OrganicCertifierSurvey/SetCertificationSummary/UpdateSetCertificationSummary'
+ ),
);
-const RequestCertifier = React.lazy(() =>
- import('../containers/OrganicCertifierSurvey/RequestCertifier/UpdateRequestCertifier'),
+const RequestCertifier = React.lazy(
+ () => import('../containers/OrganicCertifierSurvey/RequestCertifier/UpdateRequestCertifier'),
);
-const ViewCertification = React.lazy(() =>
- import('../containers/OrganicCertifierSurvey/ViewCertification/ViewCertification'),
+const ViewCertification = React.lazy(
+ () => import('../containers/OrganicCertifierSurvey/ViewCertification/ViewCertification'),
);
const RenderSurvey = React.lazy(() => import('../containers/RenderSurvey/RenderSurvey'));
const ExportDownload = React.lazy(() => import('../containers/ExportDownload'));
-const ManagementTasks = React.lazy(() =>
- import('../containers/Crop/ManagementDetail/ManagementTasks'),
+const ManagementTasks = React.lazy(
+ () => import('../containers/Crop/ManagementDetail/ManagementTasks'),
);
-const ManagementDetails = React.lazy(() =>
- import('../containers/Crop/ManagementDetail/ManagementDetails'),
+const ManagementDetails = React.lazy(
+ () => import('../containers/Crop/ManagementDetail/ManagementDetails'),
);
-const EditManagementDetails = React.lazy(() =>
- import('../containers/Crop/ManagementDetail/EditManagementDetails'),
+const EditManagementDetails = React.lazy(
+ () => import('../containers/Crop/ManagementDetail/EditManagementDetails'),
);
-const CompleteManagementPlan = React.lazy(() =>
- import('../containers/Crop/CompleteManagementPlan/CompleteManagementPlan'),
+const CompleteManagementPlan = React.lazy(
+ () => import('../containers/Crop/CompleteManagementPlan/CompleteManagementPlan'),
);
-const AbandonManagementPlan = React.lazy(() =>
- import('../containers/Crop/CompleteManagementPlan/AbandonManagementPlan'),
+const AbandonManagementPlan = React.lazy(
+ () => import('../containers/Crop/CompleteManagementPlan/AbandonManagementPlan'),
);
const RepeatCropPlan = React.lazy(() => import('../containers/Crop/RepeatCropPlan'));
-const RepeatCropPlanConfirmation = React.lazy(() =>
- import('../containers/Crop/RepeatCropPlan/Confirmation'),
+const RepeatCropPlanConfirmation = React.lazy(
+ () => import('../containers/Crop/RepeatCropPlan/Confirmation'),
);
const TaskAssignment = React.lazy(() => import('../containers/Task/TaskAssignment'));
@@ -256,44 +191,44 @@ const Tasks = React.lazy(() => import('../containers/Task'));
const ManageCustomTasks = React.lazy(() => import('../containers/Task/ManageCustomTasks'));
const AddCustomTask = React.lazy(() => import('../containers/Task/AddCustomTask'));
const TaskComplete = React.lazy(() => import('../containers/Task/TaskComplete'));
-const HarvestCompleteQuantity = React.lazy(() =>
- import('../containers/Task/TaskComplete/HarvestComplete/Quantity'),
+const HarvestCompleteQuantity = React.lazy(
+ () => import('../containers/Task/TaskComplete/HarvestComplete/Quantity'),
);
-const HarvestUses = React.lazy(() =>
- import('../containers/Task/TaskComplete/HarvestComplete/HarvestUses'),
+const HarvestUses = React.lazy(
+ () => import('../containers/Task/TaskComplete/HarvestComplete/HarvestUses'),
);
const TaskCompleteStepOne = React.lazy(() => import('../containers/Task/TaskComplete/StepOne'));
const TaskReadOnly = React.lazy(() => import('../containers/Task/TaskReadOnly'));
const EditCustomTask = React.lazy(() => import('../containers/Task/EditCustomTask'));
const TaskAbandon = React.lazy(() => import('../containers/Task/TaskAbandon'));
// const EditCustomTaskUpdate = React.lazy(() => import('../containers/Task/EditCustomTaskUpdate'));
-const TaskTransplantMethod = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskTransplantMethod'),
+const TaskTransplantMethod = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskTransplantMethod'),
);
-const TaskBedMethod = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskBedMethod'),
+const TaskBedMethod = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskBedMethod'),
);
-const TaskBedGuidance = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskBedGuidance'),
+const TaskBedGuidance = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskBedGuidance'),
);
-const TaskRowMethod = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskRowMethod'),
+const TaskRowMethod = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskRowMethod'),
);
-const TaskRowGuidance = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskRowGuidance'),
+const TaskRowGuidance = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskRowGuidance'),
);
-const TaskContainerMethod = React.lazy(() =>
- import('../containers/Task/TaskTransplantMethod/TaskContainerMethod'),
+const TaskContainerMethod = React.lazy(
+ () => import('../containers/Task/TaskTransplantMethod/TaskContainerMethod'),
);
const SensorList = React.lazy(() => import('../containers/SensorList'));
const SensorReadings = React.lazy(() => import('../containers/SensorReadings/v2'));
const IrrigationPrescription = React.lazy(() => import('../containers/IrrigationPrescription'));
const Notification = React.lazy(() => import('../containers/Notification'));
-const NotificationReadOnly = React.lazy(() =>
- import('../containers/Notification/NotificationReadOnly'),
+const NotificationReadOnly = React.lazy(
+ () => import('../containers/Notification/NotificationReadOnly'),
);
-const UnknownRecord = React.lazy(() =>
- import('../containers/ErrorHandler/UnknownRecord/UnknownRecord'),
+const UnknownRecord = React.lazy(
+ () => import('../containers/ErrorHandler/UnknownRecord/UnknownRecord'),
);
const Routes = ({ isCompactSideMenu }) => {
@@ -547,88 +482,23 @@ const Routes = ({ isCompactSideMenu }) => {
- }
- />
- } />
- }
- />
- }
- />
- }
- />
- }
- />
- } />
- }
- />
- } />
- } />
- }
- />
- }
- />
- } />
- }
- />
- }
- />
+ {allLocationTypes.map((type) => (
+ }
+ />
+ ))}
- }
- />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
+ {allLocationTypes.map((type) => (
+ }
+ />
+ ))}
@@ -933,88 +803,23 @@ const Routes = ({ isCompactSideMenu }) => {
- }
- />
- } />
- }
- />
- }
- />
- }
- />
- }
- />
- } />
- }
- />
- } />
- } />
- }
- />
- }
- />
- } />
- }
- />
- }
- />
+ {allLocationTypes.map((type) => (
+ }
+ />
+ ))}
- }
- />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
+ {allLocationTypes.map((type) => (
+ }
+ />
+ ))}
@@ -1191,30 +996,13 @@ const Routes = ({ isCompactSideMenu }) => {
- }
- />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
- } />
- } />
- }
- />
- } />
- } />
- } />
+ {allLocationTypes.map((type) => (
+ }
+ />
+ ))}
diff --git a/packages/webapp/src/store/api/farmNoteApi.ts b/packages/webapp/src/store/api/farmNoteApi.ts
index 97b489add9..bbdabd8c15 100644
--- a/packages/webapp/src/store/api/farmNoteApi.ts
+++ b/packages/webapp/src/store/api/farmNoteApi.ts
@@ -138,7 +138,7 @@ export const farmNoteApi = api.injectEndpoints({
...draft[noteIndex],
note: data.note,
is_private: data.is_private,
- image_url: file ? 'pending' : data.image_url ?? draft[noteIndex].image_url,
+ image_url: file ? 'pending' : (data.image_url ?? draft[noteIndex].image_url),
updated_at: new Date().toISOString(),
to_sync: true,
};
diff --git a/packages/webapp/src/store/api/locationApi.ts b/packages/webapp/src/store/api/locationApi.ts
index 08f716ba33..71e19f29eb 100644
--- a/packages/webapp/src/store/api/locationApi.ts
+++ b/packages/webapp/src/store/api/locationApi.ts
@@ -66,11 +66,13 @@ export const locationApi = api.injectEndpoints({
type: InternalMapLocationType;
}>
>({
- query: ({ data, type, location_id }) => ({
- url: `${locationURL}/${type}/${location_id}`,
- method: 'PUT',
- body: data,
- }),
+ query: ({ data, type, location_id }) => {
+ return {
+ url: `${locationURL}/${type}/${location_id}`,
+ method: 'PUT',
+ body: data,
+ };
+ },
invalidatesTags: ['Locations'],
}),
}),
diff --git a/packages/webapp/src/store/api/types/index.ts b/packages/webapp/src/store/api/types/index.ts
index 09f7c61833..1d128a40ba 100644
--- a/packages/webapp/src/store/api/types/index.ts
+++ b/packages/webapp/src/store/api/types/index.ts
@@ -810,7 +810,7 @@ export interface SurfaceWater extends LocationWithFigure {
[InternalMapLocationType.WATER_VALVE]: null;
}
-enum BufferWidthUnit {
+export enum BufferWidthUnit {
CM = 'cm',
M = 'm',
KM = 'km',
@@ -842,14 +842,14 @@ export interface Watercourse extends LocationWithFigure {
[InternalMapLocationType.WATER_VALVE]: null;
}
-enum WaterSource {
+export enum WaterSource {
MUNICIPAL_WATER = 'Municipal water',
SURFACE_WATER = 'Surface water',
GROUNDWATER = 'Groundwater',
RAIN_WATER = 'Rain water',
}
-enum FlowRateUnit {
+export enum FlowRateUnit {
L_PER_MIN = 'l/min',
L_PER_H = 'l/h',
GAL_PER_MIN = 'gal/min',
diff --git a/packages/webapp/src/store/reducer.js b/packages/webapp/src/store/reducer.js
index 9b34c8ac7b..8bc694e479 100644
--- a/packages/webapp/src/store/reducer.js
+++ b/packages/webapp/src/store/reducer.js
@@ -29,22 +29,6 @@ import notificationReducer from '../containers/notificationSlice';
import chooseFarmFlowReducer from '../containers/ChooseFarm/chooseFarmFlowSlice';
import offlineReadinessReducer from '../hooks/useOfflineReadiness/offlineReadinessSlice';
-import barnReducer from '../containers/barnSlice';
-import ceremonialReducer from '../containers/ceremonialSlice';
-import farmSiteBoundaryReducer from '../containers/farmSiteBoundarySlice';
-import fieldReducer from '../containers/fieldSlice';
-import gardenReducer from '../containers/gardenSlice';
-import greenhouseReducer from '../containers/greenhouseSlice';
-import surfaceWaterReducer from '../containers/surfaceWaterSlice';
-import naturalAreaReducer from '../containers/naturalAreaSlice';
-import residenceReducer from '../containers/residenceSlice';
-import bufferZoneReducer from '../containers/bufferZoneSlice';
-import watercourseReducer from '../containers/watercourseSlice';
-import fenceReducer from '../containers/fenceSlice';
-import gateReducer from '../containers/gateSlice';
-import waterValveReducer from '../containers/waterValveSlice';
-import soilSampleLocationReducer from '../containers/soilSampleLocationSlice';
-
import cropReducer from '../containers/cropSlice';
import cropVarietyReducer from '../containers/cropVarietySlice';
import taskReducer from '../containers/taskSlice';
@@ -165,21 +149,6 @@ const entitiesReducer = combineReducers({
cropReducer,
cropVarietyReducer,
alertReducer,
- barnReducer,
- ceremonialReducer,
- farmSiteBoundaryReducer,
- fieldReducer,
- gardenReducer,
- greenhouseReducer,
- surfaceWaterReducer,
- naturalAreaReducer,
- residenceReducer,
- bufferZoneReducer,
- watercourseReducer,
- fenceReducer,
- gateReducer,
- waterValveReducer,
- soilSampleLocationReducer,
showedSpotlightReducer,
managementPlanReducer,
cropManagementPlanReducer,
diff --git a/packages/webapp/src/stories/MuiFullPagePopup/MuiFullPagePopup.stories.jsx b/packages/webapp/src/stories/MuiFullPagePopup/MuiFullPagePopup.stories.jsx
index 0d251ecab2..a8c993eb0e 100644
--- a/packages/webapp/src/stories/MuiFullPagePopup/MuiFullPagePopup.stories.jsx
+++ b/packages/webapp/src/stories/MuiFullPagePopup/MuiFullPagePopup.stories.jsx
@@ -1,7 +1,6 @@
-import React from 'react';
import MuiFullPagePopup from '../../components/MuiFullPagePopup/v2';
import decorator from '../Pages/config/Decorators';
-import { Post } from '../Pages/LocationDetails/AreaDetails/Barn/Barn.stories';
+import { Post } from '../Pages/LocationDetails/AreaDetails.stories';
import { chromaticSmallScreen } from '../Pages/config/chromatic';
export default {
@@ -12,11 +11,11 @@ export default {
const Template = (args) => ;
-export const Barn = Template.bind({});
-Barn.args = {
+export const Area = Template.bind({});
+Area.args = {
open: true,
children: ,
};
-Barn.parameters = {
+Area.parameters = {
...chromaticSmallScreen,
};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/AreaDetails.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails.stories.jsx
similarity index 82%
rename from packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/AreaDetails.stories.jsx
rename to packages/webapp/src/stories/Pages/LocationDetails/AreaDetails.stories.jsx
index 43551fb1c6..e5f6530d9f 100644
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/AreaDetails.stories.jsx
+++ b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails.stories.jsx
@@ -1,8 +1,7 @@
-import React from 'react';
-import AreaDetails from '../../../../components/LocationDetailLayout/AreaDetails/AreaDetails';
-import decorator from '../../config/Decorators';
+import AreaDetails from '../../../components/LocationDetailLayout/AreaDetails';
+import decorator from '../config/Decorators';
import { FormProvider, useForm } from 'react-hook-form';
-import { chromaticSmallScreen } from '../../config/chromatic';
+import { chromaticSmallScreen } from '../config/chromatic';
export default {
title: 'Form/Location/Area/AreaDetails',
@@ -56,7 +55,6 @@ Post.args = {
getValues: (data) => {},
setError: (data) => {},
control: (data) => {},
- history: (data) => {},
match: { params: { location_id: 1 } },
children: (data) => {},
errors: (data) => {},
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Barn/Barn.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Barn/Barn.stories.jsx
deleted file mode 100644
index 761dae4ab2..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Barn/Barn.stories.jsx
+++ /dev/null
@@ -1,71 +0,0 @@
-import React from 'react';
-import Barn from '../../../../../components/LocationDetailLayout/AreaDetails/Barn';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/Barn',
- decorators: decorator,
- component: Barn,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/barn/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const WorkerView = Template.bind({});
-WorkerView.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/barn/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: false,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-WorkerView.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/CeremonialArea/CeremonialArea.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/CeremonialArea/CeremonialArea.stories.jsx
deleted file mode 100644
index db785db26b..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/CeremonialArea/CeremonialArea.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import CeremonialArea from '../../../../../components/LocationDetailLayout/AreaDetails/CeremonialArea';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/CeremonialArea',
- decorators: decorator,
- component: CeremonialArea,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/ceremonial_area/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/FarmSiteBoundary/FarmSiteBoundary.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/FarmSiteBoundary/FarmSiteBoundary.stories.jsx
deleted file mode 100644
index 2e121616ea..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/FarmSiteBoundary/FarmSiteBoundary.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import FarmSiteBoundary from '../../../../../components/LocationDetailLayout/AreaDetails/FarmSiteBoundary';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/FarmSiteBoundary',
- decorators: decorator,
- component: FarmSiteBoundary,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/farm_site_boundary/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Field/Field.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Field/Field.stories.jsx
deleted file mode 100644
index 718df90ae6..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Field/Field.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import Field from '../../../../../components/LocationDetailLayout/AreaDetails/Field';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/Field',
- decorators: decorator,
- component: Field,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/field/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Garden/Garden.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Garden/Garden.stories.jsx
deleted file mode 100644
index b13c22977c..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Garden/Garden.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import Garden from '../../../../../components/LocationDetailLayout/AreaDetails/Garden';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/Garden',
- decorators: decorator,
- component: Garden,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/garden/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Greenhouse/Greenhouse.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Greenhouse/Greenhouse.stories.jsx
deleted file mode 100644
index a01a0544de..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Greenhouse/Greenhouse.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import Greenhouse from '../../../../../components/LocationDetailLayout/AreaDetails/Greenhouse';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/Greenhouse',
- decorators: decorator,
- component: Greenhouse,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/greenhouse/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/NaturalArea/NaturalArea.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/NaturalArea/NaturalArea.stories.jsx
deleted file mode 100644
index b47b02cb24..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/NaturalArea/NaturalArea.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import NaturalArea from '../../../../../components/LocationDetailLayout/AreaDetails/NaturalArea';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/NaturalArea',
- decorators: decorator,
- component: NaturalArea,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/natural_area/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Residence/Residence.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Residence/Residence.stories.jsx
deleted file mode 100644
index 4a63851626..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/Residence/Residence.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import Residence from '../../../../../components/LocationDetailLayout/AreaDetails/Residence';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/Residence',
- decorators: decorator,
- component: Residence,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/residence/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/SurfaceWater/SurfaceWater.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/SurfaceWater/SurfaceWater.stories.jsx
deleted file mode 100644
index 778b0bc5ee..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/AreaDetails/SurfaceWater/SurfaceWater.stories.jsx
+++ /dev/null
@@ -1,57 +0,0 @@
-import React from 'react';
-import SurfaceWater from '../../../../../components/LocationDetailLayout/AreaDetails/SurfaceWater';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Area/SurfaceWater',
- decorators: decorator,
- component: SurfaceWater,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- areaType: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/surface_water/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/LineDetails.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/LineDetails.stories.jsx
similarity index 73%
rename from packages/webapp/src/stories/Pages/LocationDetails/LineDetails/LineDetails.stories.jsx
rename to packages/webapp/src/stories/Pages/LocationDetails/LineDetails.stories.jsx
index 6dd174f152..2c5a17ddcc 100644
--- a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/LineDetails.stories.jsx
+++ b/packages/webapp/src/stories/Pages/LocationDetails/LineDetails.stories.jsx
@@ -1,7 +1,6 @@
-import React from 'react';
-import LineDetails from '../../../../components/LocationDetailLayout/LineDetails/LineDetails';
-import decorator from '../../config/Decorators';
-import { chromaticSmallScreen } from '../../config/chromatic';
+import LineDetails from '../../../components/LocationDetailLayout/LineDetails';
+import decorator from '../config/Decorators';
+import { chromaticSmallScreen } from '../config/chromatic';
import { FormProvider, useForm } from 'react-hook-form';
export default {
@@ -25,7 +24,6 @@ Post.args = {
children: (data) => {},
setValue: (data) => {},
handleSubmit: (data) => {},
- history: (data) => {},
match: { params: { location_id: 1 } },
onError: (data) => {},
register: (data) => {},
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/BufferZone/BufferZone.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/BufferZone/BufferZone.stories.jsx
deleted file mode 100644
index 9a3712fb7b..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/BufferZone/BufferZone.stories.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import React from 'react';
-import BufferZone from '../../../../../components/LocationDetailLayout/LineDetails/BufferZone';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Line/BufferZone',
- decorators: decorator,
- component: BufferZone,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, width: 1, length: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/buffer_zone/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Fence/Fence.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Fence/Fence.stories.jsx
deleted file mode 100644
index 6eff380eaf..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Fence/Fence.stories.jsx
+++ /dev/null
@@ -1,55 +0,0 @@
-import React from 'react';
-import Fence from '../../../../../components/LocationDetailLayout/LineDetails/Fence';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Line/Fence',
- decorators: decorator,
- component: Fence,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, width: 1, length: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/fence/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Watercourse/Watercourse.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Watercourse/Watercourse.stories.jsx
deleted file mode 100644
index c4a49a57d8..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/LineDetails/Watercourse/Watercourse.stories.jsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import React from 'react';
-import Watercourse from '../../../../../components/LocationDetailLayout/LineDetails/Watercourse';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Line/Watercourse',
- decorators: decorator,
- component: Watercourse,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- history: (data) => {},
- match: { params: { location_id: 1 } },
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, width: 1, length: 2 },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/watercourse/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/LocationFormWrapper.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/LocationFormWrapper.stories.jsx
new file mode 100644
index 0000000000..8d254ed362
--- /dev/null
+++ b/packages/webapp/src/stories/Pages/LocationDetails/LocationFormWrapper.stories.jsx
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+import decorator from '../config/Decorators';
+import { chromaticSmallScreen } from '../config/chromatic';
+import PureLocationFormWrapper from '../../../components/LocationDetailLayout/PureLocationFormWrapper';
+import { InternalMapLocationType } from '../../../store/api/types';
+import { Provider } from 'react-redux';
+import { fakeDBLocation } from './util';
+import { pick } from '../../../util/pick';
+import { areaProperties, lineProperties, pointProperties } from '../../../containers/constants';
+import state from '../../../../.storybook/state';
+
+const config = {
+ // areas
+ [InternalMapLocationType.BARN]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.BARN), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.BARN),
+ },
+ [InternalMapLocationType.CEREMONIAL_AREA]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.CEREMONIAL_AREA), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.CEREMONIAL_AREA),
+ },
+ [InternalMapLocationType.FARM_SITE_BOUNDARY]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.FARM_SITE_BOUNDARY), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.FARM_SITE_BOUNDARY),
+ },
+ [InternalMapLocationType.FIELD]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.FIELD), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.FIELD),
+ },
+ [InternalMapLocationType.GARDEN]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.GARDEN), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.GARDEN),
+ },
+ [InternalMapLocationType.GREENHOUSE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.GREENHOUSE), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.GREENHOUSE),
+ },
+ [InternalMapLocationType.NATURAL_AREA]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.NATURAL_AREA), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.NATURAL_AREA),
+ },
+ [InternalMapLocationType.RESIDENCE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.RESIDENCE), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.RESIDENCE),
+ },
+ [InternalMapLocationType.SURFACE_WATER]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.SURFACE_WATER), [
+ 'name',
+ ...areaProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.SURFACE_WATER),
+ },
+ // lines
+ [InternalMapLocationType.BUFFER_ZONE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.BUFFER_ZONE), [
+ 'name',
+ ...lineProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.BUFFER_ZONE),
+ },
+ [InternalMapLocationType.FENCE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.FENCE), [
+ 'name',
+ ...lineProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.FENCE),
+ },
+ [InternalMapLocationType.WATERCOURSE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.WATERCOURSE), [
+ 'name',
+ ...lineProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.WATERCOURSE),
+ },
+ // points
+ [InternalMapLocationType.GATE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.GATE), [
+ 'name',
+ ...pointProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.GATE),
+ },
+ [InternalMapLocationType.SOIL_SAMPLE_LOCATION]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.SOIL_SAMPLE_LOCATION), [
+ 'name',
+ ...pointProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.SOIL_SAMPLE_LOCATION),
+ },
+ [InternalMapLocationType.WATER_VALVE]: {
+ persistedFormData: pick(fakeDBLocation(InternalMapLocationType.WATER_VALVE), [
+ 'name',
+ ...pointProperties,
+ ]),
+ locationAPIData: fakeDBLocation(InternalMapLocationType.WATER_VALVE),
+ },
+};
+
+const getStore = (locationType) => ({
+ getState: () => {
+ return {
+ api: {
+ queries: {
+ // Key format: 'endpointName(serializedArgs)' — check your actual hook call
+ // e.g. if called as useGetLocationsQuery() it's 'getLocations(undefined)'
+ // e.g. if called as useGetLocationsQuery({farm_id:'1'}) it's 'getLocations({"farm_id":"1"})'
+ 'getLocations(undefined)': {
+ status: 'fulfilled',
+ endpointName: 'getLocations',
+ requestId: 'PDUb54BP0uiv3UrAsO-kD',
+ startedTimeStamp: 1774388379804,
+ data: [{ ...config[locationType].locationAPIData }],
+ fulfilledTimeStamp: 1774388380476,
+ isUninitialized: false,
+ isLoading: false,
+ isSuccess: true,
+ isError: false,
+ originalArgs: undefined,
+ requestStatus: 'fulfilled',
+ },
+ },
+ mutations: {},
+ provided: {},
+ subscriptions: {},
+ config: {
+ online: true,
+ focused: true,
+ middlewareRegistered: true,
+ refetchOnFocus: false,
+ refetchOnReconnect: false,
+ refetchOnMountOrArgChange: false,
+ keepUnusedDataFor: 60,
+ reducerPath: 'api',
+ },
+ },
+ ...state,
+ };
+ },
+ subscribe: () => () => {},
+ dispatch: () => {},
+});
+
+export default {
+ title: 'Form/Location/LocationFormWrappers',
+ decorators: decorator,
+ component: PureLocationFormWrapper,
+};
+
+const Template = (args) => ;
+
+const createStoryArgs = (locationType, mode) => {
+ const base = {
+ system: 'metric',
+ isAdmin: true,
+ history: () => {},
+ submitForm: (data) => {},
+ locationType,
+ persistedFormData: config[locationType].persistedFormData,
+ };
+
+ const location_id = config[locationType].locationAPIData.location_id;
+
+ if (mode === 'post') {
+ return {
+ ...base,
+ isCreateLocationPage: true,
+ areaType: locationType,
+ match: { params: {} },
+ };
+ }
+ if (mode === 'view') {
+ return {
+ ...base,
+ isViewLocationPage: true,
+ match: { params: { location_id } },
+ history: { location: { pathname: `/${locationType.toLowerCase()}/${location_id}/details` } },
+ };
+ }
+ if (mode === 'workerView') {
+ return {
+ ...base,
+ isViewLocationPage: true,
+ match: { params: { location_id } },
+ history: { location: { pathname: `/${locationType.toLowerCase()}/${location_id}/details` } },
+ isAdmin: false,
+ };
+ }
+ if (mode === 'edit') {
+ return {
+ ...base,
+ isEditLocationPage: true,
+ match: { params: { location_id } },
+ };
+ }
+};
+
+const createStory = (locationType, mode) => ({
+ render: () => (
+
+
+
+ ),
+ parameters: { ...chromaticSmallScreen },
+});
+
+// Areas
+export const BarnPost = createStory(InternalMapLocationType.BARN, 'post');
+export const BarnView = createStory(InternalMapLocationType.BARN, 'view');
+export const BarnWorkerView = createStory(InternalMapLocationType.BARN, 'workerView');
+export const BarnEdit = createStory(InternalMapLocationType.BARN, 'edit');
+
+export const CeremonialAreaPost = createStory(InternalMapLocationType.CEREMONIAL_AREA, 'post');
+export const CeremonialAreaView = createStory(InternalMapLocationType.CEREMONIAL_AREA, 'view');
+export const CeremonialAreaWorkerView = createStory(
+ InternalMapLocationType.CEREMONIAL_AREA,
+ 'workerView',
+);
+export const CeremonialAreaEdit = createStory(InternalMapLocationType.CEREMONIAL_AREA, 'edit');
+
+export const FarmSiteBoundaryPost = createStory(InternalMapLocationType.FARM_SITE_BOUNDARY, 'post');
+export const FarmSiteBoundaryView = createStory(InternalMapLocationType.FARM_SITE_BOUNDARY, 'view');
+export const FarmSiteBoundaryWorkerView = createStory(
+ InternalMapLocationType.FARM_SITE_BOUNDARY,
+ 'workerView',
+);
+export const FarmSiteBoundaryEdit = createStory(InternalMapLocationType.FARM_SITE_BOUNDARY, 'edit');
+
+export const FieldPost = createStory(InternalMapLocationType.FIELD, 'post');
+export const FieldView = createStory(InternalMapLocationType.FIELD, 'view');
+export const FieldWorkerView = createStory(InternalMapLocationType.FIELD, 'workerView');
+export const FieldEdit = createStory(InternalMapLocationType.FIELD, 'edit');
+
+export const GardenPost = createStory(InternalMapLocationType.GARDEN, 'post');
+export const GardenView = createStory(InternalMapLocationType.GARDEN, 'view');
+export const GardenWorkerView = createStory(InternalMapLocationType.GARDEN, 'workerView');
+export const GardenEdit = createStory(InternalMapLocationType.GARDEN, 'edit');
+
+export const GreenhousePost = createStory(InternalMapLocationType.GREENHOUSE, 'post');
+export const GreenhouseView = createStory(InternalMapLocationType.GREENHOUSE, 'view');
+export const GreenhouseWorkerView = createStory(InternalMapLocationType.GREENHOUSE, 'workerView');
+export const GreenhouseEdit = createStory(InternalMapLocationType.GREENHOUSE, 'edit');
+
+export const NaturalAreaPost = createStory(InternalMapLocationType.NATURAL_AREA, 'post');
+export const NaturalAreaView = createStory(InternalMapLocationType.NATURAL_AREA, 'view');
+export const NaturalAreaWorkerView = createStory(
+ InternalMapLocationType.NATURAL_AREA,
+ 'workerView',
+);
+export const NaturalAreaEdit = createStory(InternalMapLocationType.NATURAL_AREA, 'edit');
+
+export const ResidencePost = createStory(InternalMapLocationType.RESIDENCE, 'post');
+export const ResidenceView = createStory(InternalMapLocationType.RESIDENCE, 'view');
+export const ResidenceWorkerView = createStory(InternalMapLocationType.RESIDENCE, 'workerView');
+export const ResidenceEdit = createStory(InternalMapLocationType.RESIDENCE, 'edit');
+
+export const SurfaceWaterPost = createStory(InternalMapLocationType.SURFACE_WATER, 'post');
+export const SurfaceWaterView = createStory(InternalMapLocationType.SURFACE_WATER, 'view');
+export const SurfaceWaterWorkerView = createStory(
+ InternalMapLocationType.SURFACE_WATER,
+ 'workerView',
+);
+export const SurfaceWaterEdit = createStory(InternalMapLocationType.SURFACE_WATER, 'edit');
+
+// Lines
+export const BufferZonePost = createStory(InternalMapLocationType.BUFFER_ZONE, 'post');
+export const BufferZoneView = createStory(InternalMapLocationType.BUFFER_ZONE, 'view');
+export const BufferZoneWorkerView = createStory(InternalMapLocationType.BUFFER_ZONE, 'workerView');
+export const BufferZoneEdit = createStory(InternalMapLocationType.BUFFER_ZONE, 'edit');
+
+export const FencePost = createStory(InternalMapLocationType.FENCE, 'post');
+export const FenceView = createStory(InternalMapLocationType.FENCE, 'view');
+export const FenceWorkerView = createStory(InternalMapLocationType.FENCE, 'workerView');
+export const FenceEdit = createStory(InternalMapLocationType.FENCE, 'edit');
+
+export const WatercoursePost = createStory(InternalMapLocationType.WATERCOURSE, 'post');
+export const WatercourseView = createStory(InternalMapLocationType.WATERCOURSE, 'view');
+export const WatercourseWorkerView = createStory(InternalMapLocationType.WATERCOURSE, 'workerView');
+export const WatercourseEdit = createStory(InternalMapLocationType.WATERCOURSE, 'edit');
+
+// Points
+export const GatePost = createStory(InternalMapLocationType.GATE, 'post');
+export const GateView = createStory(InternalMapLocationType.GATE, 'view');
+export const GateWorkerView = createStory(InternalMapLocationType.GATE, 'workerView');
+export const GateEdit = createStory(InternalMapLocationType.GATE, 'edit');
+
+export const SoilSampleLocationPost = createStory(
+ InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ 'post',
+);
+export const SoilSampleLocationView = createStory(
+ InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ 'view',
+);
+export const SoilSampleLocationWorkerView = createStory(
+ InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ 'workerView',
+);
+export const SoilSampleLocationEdit = createStory(
+ InternalMapLocationType.SOIL_SAMPLE_LOCATION,
+ 'edit',
+);
+
+export const WaterValvePost = createStory(InternalMapLocationType.WATER_VALVE, 'post');
+export const WaterValveView = createStory(InternalMapLocationType.WATER_VALVE, 'view');
+export const WaterValveWorkerView = createStory(InternalMapLocationType.WATER_VALVE, 'workerView');
+export const WaterValveEdit = createStory(InternalMapLocationType.WATER_VALVE, 'edit');
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/PointDetails.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/PointDetails.stories.jsx
similarity index 72%
rename from packages/webapp/src/stories/Pages/LocationDetails/PointDetails/PointDetails.stories.jsx
rename to packages/webapp/src/stories/Pages/LocationDetails/PointDetails.stories.jsx
index 8f00565fc9..b7d0ed61bd 100644
--- a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/PointDetails.stories.jsx
+++ b/packages/webapp/src/stories/Pages/LocationDetails/PointDetails.stories.jsx
@@ -1,7 +1,6 @@
-import React from 'react';
-import PointDetails from '../../../../components/LocationDetailLayout/PointDetails/PointDetails';
-import decorator from '../../config/Decorators';
-import { chromaticSmallScreen } from '../../config/chromatic';
+import PointDetails from '../../../components/LocationDetailLayout/PointDetails';
+import decorator from '../config/Decorators';
+import { chromaticSmallScreen } from '../config/chromatic';
import { FormProvider, useForm } from 'react-hook-form';
export default {
@@ -25,7 +24,6 @@ Post.args = {
children: (data) => {},
setValue: (data) => {},
handleSubmit: (data) => {},
- history: (data) => {},
match: { params: { location_id: 1 } },
onError: (data) => {},
register: (data) => {},
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/Gate/Gate.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/Gate/Gate.stories.jsx
deleted file mode 100644
index 7a690a8ade..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/Gate/Gate.stories.jsx
+++ /dev/null
@@ -1,51 +0,0 @@
-import React from 'react';
-import Gate from '../../../../../components/LocationDetailLayout/PointDetails/Gate';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Point/Gate',
- decorators: decorator,
- component: Gate,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- match: { params: { location_id: 1 } },
-
- persistedFormData: { name: 'location', point: {}, type: 'type' },
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/gate/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/WaterValve/WaterValve.stories.jsx b/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/WaterValve/WaterValve.stories.jsx
deleted file mode 100644
index 4f84993b0b..0000000000
--- a/packages/webapp/src/stories/Pages/LocationDetails/PointDetails/WaterValve/WaterValve.stories.jsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import React from 'react';
-import WaterValve from '../../../../../components/LocationDetailLayout/PointDetails/WaterValve';
-import decorator from '../../../config/Decorators';
-import { chromaticSmallScreen } from '../../../config/chromatic';
-
-export default {
- title: 'Form/Location/Point/WaterValve',
- decorators: decorator,
- component: WaterValve,
-};
-
-const Template = (args) => ;
-
-export const Post = Template.bind({});
-Post.args = {
- isCreateLocationPage: true,
- match: { params: { location_id: 1 } },
-
- persistedFormData: { name: 'location', point: {}, type: 'type' },
-
- system: 'imperial',
-};
-Post.parameters = {
- ...chromaticSmallScreen,
-};
-export const View = Template.bind({});
-View.args = {
- isViewLocationPage: true,
- history: { location: { pathname: '/water_valve/location_id/details' } },
- match: { params: { location_id: 'location_id' } },
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-View.parameters = {
- ...chromaticSmallScreen,
-};
-
-export const Edit = Template.bind({});
-Edit.args = {
- match: { params: {} },
- isEditLocationPage: true,
- submitForm: (data) => {},
- system: 'metric',
- isAdmin: true,
-
- persistedFormData: { name: 'location', grid_points: {}, total_area: 1, perimeter: 2 },
-};
-Edit.parameters = {
- ...chromaticSmallScreen,
-};
diff --git a/packages/webapp/src/stories/Pages/LocationDetails/util.js b/packages/webapp/src/stories/Pages/LocationDetails/util.js
new file mode 100644
index 0000000000..f664ac4d35
--- /dev/null
+++ b/packages/webapp/src/stories/Pages/LocationDetails/util.js
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2026 LiteFarm.org
+ * This file is part of LiteFarm.
+ *
+ * LiteFarm is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LiteFarm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details, see .
+ */
+
+import { getFigureType } from '../../../containers/LocationDetails/utils';
+import {
+ BufferWidthUnit,
+ FlowRateUnit,
+ InternalMapLocationType,
+ LengthWidthUnit,
+ PerimeterUnit,
+ TotalAreaUnit,
+ WaterSource,
+} from '../../../store/api/types';
+import { OrganicStatus } from '../../../types';
+
+const farm_id = '31881f94-83c6-11ec-9fa9-0242ac130004';
+
+// Locations
+const fakeGridPoints = [
+ {
+ lat: 49.26822337992714,
+ lng: -123.2591160736328,
+ },
+ {
+ lat: 49.2656190259034,
+ lng: -123.25606908419188,
+ },
+ {
+ lat: 49.267131248202105,
+ lng: -123.25177754976805,
+ },
+ {
+ lat: 49.27068758833716,
+ lng: -123.25430955507811,
+ },
+];
+
+const fakeArea = {
+ grid_points: fakeGridPoints,
+ total_area: 40,
+ total_area_unit: TotalAreaUnit.M2,
+ perimeter: 26,
+ perimeter_unit: PerimeterUnit.M,
+};
+
+const fakeLine = {
+ line_points: fakeGridPoints, // minimum 2
+ length: 40,
+ length_unit: LengthWidthUnit.M,
+ width: 1,
+ width_unit: LengthWidthUnit.M,
+ total_area: 40,
+ total_area_unit: TotalAreaUnit.M2,
+};
+
+const fakePoint = {
+ point: fakeGridPoints[0],
+};
+
+const figure_id = '8b56f10c-2724-11f1-b435-ce0b8496eaa9';
+const hasFigureId = (figure_id) => (figure_id ? { figure_id } : {});
+
+const fakeBaseFigure = (locationType, figure_id, location_id) => ({
+ ...hasFigureId(figure_id),
+ ...hasLocationId(location_id),
+ type: locationType,
+});
+
+const fakeFigure = (locationType, figure_id, location_id) => {
+ const figureType = getFigureType(locationType);
+ switch (figureType) {
+ case 'area':
+ return { ...fakeBaseFigure(locationType, figure_id, location_id), ...fakeArea };
+ case 'line':
+ return { ...fakeBaseFigure(locationType, figure_id, location_id), ...fakeLine };
+ case 'point':
+ return { ...fakeBaseFigure(locationType, figure_id, location_id), ...fakePoint };
+ default:
+ return {};
+ }
+};
+
+const fakeStationId = {
+ station_id: null,
+};
+
+const fakeOrganicStatus = {
+ organic_status: OrganicStatus.NON_ORGANIC,
+ transition_date: null,
+};
+
+const fakeBarn = {
+ wash_and_pack: null,
+ cold_storage: null,
+ used_for_animals: null,
+};
+
+const fakeFence = {
+ pressure_treated: null,
+};
+
+const fakeField = {
+ ...fakeStationId,
+ ...fakeOrganicStatus,
+};
+
+const fakeGarden = {
+ ...fakeStationId,
+ ...fakeOrganicStatus,
+};
+
+const fakeGreenhouse = {
+ ...fakeOrganicStatus,
+ supplemental_lighting: null,
+ co2_enrichment: null,
+ greenhouse_heated: null,
+};
+
+const fakeSurfaceWater = {
+ used_for_irrigation: null,
+};
+
+const fakeWatercourse = {
+ used_for_irrigation: null,
+ buffer_width: 2,
+ buffer_width_unit: BufferWidthUnit.M,
+};
+
+const fakeWaterValve = {
+ source: WaterSource.GROUNDWATER,
+ flow_rate: 1,
+ flow_rate_unit: FlowRateUnit.L_PER_MIN,
+};
+
+const fakeLocationTypeDetails = {
+ [InternalMapLocationType.BARN]: fakeBarn,
+ [InternalMapLocationType.BUFFER_ZONE]: {},
+ [InternalMapLocationType.CEREMONIAL_AREA]: {},
+ [InternalMapLocationType.FARM_SITE_BOUNDARY]: {},
+ [InternalMapLocationType.FENCE]: fakeFence,
+ [InternalMapLocationType.FIELD]: fakeField,
+ [InternalMapLocationType.GARDEN]: fakeGarden,
+ [InternalMapLocationType.GATE]: {},
+ [InternalMapLocationType.GREENHOUSE]: fakeGreenhouse,
+ [InternalMapLocationType.NATURAL_AREA]: {},
+ [InternalMapLocationType.RESIDENCE]: {},
+ [InternalMapLocationType.SOIL_SAMPLE_LOCATION]: {},
+ [InternalMapLocationType.SURFACE_WATER]: fakeSurfaceWater,
+ [InternalMapLocationType.WATERCOURSE]: fakeWatercourse,
+ [InternalMapLocationType.WATER_VALVE]: fakeWaterValve,
+};
+
+const location_id = '8b566c14-2724-11f1-b435-ce0b8496eaa9';
+const hasLocationId = (location_id) => (location_id ? { location_id } : {});
+
+export const fakeDBLocation = (locationType) => ({
+ ...fakeLocationTypeDetails[locationType],
+ ...hasLocationId(location_id),
+ figure: fakeFigure(locationType, figure_id, location_id),
+ farm_id: farm_id,
+ name: locationType,
+ notes: null,
+ location_defaults: null,
+ deleted: false,
+});