diff --git a/App.tsx b/App.tsx
index 8955ba7f..b8e152d3 100644
--- a/App.tsx
+++ b/App.tsx
@@ -424,11 +424,15 @@ const BaseApp: React.FunctionComponent<{
filter: (url: string) => url.includes('/observations/'), // Only handle observation links
config: {
screens: {
- Observations: {
+ MainStack: {
path: 'observations/#/view/observations',
screens: {
- observationsList: '',
- observation: ':id',
+ bottomTabs: {
+ screens: {
+ Observations: '',
+ },
+ },
+ observationModal: ':id',
},
},
},
diff --git a/components/observations/ObservationDetailView.tsx b/components/observations/ObservationDetailView.tsx
index 05de6649..4ae96bb6 100644
--- a/components/observations/ObservationDetailView.tsx
+++ b/components/observations/ObservationDetailView.tsx
@@ -1,5 +1,5 @@
import React, {useCallback, useMemo} from 'react';
-import {Image, ScrollView, StyleSheet} from 'react-native';
+import {Image, ScrollView} from 'react-native';
import Ionicons from '@expo/vector-icons/Ionicons';
import {useFocusEffect, useNavigation} from '@react-navigation/native';
@@ -46,7 +46,6 @@ import {
FormatSnowAvailableForTransport,
FormatWindLoading,
InstabilityDistribution,
- MapLayerFeature,
Observation,
Position,
SnowAvailableForTransport,
@@ -56,6 +55,7 @@ import {
} from 'types/nationalAvalancheCenter';
import {observationDateToLocalShortDateString, utcDateToLocalShortDateString} from 'utils/date';
+// TODO: Remove NWACObs issue:1152
export const NWACObservationDetailView: React.FunctionComponent<{
id: string;
}> = ({id}) => {
@@ -66,13 +66,11 @@ export const NWACObservationDetailView: React.FunctionComponent<{
const capabilitiesResult = useAvalancheCenterCapabilities();
const capabilities = capabilitiesResult.data;
- const mapFeatures = useMemo(() => mapFeaturesForCenter(mapLayer, observation?.center_id.toUpperCase() as AvalancheCenterID), [mapLayer, observation]);
-
if (incompleteQueryState(observationResult, mapResult, capabilitiesResult) || !observation || !mapLayer || !capabilities) {
return ;
}
- return ;
+ return ;
};
export const ObservationDetailView: React.FunctionComponent<{
@@ -86,12 +84,23 @@ export const ObservationDetailView: React.FunctionComponent<{
const capabilities = capabilitiesResult.data;
const mapFeatures = useMemo(() => mapFeaturesForCenter(mapLayer, observation?.center_id.toUpperCase() as AvalancheCenterID), [mapLayer, observation?.center_id]);
+ const navigation = useNavigation();
+ const zone_name = useMemo(
+ () => observation?.location_point?.lat && observation?.location_point?.lng && matchesZone(mapFeatures ?? [], observation.location_point?.lat, observation.location_point?.lng),
+ [observation, mapFeatures],
+ );
+
+ React.useEffect(() => {
+ if (zone_name) {
+ navigation.setOptions({title: `${zone_name} Observation`});
+ }
+ }, [navigation, zone_name]);
if (incompleteQueryState(observationResult, mapResult, capabilitiesResult) || !observation || !mapLayer || !capabilities || !capabilities) {
return ;
}
- return ;
+ return ;
};
const dataTableFlex = [1, 1];
@@ -177,18 +186,10 @@ export const withUnits = (value: string | number | null | undefined, units: stri
export const ObservationCard: React.FunctionComponent<{
observation: Observation;
- mapLayerFeatures: MapLayerFeature[];
capabilities: AllAvalancheCenterCapabilities;
-}> = ({observation, mapLayerFeatures, capabilities}) => {
- const navigation = useNavigation();
+}> = ({observation, capabilities}) => {
const {avalanches_observed, avalanches_triggered, avalanches_caught} = observation.instability;
- const zone_name =
- observation.location_point?.lat && observation.location_point?.lng && matchesZone(mapLayerFeatures, observation.location_point?.lat, observation.location_point?.lng);
- React.useEffect(() => {
- if (zone_name) {
- navigation.setOptions({title: `${zone_name} Observation`});
- }
- }, [navigation, zone_name]);
+
const postHog = usePostHog();
const recordAnalytics = useCallback(() => {
@@ -208,7 +209,7 @@ export const ObservationCard: React.FunctionComponent<{
const initialCameraBounds: CameraBounds = {ne: nePosition, sw: swPosition};
return (
-
+
diff --git a/components/observations/ObservationDetailViewModal.tsx b/components/observations/ObservationDetailViewModal.tsx
new file mode 100644
index 00000000..ba3f8547
--- /dev/null
+++ b/components/observations/ObservationDetailViewModal.tsx
@@ -0,0 +1,76 @@
+import Ionicons from '@expo/vector-icons/Ionicons';
+import {useNavigation} from '@react-navigation/native';
+import {AvalancheCenterLogo} from 'components/AvalancheCenterLogo';
+import {incompleteQueryState, QueryState} from 'components/content/QueryState';
+import {HStack, View} from 'components/core';
+import {ObservationCard} from 'components/observations/ObservationDetailView';
+import {matchesZone} from 'components/observations/ObservationsFilterForm';
+import {Title3Black} from 'components/text';
+import {useAllMapLayers} from 'hooks/useAllMapLayers';
+import {useAvalancheCenterCapabilities} from 'hooks/useAvalancheCenterCapabilities';
+import {useNACObservation} from 'hooks/useNACObservation';
+import React, {useCallback, useMemo} from 'react';
+import {MainStackNavigationProps} from 'routes';
+import {colorLookup} from 'theme';
+import {AvalancheCenterID, mapFeaturesForCenter} from 'types/nationalAvalancheCenter';
+
+export const ObservationDetailModalView: React.FunctionComponent<{
+ id: string;
+}> = ({id}) => {
+ const observationResult = useNACObservation(id);
+ const observation = observationResult.data;
+ const mapResult = useAllMapLayers();
+ const mapLayer = mapResult.data;
+ const capabilitiesResult = useAvalancheCenterCapabilities();
+ const capabilities = capabilitiesResult.data;
+
+ const mapFeatures = useMemo(() => mapFeaturesForCenter(mapLayer, observation?.center_id.toUpperCase() as AvalancheCenterID), [mapLayer, observation?.center_id]);
+ const navigation = useNavigation();
+ const zone_name = useMemo(
+ () => observation?.location_point?.lat && observation?.location_point?.lng && matchesZone(mapFeatures ?? [], observation.location_point?.lat, observation.location_point?.lng),
+ [observation, mapFeatures],
+ );
+
+ const closeModal = useCallback(() => navigation.goBack(), [navigation]);
+
+ if (incompleteQueryState(observationResult, mapResult, capabilitiesResult) || !observation || !mapLayer || !capabilities || !capabilities) {
+ return ;
+ }
+
+ return (
+
+
+
+
+ );
+};
+
+interface ObsDetailModalHeaderProps {
+ title: string;
+ centerId: AvalancheCenterID;
+ onClosePressed: () => void;
+}
+
+const ObsDetailModalHeader: React.FunctionComponent = ({title, centerId, onClosePressed}) => {
+ return (
+
+
+
+
+
+ {title}
+
+
+
+
+
+ );
+};
diff --git a/components/screens/navigation/MainStack.tsx b/components/screens/navigation/MainStack.tsx
index a33e94fc..ea7923ed 100644
--- a/components/screens/navigation/MainStack.tsx
+++ b/components/screens/navigation/MainStack.tsx
@@ -5,6 +5,7 @@ import {NavigationHeader} from 'components/content/NavigationHeader';
import {View} from 'components/core';
import {FeatureFlagsDebuggerScreen} from 'components/FeatureFlagsDebugger';
import {NWACObservationDetailView, ObservationDetailView} from 'components/observations/ObservationDetailView';
+import {ObservationDetailModalView} from 'components/observations/ObservationDetailViewModal';
import {ObservationForm} from 'components/observations/ObservationForm';
import {ObservationsPortal} from 'components/observations/ObservationsPortal';
import {ForecastScreen} from 'components/screens/ForecastScreen';
@@ -78,6 +79,16 @@ export const MainStackNavigator: React.FunctionComponent<{
title: 'Observation',
}}
/>
+
+
+
{
return ;
};
-export const ObservationDetailScreen = ({route}: NativeStackScreenProps) => {
+const ObservationDetailScreen = ({route}: NativeStackScreenProps) => {
const {id} = route.params;
return (
@@ -158,7 +169,17 @@ export const ObservationDetailScreen = ({route}: NativeStackScreenProps) => {
+const ObservationDetailModal = ({route}: NativeStackScreenProps) => {
+ const {id} = route.params;
+
+ return (
+
+
+
+ );
+};
+
+const NWACObservationDetailScreen = ({route}: NativeStackScreenProps) => {
const {id} = route.params;
return (
@@ -169,7 +190,7 @@ export const NWACObservationDetailScreen = ({route}: NativeStackScreenProps) => {
+const WeatherStationsDetailScreen = ({route}: NativeStackScreenProps) => {
const {preferences} = usePreferences();
const center_id = preferences.center;
return (
@@ -182,7 +203,7 @@ export const WeatherStationsDetailScreen = ({route}: NativeStackScreenProps) => {
+const WeatherStationDetailScreen = ({route}: NativeStackScreenProps) => {
const {preferences} = usePreferences();
const center_id = preferences.center;
return (
diff --git a/routes.ts b/routes.ts
index 006d5bdb..b0776daf 100644
--- a/routes.ts
+++ b/routes.ts
@@ -29,6 +29,9 @@ export type MainStackParamList = {
observation: {
id: string;
};
+ observationModal: {
+ id: string;
+ };
nwacObservation: {
id: string;
};