Skip to content

Commit

Permalink
feat: Only stop places checkbox in location search (#4719)
Browse files Browse the repository at this point in the history
When looking at geocoder request logs, we see that only ~8% of
location searches end up in the user selecting an address. They
instead use my position or a stop place.

To make searching for stop places easier we add a checkbox the user
can check so only stop places are returned when searching for a
location. We will enable this to a subset of the users, and see if
it is a feature which will be used.
  • Loading branch information
gorandalum committed Sep 20, 2024
1 parent 50636bb commit 3f6bd01
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/analytics/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type AnalyticsEventContext =
| 'Favorites'
| 'Flexible transport'
| 'Loading boundary'
| 'Location search'
| 'Map'
| 'Mobility'
| 'Onboarding'
Expand Down
4 changes: 3 additions & 1 deletion src/api/geocoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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},
);
Expand Down
48 changes: 48 additions & 0 deletions src/components/checkbox/CheckboxWithLabel.tsx
Original file line number Diff line number Diff line change
@@ -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<ViewStyle>;
}) => {
const {t} = useTranslation();
const styles = useStyles();

const a11yLabel =
label +
screenReaderPause +
t(checked ? dictionary.checked : dictionary.unchecked);

return (
<TouchableOpacity
style={[styles.container, style]}
accessible={true}
accessibilityLabel={a11yLabel}
onPress={() => onPress(!checked)}
>
<Checkbox checked={checked} />
<ThemeText color={color}>{label}</ThemeText>
</TouchableOpacity>
);
};

const useStyles = StyleSheet.createThemeHook((theme) => ({
container: {flexDirection: 'row', gap: theme.spacings.small},
}));
1 change: 1 addition & 0 deletions src/components/checkbox/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {Checkbox} from './Checkbox';
export {CheckboxWithLabel} from './CheckboxWithLabel';
4 changes: 3 additions & 1 deletion src/geocoder/use-geocoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useGeocoder(
text: string | null,
coords: Coordinates | null,
onlyLocalTariffZoneAuthority?: boolean,
onlyStopPlaces?: boolean,
): GeocoderState {
const [state, dispatch] = useGeocoderReducer();

Expand All @@ -25,6 +26,7 @@ export function useGeocoder(
text,
coords,
onlyLocalTariffZoneAuthority,
onlyStopPlaces,
{
cancelToken: source.token,
},
Expand All @@ -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;
}
6 changes: 6 additions & 0 deletions src/remote-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -48,6 +51,7 @@ export function LocationSearchContent({
const {favorites} = useFavorites();
const {history, addSearchEntry} = useSearchHistory();
const {t} = useTranslation();
const analytics = useAnalytics();

const [text, setText] = useState<string>(defaultText ?? '');
const debouncedText = useDebounce(text, 200);
Expand All @@ -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[] =
Expand Down Expand Up @@ -141,6 +149,22 @@ export function LocationSearchContent({
onAddFavorite={onAddFavorite}
/>
)}
{onlyStopPlacesCheckboxEnabled && (
<CheckboxWithLabel
label={t(LocationSearchTexts.onlyStopPlacesCheckbox)}
checked={onlyStopPlaces}
onPress={(v) => {
analytics.logEvent(
'Location search',
'Only stop places checkbox pressed',
{checked: v},
);
setOnlyStopPlaces(v);
}}
color="background_accent_0"
style={styles.onlyStopPlacesCheckbox}
/>
)}
</View>
{error && (
<View style={styles.withMargin}>
Expand Down Expand Up @@ -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,
},
Expand Down
Original file line number Diff line number Diff line change
@@ -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,
);
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -145,6 +146,8 @@ export const Profile_DebugInfoScreen = () => {
useActivateTicketNowEnabledDebugOverride();
const backendSmsAuthEnabledDebugOverride =
useBackendSmsAuthEnabledDebugOverride();
const onlyStopPlacesCheckboxEnabledDebugOverride =
useOnlyStopPlacesCheckboxEnabledDebugOverride();

useEffect(() => {
(async function () {
Expand Down Expand Up @@ -484,6 +487,12 @@ export const Profile_DebugInfoScreen = () => {
override={backendSmsAuthEnabledDebugOverride}
/>
</GenericSectionItem>
<GenericSectionItem>
<DebugOverride
description="Enable only stop places checkbox"
override={onlyStopPlacesCheckboxEnabledDebugOverride}
/>
</GenericSectionItem>
</Section>

<Section style={styles.section}>
Expand Down
1 change: 1 addition & 0 deletions src/storage/StorageModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions src/translations/screens/subscreens/LocationSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,10 @@ const LocationSearchTexts = {
},
},
},
onlyStopPlacesCheckbox: _(
'Vis kun holdeplasser',
'Show only stop places',
'Vis berre haldeplassar',
),
};
export default LocationSearchTexts;

0 comments on commit 3f6bd01

Please sign in to comment.