From 7fe82a5689a2e0d4548d4788db86f51d4c2e475c Mon Sep 17 00:00:00 2001 From: Abbey Campbell Date: Fri, 10 Jul 2026 12:36:00 -0700 Subject: [PATCH 1/3] add feature flag for myobs sort --- src/sharedHooks/useRozenite.tsx | 15 +++++++++++++++ src/stores/createFeatureFlagSlice.ts | 3 +++ 2 files changed, 18 insertions(+) diff --git a/src/sharedHooks/useRozenite.tsx b/src/sharedHooks/useRozenite.tsx index 7fd008798..fa0656980 100644 --- a/src/sharedHooks/useRozenite.tsx +++ b/src/sharedHooks/useRozenite.tsx @@ -75,6 +75,10 @@ const useRozenite = ( { queryClient, storageAdapters }: RozeniteOptions ) => { resolvedValue: searchMyObservationsEnabled, setOverride: setSearchMyObservationsEnabled, } = useFeatureFlagForDebug( FeatureFlag.SearchMyObservationsEnabled ); + const { + resolvedValue: sortMyObservationsEnabled, + setOverride: setSortMyObservationsEnabled, + } = useFeatureFlagForDebug( FeatureFlag.SortMyObservationsEnabled ); const sections = useMemo( () => [ @@ -135,6 +139,15 @@ const useRozenite = ( { queryClient, storageAdapters }: RozeniteOptions ) => { setSearchMyObservationsEnabled( !searchMyObservationsEnabled ); }, }, + { + id: "sort-my-observations", + type: "toggle", + title: "Sort My Observations", + value: sortMyObservationsEnabled, + onUpdate: () => { + setSortMyObservationsEnabled( !sortMyObservationsEnabled ); + }, + }, ], } ), ], @@ -147,6 +160,8 @@ const useRozenite = ( { queryClient, storageAdapters }: RozeniteOptions ) => { setTraditionalProjectsEnabled, searchMyObservationsEnabled, setSearchMyObservationsEnabled, + sortMyObservationsEnabled, + setSortMyObservationsEnabled, ], ); diff --git a/src/stores/createFeatureFlagSlice.ts b/src/stores/createFeatureFlagSlice.ts index c96ad73a7..c00a8ac3b 100644 --- a/src/stores/createFeatureFlagSlice.ts +++ b/src/stores/createFeatureFlagSlice.ts @@ -24,6 +24,7 @@ export enum FeatureFlag { NewsEnabled = "newsEnabled", TraditionalProjectsEnabled = "traditionalProjectsEnabled", SearchMyObservationsEnabled = "searchMyObservationsEnabled", + SortMyObservationsEnabled = "sortMyObservationsEnabled", } const initialFeatureFlagConfig: Record = { @@ -32,6 +33,7 @@ const initialFeatureFlagConfig: Record = { [FeatureFlag.NewsEnabled]: false, [FeatureFlag.TraditionalProjectsEnabled]: false, [FeatureFlag.SearchMyObservationsEnabled]: false, + [FeatureFlag.SortMyObservationsEnabled]: false, }; const initialFeatureFlagDebugOverrides: Record = { @@ -40,6 +42,7 @@ const initialFeatureFlagDebugOverrides: Record = { [FeatureFlag.NewsEnabled]: null, [FeatureFlag.TraditionalProjectsEnabled]: null, [FeatureFlag.SearchMyObservationsEnabled]: null, + [FeatureFlag.SortMyObservationsEnabled]: null, }; const DEFAULT_STATE = { From d795f9939dd60a933e105e50c052b84c5ea7ecc5 Mon Sep 17 00:00:00 2001 From: Abbey Campbell Date: Fri, 10 Jul 2026 13:06:10 -0700 Subject: [PATCH 2/3] gate obs sort on feature flag --- .../MyObservations/MyObservationsSimple.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/components/MyObservations/MyObservationsSimple.tsx b/src/components/MyObservations/MyObservationsSimple.tsx index a81588beb..4d7284474 100644 --- a/src/components/MyObservations/MyObservationsSimple.tsx +++ b/src/components/MyObservations/MyObservationsSimple.tsx @@ -137,6 +137,9 @@ const MyObservationsSimple = ( { const searchMyObservationsEnabled = useFeatureFlag( FeatureFlag.SearchMyObservationsEnabled, ); + const sortMyObservationsEnabled = useFeatureFlag( + FeatureFlag.SortMyObservationsEnabled, + ); const speciesSortLabels = useSpeciesSortLabels( ); const navigation = useNavigation( ); const route = useRoute( ); @@ -396,10 +399,12 @@ const MyObservationsSimple = ( { layout={layout} updateObservationsView={toggleLayout} /> - {/* setOpenSheet( ACTIVE_SHEET.SORT )} - accessibilityLabel={t( "Change-observations-sort-order" )} - /> */} + {sortMyObservationsEnabled && ( + setOpenSheet( ACTIVE_SHEET.SORT )} + accessibilityLabel={t( "Change-observations-sort-order" )} + /> + )} ) } { ( activeTab === TAXA_TAB && taxa.length > 0 ) && ( From 7a1e414c680655b33f2fbeaad2e576aadda217bd Mon Sep 17 00:00:00 2001 From: Abbey Campbell Date: Fri, 10 Jul 2026 15:20:43 -0700 Subject: [PATCH 3/3] add obs sort sheet and wire to new context --- .../MyObservations/MyObservationsResults.tsx | 10 ++++ .../MyObservations/MyObservationsSimple.tsx | 54 +++++++++++++++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/src/components/MyObservations/MyObservationsResults.tsx b/src/components/MyObservations/MyObservationsResults.tsx index d35b16b5b..188c179a2 100644 --- a/src/components/MyObservations/MyObservationsResults.tsx +++ b/src/components/MyObservations/MyObservationsResults.tsx @@ -20,6 +20,7 @@ import { Alert } from "react-native"; import Observation from "realmModels/Observation"; import Taxon from "realmModels/Taxon"; import type { RealmObservation } from "realmModels/types"; +import type { OBSERVATIONS_SORT } from "sharedHelpers/observationsSort"; import type { SPECIES_SORT } from "sharedHelpers/speciesSort"; import { sortSpeciesCounts, @@ -134,6 +135,13 @@ const MyObservationsResults = ( ) => { } ); }; + const setObservationsSortOptionId = ( value: OBSERVATIONS_SORT ) => { + myObsDispatch( { + type: MY_OBSERVATIONS_ACTION.SET_OBSERVATIONS_SORT, + observationsSort: value, + } ); + }; + const toggleLayout = ( ) => { writeLayoutToStorage( layout === "grid" ? "list" @@ -446,12 +454,14 @@ const MyObservationsResults = ( ) => { numUnuploadedObservations={numUnuploadedObservations} numObsMissingBasics={numObsMissingBasics} observationIds={observationIds} + observationsSortOptionId={myObsState.observationsSort} onEndReached={fetchNextPage} onListLayout={restoreScrollOffset} onScroll={onScroll} openSheet={openSheet} refetchTaxa={refetchTaxa} setActiveTab={setActiveTab} + setObservationsSortOptionId={setObservationsSortOptionId} setOpenSheet={setOpenSheet} setSpeciesSortOptionId={setSpeciesSortOptionId} showNoResults={showNoResults} diff --git a/src/components/MyObservations/MyObservationsSimple.tsx b/src/components/MyObservations/MyObservationsSimple.tsx index 4d7284474..02c283db7 100644 --- a/src/components/MyObservations/MyObservationsSimple.tsx +++ b/src/components/MyObservations/MyObservationsSimple.tsx @@ -28,6 +28,11 @@ import type { RealmObservation, RealmUser, } from "realmModels/types"; +import type { OBSERVATIONS_SORT } from "sharedHelpers/observationsSort"; +import { + OBSERVATIONS_SORT_OPTIONS, + useObservationsSortLabels, +} from "sharedHelpers/observationsSort"; import type { SPECIES_SORT } from "sharedHelpers/speciesSort"; import { MY_OBSERVATIONS_SPECIES_SORT_OPTIONS, @@ -65,11 +70,13 @@ interface Props { numUnuploadedObservations: number; numObsMissingBasics: number; observationIds: { uuid: string }[]; + observationsSortOptionId: OBSERVATIONS_SORT; onEndReached: ( ) => void; onListLayout?: ( ) => void; onScroll?: ( ) => void; openSheet: ACTIVE_SHEET; setActiveTab: ( newTab: string ) => void; + setObservationsSortOptionId: ( value: OBSERVATIONS_SORT ) => void; setOpenSheet: ( value: ACTIVE_SHEET ) => void; setSpeciesSortOptionId: ( value: SPECIES_SORT ) => void; showNoResults: boolean; @@ -95,6 +102,12 @@ interface TaxaSortOption { value: SPECIES_SORT; } +interface ObservationsSortOption { + label: string; + text?: string; + value: OBSERVATIONS_SORT; +} + export const OBSERVATIONS_TAB = "observations"; export const TAXA_TAB = "taxa"; @@ -115,11 +128,13 @@ const MyObservationsSimple = ( { numUnuploadedObservations, numObsMissingBasics: numUnuploadedObsMissingBasics, observationIds, + observationsSortOptionId, onEndReached, onListLayout, onScroll, openSheet, setActiveTab, + setObservationsSortOptionId, setOpenSheet, setSpeciesSortOptionId, showNoResults, @@ -141,6 +156,7 @@ const MyObservationsSimple = ( { FeatureFlag.SortMyObservationsEnabled, ); const speciesSortLabels = useSpeciesSortLabels( ); + const observationsSortLabels = useObservationsSortLabels( ); const navigation = useNavigation( ); const route = useRoute( ); const { @@ -166,6 +182,19 @@ const MyObservationsSimple = ( { {} as Record, ); + const observationsSortOptions = OBSERVATIONS_SORT_OPTIONS.reduce( + ( acc, sortBy ) => { + const { label, text } = observationsSortLabels[sortBy]; + acc[sortBy] = { + label, + text, + value: sortBy, + }; + return acc; + }, + {} as Record, + ); + const renderTaxaItem = useCallback( ( { item: speciesCount }: TaxaFlashListRenderItemProps ) => { const taxonId = speciesCount.taxon.id; const navToTaxonDetails = ( ) => ( @@ -306,7 +335,7 @@ const MyObservationsSimple = ( { Alert.alert( t( "You-are-offline" ), t( "Please-try-again-when-you-are-online" ) ); } - const handleSortConfirm = ( optionId: SPECIES_SORT ) => { + const handleSpeciesSortConfirm = ( optionId: SPECIES_SORT ) => { if ( currentUser && !isConnected ) { showOfflineAlert( ); return; @@ -324,6 +353,16 @@ const MyObservationsSimple = ( { setOpenSheet( ACTIVE_SHEET.NONE ); }; + const handleObservationsSortConfirm = ( optionId: OBSERVATIONS_SORT ) => { + if ( currentUser && !isConnected ) { + showOfflineAlert( ); + return; + } + setObservationsSortOptionId( optionId ); + + setOpenSheet( ACTIVE_SHEET.NONE ); + }; + const handlePivotCardGridItemPress = ( ) => { const { uuid } = observationIds[0]; navigation.navigate( { @@ -439,12 +478,21 @@ const MyObservationsSimple = ( { )} { ( activeTab === TAXA_TAB && taxa.length === 0 ) && renderOfflineNotice( )} - {openSheet === ACTIVE_SHEET.SORT && ( + {openSheet === ACTIVE_SHEET.SORT && activeTab === OBSERVATIONS_TAB && ( + handleObservationsSortConfirm( optionId as OBSERVATIONS_SORT )} + onPressClose={() => setOpenSheet( ACTIVE_SHEET.NONE )} + /> + )} + {openSheet === ACTIVE_SHEET.SORT && activeTab === TAXA_TAB && ( handleSortConfirm( optionId as SPECIES_SORT )} + confirm={optionId => handleSpeciesSortConfirm( optionId as SPECIES_SORT )} onPressClose={() => setOpenSheet( ACTIVE_SHEET.NONE )} /> )}