From b8676045a60e9bb227308c5758eee45dc7e1dbcc Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:05:34 -0400 Subject: [PATCH 1/8] Add missing animal type use route, model, controller --- .../animalTypeUseRelationshipController.js | 33 ++++++++++++++ .../models/animalTypeUseRelationshipModel.js | 43 +++++++++++++++++++ .../routes/animalTypeUseRelationshipRoute.js | 28 ++++++++++++ 3 files changed, 104 insertions(+) create mode 100644 packages/api/src/controllers/animalTypeUseRelationshipController.js create mode 100644 packages/api/src/models/animalTypeUseRelationshipModel.js create mode 100644 packages/api/src/routes/animalTypeUseRelationshipRoute.js diff --git a/packages/api/src/controllers/animalTypeUseRelationshipController.js b/packages/api/src/controllers/animalTypeUseRelationshipController.js new file mode 100644 index 0000000000..533ffc5a3f --- /dev/null +++ b/packages/api/src/controllers/animalTypeUseRelationshipController.js @@ -0,0 +1,33 @@ +/* + * Copyright 2024 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 AnimalTypeUseRelationship from '../models/animalTypeUseRelationshipModel.js'; + +const animalUseController = { + getAnimalTypeUseRelationships() { + return async (_req, res) => { + try { + const useRelationships = await AnimalTypeUseRelationship.query(); + return res.status(200).send(useRelationships); + } catch (error) { + console.error(error); + return res.status(500).json({ + error, + }); + } + }; + }, +}; + +export default animalUseController; diff --git a/packages/api/src/models/animalTypeUseRelationshipModel.js b/packages/api/src/models/animalTypeUseRelationshipModel.js new file mode 100644 index 0000000000..d20b43158a --- /dev/null +++ b/packages/api/src/models/animalTypeUseRelationshipModel.js @@ -0,0 +1,43 @@ +/* + * Copyright 2024 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 Model from './baseFormatModel.js'; + +class AnimalTypeUseRelationshipModel extends Model { + static get tableName() { + return 'animal_type_use_relationship'; + } + + static get idColumn() { + return ['default_type_id', 'animal_use_id']; + } + + // Optional JSON schema. This is not the database schema! Nothing is generated + // based on this. This is only used for validation. Whenever a model instance + // is created it is checked against this schema. http://json-schema.org/. + static get jsonSchema() { + return { + type: 'object', + required: ['default_type_id', 'animal_use_id'], + properties: { + default_type_id: { type: 'integer' }, + animal_use_id: { type: 'integer' }, + }, + additionalProperties: false, + }; + } +} + +export default AnimalTypeUseRelationshipModel; diff --git a/packages/api/src/routes/animalTypeUseRelationshipRoute.js b/packages/api/src/routes/animalTypeUseRelationshipRoute.js new file mode 100644 index 0000000000..2e6b47cf80 --- /dev/null +++ b/packages/api/src/routes/animalTypeUseRelationshipRoute.js @@ -0,0 +1,28 @@ +/* + * Copyright 2024 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 express from 'express'; + +const router = express.Router(); +import checkScope from '../middleware/acl/checkScope.js'; +import animalTypeUseRelationshipController from '../controllers/animalTypeUseRelationshipController.js'; + +router.get( + '/', + checkScope(['get:animal_uses']), + animalTypeUseRelationshipController.getAnimalTypeUseRelationships(), +); + +export default router; From 3fdbe1f8736b3202543aad596b691374aced33a8 Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:08:25 -0400 Subject: [PATCH 2/8] Update animal use endpointto only return animal uses --- .../src/controllers/animalUseController.js | 2 +- packages/api/src/models/animalUseModel.js | 27 ------------------- 2 files changed, 1 insertion(+), 28 deletions(-) diff --git a/packages/api/src/controllers/animalUseController.js b/packages/api/src/controllers/animalUseController.js index 4a6529c269..1028eabb7f 100644 --- a/packages/api/src/controllers/animalUseController.js +++ b/packages/api/src/controllers/animalUseController.js @@ -19,7 +19,7 @@ const animalUseController = { getAnimalUses() { return async (_req, res) => { try { - const uses = await AnimalUse.getAnimalUsesForTypes(); + const uses = await AnimalUse.query(); return res.status(200).send(uses); } catch (error) { console.error(error); diff --git a/packages/api/src/models/animalUseModel.js b/packages/api/src/models/animalUseModel.js index ae2ec18eba..aac49e0ac8 100644 --- a/packages/api/src/models/animalUseModel.js +++ b/packages/api/src/models/animalUseModel.js @@ -13,7 +13,6 @@ * GNU General Public License for more details, see . */ -import knex from '../util/knex.js'; import baseModel from './baseModel.js'; class AnimalUse extends baseModel { @@ -39,32 +38,6 @@ class AnimalUse extends baseModel { additionalProperties: false, }; } - - static async getAnimalUsesForTypes() { - const typeUseRelationships = await knex('animal_type_use_relationship') - .select({ - default_type_id: 'default_type_id', - useId: 'animal_use.id', - useKey: 'animal_use.key', - }) - .join('animal_use', 'animal_type_use_relationship.animal_use_id', '=', 'animal_use.id'); - - const usesPerType = typeUseRelationships.reduce((map, { default_type_id, useId, useKey }) => { - map[default_type_id] = map[default_type_id] || []; - map[default_type_id].push({ id: useId, key: useKey }); - - return map; - }, {}); - - const response = Object.entries(usesPerType).map(([defaultTypeId, uses]) => { - return { default_type_id: +defaultTypeId, uses }; - }); - - const allUses = await AnimalUse.query(); - response.push({ default_type_id: null, uses: allUses }); - - return response; - } } export default AnimalUse; From 32ae12e8d1e4a6554734aaf2b79497bfe0f94ebd Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:09:15 -0400 Subject: [PATCH 3/8] Upate backend routes to add type use relationships --- packages/api/src/server.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/api/src/server.js b/packages/api/src/server.js index 2ff266b295..cee75a6f13 100644 --- a/packages/api/src/server.js +++ b/packages/api/src/server.js @@ -137,6 +137,7 @@ import animalOriginRoute from './routes/animalOriginRoute.js'; import animalGroupRoute from './routes/animalGroupRoute.js'; import animalRemovalReasonRoute from './routes/animalRemovalReasonRoute.js'; import animalUseRoute from './routes/animalUseRoute.js'; +import animalTypeUseRelationshipRoute from './routes/animalTypeUseRelationshipRoute.js'; import cropRoutes from './routes/cropRoute.js'; import cropVarietyRoutes from './routes/cropVarietyRoute.js'; import fieldRoutes from './routes/fieldRoute.js'; @@ -293,6 +294,7 @@ app .use('/animal_groups', animalGroupRoute) .use('/animal_removal_reasons', animalRemovalReasonRoute) .use('/animal_uses', animalUseRoute) + .use('/animal_type_use_relationships', animalTypeUseRelationshipRoute) .use('/location', locationRoute) .use('/userLog', userLogRoute) .use('/crop', cropRoutes) From 567419ca9b2ad1dea2d48e8706c86101018c40e4 Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:11:49 -0400 Subject: [PATCH 4/8] Update frontend routes and types --- packages/webapp/src/apiConfig.js | 2 ++ packages/webapp/src/store/api/apiSlice.ts | 8 ++++++++ packages/webapp/src/store/api/types/index.ts | 9 +++++++-- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/packages/webapp/src/apiConfig.js b/packages/webapp/src/apiConfig.js index e6238d1139..9eacb2fc6d 100644 --- a/packages/webapp/src/apiConfig.js +++ b/packages/webapp/src/apiConfig.js @@ -86,6 +86,7 @@ export const animalIdentifierTypesUrl = `${URI}/animal_identifier_types`; export const animalIdentifierColorsUrl = `${URI}/animal_identifier_colors`; export const animalOriginsUrl = `${URI}/animal_origins`; export const animalUsesUrl = `${URI}/animal_uses`; +export const animalTypeUseRelationshipsUrl = `${URI}/animal_type_use_relationships`; export const animalRemovalReasonsUrl = `${URI}/animal_removal_reasons`; export const soilAmendmentMethodsUrl = `${URI}/soil_amendment_methods`; export const soilAmendmentPurposesUrl = `${URI}/soil_amendment_purposes`; @@ -147,6 +148,7 @@ export default { animalIdentifierColorsUrl, animalOriginsUrl, animalUsesUrl, + animalTypeUseRelationshipsUrl, animalRemovalReasonsUrl, soilAmendmentMethodsUrl, soilAmendmentPurposesUrl, diff --git a/packages/webapp/src/store/api/apiSlice.ts b/packages/webapp/src/store/api/apiSlice.ts index dc188d7e1e..4f6fc180e2 100644 --- a/packages/webapp/src/store/api/apiSlice.ts +++ b/packages/webapp/src/store/api/apiSlice.ts @@ -28,6 +28,7 @@ import { animalIdentifierColorsUrl, animalOriginsUrl, animalUsesUrl, + animalTypeUseRelationshipsUrl, animalRemovalReasonsUrl, soilAmendmentMethodsUrl, soilAmendmentPurposesUrl, @@ -53,6 +54,7 @@ import type { AnimalIdentifierColor, AnimalOrigin, AnimalUse, + AnimalTypeUseRelationship, } from './types'; export const api = createApi({ @@ -83,6 +85,7 @@ export const api = createApi({ 'AnimalIdentifierColors', 'AnimalOrigins', 'AnimalUses', + 'AnimalTypeUseRelationships', 'AnimalRemovalReasons', 'SoilAmendmentMethods', 'SoilAmendmentPurposes', @@ -140,6 +143,10 @@ export const api = createApi({ query: () => `${animalUsesUrl}`, providesTags: ['AnimalUses'], }), + getAnimalTypeUseRelationships: build.query({ + query: () => `${animalTypeUseRelationshipsUrl}`, + providesTags: ['AnimalTypeUseRelationships'], + }), getAnimalRemovalReasons: build.query({ query: () => `${animalRemovalReasonsUrl}`, providesTags: ['AnimalRemovalReasons'], @@ -236,6 +243,7 @@ export const { useGetAnimalIdentifierColorsQuery, useGetAnimalOriginsQuery, useGetAnimalUsesQuery, + useGetAnimalTypeUseRelationshipsQuery, useGetAnimalRemovalReasonsQuery, useRemoveAnimalsMutation, useRemoveAnimalBatchesMutation, diff --git a/packages/webapp/src/store/api/types/index.ts b/packages/webapp/src/store/api/types/index.ts index 175ba28312..35f973ae5e 100644 --- a/packages/webapp/src/store/api/types/index.ts +++ b/packages/webapp/src/store/api/types/index.ts @@ -120,8 +120,13 @@ export interface AnimalOrigin { } export interface AnimalUse { - default_type_id: number | null; - uses: { id: number; key: string }[]; + id: number; + key: string; +} + +export interface AnimalTypeUseRelationship { + default_type_id: number; + animal_use_id: number; } export type AnimalRemovalReasonKeys = From 01290181248cb3c7397932bc619cd8623326d017 Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:13:43 -0400 Subject: [PATCH 5/8] Refactor useAnimalOptions to use new endpoints --- .../Animals/AddAnimals/useAnimalOptions.ts | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts index 788ebb48e6..f8dd592a7d 100644 --- a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts +++ b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts @@ -23,10 +23,12 @@ import { useGetAnimalIdentifierColorsQuery, useGetAnimalOriginsQuery, useGetAnimalUsesQuery, + useGetAnimalTypeUseRelationshipsQuery, } from '../../../store/api/apiSlice'; import { useTranslation } from 'react-i18next'; import { generateUniqueAnimalId } from '../../../util/animal'; import { ANIMAL_ID_PREFIX } from '../types'; +import { AnimalUse, AnimalTypeUseRelationship, DefaultAnimalType } from '../../../store/api/types'; type OptionType = | 'default_types' @@ -52,6 +54,7 @@ export const useAnimalOptions = (...optionTypes: OptionType[]) => { const { data: identifierColors = [] } = useGetAnimalIdentifierColorsQuery(); const { data: orgins = [] } = useGetAnimalOriginsQuery(); const { data: uses = [] } = useGetAnimalUsesQuery(); + const { data: typeUseRelationships = [] } = useGetAnimalTypeUseRelationshipsQuery(); const options: any = {}; @@ -106,14 +109,32 @@ export const useAnimalOptions = (...optionTypes: OptionType[]) => { } if (optionTypes.includes('use')) { - options.useOptions = uses.map((animalType) => ({ - default_type_id: animalType.default_type_id, - uses: animalType.uses.map((use) => ({ - value: use.id, - label: t(`animal:USE.${use.key}`), - key: use.key, - })), - })); + options.useOptions = defaultTypes.map((animalType: DefaultAnimalType) => { + return { + default_type_id: animalType.id, + uses: typeUseRelationships + .filter((typeUse: AnimalTypeUseRelationship) => typeUse.default_type_id === animalType.id) + .map((animalUse: AnimalTypeUseRelationship) => { + const useKey = uses.find((use: AnimalUse) => use.id === animalUse.animal_use_id); + return { + value: animalUse.animal_use_id, + label: t(`animal:USE.${useKey?.key}`), + key: useKey?.key, + }; + }), + }; + }); + // Add all uses to custom type + options.useOptions.push({ + default_type_id: null, + uses: uses.map((use: AnimalUse) => { + return { + value: use.id, + label: t(`animal:USE.${use.key}`), + key: use.key, + }; + }), + }); } if (optionTypes.includes('tagType')) { From 96125ea3f7820bd29ccd0890d87e26e2a3e96f0c Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:31:02 -0400 Subject: [PATCH 6/8] Add animal type use relationship test --- .../animal_type_use_relationship.test.js | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 packages/api/tests/animal_type_use_relationship.test.js diff --git a/packages/api/tests/animal_type_use_relationship.test.js b/packages/api/tests/animal_type_use_relationship.test.js new file mode 100644 index 0000000000..2d05f34d4f --- /dev/null +++ b/packages/api/tests/animal_type_use_relationship.test.js @@ -0,0 +1,141 @@ +/* + * Copyright 2024 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 chai from 'chai'; + +import chaiHttp from 'chai-http'; +chai.use(chaiHttp); + +import server from '../src/server.js'; +import knex from '../src/util/knex.js'; +import { tableCleanup } from './testEnvironment.js'; + +jest.mock('jsdom'); +jest.mock('../src/middleware/acl/checkJwt.js', () => + jest.fn((req, _res, next) => { + req.auth = {}; + req.auth.user_id = req.get('user_id'); + next(); + }), +); +import mocks from './mock.factories.js'; + +describe('Animal Type Use Relationship Tests', () => { + let farm; + let newOwner; + + const getRequest = async ({ user_id = newOwner.user_id, farm_id = farm.farm_id }) => { + const response = await chai + .request(server) + .get('/animal_type_use_relationships') + .set('user_id', user_id) + .set('farm_id', farm_id); + + return response; + }; + + function fakeUserFarm(role = 1) { + return { ...mocks.fakeUserFarm(), role_id: role }; + } + + async function returnUserFarms(role) { + const [mainFarm] = await mocks.farmFactory(); + const [user] = await mocks.usersFactory(); + + await mocks.userFarmFactory( + { + promisedUser: [user], + promisedFarm: [mainFarm], + }, + fakeUserFarm(role), + ); + return { mainFarm, user }; + } + + async function makeAnimalUse(properties) { + const [animalUse] = await mocks.animal_useFactory({ + properties, + }); + return animalUse; + } + + async function makeAnimalTypeUseRelationship(defaultType, use) { + const [animalTypeUseRelationship] = await mocks.animal_type_use_relationshipFactory({ + promisedDefaultAnimalType: [defaultType], + promisedAnimalUse: [use], + }); + return animalTypeUseRelationship; + } + + beforeEach(async () => { + [farm] = await mocks.farmFactory(); + [newOwner] = await mocks.usersFactory(); + }); + + afterEach(async (done) => { + await tableCleanup(knex); + done(); + }); + + afterAll(async (done) => { + await knex.destroy(); + done(); + }); + + describe('Get animal type use relationship tests', () => { + test('All users should get animal type use relationships', async () => { + const roles = [1, 2, 3, 5]; + const [use1, use2, use3, use4, use5, use6, use7, use8] = await Promise.all( + [1, 2, 3, 4, 5, 6, 7, 8].map(async () => await makeAnimalUse()), + ); + + const [defaultType1] = await mocks.default_animal_typeFactory(); + const [defaultType2] = await mocks.default_animal_typeFactory(); + + const testCase = [ + { defaultType: defaultType1, uses: [use1, use2, use3, use6, use7, use8] }, + { defaultType: defaultType2, uses: [use1, use5, use6, use7, use8] }, + ]; + + for (let { defaultType, uses } of testCase) { + if (defaultType) { + for (let use of uses) { + await makeAnimalTypeUseRelationship(defaultType, use); + } + } + } + + for (const role of roles) { + const { mainFarm, user } = await returnUserFarms(role); + + const res = await getRequest({ + user_id: user.user_id, + farm_id: mainFarm.farm_id, + }); + + expect(res.status).toBe(200); + expect(res.body.length).toBe(11); + const filteredDefaultType1 = res.body.filter( + (useRelationship) => useRelationship.default_type_id === defaultType1.id, + ); + expect(filteredDefaultType1.length).toBe(6); + const filteredDefaultType2 = res.body.filter( + (useRelationship) => useRelationship.default_type_id === defaultType2.id, + ); + expect(filteredDefaultType2.length).toBe(5); + } + }); + }); +}); From 710d9405d2f4fb4eeabed1de1bc821a91da9850e Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 13:31:29 -0400 Subject: [PATCH 7/8] Refactor animal use test --- packages/api/tests/animal_use.test.js | 37 +-------------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/packages/api/tests/animal_use.test.js b/packages/api/tests/animal_use.test.js index 777f971110..eebdefc5cc 100644 --- a/packages/api/tests/animal_use.test.js +++ b/packages/api/tests/animal_use.test.js @@ -71,14 +71,6 @@ describe('Animal Use Tests', () => { return animalUse; } - async function makeAnimalTypeUseRelationship(defaultType, use) { - const [animalTypeUseRelationship] = await mocks.animal_type_use_relationshipFactory({ - promisedDefaultAnimalType: [defaultType], - promisedAnimalUse: [use], - }); - return animalTypeUseRelationship; - } - beforeEach(async () => { [farm] = await mocks.farmFactory(); [newOwner] = await mocks.usersFactory(); @@ -101,23 +93,6 @@ describe('Animal Use Tests', () => { [1, 2, 3, 4, 5, 6, 7, 8].map(async () => await makeAnimalUse()), ); - const [defaultType1] = await mocks.default_animal_typeFactory(); - const [defaultType2] = await mocks.default_animal_typeFactory(); - - const testCase = [ - { defaultType: defaultType1, uses: [use1, use2, use3, use6, use7, use8] }, - { defaultType: defaultType2, uses: [use1, use5, use6, use7, use8] }, - { defaultType: null, uses: [use1, use2, use3, use4, use5, use6, use7, use8] }, // for custom types - ]; - - for (let { defaultType, uses } of testCase) { - if (defaultType) { - for (let use of uses) { - await makeAnimalTypeUseRelationship(defaultType, use); - } - } - } - for (const role of roles) { const { mainFarm, user } = await returnUserFarms(role); @@ -127,17 +102,7 @@ describe('Animal Use Tests', () => { }); expect(res.status).toBe(200); - expect(res.body.length).toBe(3); - - res.body.forEach(({ default_type_id, uses }) => { - const expectedTypeAndUses = testCase.find(({ defaultType }) => { - return default_type_id ? defaultType.id === default_type_id : !defaultType; - }); - - expect(uses.map(({ id }) => id).sort()).toEqual( - expectedTypeAndUses.uses.map(({ id }) => id).sort(), - ); - }); + expect(res.body.length).toBe(8); } }); }); From 549c259ba8c58f942eb7c5c169e7dbc904feec13 Mon Sep 17 00:00:00 2001 From: Duncan-Brain Date: Tue, 27 Aug 2024 15:16:47 -0400 Subject: [PATCH 8/8] Remove excess types --- .../containers/Animals/AddAnimals/useAnimalOptions.ts | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts index f8dd592a7d..b3efdf052e 100644 --- a/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts +++ b/packages/webapp/src/containers/Animals/AddAnimals/useAnimalOptions.ts @@ -28,7 +28,6 @@ import { import { useTranslation } from 'react-i18next'; import { generateUniqueAnimalId } from '../../../util/animal'; import { ANIMAL_ID_PREFIX } from '../types'; -import { AnimalUse, AnimalTypeUseRelationship, DefaultAnimalType } from '../../../store/api/types'; type OptionType = | 'default_types' @@ -109,13 +108,13 @@ export const useAnimalOptions = (...optionTypes: OptionType[]) => { } if (optionTypes.includes('use')) { - options.useOptions = defaultTypes.map((animalType: DefaultAnimalType) => { + options.useOptions = defaultTypes.map((animalType) => { return { default_type_id: animalType.id, uses: typeUseRelationships - .filter((typeUse: AnimalTypeUseRelationship) => typeUse.default_type_id === animalType.id) - .map((animalUse: AnimalTypeUseRelationship) => { - const useKey = uses.find((use: AnimalUse) => use.id === animalUse.animal_use_id); + .filter((typeUse) => typeUse.default_type_id === animalType.id) + .map((animalUse) => { + const useKey = uses.find((use) => use.id === animalUse.animal_use_id); return { value: animalUse.animal_use_id, label: t(`animal:USE.${useKey?.key}`), @@ -127,7 +126,7 @@ export const useAnimalOptions = (...optionTypes: OptionType[]) => { // Add all uses to custom type options.useOptions.push({ default_type_id: null, - uses: uses.map((use: AnimalUse) => { + uses: uses.map((use) => { return { value: use.id, label: t(`animal:USE.${use.key}`),