diff --git a/src/analytics/types.ts b/src/analytics/types.ts index b97a976ac3..cb9aa3aff3 100644 --- a/src/analytics/types.ts +++ b/src/analytics/types.ts @@ -5,6 +5,7 @@ export type AnalyticsEventContext = | 'Favorites' | 'Flexible transport' | 'Loading boundary' + | 'Location search' | 'Map' | 'Mobility' | 'Onboarding' diff --git a/src/api/geocoder.ts b/src/api/geocoder.ts index 62f0f7630d..25a529d9ab 100644 --- a/src/api/geocoder.ts +++ b/src/api/geocoder.ts @@ -14,6 +14,7 @@ export async function autocomplete( text: string, coordinates: Coordinates | null, onlyLocalTariffZoneAuthority: boolean = false, + onlyStopPlaces: boolean = false, config?: AxiosRequestConfig, ) { const url = 'bff/v1/geocoder/features'; @@ -26,7 +27,8 @@ export async function autocomplete( tariff_zone_authorities: onlyLocalTariffZoneAuthority ? TARIFF_ZONE_AUTHORITY : null, - multiModal: 'parent' + layers: onlyStopPlaces ? ['venue'] : undefined, + multiModal: 'parent', }, {skipNull: true}, ); diff --git a/src/components/checkbox/CheckboxWithLabel.tsx b/src/components/checkbox/CheckboxWithLabel.tsx new file mode 100644 index 0000000000..b8ab004567 --- /dev/null +++ b/src/components/checkbox/CheckboxWithLabel.tsx @@ -0,0 +1,48 @@ +import { + screenReaderPause, + ThemeText, + ThemeTextProps, +} from '@atb/components/text'; +import {StyleProp, TouchableOpacity, ViewStyle} from 'react-native'; +import {dictionary, useTranslation} from '@atb/translations'; +import {Checkbox} from '.'; +import React from 'react'; +import {StyleSheet} from '@atb/theme'; + +export const CheckboxWithLabel = ({ + label, + checked, + onPress, + color, + style, +}: { + label: string; + checked: boolean; + onPress: (v: boolean) => void; + color?: ThemeTextProps['color']; + style: StyleProp; +}) => { + const {t} = useTranslation(); + const styles = useStyles(); + + const a11yLabel = + label + + screenReaderPause + + t(checked ? dictionary.checked : dictionary.unchecked); + + return ( + onPress(!checked)} + > + + {label} + + ); +}; + +const useStyles = StyleSheet.createThemeHook((theme) => ({ + container: {flexDirection: 'row', gap: theme.spacings.small}, +})); diff --git a/src/components/checkbox/index.ts b/src/components/checkbox/index.ts index f96d6970e4..158cd53340 100644 --- a/src/components/checkbox/index.ts +++ b/src/components/checkbox/index.ts @@ -1 +1,2 @@ export {Checkbox} from './Checkbox'; +export {CheckboxWithLabel} from './CheckboxWithLabel'; diff --git a/src/geocoder/use-geocoder.ts b/src/geocoder/use-geocoder.ts index 4f9e8dd69f..cf0bbd9e24 100644 --- a/src/geocoder/use-geocoder.ts +++ b/src/geocoder/use-geocoder.ts @@ -10,6 +10,7 @@ export function useGeocoder( text: string | null, coords: Coordinates | null, onlyLocalTariffZoneAuthority?: boolean, + onlyStopPlaces?: boolean, ): GeocoderState { const [state, dispatch] = useGeocoderReducer(); @@ -25,6 +26,7 @@ export function useGeocoder( text, coords, onlyLocalTariffZoneAuthority, + onlyStopPlaces, { cancelToken: source.token, }, @@ -48,7 +50,7 @@ export function useGeocoder( textLookup(); return () => source.cancel('Cancelling previous autocomplete'); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [coords?.latitude, coords?.longitude, text]); + }, [coords?.latitude, coords?.longitude, text, onlyStopPlaces]); return state; } diff --git a/src/remote-config.ts b/src/remote-config.ts index b657c3b27c..3e9d145b61 100644 --- a/src/remote-config.ts +++ b/src/remote-config.ts @@ -46,6 +46,7 @@ export type RemoteConfig = { enable_vipps_login: boolean; enable_save_ticket_recipients: boolean; enable_shmo_deep_integration: boolean; + enable_only_stop_places_checkbox: boolean; favourite_departures_poll_interval: number; feedback_questions: string; flex_booking_number_of_days_available: number; @@ -111,6 +112,7 @@ export const defaultRemoteConfig: RemoteConfig = { enable_vipps_login: false, enable_save_ticket_recipients: false, enable_shmo_deep_integration: false, + enable_only_stop_places_checkbox: false, favourite_departures_poll_interval: 30000, feedback_questions: '', flex_booking_number_of_days_available: 7, @@ -247,6 +249,9 @@ export function getConfig(): RemoteConfig { const enable_shmo_deep_integration = values['enable_shmo_deep_integration']?.asBoolean() ?? defaultRemoteConfig.enable_shmo_deep_integration; + const enable_only_stop_places_checkbox = + values['enable_only_stop_places_checkbox']?.asBoolean() ?? + defaultRemoteConfig.enable_only_stop_places_checkbox; const favourite_departures_poll_interval = values['favourite_departures_poll_interval']?.asNumber() ?? defaultRemoteConfig.favourite_departures_poll_interval; @@ -344,6 +349,7 @@ export function getConfig(): RemoteConfig { enable_vipps_login, enable_save_ticket_recipients, enable_shmo_deep_integration, + enable_only_stop_places_checkbox, favourite_departures_poll_interval, feedback_questions, flex_booking_number_of_days_available, diff --git a/src/stacks-hierarchy/Root_LocationSearchByTextScreen/components/LocationSearchContent.tsx b/src/stacks-hierarchy/Root_LocationSearchByTextScreen/components/LocationSearchContent.tsx index 17b94a181a..08f9b49a3a 100644 --- a/src/stacks-hierarchy/Root_LocationSearchByTextScreen/components/LocationSearchContent.tsx +++ b/src/stacks-hierarchy/Root_LocationSearchByTextScreen/components/LocationSearchContent.tsx @@ -18,6 +18,9 @@ import {LocationResults} from './LocationResults'; import {StyleSheet} from '@atb/theme'; import {translateErrorType} from '@atb/stacks-hierarchy/utils'; import {animateNextChange} from '@atb/utils/animation'; +import {CheckboxWithLabel} from '@atb/components/checkbox'; +import {useOnlyStopPlacesCheckboxEnabled} from '../use-only-stop-places-checkbox-enabled.tsx'; +import {useAnalytics} from '@atb/analytics'; type LocationSearchContentProps = { label: string; @@ -48,6 +51,7 @@ export function LocationSearchContent({ const {favorites} = useFavorites(); const {history, addSearchEntry} = useSearchHistory(); const {t} = useTranslation(); + const analytics = useAnalytics(); const [text, setText] = useState(defaultText ?? ''); const debouncedText = useDebounce(text, 200); @@ -60,12 +64,16 @@ export function LocationSearchContent({ onlyLocalTariffZoneAuthority, ); + const onlyStopPlacesCheckboxEnabled = useOnlyStopPlacesCheckboxEnabled(); + const [onlyStopPlaces, setOnlyStopPlaces] = useState(false); + const {location: geolocation} = useGeolocationState(); const {locations, error, isSearching} = useGeocoder( debouncedText, geolocation?.coordinates ?? null, onlyLocalTariffZoneAuthority, + onlyStopPlaces, ); const locationSearchResults: LocationSearchResultType[] = @@ -141,6 +149,22 @@ export function LocationSearchContent({ onAddFavorite={onAddFavorite} /> )} + {onlyStopPlacesCheckboxEnabled && ( + { + analytics.logEvent( + 'Location search', + 'Only stop places checkbox pressed', + {checked: v}, + ); + setOnlyStopPlaces(v); + }} + color="background_accent_0" + style={styles.onlyStopPlacesCheckbox} + /> + )} {error && ( @@ -212,6 +236,10 @@ const useThemeStyles = StyleSheet.createThemeHook((theme) => ({ marginTop: theme.spacings.medium, paddingHorizontal: theme.spacings.medium, }, + onlyStopPlacesCheckbox: { + marginTop: theme.spacings.medium, + paddingHorizontal: theme.spacings.medium, + }, contentBlock: { marginHorizontal: theme.spacings.medium, }, diff --git a/src/stacks-hierarchy/Root_LocationSearchByTextScreen/use-only-stop-places-checkbox-enabled.tsx b/src/stacks-hierarchy/Root_LocationSearchByTextScreen/use-only-stop-places-checkbox-enabled.tsx new file mode 100644 index 0000000000..ca23991847 --- /dev/null +++ b/src/stacks-hierarchy/Root_LocationSearchByTextScreen/use-only-stop-places-checkbox-enabled.tsx @@ -0,0 +1,16 @@ +import {useRemoteConfig} from '@atb/RemoteConfigContext'; +import {useDebugOverride} from '@atb/debug'; +import {StorageModelKeysEnum} from '@atb/storage'; + +export const useOnlyStopPlacesCheckboxEnabled = () => { + const {enable_only_stop_places_checkbox} = useRemoteConfig(); + const [debugOverride] = useOnlyStopPlacesCheckboxEnabledDebugOverride(); + return debugOverride !== undefined + ? debugOverride + : enable_only_stop_places_checkbox; +}; + +export const useOnlyStopPlacesCheckboxEnabledDebugOverride = () => + useDebugOverride( + StorageModelKeysEnum.EnableOnlyStopPlacesCheckboxDebugOverride, + ); diff --git a/src/stacks-hierarchy/Root_TabNavigatorStack/TabNav_ProfileStack/Profile_DebugInfoScreen.tsx b/src/stacks-hierarchy/Root_TabNavigatorStack/TabNav_ProfileStack/Profile_DebugInfoScreen.tsx index d263c44aeb..f2bcf57b64 100644 --- a/src/stacks-hierarchy/Root_TabNavigatorStack/TabNav_ProfileStack/Profile_DebugInfoScreen.tsx +++ b/src/stacks-hierarchy/Root_TabNavigatorStack/TabNav_ProfileStack/Profile_DebugInfoScreen.tsx @@ -68,6 +68,7 @@ import {useServerTimeEnabledDebugOverride} from '@atb/time'; import Bugsnag from '@bugsnag/react-native'; import {useActivateTicketNowEnabledDebugOverride} from '@atb/fare-contracts/use-is-activate-now-enabled'; import {useBackendSmsAuthEnabledDebugOverride} from '@atb/auth/use-is-backend-sms-auth-enabled'; +import {useOnlyStopPlacesCheckboxEnabledDebugOverride} from '@atb/stacks-hierarchy/Root_LocationSearchByTextScreen/use-only-stop-places-checkbox-enabled.tsx'; function setClipboard(content: string) { Clipboard.setString(content); @@ -145,6 +146,8 @@ export const Profile_DebugInfoScreen = () => { useActivateTicketNowEnabledDebugOverride(); const backendSmsAuthEnabledDebugOverride = useBackendSmsAuthEnabledDebugOverride(); + const onlyStopPlacesCheckboxEnabledDebugOverride = + useOnlyStopPlacesCheckboxEnabledDebugOverride(); useEffect(() => { (async function () { @@ -484,6 +487,12 @@ export const Profile_DebugInfoScreen = () => { override={backendSmsAuthEnabledDebugOverride} /> + + +
diff --git a/src/storage/StorageModel.tsx b/src/storage/StorageModel.tsx index 86197422cb..dea80d638f 100644 --- a/src/storage/StorageModel.tsx +++ b/src/storage/StorageModel.tsx @@ -27,6 +27,7 @@ export enum StorageModelKeysEnum { EnableVehiclesInMapDebugOverride = '@ATB_enable_vehicles_in_map_debug_override', EnableSaveTicketRecipientsDebugOverride = '@ATB_enable_save_ticket_recipients_debug_override', EnableShmoDeepIntegrationDebugOverride = '@ATB_enable_shmo_deep_integration_debug_override', + EnableOnlyStopPlacesCheckboxDebugOverride = '@ATB_enable_only_stop_places_checkbox_debug_override', OneTimePopOver = '@ATB_one_time_popovers_seen', ShowValidTimeInfoDebugOverride = '@ATB_show_valid_time_info_debug_override', UseFlexibleTransportAccessModeDebugOverride = '@ATB_use_flexible_on_accessMode', diff --git a/src/translations/screens/subscreens/LocationSearch.ts b/src/translations/screens/subscreens/LocationSearch.ts index 1944a2a319..168aff7c4e 100644 --- a/src/translations/screens/subscreens/LocationSearch.ts +++ b/src/translations/screens/subscreens/LocationSearch.ts @@ -123,5 +123,10 @@ const LocationSearchTexts = { }, }, }, + onlyStopPlacesCheckbox: _( + 'Vis kun holdeplasser', + 'Show only stop places', + 'Vis berre haldeplassar', + ), }; export default LocationSearchTexts;