diff --git a/packages/webapp/src/components/Animals/RemoveAnimalsModal/index.tsx b/packages/webapp/src/components/Animals/RemoveAnimalsModal/index.tsx
index 471107a2a5..049e28d07d 100644
--- a/packages/webapp/src/components/Animals/RemoveAnimalsModal/index.tsx
+++ b/packages/webapp/src/components/Animals/RemoveAnimalsModal/index.tsx
@@ -25,7 +25,7 @@ import { ReactComponent as WarningIcon } from '../../../assets/images/warning.sv
import { ReactComponent as CheckIcon } from '../../../assets/images/check-circle.svg';
import { useTranslation } from 'react-i18next';
import { getLocalDateInYYYYDDMM } from '../../../util/date';
-import { useGetAnimalRemovalReasonsQuery } from '../../../store/api/apiSlice';
+import { useGetAnimalRemovalReasonsQuery } from '../../../store/api/libraryApiSlice';
import type { AnimalRemovalReasonKeys } from '../../../store/api/types';
const REASON = 'reason';
diff --git a/packages/webapp/src/components/Task/MovementTask/index.tsx b/packages/webapp/src/components/Task/MovementTask/index.tsx
index b3c00b837f..2392bf6f88 100644
--- a/packages/webapp/src/components/Task/MovementTask/index.tsx
+++ b/packages/webapp/src/components/Task/MovementTask/index.tsx
@@ -21,7 +21,7 @@ import ReactSelect from '../../Form/ReactSelect';
import Input, { getInputErrors } from '../../Form/Input';
import { hookFormMaxCharsValidation } from '../../Form/hookformValidationUtils';
import styles from './styles.module.scss';
-import { useGetAnimalMovementPurposesQuery } from '../../../store/api/apiSlice';
+import { useGetAnimalMovementPurposesQuery } from '../../../store/api/libraryApiSlice';
import { AnimalMovementPurpose } from '../../../store/api/types';
type PureMovementTaskProps = UseFormReturn & {
diff --git a/packages/webapp/src/components/Task/SoilAmendmentTask/index.tsx b/packages/webapp/src/components/Task/SoilAmendmentTask/index.tsx
index 5fd642ed01..0ebdc7e2f8 100644
--- a/packages/webapp/src/components/Task/SoilAmendmentTask/index.tsx
+++ b/packages/webapp/src/components/Task/SoilAmendmentTask/index.tsx
@@ -20,7 +20,7 @@ import {
useGetSoilAmendmentMethodsQuery,
useGetSoilAmendmentPurposesQuery,
useGetSoilAmendmentFertiliserTypesQuery,
-} from '../../../store/api/apiSlice';
+} from '../../../store/api/libraryApiSlice';
import ReactSelect from '../../Form/ReactSelect';
import Input, { getInputErrors } from '../../Form/Input';
import { hookFormMaxCharsValidation } from '../../Form/hookformValidationUtils';
diff --git a/packages/webapp/src/containers/AddFarm/saga.js b/packages/webapp/src/containers/AddFarm/saga.js
index e5c640169d..d140659652 100644
--- a/packages/webapp/src/containers/AddFarm/saga.js
+++ b/packages/webapp/src/containers/AddFarm/saga.js
@@ -29,8 +29,7 @@ import { axios, getHeader } from '../saga';
import { createAction } from '@reduxjs/toolkit';
import i18n from '../../locales/i18n';
import { enqueueErrorSnackbar } from '../Snackbar/snackbarSlice';
-import { invalidateTags } from '../../store/api/apiSlice';
-import { FarmLibraryTags, FarmTags } from '../../store/api/apiTags';
+import { resetApiState } from '../../store/api/apiSlice';
const patchRoleUrl = (farm_id, user_id) => `${userFarmUrl}/role/farm/${farm_id}/user/${user_id}`;
const patchFarmUrl = (farm_id) => `${farmUrl}/owner_operated/${farm_id}`;
@@ -62,7 +61,7 @@ export function* postFarmSaga({ payload: { showFarmNameCharacterLimitExceededErr
yield call(axios.patch, patchStepUrl(farm_id, user_id), step, getHeader(user_id, farm_id));
// Clear old farm RTK Query data
- yield put(invalidateTags([...FarmTags, ...FarmLibraryTags]));
+ yield put(resetApiState());
const user = getUserResult?.data;
yield put(
diff --git a/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalDetails/usePopulateDetails.ts b/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalDetails/usePopulateDetails.ts
index 0f9022bc28..4f15980170 100644
--- a/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalDetails/usePopulateDetails.ts
+++ b/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalDetails/usePopulateDetails.ts
@@ -24,7 +24,7 @@ import {
DetailsFields,
} from '../types';
import { AnimalOrBatchKeys } from '../../types';
-import { useGetAnimalUsesQuery } from '../../../../store/api/apiSlice';
+import { useGetAnimalUsesQuery } from '../../../../store/api/libraryApiSlice';
import { parseUniqueDefaultId } from '../../../../util/animal';
export const usePopulateDetails = (
diff --git a/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalSummary/index.tsx b/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalSummary/index.tsx
index 99627c8a86..8449542bc2 100644
--- a/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalSummary/index.tsx
+++ b/packages/webapp/src/containers/Animals/AddAnimals/AddAnimalSummary/index.tsx
@@ -17,12 +17,14 @@ import { useHistory } from 'react-router-dom';
import { AddAnimalsSummaryCard } from '../../../../components/Animals/AddAnimalsSummaryCard';
import { ANIMALS_INVENTORY_URL } from '../../../../util/siteMapConstants';
import {
- useGetAnimalSexesQuery,
useGetCustomAnimalBreedsQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetDefaultAnimalTypesQuery,
} from '../../../../store/api/apiSlice';
+import {
+ useGetAnimalSexesQuery,
+ useGetDefaultAnimalBreedsQuery,
+} from '../../../../store/api/libraryApiSlice';
import useQueries from '../../../../hooks/api/useQueries';
import { formatDBAnimalsToSummary, formatDBBatchesToSummary } from '../../AddAnimals/utils';
import { Animal, AnimalBatch } from '../../../../store/api/types';
diff --git a/packages/webapp/src/containers/Animals/AddAnimals/index.tsx b/packages/webapp/src/containers/Animals/AddAnimals/index.tsx
index 1ca167006f..7d4b76b876 100644
--- a/packages/webapp/src/containers/Animals/AddAnimals/index.tsx
+++ b/packages/webapp/src/containers/Animals/AddAnimals/index.tsx
@@ -22,11 +22,8 @@ import { ContextForm, Variant } from '../../../components/Form/ContextForm/';
import AddAnimalBasics, { animalBasicsDefaultValues } from './AddAnimalBasics';
import AddAnimalDetails from './AddAnimalDetails';
import AddAnimalSummary from './AddAnimalSummary';
-import {
- useAddAnimalBatchesMutation,
- useAddAnimalsMutation,
- useGetAnimalOriginsQuery,
-} from '../../../store/api/apiSlice';
+import { useAddAnimalBatchesMutation, useAddAnimalsMutation } from '../../../store/api/apiSlice';
+import { useGetAnimalOriginsQuery } from '../../../store/api/libraryApiSlice';
import { Animal, AnimalBatch } from '../../../store/api/types';
import { enqueueErrorSnackbar, enqueueSuccessSnackbar } from '../../Snackbar/snackbarSlice';
import { formatAnimalDetailsToDBStructure, formatBatchDetailsToDBStructure } from './utils';
diff --git a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts
index f55be5c53c..daaad08bcc 100644
--- a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts
+++ b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts
@@ -16,14 +16,16 @@
import {
useGetDefaultAnimalTypesQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetCustomAnimalBreedsQuery,
+} from '../../../store/api/apiSlice';
+import {
+ useGetDefaultAnimalBreedsQuery,
useGetAnimalSexesQuery,
useGetAnimalIdentifierTypesQuery,
useGetAnimalIdentifierColorsQuery,
useGetAnimalOriginsQuery,
useGetAnimalUsesQuery,
-} from '../../../store/api/apiSlice';
+} from '../../../store/api/libraryApiSlice';
import { useTranslation } from 'react-i18next';
import { generateUniqueAnimalId } from '../../../util/animal';
import { ANIMAL_ID_PREFIX } from '../types';
diff --git a/packages/webapp/src/containers/Animals/Inventory/useAnimalInventory.tsx b/packages/webapp/src/containers/Animals/Inventory/useAnimalInventory.tsx
index eed4bcaed3..19198cdd2f 100644
--- a/packages/webapp/src/containers/Animals/Inventory/useAnimalInventory.tsx
+++ b/packages/webapp/src/containers/Animals/Inventory/useAnimalInventory.tsx
@@ -19,10 +19,12 @@ import {
useGetAnimalBatchesQuery,
useGetCustomAnimalBreedsQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetDefaultAnimalTypesQuery,
- useGetAnimalSexesQuery,
} from '../../../store/api/apiSlice';
+import {
+ useGetDefaultAnimalBreedsQuery,
+ useGetAnimalSexesQuery,
+} from '../../../store/api/libraryApiSlice';
import useQueries from '../../../hooks/api/useQueries';
import {
Animal,
diff --git a/packages/webapp/src/containers/Animals/SingleAnimalView/index.tsx b/packages/webapp/src/containers/Animals/SingleAnimalView/index.tsx
index 387d5fbd58..98f3edc8b1 100644
--- a/packages/webapp/src/containers/Animals/SingleAnimalView/index.tsx
+++ b/packages/webapp/src/containers/Animals/SingleAnimalView/index.tsx
@@ -27,14 +27,16 @@ import FixedHeaderContainer from '../../../components/Animals/FixedHeaderContain
import { addNullstoMissingFields } from './utils';
import { useInitialAnimalData } from './useInitialAnimalData';
import {
- useGetAnimalOriginsQuery,
useUpdateAnimalsMutation,
useUpdateAnimalBatchesMutation,
useGetCustomAnimalBreedsQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetDefaultAnimalTypesQuery,
} from '../../../store/api/apiSlice';
+import {
+ useGetAnimalOriginsQuery,
+ useGetDefaultAnimalBreedsQuery,
+} from '../../../store/api/libraryApiSlice';
import { locationsSelector } from '../../locationSlice';
import {
formatAnimalDetailsToDBStructure,
diff --git a/packages/webapp/src/containers/Filter/Animals/index.tsx b/packages/webapp/src/containers/Filter/Animals/index.tsx
index cd55655963..832f2c8626 100644
--- a/packages/webapp/src/containers/Filter/Animals/index.tsx
+++ b/packages/webapp/src/containers/Filter/Animals/index.tsx
@@ -23,10 +23,12 @@ import { FilterType, type ComponentFilter } from '../../../components/Filter/typ
import {
useGetDefaultAnimalTypesQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetCustomAnimalBreedsQuery,
- useGetAnimalSexesQuery,
} from '../../../store/api/apiSlice';
+import {
+ useGetDefaultAnimalBreedsQuery,
+ useGetAnimalSexesQuery,
+} from '../../../store/api/libraryApiSlice';
import { generateUniqueAnimalId } from '../../../util/animal';
import { useVisibleBreeds } from './useVisibleBreeds';
import { locationsSelector } from '../../locationSlice';
diff --git a/packages/webapp/src/containers/Filter/ProductInventory/index.tsx b/packages/webapp/src/containers/Filter/ProductInventory/index.tsx
index 001b7132f8..07de8c9df7 100644
--- a/packages/webapp/src/containers/Filter/ProductInventory/index.tsx
+++ b/packages/webapp/src/containers/Filter/ProductInventory/index.tsx
@@ -17,7 +17,7 @@ import { useTranslation } from 'react-i18next';
import FilterGroup from '../../../components/Filter/FilterGroup';
import type { ReduxFilterEntity, ContainerOnChangeCallback, FilterState } from '../types';
import { FilterType, type ComponentFilter } from '../../../components/Filter/types';
-import { useGetSoilAmendmentFertiliserTypesQuery } from '../../../store/api/apiSlice';
+import { useGetSoilAmendmentFertiliserTypesQuery } from '../../../store/api/libraryApiSlice';
import { InventoryFilterKeys } from './types';
import { sortFilterOptions } from '../../../components/Filter/utils';
diff --git a/packages/webapp/src/containers/ProductInventory/ProductForm/SoilAmendmentProductForm.tsx b/packages/webapp/src/containers/ProductInventory/ProductForm/SoilAmendmentProductForm.tsx
index d0bea09e90..c10536677c 100644
--- a/packages/webapp/src/containers/ProductInventory/ProductForm/SoilAmendmentProductForm.tsx
+++ b/packages/webapp/src/containers/ProductInventory/ProductForm/SoilAmendmentProductForm.tsx
@@ -14,7 +14,7 @@
*/
import { shallowEqual, useSelector } from 'react-redux';
import { useTranslation } from 'react-i18next';
-import { useGetSoilAmendmentFertiliserTypesQuery } from '../../../store/api/apiSlice';
+import { useGetSoilAmendmentFertiliserTypesQuery } from '../../../store/api/libraryApiSlice';
import PureSoilAmendmentProductForm from '../../../components/ProductInventory/ProductForm/PureSoilAmendmentProductForm';
import { userFarmSelector } from '../../userFarmSlice';
import { certifierSurveySelector } from '../../OrganicCertifierSurvey/slice';
diff --git a/packages/webapp/src/containers/Task/saga.js b/packages/webapp/src/containers/Task/saga.js
index ad6fd54934..6131774420 100644
--- a/packages/webapp/src/containers/Task/saga.js
+++ b/packages/webapp/src/containers/Task/saga.js
@@ -112,7 +112,7 @@ import {
getMovementTaskBody,
getSoilSampleTaskBody,
} from './sagaUtils';
-import { api } from '../../store/api/apiSlice';
+import { invalidateTags } from '../../store/api/apiSlice';
const taskTypeEndpoint = [
'cleaning_task',
@@ -692,7 +692,7 @@ export function* createTaskSaga({ payload }) {
task_translation_key === 'HARVEST_TASK' ? result.data[0] : result.data;
yield call(getTasksSuccessSaga, { payload: isHarvest ? result.data : [result.data] });
if (task_translation_key === 'IRRIGATION_TASK') {
- yield put(api.util.invalidateTags(['IrrigationPrescriptions']));
+ yield put(invalidateTags(['IrrigationPrescriptions']));
}
if (alreadyCompleted) {
if (['CLEANING_TASK', 'PEST_CONTROL_TASK'].includes(task_translation_key)) {
@@ -905,7 +905,7 @@ export function* completeTaskSaga({ payload: { task_id, data, returnPath } }) {
});
if (task_translation_key === 'MOVEMENT_TASK') {
- yield put(api.util.invalidateTags(['Animals', 'AnimalBatches']));
+ yield put(invalidateTags(['Animals', 'AnimalBatches']));
}
}
} catch (e) {
@@ -1096,7 +1096,7 @@ export function* deleteTaskSaga({ payload: data }) {
}
yield put(deleteTaskSuccess(result.data));
if (task_type.task_translation_key === 'IRRIGATION_TASK') {
- yield put(api.util.invalidateTags(['IrrigationPrescriptions']));
+ yield put(invalidateTags(['IrrigationPrescriptions']));
}
yield put(enqueueSuccessSnackbar(i18n.t('TASK.DELETE.SUCCESS')));
}
diff --git a/packages/webapp/src/containers/saga.js b/packages/webapp/src/containers/saga.js
index 3e49cdd967..09ad6b58ac 100644
--- a/packages/webapp/src/containers/saga.js
+++ b/packages/webapp/src/containers/saga.js
@@ -151,14 +151,14 @@ import {
onLoadingWatercourseFail,
onLoadingWatercourseStart,
} from './watercourseSlice';
-import { api, invalidateTags } from '../store/api/apiSlice';
-import { FarmLibraryTags, FarmTags } from '../store/api/apiTags';
+import { api, resetApiState } from '../store/api/apiSlice';
import {
getSoilSampleLocationsSuccess,
onLoadingSoilSampleLocationFail,
} from './soilSampleLocationSlice';
import { getFieldWorkTypes } from './Task/FieldWorkTask/saga';
import { getIrrigationTaskTypes } from './Task/IrrigationTaskTypes/saga';
+import { libraryApi } from '../store/api/libraryApiSlice';
const logUserInfoUrl = () => `${url}/userLog`;
const getCropsByFarmIdUrl = (farm_id) => `${url}/crop/farm/${farm_id}`;
@@ -617,10 +617,10 @@ export function* fetchAllSaga() {
call(getAllUserFarmsByFarmIDSaga),
put(getFieldWorkTypes()),
put(getIrrigationTaskTypes()),
- put(api.endpoints.getSoilAmendmentMethods.initiate()),
- put(api.endpoints.getSoilAmendmentPurposes.initiate()),
- put(api.endpoints.getSoilAmendmentFertiliserTypes.initiate()),
- put(api.endpoints.getAnimalMovementPurposes.initiate()),
+ put(libraryApi.endpoints.getSoilAmendmentMethods.initiate()),
+ put(libraryApi.endpoints.getSoilAmendmentPurposes.initiate()),
+ put(libraryApi.endpoints.getSoilAmendmentFertiliserTypes.initiate()),
+ put(libraryApi.endpoints.getAnimalMovementPurposes.initiate()),
];
yield all(isAdmin ? [...tasks, ...adminTasks] : tasks);
@@ -632,15 +632,15 @@ export function* fetchAllSaga() {
put(api.endpoints.getAnimals.initiate()),
put(api.endpoints.getAnimalBatches.initiate()),
put(api.endpoints.getDefaultAnimalTypes.initiate()),
- put(api.endpoints.getDefaultAnimalBreeds.initiate()),
+ put(libraryApi.endpoints.getDefaultAnimalBreeds.initiate()),
put(api.endpoints.getCustomAnimalTypes.initiate()),
put(api.endpoints.getCustomAnimalBreeds.initiate()),
- put(api.endpoints.getAnimalSexes.initiate()),
- put(api.endpoints.getAnimalIdentifierTypes.initiate()),
- put(api.endpoints.getAnimalIdentifierColors.initiate()),
- put(api.endpoints.getAnimalMovementPurposes.initiate()),
- put(api.endpoints.getAnimalOrigins.initiate()),
- put(api.endpoints.getAnimalUses.initiate()),
+ put(libraryApi.endpoints.getAnimalSexes.initiate()),
+ put(libraryApi.endpoints.getAnimalIdentifierTypes.initiate()),
+ put(libraryApi.endpoints.getAnimalIdentifierColors.initiate()),
+ put(libraryApi.endpoints.getAnimalMovementPurposes.initiate()),
+ put(libraryApi.endpoints.getAnimalOrigins.initiate()),
+ put(libraryApi.endpoints.getAnimalUses.initiate()),
]);
const {
@@ -658,7 +658,7 @@ export function* fetchAllSaga() {
export function* clearOldFarmStateSaga() {
yield put(resetTasks());
yield put(resetDateRange());
- yield put(invalidateTags([...FarmTags, ...FarmLibraryTags]));
+ yield put(resetApiState());
// Reset finance loading state
yield put(setIsFetchingData(true));
diff --git a/packages/webapp/src/store/api/apiSlice.ts b/packages/webapp/src/store/api/apiSlice.ts
index 61b39fc107..a57ff432fa 100644
--- a/packages/webapp/src/store/api/apiSlice.ts
+++ b/packages/webapp/src/store/api/apiSlice.ts
@@ -13,27 +13,14 @@
* GNU General Public License for more details, see .
*/
-import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
-import { RootState } from '../store';
+import { createApi } from '@reduxjs/toolkit/query/react';
import {
animalsUrl,
animalBatchesUrl,
customAnimalBreedsUrl,
customAnimalTypesUrl,
- defaultAnimalBreedsUrl,
defaultAnimalTypesUrl,
- animalSexesUrl,
- animalIdentifierTypesUrl,
- animalIdentifierColorsUrl,
- animalOriginsUrl,
- animalUsesUrl,
- animalRemovalReasonsUrl,
- soilAmendmentMethodsUrl,
- soilAmendmentPurposesUrl,
- soilAmendmentFertiliserTypesUrl,
productUrl,
- url,
- animalMovementPurposesUrl,
sensorUrl,
farmAddonUrl,
irrigationPrescriptionUrl,
@@ -43,19 +30,8 @@ import type {
AnimalBatch,
CustomAnimalBreed,
CustomAnimalType,
- DefaultAnimalBreed,
DefaultAnimalType,
- AnimalSex,
- AnimalRemovalReason,
- SoilAmendmentMethod,
- SoilAmendmentPurpose,
- SoilAmendmentFertiliserType,
SoilAmendmentProduct,
- AnimalIdentifierType,
- AnimalIdentifierColor,
- AnimalOrigin,
- AnimalUse,
- AnimalMovementPurpose,
SensorData,
FarmAddon,
SensorReadings,
@@ -65,6 +41,7 @@ import type {
import { addDaysToDate } from '../../util/date';
import { API_TAGS, ApiTag } from './apiTags';
+import { BASE_QUERY } from './constants';
/**
* Invalidates one or more RTK Query cache tags.
@@ -77,28 +54,10 @@ import { API_TAGS, ApiTag } from './apiTags';
* which can be dispatched directly or used inside a saga (e.g., `yield put(...)`).
*/
export const invalidateTags = (tags: ApiTag[]) => api.util.invalidateTags(tags);
-
-const NON_JSON_ENDPOINT_KEYS = new Set(['addSupportTicket']);
+export const resetApiState = () => api.util.resetApiState();
export const api = createApi({
- baseQuery: fetchBaseQuery({
- baseUrl: url,
- prepareHeaders: (headers, { getState, endpoint }) => {
- const state = getState() as RootState;
-
- headers.set('Authorization', `Bearer ${localStorage.getItem('id_token')}`);
- headers.set('user_id', state.entitiesReducer.userFarmReducer.user_id || '');
- headers.set('farm_id', state.entitiesReducer.userFarmReducer.farm_id || '');
-
- // Only set the content-type to json if appropriate.
- if (!NON_JSON_ENDPOINT_KEYS.has(endpoint) && !headers.has('Content-Type')) {
- headers.set('content-type', 'application/json');
- }
-
- return headers;
- },
- responseHandler: 'content-type',
- }),
+ baseQuery: BASE_QUERY,
tagTypes: API_TAGS,
keepUnusedDataFor: 60 * 60 * 24 * 7, // 7 days
refetchOnMountOrArgChange: 60,
@@ -125,38 +84,6 @@ export const api = createApi({
query: () => `${customAnimalBreedsUrl}`,
providesTags: ['CustomAnimalBreeds'],
}),
- getDefaultAnimalBreeds: build.query({
- query: () => `${defaultAnimalBreedsUrl}`,
- providesTags: ['DefaultAnimalBreeds'],
- }),
- getAnimalSexes: build.query({
- query: () => `${animalSexesUrl}`,
- providesTags: ['AnimalSexes'],
- }),
- getAnimalIdentifierTypes: build.query({
- query: () => `${animalIdentifierTypesUrl}`,
- providesTags: ['AnimalIdentifierTypes'],
- }),
- getAnimalIdentifierColors: build.query({
- query: () => `${animalIdentifierColorsUrl}`,
- providesTags: ['AnimalIdentifierColors'],
- }),
- getAnimalMovementPurposes: build.query({
- query: () => `${animalMovementPurposesUrl}`,
- providesTags: ['AnimalMovementPurposes'],
- }),
- getAnimalOrigins: build.query({
- query: () => `${animalOriginsUrl}`,
- providesTags: ['AnimalOrigins'],
- }),
- getAnimalUses: build.query({
- query: () => `${animalUsesUrl}`,
- providesTags: ['AnimalUses'],
- }),
- getAnimalRemovalReasons: build.query({
- query: () => `${animalRemovalReasonsUrl}`,
- providesTags: ['AnimalRemovalReasons'],
- }),
removeAnimals: build.mutation[]>({
query: (patch) => ({
url: `${animalsUrl}/remove`,
@@ -323,18 +250,6 @@ export const api = createApi({
'CustomAnimalBreeds',
],
}),
- getSoilAmendmentMethods: build.query({
- query: () => `${soilAmendmentMethodsUrl}`,
- providesTags: ['SoilAmendmentMethods'],
- }),
- getSoilAmendmentPurposes: build.query({
- query: () => `${soilAmendmentPurposesUrl}`,
- providesTags: ['SoilAmendmentPurposes'],
- }),
- getSoilAmendmentFertiliserTypes: build.query({
- query: () => `${soilAmendmentFertiliserTypesUrl}`,
- providesTags: ['SoilAmendmentFertiliserTypes'],
- }),
addSoilAmendmentProduct: build.mutation>({
query: (body) => ({
url: `${productUrl}`,
@@ -434,15 +349,7 @@ export const {
useGetAnimalBatchesQuery,
useGetCustomAnimalBreedsQuery,
useGetCustomAnimalTypesQuery,
- useGetDefaultAnimalBreedsQuery,
useGetDefaultAnimalTypesQuery,
- useGetAnimalSexesQuery,
- useGetAnimalIdentifierTypesQuery,
- useGetAnimalIdentifierColorsQuery,
- useGetAnimalMovementPurposesQuery,
- useGetAnimalOriginsQuery,
- useGetAnimalUsesQuery,
- useGetAnimalRemovalReasonsQuery,
useRemoveAnimalsMutation,
useRemoveAnimalBatchesMutation,
useDeleteAnimalsMutation,
@@ -451,9 +358,6 @@ export const {
useAddAnimalBatchesMutation,
useUpdateAnimalsMutation,
useUpdateAnimalBatchesMutation,
- useGetSoilAmendmentMethodsQuery,
- useGetSoilAmendmentPurposesQuery,
- useGetSoilAmendmentFertiliserTypesQuery,
useAddSoilAmendmentProductMutation,
useUpdateSoilAmendmentProductMutation,
useDeleteSoilAmendmentProductMutation,
diff --git a/packages/webapp/src/store/api/apiTags.ts b/packages/webapp/src/store/api/apiTags.ts
index 89952cdbc2..d5752de782 100644
--- a/packages/webapp/src/store/api/apiTags.ts
+++ b/packages/webapp/src/store/api/apiTags.ts
@@ -70,6 +70,7 @@ export const FarmLibraryTags = [
'MarketDirectoryPartners',
] as const;
-export const API_TAGS = [...LibraryTags, ...FarmTags, ...FarmLibraryTags] as const;
+export const LIBRARY_API_TAGS = [...LibraryTags] as const;
+export const API_TAGS = [...FarmTags, ...FarmLibraryTags] as const;
export type ApiTag = (typeof API_TAGS)[number];
diff --git a/packages/webapp/src/store/api/constants.ts b/packages/webapp/src/store/api/constants.ts
new file mode 100644
index 0000000000..ee4f13798f
--- /dev/null
+++ b/packages/webapp/src/store/api/constants.ts
@@ -0,0 +1,39 @@
+/*
+ * 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 { fetchBaseQuery } from '@reduxjs/toolkit/query';
+import { url } from '../../apiConfig';
+import { RootState } from '../store';
+
+export const NON_JSON_ENDPOINT_KEYS = new Set(['addSupportTicket']);
+
+export const BASE_QUERY = fetchBaseQuery({
+ baseUrl: url,
+ prepareHeaders: (headers, { getState, endpoint }) => {
+ const state = getState() as RootState;
+
+ headers.set('Authorization', `Bearer ${localStorage.getItem('id_token')}`);
+ headers.set('user_id', state.entitiesReducer.userFarmReducer.user_id || '');
+ headers.set('farm_id', state.entitiesReducer.userFarmReducer.farm_id || '');
+
+ // Only set the content-type to json if appropriate.
+ if (!NON_JSON_ENDPOINT_KEYS.has(endpoint) && !headers.has('Content-Type')) {
+ headers.set('content-type', 'application/json');
+ }
+
+ return headers;
+ },
+ responseHandler: 'content-type',
+});
diff --git a/packages/webapp/src/store/api/libraryApiSlice.ts b/packages/webapp/src/store/api/libraryApiSlice.ts
new file mode 100644
index 0000000000..5914040f3d
--- /dev/null
+++ b/packages/webapp/src/store/api/libraryApiSlice.ts
@@ -0,0 +1,113 @@
+/*
+ * 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 { createApi } from '@reduxjs/toolkit/query/react';
+import {
+ defaultAnimalBreedsUrl,
+ animalSexesUrl,
+ animalIdentifierTypesUrl,
+ animalIdentifierColorsUrl,
+ animalOriginsUrl,
+ animalUsesUrl,
+ animalRemovalReasonsUrl,
+ soilAmendmentMethodsUrl,
+ soilAmendmentPurposesUrl,
+ soilAmendmentFertiliserTypesUrl,
+ animalMovementPurposesUrl,
+} from '../../apiConfig';
+import type {
+ DefaultAnimalBreed,
+ AnimalSex,
+ AnimalRemovalReason,
+ SoilAmendmentMethod,
+ SoilAmendmentPurpose,
+ SoilAmendmentFertiliserType,
+ AnimalIdentifierType,
+ AnimalIdentifierColor,
+ AnimalOrigin,
+ AnimalUse,
+ AnimalMovementPurpose,
+} from './types';
+
+import { LIBRARY_API_TAGS } from './apiTags';
+import { BASE_QUERY } from './constants';
+
+export const libraryApi = createApi({
+ reducerPath: 'libraryApi',
+ baseQuery: BASE_QUERY,
+ tagTypes: LIBRARY_API_TAGS,
+ endpoints: (build) => ({
+ // redux-toolkit.js.org/rtk-query/usage-with-typescript#typing-query-and-mutation-endpoints
+ //
+ getDefaultAnimalBreeds: build.query({
+ query: () => `${defaultAnimalBreedsUrl}`,
+ providesTags: ['DefaultAnimalBreeds'],
+ }),
+ getAnimalSexes: build.query({
+ query: () => `${animalSexesUrl}`,
+ providesTags: ['AnimalSexes'],
+ }),
+ getAnimalIdentifierTypes: build.query({
+ query: () => `${animalIdentifierTypesUrl}`,
+ providesTags: ['AnimalIdentifierTypes'],
+ }),
+ getAnimalIdentifierColors: build.query({
+ query: () => `${animalIdentifierColorsUrl}`,
+ providesTags: ['AnimalIdentifierColors'],
+ }),
+ getAnimalMovementPurposes: build.query({
+ query: () => `${animalMovementPurposesUrl}`,
+ providesTags: ['AnimalMovementPurposes'],
+ }),
+ getAnimalOrigins: build.query({
+ query: () => `${animalOriginsUrl}`,
+ providesTags: ['AnimalOrigins'],
+ }),
+ getAnimalUses: build.query({
+ query: () => `${animalUsesUrl}`,
+ providesTags: ['AnimalUses'],
+ }),
+ getAnimalRemovalReasons: build.query({
+ query: () => `${animalRemovalReasonsUrl}`,
+ providesTags: ['AnimalRemovalReasons'],
+ }),
+ getSoilAmendmentMethods: build.query({
+ query: () => `${soilAmendmentMethodsUrl}`,
+ providesTags: ['SoilAmendmentMethods'],
+ }),
+ getSoilAmendmentPurposes: build.query({
+ query: () => `${soilAmendmentPurposesUrl}`,
+ providesTags: ['SoilAmendmentPurposes'],
+ }),
+ getSoilAmendmentFertiliserTypes: build.query({
+ query: () => `${soilAmendmentFertiliserTypesUrl}`,
+ providesTags: ['SoilAmendmentFertiliserTypes'],
+ }),
+ }),
+});
+
+export const {
+ useGetDefaultAnimalBreedsQuery,
+ useGetAnimalSexesQuery,
+ useGetAnimalIdentifierTypesQuery,
+ useGetAnimalIdentifierColorsQuery,
+ useGetAnimalMovementPurposesQuery,
+ useGetAnimalOriginsQuery,
+ useGetAnimalUsesQuery,
+ useGetAnimalRemovalReasonsQuery,
+ useGetSoilAmendmentMethodsQuery,
+ useGetSoilAmendmentPurposesQuery,
+ useGetSoilAmendmentFertiliserTypesQuery,
+} = libraryApi;
diff --git a/packages/webapp/src/store/api/marketProductCategoryApi.ts b/packages/webapp/src/store/api/marketProductCategoryApi.ts
index c2303efbe2..cf59c86b08 100644
--- a/packages/webapp/src/store/api/marketProductCategoryApi.ts
+++ b/packages/webapp/src/store/api/marketProductCategoryApi.ts
@@ -13,11 +13,11 @@
* GNU General Public License for more details, see .
*/
-import { api } from './apiSlice';
+import { libraryApi } from './libraryApiSlice';
import { marketProductCategoryUrl } from '../../apiConfig';
import { MarketProductCategory } from './types';
-export const MarketProductCategories = api.injectEndpoints({
+export const MarketProductCategories = libraryApi.injectEndpoints({
endpoints: (build) => ({
getMarketProductCategories: build.query({
query: () => ({
diff --git a/packages/webapp/src/store/reducer.js b/packages/webapp/src/store/reducer.js
index 4ecf2a4c24..d8a26f08af 100644
--- a/packages/webapp/src/store/reducer.js
+++ b/packages/webapp/src/store/reducer.js
@@ -18,6 +18,7 @@ import baseReducer from '../containers/reducer';
import { combineForms } from 'react-redux-form';
import { PURGE } from 'redux-persist';
import { api } from './api/apiSlice';
+import { libraryApi } from './api/libraryApiSlice';
import insightReducer from '../containers/Insights/reducer';
import financeReducer from '../containers/Finances/reducer';
import certifierSurveyReducer from '../containers/OrganicCertifierSurvey/slice';
@@ -239,6 +240,7 @@ const tempStateReducer = combineReducers({
// combine all reducers here and pass it to application
const appReducer = combineReducers({
[api.reducerPath]: api.reducer,
+ [libraryApi.reducerPath]: libraryApi.reducer,
profileForms: combineForms(
{
addInfo: addUserInfo,
diff --git a/packages/webapp/src/store/store.ts b/packages/webapp/src/store/store.ts
index 4af01b9c9f..89ce673e97 100644
--- a/packages/webapp/src/store/store.ts
+++ b/packages/webapp/src/store/store.ts
@@ -2,6 +2,7 @@ import { persistReducer, persistStore } from 'redux-persist';
import { AnyAction, Middleware, configureStore } from '@reduxjs/toolkit';
import { sagaMiddleware } from './sagaMiddleware';
import { api } from './api/apiSlice';
+import { libraryApi } from './api/libraryApiSlice';
import rootReducer from './reducer';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import storage from 'redux-persist/lib/storage';
@@ -26,6 +27,7 @@ export const store = configureStore({
serializableCheck: false,
})
.concat(api.middleware)
+ .concat(libraryApi.middleware)
.concat(sagaMiddleware),
],
devTools: import.meta.env.VITE_ENV !== 'production',