From 33845ecd563aec91edf896ab5eb89c1d79af1387 Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Wed, 20 Nov 2024 16:41:57 -0500 Subject: [PATCH 01/14] feat: update deps and add slice for soil metadata --- .../models/soilId/soilIdSelectors.test.ts | 3 + dev-client/package-lock.json | 20 ++++-- dev-client/package.json | 2 +- .../src/model/soilId/soilIdGlobalReducer.ts | 2 + .../src/model/soilId/soilMetadataSlice.ts | 67 +++++++++++++++++++ dev-client/src/store/reducers.ts | 2 + 6 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 dev-client/src/model/soilId/soilMetadataSlice.ts diff --git a/dev-client/__tests__/integration/models/soilId/soilIdSelectors.test.ts b/dev-client/__tests__/integration/models/soilId/soilIdSelectors.test.ts index f09bcc249..34ae230fc 100644 --- a/dev-client/__tests__/integration/models/soilId/soilIdSelectors.test.ts +++ b/dev-client/__tests__/integration/models/soilId/soilIdSelectors.test.ts @@ -49,6 +49,9 @@ const appState = (): AppState => { soilData: {}, status: 'ready', }, + soilMetadata: { + soilMetadata: {}, + }, }; }; diff --git a/dev-client/package-lock.json b/dev-client/package-lock.json index d74ba7197..a072dc843 100644 --- a/dev-client/package-lock.json +++ b/dev-client/package-lock.json @@ -62,7 +62,7 @@ "react-native-svg": "^15.9.0", "react-native-tab-view": "^4.0.2", "reduce-reducers": "^1.0.4", - "terraso-client-shared": "github:techmatters/terraso-client-shared#cdf2161", + "terraso-client-shared": "github:techmatters/terraso-client-shared#6d2aeee", "use-debounce": "^10.0.4", "uuid": "^10.0.0", "yup": "^1.4.0" @@ -24163,20 +24163,32 @@ }, "node_modules/terraso-client-shared": { "version": "0.1.0", - "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#cdf21619c807121a8b02069638ee9a16f7969915", + "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#6d2aeee3df84c01201034d17af7eb492e141d74a", "dependencies": { "@reduxjs/toolkit": "^1.9.7", "jwt-decode": "^4.0.0", "lodash": "^4.17.21", "react": "^18.3.1", "react-redux": "^8.1.3", - "terraso-backend": "github:techmatters/terraso-backend#74fc2fc", - "uuid": "^10.0.0" + "terraso-backend": "github:techmatters/terraso-backend#fac222b", + "uuid": "^11.0.3" }, "engines": { "node": ">=18" } }, + "node_modules/terraso-client-shared/node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/terser": { "version": "5.36.0", "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz", diff --git a/dev-client/package.json b/dev-client/package.json index 1fbf7b5f9..583ef02ee 100644 --- a/dev-client/package.json +++ b/dev-client/package.json @@ -80,7 +80,7 @@ "react-native-svg": "^15.9.0", "react-native-tab-view": "^4.0.2", "reduce-reducers": "^1.0.4", - "terraso-client-shared": "github:techmatters/terraso-client-shared#cdf2161", + "terraso-client-shared": "github:techmatters/terraso-client-shared#6d2aeee", "use-debounce": "^10.0.4", "uuid": "^10.0.0", "yup": "^1.4.0" diff --git a/dev-client/src/model/soilId/soilIdGlobalReducer.ts b/dev-client/src/model/soilId/soilIdGlobalReducer.ts index 7c1eb8cf2..952aa5a97 100644 --- a/dev-client/src/model/soilId/soilIdGlobalReducer.ts +++ b/dev-client/src/model/soilId/soilIdGlobalReducer.ts @@ -26,6 +26,7 @@ import { setSoilData, updateSoilIdStatus, } from 'terraso-mobile-client/model/soilId/soilIdSlice'; +import {setSoilMetadata} from 'terraso-mobile-client/model/soilId/soilMetadataSlice'; import {createGlobalReducer} from 'terraso-mobile-client/store/reducers'; export const fetchSoilDataForUser = createAsyncThunk( @@ -40,6 +41,7 @@ export const soilIdGlobalReducer = createGlobalReducer(builder => { setUsers(state.account, payload.users); setProjectSettings(state.soilId, payload.projectSoilSettings); setSoilData(state.soilId, payload.soilData); + setSoilMetadata(state.soilMetadata, payload.soilMetadata); updateSoilIdStatus(state.soilId, 'ready'); }); diff --git a/dev-client/src/model/soilId/soilMetadataSlice.ts b/dev-client/src/model/soilId/soilMetadataSlice.ts new file mode 100644 index 000000000..1545c7329 --- /dev/null +++ b/dev-client/src/model/soilId/soilMetadataSlice.ts @@ -0,0 +1,67 @@ +/* + * Copyright © 2023 Technology Matters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import {createSlice, Draft} from '@reduxjs/toolkit'; + +import {SoilMetadata} from 'terraso-client-shared/soilId/soilIdTypes'; +import * as soilMetadataService from 'terraso-client-shared/soilId/soilMetadataService'; +import {createAsyncThunk} from 'terraso-client-shared/store/utils'; + +export * from 'terraso-client-shared/soilId/soilIdTypes'; +export * from 'terraso-mobile-client/model/soilId/soilIdFunctions'; + +export type SoilState = { + soilMetadata: Record; +}; + +export const initialState: SoilState = { + soilMetadata: {}, +}; + +export const setSoilMetadata = ( + state: Draft, + soilMetadata: Record, +) => { + state.soilMetadata = soilMetadata; +}; + +export const deleteSoilMetadata = ( + state: Draft, + siteIds: string[], +) => { + for (const siteId of siteIds) { + delete state.soilMetadata[siteId]; + } +}; + +const soilMetadataSlice = createSlice({ + name: 'soilMetadata', + initialState, + reducers: {}, + extraReducers: builder => { + builder.addCase(updateSoilMetadata.fulfilled, (state, action) => { + state.soilMetadata[action.meta.arg.siteId] = action.payload; + }); + }, +}); + +export const updateSoilMetadata = createAsyncThunk( + 'soilId/updateSoilMetadata', + soilMetadataService.updateSoilMetadata, +); + +export default soilMetadataSlice.reducer; diff --git a/dev-client/src/store/reducers.ts b/dev-client/src/store/reducers.ts index 20444a1f2..deef35156 100644 --- a/dev-client/src/store/reducers.ts +++ b/dev-client/src/store/reducers.ts @@ -30,6 +30,7 @@ import {reducer as preferencesReducer} from 'terraso-mobile-client/model/prefere import projectReducer from 'terraso-mobile-client/model/project/projectSlice'; import siteReducer from 'terraso-mobile-client/model/site/siteSlice'; import soilIdReducer from 'terraso-mobile-client/model/soilId/soilIdSlice'; +import soilMetadataReducer from 'terraso-mobile-client/model/soilId/soilMetadataSlice'; const sliceReducers = { ...sharedReducers, @@ -39,6 +40,7 @@ const sliceReducers = { site: siteReducer, project: projectReducer, soilId: soilIdReducer, + soilMetadata: soilMetadataReducer, }; export type AppState = StateFromReducersMapObject; From f027baf824b6207cff2c3896036bdae1e3939692 Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Thu, 21 Nov 2024 10:52:44 -0500 Subject: [PATCH 02/14] feat: selector and hook for soil id rating --- .../src/model/soilId/soilMetadataHooks.ts | 50 +++++++++++++++++++ .../src/model/soilId/soilMetadataSelectors.ts | 26 ++++++++++ 2 files changed, 76 insertions(+) create mode 100644 dev-client/src/model/soilId/soilMetadataHooks.ts create mode 100644 dev-client/src/model/soilId/soilMetadataSelectors.ts diff --git a/dev-client/src/model/soilId/soilMetadataHooks.ts b/dev-client/src/model/soilId/soilMetadataHooks.ts new file mode 100644 index 000000000..38b208b07 --- /dev/null +++ b/dev-client/src/model/soilId/soilMetadataHooks.ts @@ -0,0 +1,50 @@ +/* + * Copyright © 2024 Technology Matters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import {useCallback} from 'react'; +import {useDispatch, useSelector} from 'react-redux'; + +import type {SharedDispatch} from 'terraso-client-shared/store/store'; + +import {selectSoilMetadata} from 'terraso-mobile-client/model/soilId/soilMetadataSelectors'; +import {updateSoilMetadata} from 'terraso-mobile-client/model/soilId/soilMetadataSlice'; + +export const useSoilIdSelection = ( + siteId: string, +): { + selectedSoilId?: string; + selectSoilId: (selectedSoilId: string | null) => Promise; +} => { + const dispatch = useDispatch(); + + const soilMetadata = useSelector(selectSoilMetadata(siteId)); + const selectedSoilId = + soilMetadata.selectedSoilId === null || + soilMetadata.selectedSoilId === undefined + ? undefined + : soilMetadata.selectedSoilId; + + const selectSoilId = useCallback( + (newSelection: string | null) => + dispatch( + updateSoilMetadata({siteId: siteId, selectedSoilId: newSelection}), + ).then(() => {}), + [dispatch, siteId], + ); + + return {selectedSoilId, selectSoilId}; +}; diff --git a/dev-client/src/model/soilId/soilMetadataSelectors.ts b/dev-client/src/model/soilId/soilMetadataSelectors.ts new file mode 100644 index 000000000..62fe68f0c --- /dev/null +++ b/dev-client/src/model/soilId/soilMetadataSelectors.ts @@ -0,0 +1,26 @@ +/* + * Copyright © 2024 Technology Matters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import {createSelector} from '@reduxjs/toolkit'; + +import {AppState} from 'terraso-mobile-client/store'; + +export const selectSoilMetadata = (siteId: string) => + createSelector( + (state: AppState) => state.soilMetadata.soilMetadata[siteId], + metaData => metaData ?? {}, + ); From 91924117ee1bfa001aa117ea15583a9c6de3d59a Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Thu, 21 Nov 2024 12:53:31 -0500 Subject: [PATCH 03/14] feat: add soil id selector to score info sheet --- dev-client/package-lock.json | 4 +- dev-client/package.json | 2 +- .../src/model/soilId/soilMetadataFunctions.ts | 23 ++++++++ .../soilId/SoilIdMatchesSection.tsx | 9 ++- .../soilInfo/SiteScoreInfoContent.tsx | 8 ++- .../soilInfo/SoilIdMatchSelector.tsx | 59 +++++++++++++++++++ dev-client/src/translations/en.json | 3 +- 7 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 dev-client/src/model/soilId/soilMetadataFunctions.ts create mode 100644 dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx diff --git a/dev-client/package-lock.json b/dev-client/package-lock.json index a072dc843..8603acc23 100644 --- a/dev-client/package-lock.json +++ b/dev-client/package-lock.json @@ -62,7 +62,7 @@ "react-native-svg": "^15.9.0", "react-native-tab-view": "^4.0.2", "reduce-reducers": "^1.0.4", - "terraso-client-shared": "github:techmatters/terraso-client-shared#6d2aeee", + "terraso-client-shared": "github:techmatters/terraso-client-shared#1380ddd", "use-debounce": "^10.0.4", "uuid": "^10.0.0", "yup": "^1.4.0" @@ -24163,7 +24163,7 @@ }, "node_modules/terraso-client-shared": { "version": "0.1.0", - "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#6d2aeee3df84c01201034d17af7eb492e141d74a", + "resolved": "git+ssh://git@github.com/techmatters/terraso-client-shared.git#1380ddda4c6f362a29c3b7271866fcd4a49b4b96", "dependencies": { "@reduxjs/toolkit": "^1.9.7", "jwt-decode": "^4.0.0", diff --git a/dev-client/package.json b/dev-client/package.json index 583ef02ee..6ba20fe51 100644 --- a/dev-client/package.json +++ b/dev-client/package.json @@ -80,7 +80,7 @@ "react-native-svg": "^15.9.0", "react-native-tab-view": "^4.0.2", "reduce-reducers": "^1.0.4", - "terraso-client-shared": "github:techmatters/terraso-client-shared#6d2aeee", + "terraso-client-shared": "github:techmatters/terraso-client-shared#1380ddd", "use-debounce": "^10.0.4", "uuid": "^10.0.0", "yup": "^1.4.0" diff --git a/dev-client/src/model/soilId/soilMetadataFunctions.ts b/dev-client/src/model/soilId/soilMetadataFunctions.ts new file mode 100644 index 000000000..6d0081ea9 --- /dev/null +++ b/dev-client/src/model/soilId/soilMetadataFunctions.ts @@ -0,0 +1,23 @@ +/* + * Copyright © 2024 Technology Matters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import {DataBasedSoilMatch} from 'terraso-client-shared/graphqlSchema/graphql'; + +export const getMatchSelectionId = (match: DataBasedSoilMatch) => { + /* TODO is this actually a unique id?? */ + return match.soilInfo.soilSeries.name; +}; diff --git a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx index 7065af66b..22467b49a 100644 --- a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx @@ -29,6 +29,7 @@ import { Row, } from 'terraso-mobile-client/components/NativeBaseAdapters'; import {InfoSheet} from 'terraso-mobile-client/components/sheets/InfoSheet'; +import {SiteRoleContextProvider} from 'terraso-mobile-client/context/SiteRoleContext'; import {useIsOffline} from 'terraso-mobile-client/hooks/connectivityHooks'; import {useSoilIdData} from 'terraso-mobile-client/model/soilId/soilIdHooks'; import { @@ -100,7 +101,13 @@ const MatchTilesOrMessage = ({siteId, coords}: SoilIdMatchesSectionProps) => { onPress={onOpen} /> )}> - + + + )); } else { diff --git a/dev-client/src/screens/LocationScreens/components/soilInfo/SiteScoreInfoContent.tsx b/dev-client/src/screens/LocationScreens/components/soilInfo/SiteScoreInfoContent.tsx index cb119ac60..790a5bf27 100644 --- a/dev-client/src/screens/LocationScreens/components/soilInfo/SiteScoreInfoContent.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilInfo/SiteScoreInfoContent.tsx @@ -23,16 +23,19 @@ import {Coords} from 'terraso-client-shared/types'; import {LocationScoreDisplay} from 'terraso-mobile-client/screens/LocationScreens/components/soilInfo/LocationScoreDisplay'; import {PropertiesScoreDisplay} from 'terraso-mobile-client/screens/LocationScreens/components/soilInfo/PropertiesScoreDisplay'; import {ScoreInfoContainer} from 'terraso-mobile-client/screens/LocationScreens/components/soilInfo/ScoreInfoContainer'; +import {SoilIdMatchSelector} from 'terraso-mobile-client/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector'; import {SoilInfoDisplay} from 'terraso-mobile-client/screens/LocationScreens/components/soilInfo/SoilInfoDisplay'; type SiteScoreInfoContentProps = { - dataMatch: DataBasedSoilMatch; + siteId: string; coords: Coords; + dataMatch: DataBasedSoilMatch; }; export function SiteScoreInfoContent({ - dataMatch, + siteId, coords, + dataMatch, }: SiteScoreInfoContentProps) { return ( @@ -52,6 +55,7 @@ export function SiteScoreInfoContent({ match={dataMatch} matchInfo={dataMatch.dataMatch} /> + ); } diff --git a/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx new file mode 100644 index 000000000..bbd7a9081 --- /dev/null +++ b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx @@ -0,0 +1,59 @@ +/* + * Copyright © 2024 Technology Matters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import {StyleSheet, View} from 'react-native'; + +import CheckBox from '@react-native-community/checkbox'; + +import {DataBasedSoilMatch} from 'terraso-client-shared/graphqlSchema/graphql'; + +import {TranslatedParagraph} from 'terraso-mobile-client/components/content/typography/TranslatedParagraph'; +import {RestrictBySiteRole} from 'terraso-mobile-client/components/RestrictByRole'; +import {SITE_EDITOR_ROLES} from 'terraso-mobile-client/model/permissions/permissions'; +import {getMatchSelectionId} from 'terraso-mobile-client/model/soilId/soilMetadataFunctions'; +import {useSoilIdSelection} from 'terraso-mobile-client/model/soilId/soilMetadataHooks'; + +type SoilIdMatchSelectorProps = { + match: DataBasedSoilMatch; + siteId: string; +}; + +export function SoilIdMatchSelector({siteId, match}: SoilIdMatchSelectorProps) { + const {selectedSoilId, selectSoilId} = useSoilIdSelection(siteId); + const matchId = getMatchSelectionId(match); + + return ( + + + { + selectSoilId(value ? matchId : null); + }} + /> + + + + ); +} + +const styles = StyleSheet.create({ + container: { + flexDirection: 'row', + alignItems: 'center', + }, +}); diff --git a/dev-client/src/translations/en.json b/dev-client/src/translations/en.json index 9f064cfdd..5a614c377 100644 --- a/dev-client/src/translations/en.json +++ b/dev-client/src/translations/en.json @@ -121,7 +121,8 @@ "native_lands_link": "nativeland.info", "native_lands_url": "https://nativeland.info/", "offline_title": "You are offline", - "offline_body": "Soil matches will update here when you are online." + "offline_body": "Soil matches will update here when you are online.", + "selector": "This is the correct soil" }, "site_data": { "title": "Site Data", From 5386824e24f52a65d25903c68fd192357d3c1749 Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Thu, 21 Nov 2024 16:15:29 -0500 Subject: [PATCH 04/14] feat: add selection state to SoilMatchTile, clean up internals --- .../soilId/SoilIdMatchesSection.tsx | 4 +- .../components/soilId/SoilMatchTile.tsx | 68 ++++++++++++------- dev-client/src/theme.ts | 5 ++ dev-client/src/translations/en.json | 4 +- 4 files changed, 55 insertions(+), 26 deletions(-) diff --git a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx index 22467b49a..2dc031ce4 100644 --- a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx @@ -96,7 +96,7 @@ const MatchTilesOrMessage = ({siteId, coords}: SoilIdMatchesSectionProps) => { } trigger={onOpen => ( @@ -121,7 +121,7 @@ const MatchTilesOrMessage = ({siteId, coords}: SoilIdMatchesSectionProps) => { } trigger={onOpen => ( diff --git a/dev-client/src/screens/LocationScreens/components/soilId/SoilMatchTile.tsx b/dev-client/src/screens/LocationScreens/components/soilId/SoilMatchTile.tsx index 95d6757d5..6b44092da 100644 --- a/dev-client/src/screens/LocationScreens/components/soilId/SoilMatchTile.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilId/SoilMatchTile.tsx @@ -15,20 +15,31 @@ * along with this program. If not, see https://www.gnu.org/licenses/. */ -import {useTranslation} from 'react-i18next'; import {Pressable} from 'react-native'; +import {TranslatedContent} from 'terraso-mobile-client/components/content/typography/TranslatedContent'; import {Icon} from 'terraso-mobile-client/components/icons/Icon'; import {Box, Text} from 'terraso-mobile-client/components/NativeBaseAdapters'; import {formatPercent} from 'terraso-mobile-client/util'; -type Props = {soil_name: string; score: number; onPress: () => void}; - -export const SoilMatchTile = ({soil_name, score, onPress}: Props) => { - const {t} = useTranslation(); +type Props = { + soilName: string; + score: number; + isSelected?: boolean; + onPress: () => void; +}; +export const SoilMatchTile = ({ + soilName, + score, + isSelected, + onPress, +}: Props) => { return ( - + { my="4px" py="6px"> - - {formatPercent(score)} - - - {t('site.soil_id.matches.match')} - + {isSelected ? ( + + + + ) : ( + <> + + + + + + + + )} - - {soil_name} + {soilName} - diff --git a/dev-client/src/theme.ts b/dev-client/src/theme.ts index 3af13f0bb..b0912845f 100644 --- a/dev-client/src/theme.ts +++ b/dev-client/src/theme.ts @@ -422,6 +422,11 @@ export const theme = extendTheme({ adjustsFontSizeToFit: true, numberOfLines: 1, }, + 'match-tile-selected': { + fontWeight: 700, + fontSize: '16px', + lineHeight: '24px', + }, 'chip-text': { fontWeight: 400, fontSize: '13px', diff --git a/dev-client/src/translations/en.json b/dev-client/src/translations/en.json index 5a614c377..dc7a861e4 100644 --- a/dev-client/src/translations/en.json +++ b/dev-client/src/translations/en.json @@ -112,6 +112,7 @@ "temp_location": "The soils listed are the most likely to be found at this location based on USDA NRCS soil maps.\n\nCreate a site here and enter the recommended data to improve accuracy of the match scores." } }, + "match_score": "{{score}}", "match": "match", "error_generic_title": "Can’t fetch soil map", "error_generic_body": "LandPKS was unable to fetch the soil map for this location. Try again later.", @@ -122,7 +123,8 @@ "native_lands_url": "https://nativeland.info/", "offline_title": "You are offline", "offline_body": "Soil matches will update here when you are online.", - "selector": "This is the correct soil" + "selector": "This is the correct soil", + "selected": "Selected Soil" }, "site_data": { "title": "Site Data", From 9043a2d3cc251fa2692c25d303bbcb87db012ad1 Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Thu, 21 Nov 2024 16:40:08 -0500 Subject: [PATCH 05/14] feat: display selected soil id at top of screen --- .../src/model/soilId/soilMetadataFunctions.ts | 10 +++ .../LocationScreens/LocationSoilIdScreen.tsx | 12 ++- .../soilId/SoilIdMatchesSection.tsx | 4 +- .../soilId/SoilIdSelectionSection.tsx | 73 +++++++++++++++++++ .../soilInfo/SoilIdMatchSelector.tsx | 1 + 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 dev-client/src/screens/LocationScreens/components/soilId/SoilIdSelectionSection.tsx diff --git a/dev-client/src/model/soilId/soilMetadataFunctions.ts b/dev-client/src/model/soilId/soilMetadataFunctions.ts index 6d0081ea9..992e394e6 100644 --- a/dev-client/src/model/soilId/soilMetadataFunctions.ts +++ b/dev-client/src/model/soilId/soilMetadataFunctions.ts @@ -21,3 +21,13 @@ export const getMatchSelectionId = (match: DataBasedSoilMatch) => { /* TODO is this actually a unique id?? */ return match.soilInfo.soilSeries.name; }; + +export const findSelectedMatch = ( + matches: DataBasedSoilMatch[], + selectedSoilId?: string, +): DataBasedSoilMatch | undefined => { + if (selectedSoilId === undefined) { + return undefined; + } + return matches.find(match => selectedSoilId === getMatchSelectionId(match)); +}; diff --git a/dev-client/src/screens/LocationScreens/LocationSoilIdScreen.tsx b/dev-client/src/screens/LocationScreens/LocationSoilIdScreen.tsx index 2668064d9..c3427f5c1 100644 --- a/dev-client/src/screens/LocationScreens/LocationSoilIdScreen.tsx +++ b/dev-client/src/screens/LocationScreens/LocationSoilIdScreen.tsx @@ -27,6 +27,7 @@ import {CreateSiteButton} from 'terraso-mobile-client/screens/LocationScreens/co import {SiteDataSection} from 'terraso-mobile-client/screens/LocationScreens/components/soilId/SiteDataSection'; import {SoilIdDescriptionSection} from 'terraso-mobile-client/screens/LocationScreens/components/soilId/SoilIdDescriptionSection'; import {SoilIdMatchesSection} from 'terraso-mobile-client/screens/LocationScreens/components/soilId/SoilIdMatchesSection'; +import {SoilIdSelectionSection} from 'terraso-mobile-client/screens/LocationScreens/components/soilId/SoilIdSelectionSection'; import {ScreenScaffold} from 'terraso-mobile-client/screens/ScreenScaffold'; import {useSelector} from 'terraso-mobile-client/store'; import {selectSite} from 'terraso-mobile-client/store/selectors'; @@ -38,8 +39,10 @@ type Props = { export const LocationSoilIdScreen = ({siteId, coords}: Props) => { const {t} = useTranslation(); + + const isSite = !!siteId; const site = useSelector(state => - siteId === undefined ? undefined : selectSite(siteId)(state), + isSite ? selectSite(siteId)(state) : undefined, ); return ( @@ -48,9 +51,14 @@ export const LocationSoilIdScreen = ({siteId, coords}: Props) => { }> + {isSite ? ( + + ) : ( + <> + )} - {siteId ? ( + {isSite ? ( diff --git a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx index 2dc031ce4..b8f256069 100644 --- a/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilId/SoilIdMatchesSection.tsx @@ -90,9 +90,7 @@ const MatchTilesOrMessage = ({siteId, coords}: SoilIdMatchesSectionProps) => { - {dataMatch.soilInfo.soilSeries.name} - + } trigger={onOpen => ( { + const soilIdData = useSoilIdData(coords, siteId); + const {selectedSoilId} = useSoilIdSelection(siteId); + const selectedSoilMatch = findSelectedMatch( + soilIdData.dataBasedMatches, + selectedSoilId, + ); + + if (!selectedSoilMatch) { + return <>; + } + + return ( + + + } + trigger={onOpen => ( + + )}> + + + + + + ); +}; diff --git a/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx index bbd7a9081..e944732b4 100644 --- a/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx +++ b/dev-client/src/screens/LocationScreens/components/soilInfo/SoilIdMatchSelector.tsx @@ -40,6 +40,7 @@ export function SoilIdMatchSelector({siteId, match}: SoilIdMatchSelectorProps) { { selectSoilId(value ? matchId : null); From 8cc2c961941904d1d4cdcbe41b44d8881d012ff5 Mon Sep 17 00:00:00 2001 From: Ruxandra Machedon Date: Thu, 21 Nov 2024 17:25:37 -0500 Subject: [PATCH 06/14] feat: make location soil id card display selected soil id. refactor for clarity. --- .../LocationDashboardContent.tsx | 5 +- ...nPrediction.tsx => LocationSoilIdCard.tsx} | 136 ++++++++++-------- 2 files changed, 80 insertions(+), 61 deletions(-) rename dev-client/src/screens/LocationScreens/components/{LocationPrediction.tsx => LocationSoilIdCard.tsx} (54%) diff --git a/dev-client/src/screens/LocationScreens/LocationDashboardContent.tsx b/dev-client/src/screens/LocationScreens/LocationDashboardContent.tsx index f1086bfd8..6a89dcba5 100644 --- a/dev-client/src/screens/LocationScreens/LocationDashboardContent.tsx +++ b/dev-client/src/screens/LocationScreens/LocationDashboardContent.tsx @@ -40,7 +40,7 @@ import {updateSite} from 'terraso-mobile-client/model/site/siteGlobalReducer'; import {useSoilIdData} from 'terraso-mobile-client/model/soilId/soilIdHooks'; import {useNavigation} from 'terraso-mobile-client/navigation/hooks/useNavigation'; import {CreateSiteButton} from 'terraso-mobile-client/screens/LocationScreens/components/CreateSiteButton'; -import {LocationPrediction} from 'terraso-mobile-client/screens/LocationScreens/components/LocationPrediction'; +import {LocationSoilIdCard} from 'terraso-mobile-client/screens/LocationScreens/components/LocationSoilIdCard'; import {ProjectInstructionsButton} from 'terraso-mobile-client/screens/LocationScreens/components/ProjectInstructionsButton'; import {useDispatch, useSelector} from 'terraso-mobile-client/store'; import {formatCoordinate} from 'terraso-mobile-client/util'; @@ -167,8 +167,7 @@ export const LocationDashboardContent = ({site, coords, elevation}: Props) => { )} - void; }; -export const LocationPrediction = ({ - label, +export const LocationSoilIdCard = ({ coords, siteId, onExploreDataPress, -}: LocationPredictionProps) => { +}: LocationSoilIdCardProps) => { const {t} = useTranslation(); - const soilIdData = useSoilIdData(coords, siteId); - const topSoilMatch = useMemo(() => getTopMatch(soilIdData), [soilIdData]); + const isSite = !!siteId; return ( @@ -68,26 +66,15 @@ export const LocationPrediction = ({ color="primary.lighter" textTransform="uppercase" bold> - {label} + {t('soil.soil_id')} - - {t('soil.top_match')}: - - - - {t('soil.ecological_site_name')}: - - + {isSite ? ( + + ) : ( + + )}