mirror of
https://github.com/inaturalist/iNaturalistReactNative.git
synced 2025-12-23 22:18:36 -05:00
1746 radio bottom sheet (#1769)
* Update radio bottom sheet element margins and paddings
* Update radio button row element margins and paddings
* Revert "Update radio button row element margins and paddings"
This reverts commit 269882b93c.
* Label margin
* Explainer
* Add four pixel between radio button and text
* Actually, let's patch the radio button to not have intrinsic margin, that makes everything easy peasy
* Create react-native-paper+5.12.3.patch
* Add margin between label and description
* RadioButtonRow TS
* Icon is optional
* Update RadioButtonSheet.js
* RadioButtonSheet TS
* Radio labels in ExploreFilters should be smaller
* BottomSheetStandardBackdrop TS
* Move key
* Update Settings radio button containers
* Update containers of radio filters
* Modal TS
* Update types
* Update types
* Update interface
* Update types
* Update types
This commit is contained in:
12
patches/react-native-paper+5.12.3.patch
Normal file
12
patches/react-native-paper+5.12.3.patch
Normal file
@@ -0,0 +1,12 @@
|
||||
diff --git a/node_modules/react-native-paper/src/components/RadioButton/RadioButtonAndroid.tsx b/node_modules/react-native-paper/src/components/RadioButton/RadioButtonAndroid.tsx
|
||||
index 515efe5..67082de 100644
|
||||
--- a/node_modules/react-native-paper/src/components/RadioButton/RadioButtonAndroid.tsx
|
||||
+++ b/node_modules/react-native-paper/src/components/RadioButton/RadioButtonAndroid.tsx
|
||||
@@ -187,7 +187,6 @@ const styles = StyleSheet.create({
|
||||
height: 20,
|
||||
width: 20,
|
||||
borderRadius: 10,
|
||||
- margin: 8,
|
||||
},
|
||||
dot: {
|
||||
height: 10,
|
||||
@@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import type { Node } from "react";
|
||||
import React from "react";
|
||||
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// @flow
|
||||
|
||||
import ExploreLocationSearch from "components/Explore/SearchScreens/ExploreLocationSearch";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import type { Node } from "react";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
showModal: boolean,
|
||||
closeModal: Function,
|
||||
updateLocation: Function
|
||||
showModal: boolean;
|
||||
closeModal: () => void;
|
||||
// TODO: Param not typed yet, because ExploreLocationSearch is not typed yet
|
||||
updateLocation: ( _location: any ) => void;
|
||||
}
|
||||
|
||||
const ExploreLocationSearchModal = ( {
|
||||
showModal,
|
||||
closeModal,
|
||||
updateLocation
|
||||
}: Props ): Node => (
|
||||
}: Props ) => (
|
||||
<Modal
|
||||
showModal={showModal}
|
||||
fullScreen
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// @flow
|
||||
|
||||
import ExploreProjectSearch from "components/Explore/SearchScreens/ExploreProjectSearch";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import type { Node } from "react";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
showModal: boolean,
|
||||
closeModal: Function,
|
||||
updateProject: Function
|
||||
showModal: boolean;
|
||||
closeModal: () => void;
|
||||
// TODO: Param not typed yet, because ExploreProjectSearch is not typed yet
|
||||
updateProject: ( _project: any ) => void;
|
||||
}
|
||||
|
||||
const ExploreProjectSearchModal = ( {
|
||||
showModal,
|
||||
closeModal,
|
||||
updateProject
|
||||
}: Props ): Node => (
|
||||
}: Props ) => (
|
||||
<Modal
|
||||
showModal={showModal}
|
||||
fullScreen
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import ExploreTaxonSearch from "components/Explore/SearchScreens/ExploreTaxonSearch";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import type { Node } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// @flow
|
||||
|
||||
import ExploreUserSearch from "components/Explore/SearchScreens/ExploreUserSearch";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import type { Node } from "react";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import React from "react";
|
||||
|
||||
interface Props {
|
||||
showModal: boolean,
|
||||
closeModal: Function,
|
||||
updateUser: Function
|
||||
showModal: boolean;
|
||||
closeModal: () => void;
|
||||
// TODO: Param not typed yet, because ExploreUserSearch is not typed yet
|
||||
updateUser: ( _user: any ) => void;
|
||||
}
|
||||
|
||||
const ExploreUserSearchModal = ( {
|
||||
showModal,
|
||||
closeModal,
|
||||
updateUser
|
||||
}: Props ): Node => (
|
||||
}: Props ) => (
|
||||
<Modal
|
||||
showModal={showModal}
|
||||
fullScreen
|
||||
|
||||
@@ -57,12 +57,15 @@ const DROP_SHADOW = getShadowForColor( colors.darkGray, {
|
||||
const { useRealm } = RealmContext;
|
||||
|
||||
interface Props {
|
||||
closeModal: Function,
|
||||
filterByIconicTaxonUnknown: Function
|
||||
updateTaxon: Function,
|
||||
updateLocation: Function,
|
||||
updateUser: Function,
|
||||
updateProject: Function
|
||||
closeModal: () => void;
|
||||
filterByIconicTaxonUnknown: () => void;
|
||||
updateTaxon: ( _taxon: Object | null ) => void;
|
||||
// TODO: Param not typed yet, because ExploreLocationSearch is not typed yet
|
||||
updateLocation: ( _location: any ) => void;
|
||||
// TODO: Param not typed yet, because ExploreUserSearch is not typed yet
|
||||
updateUser: ( _user: any ) => void;
|
||||
// TODO: Param not typed yet, because ExploreProjectSearch is not typed yet
|
||||
updateProject: ( _project: any ) => void;
|
||||
}
|
||||
|
||||
const FilterModal = ( {
|
||||
@@ -1084,75 +1087,84 @@ const FilterModal = ( {
|
||||
</View>
|
||||
|
||||
{/* Media section */}
|
||||
<View className="mb-7">
|
||||
<View className="mb-3">
|
||||
<Heading4 className="mb-5">{t( "MEDIA" )}</Heading4>
|
||||
{Object.keys( mediaValues ).map( mediaKey => (
|
||||
<RadioButtonRow
|
||||
key={mediaKey}
|
||||
value={mediaValues[mediaKey]}
|
||||
checked={mediaValues[mediaKey].value === media}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_MEDIA,
|
||||
media: mediaValues[mediaKey].value
|
||||
} )}
|
||||
label={mediaValues[mediaKey].label}
|
||||
/>
|
||||
<View key={mediaKey} className="mb-4">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
value={mediaValues[mediaKey]}
|
||||
checked={mediaValues[mediaKey].value === media}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_MEDIA,
|
||||
media: mediaValues[mediaKey].value
|
||||
} )}
|
||||
label={mediaValues[mediaKey].label}
|
||||
/>
|
||||
</View>
|
||||
) )}
|
||||
</View>
|
||||
|
||||
{/* Establishment Means section */}
|
||||
<View className="mb-7">
|
||||
<View className="mb-3">
|
||||
<Heading4 className="mb-5">{t( "ESTABLISHMENT-MEANS" )}</Heading4>
|
||||
{Object.keys( establishmentValues ).map( establishmentKey => (
|
||||
<RadioButtonRow
|
||||
key={establishmentKey}
|
||||
value={establishmentValues[establishmentKey]}
|
||||
checked={
|
||||
establishmentValues[establishmentKey].value
|
||||
=== establishmentMean
|
||||
}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_ESTABLISHMENT_MEAN,
|
||||
establishmentMean:
|
||||
<View key={establishmentKey} className="mb-4">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
value={establishmentValues[establishmentKey]}
|
||||
checked={
|
||||
establishmentValues[establishmentKey].value
|
||||
} )}
|
||||
label={establishmentValues[establishmentKey].label}
|
||||
/>
|
||||
=== establishmentMean
|
||||
}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_ESTABLISHMENT_MEAN,
|
||||
establishmentMean:
|
||||
establishmentValues[establishmentKey].value
|
||||
} )}
|
||||
label={establishmentValues[establishmentKey].label}
|
||||
/>
|
||||
</View>
|
||||
) )}
|
||||
</View>
|
||||
|
||||
{/* Wild Status section */}
|
||||
<View className="mb-7">
|
||||
<View className="mb-3">
|
||||
<Heading4 className="mb-5">{t( "WILD-STATUS" )}</Heading4>
|
||||
{Object.keys( wildValues ).map( wildKey => (
|
||||
<RadioButtonRow
|
||||
key={wildKey}
|
||||
value={wildValues[wildKey]}
|
||||
checked={wildValues[wildKey].value === wildStatus}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_WILD_STATUS,
|
||||
wildStatus: wildValues[wildKey].value
|
||||
} )}
|
||||
label={wildValues[wildKey].label}
|
||||
/>
|
||||
<View key={wildKey} className="mb-4">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
value={wildValues[wildKey]}
|
||||
checked={wildValues[wildKey].value === wildStatus}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_WILD_STATUS,
|
||||
wildStatus: wildValues[wildKey].value
|
||||
} )}
|
||||
label={wildValues[wildKey].label}
|
||||
/>
|
||||
</View>
|
||||
) )}
|
||||
</View>
|
||||
|
||||
{/* Reviewed section */}
|
||||
{currentUser && (
|
||||
<View className="mb-7">
|
||||
<View className="mb-3">
|
||||
<Heading4 className="mb-5">{t( "REVIEWED" )}</Heading4>
|
||||
{Object.keys( reviewedValues ).map( reviewedKey => (
|
||||
<RadioButtonRow
|
||||
key={reviewedKey}
|
||||
value={reviewedValues[reviewedKey]}
|
||||
checked={reviewedValues[reviewedKey].value === reviewedFilter}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_REVIEWED,
|
||||
reviewedFilter: reviewedValues[reviewedKey].value
|
||||
} )}
|
||||
label={reviewedValues[reviewedKey].label}
|
||||
/>
|
||||
<View key={reviewedKey} className="mb-4">
|
||||
<RadioButtonRow
|
||||
key={reviewedKey}
|
||||
smallLabel
|
||||
value={reviewedValues[reviewedKey]}
|
||||
checked={reviewedValues[reviewedKey].value === reviewedFilter}
|
||||
onPress={() => dispatch( {
|
||||
type: EXPLORE_ACTION.SET_REVIEWED,
|
||||
reviewedFilter: reviewedValues[reviewedKey].value
|
||||
} )}
|
||||
label={reviewedValues[reviewedKey].label}
|
||||
/>
|
||||
</View>
|
||||
) )}
|
||||
</View>
|
||||
)}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import MediaViewer from "components/MediaViewer/MediaViewer";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import type { Node } from "react";
|
||||
import React from "react";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
Heading2
|
||||
} from "components/SharedComponents";
|
||||
import GradientButton from "components/SharedComponents/Buttons/GradientButton";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import { View } from "components/styledComponents";
|
||||
import type { Node } from "react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
@@ -143,7 +143,7 @@ const Settings = ( ) => {
|
||||
<>
|
||||
<Heading4>{t( "OBSERVATION-BUTTON" )}</Heading4>
|
||||
<Body2 className="mt-3">{t( "When-tapping-the-green-observation-button" )}</Body2>
|
||||
<View className="mt-5">
|
||||
<View className="mt-[22px] pr-5">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
checked={!isAdvancedUser}
|
||||
@@ -151,7 +151,7 @@ const Settings = ( ) => {
|
||||
label={t( "iNaturalist-AI-Camera" )}
|
||||
/>
|
||||
</View>
|
||||
<View className="mt-2 pr-5">
|
||||
<View className="mt-4 pr-5">
|
||||
<RadioButtonRow
|
||||
testID="all-observation-option"
|
||||
smallLabel
|
||||
@@ -167,7 +167,7 @@ const Settings = ( ) => {
|
||||
<>
|
||||
<Heading4 className="mt-7">{t( "TAXON-NAMES-DISPLAY" )}</Heading4>
|
||||
<Body2 className="mt-3">{t( "This-is-how-taxon-names-will-be-displayed" )}</Body2>
|
||||
<View className="mt-5">
|
||||
<View className="mt-[22px]">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
checked={settings.prefers_common_names && !settings.prefers_scientific_name_first}
|
||||
@@ -175,7 +175,7 @@ const Settings = ( ) => {
|
||||
label={t( "Common-Name-Scientific-Name" )}
|
||||
/>
|
||||
</View>
|
||||
<View className="mt-2">
|
||||
<View className="mt-4">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
checked={settings.prefers_common_names && settings.prefers_scientific_name_first}
|
||||
@@ -183,7 +183,7 @@ const Settings = ( ) => {
|
||||
label={t( "Scientific-Name-Common-Name" )}
|
||||
/>
|
||||
</View>
|
||||
<View className="mt-2">
|
||||
<View className="mt-4">
|
||||
<RadioButtonRow
|
||||
smallLabel
|
||||
checked={!settings.prefers_common_names && !settings.prefers_scientific_name_first}
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
// @flow
|
||||
import * as React from "react";
|
||||
import { ViewStyle } from "react-native";
|
||||
import RNModal from "react-native-modal";
|
||||
|
||||
// repurposed from Seek: https://github.com/inaturalist/SeekReactNative/blob/main/components/UIComponents/Modals/Modal.js
|
||||
|
||||
type Props = {
|
||||
showModal: boolean,
|
||||
closeModal: Function,
|
||||
// $FlowIgnore
|
||||
modal: unknown,
|
||||
backdropOpacity?: number,
|
||||
fullScreen?: boolean,
|
||||
onModalHide?: Function,
|
||||
style?: Object,
|
||||
animationIn?: string,
|
||||
animationOut?: string,
|
||||
disableSwipeDirection?: boolean
|
||||
interface Props {
|
||||
showModal: boolean;
|
||||
closeModal: () => void;
|
||||
modal: React.ReactNode,
|
||||
backdropOpacity?: number;
|
||||
fullScreen?: boolean;
|
||||
onModalHide?: () => void,
|
||||
style?: ViewStyle,
|
||||
animationIn?: string;
|
||||
animationOut?: string;
|
||||
disableSwipeDirection?: boolean;
|
||||
}
|
||||
|
||||
const modalStyle = {
|
||||
flex: 1,
|
||||
justifyContent: "flex-end"
|
||||
};
|
||||
} as const;
|
||||
|
||||
const fullScreenModalStyle = {
|
||||
...modalStyle,
|
||||
margin: 0
|
||||
};
|
||||
} as const;
|
||||
|
||||
// accessibility might not work on Android because of backdrop
|
||||
// https://github.com/react-native-modal/react-native-modal/issues/525
|
||||
@@ -42,9 +41,9 @@ const Modal = ( {
|
||||
onModalHide,
|
||||
showModal,
|
||||
style
|
||||
}: Props ): React.Node => {
|
||||
}: Props ) => {
|
||||
const swipeDirection = disableSwipeDirection
|
||||
? null
|
||||
? undefined
|
||||
: "down";
|
||||
return (
|
||||
<RNModal
|
||||
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import { useNavigation } from "@react-navigation/native";
|
||||
import Modal from "components/SharedComponents/Modal";
|
||||
import Modal from "components/SharedComponents/Modal.tsx";
|
||||
import _ from "lodash";
|
||||
import type { Node } from "react";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @flow
|
||||
import {
|
||||
Body1,
|
||||
Body2,
|
||||
@@ -6,19 +5,19 @@ import {
|
||||
List2
|
||||
} from "components/SharedComponents";
|
||||
import { Pressable, View } from "components/styledComponents";
|
||||
import type { Node } from "react";
|
||||
import React from "react";
|
||||
import { GestureResponderEvent } from "react-native";
|
||||
import { RadioButton, useTheme } from "react-native-paper";
|
||||
|
||||
type Props = {
|
||||
testID: string,
|
||||
checked: boolean,
|
||||
description: ?string,
|
||||
icon: string,
|
||||
label: string,
|
||||
onPress: Function,
|
||||
value: string,
|
||||
smallLabel: ?boolean
|
||||
interface Props {
|
||||
testID?: string;
|
||||
icon?: string;
|
||||
label: string;
|
||||
smallLabel?: boolean;
|
||||
description?: string;
|
||||
onPress: ( _e: GestureResponderEvent ) => void;
|
||||
checked: boolean;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const RadioButtonRow = ( {
|
||||
@@ -30,7 +29,7 @@ const RadioButtonRow = ( {
|
||||
icon,
|
||||
value,
|
||||
smallLabel = false
|
||||
}: Props ): Node => {
|
||||
}: Props ) => {
|
||||
const theme = useTheme( );
|
||||
|
||||
const status = checked
|
||||
@@ -50,13 +49,13 @@ const RadioButtonRow = ( {
|
||||
status={status}
|
||||
accessibilityLabel={label}
|
||||
/>
|
||||
<View className="flex-row">
|
||||
<Label className="mr-2">{label}</Label>
|
||||
<View className="ml-3 flex-row">
|
||||
<Label className="mr-[10px]">{label}</Label>
|
||||
{icon && <INatIcon name={icon} size={19} color={theme.colors.secondary} />}
|
||||
</View>
|
||||
</View>
|
||||
{description && (
|
||||
<List2 className="ml-[37px] mr-[33px] py-1">{description}</List2>
|
||||
<List2 className="ml-[32px] mt-[3px]">{description}</List2>
|
||||
)}
|
||||
</Pressable>
|
||||
);
|
||||
@@ -1,16 +1,14 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
BottomSheetBackdrop
|
||||
BottomSheetBackdrop,
|
||||
BottomSheetBackdropProps
|
||||
} from "@gorhom/bottom-sheet";
|
||||
import type { Node } from "react";
|
||||
import React from "react";
|
||||
|
||||
type Props = {
|
||||
props: Object
|
||||
props: BottomSheetBackdropProps
|
||||
}
|
||||
|
||||
const BottomSheetStandardBackdrop = ( { props }: Props ): Node => (
|
||||
const BottomSheetStandardBackdrop = ( { props }: Props ) => (
|
||||
<BottomSheetBackdrop
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
@@ -1,65 +0,0 @@
|
||||
// @flow
|
||||
|
||||
import {
|
||||
BottomSheet,
|
||||
Button,
|
||||
RadioButtonRow
|
||||
} from "components/SharedComponents";
|
||||
import { View } from "components/styledComponents";
|
||||
import type { Node } from "react";
|
||||
import React, { useState } from "react";
|
||||
import useTranslation from "sharedHooks/useTranslation";
|
||||
|
||||
type Props = {
|
||||
handleClose: Function,
|
||||
confirm: Function,
|
||||
headerText: string,
|
||||
radioValues: Object,
|
||||
selectedValue?: string,
|
||||
insideModal?: boolean
|
||||
}
|
||||
|
||||
const RadioButtonSheet = ( {
|
||||
handleClose,
|
||||
confirm,
|
||||
headerText,
|
||||
radioValues,
|
||||
selectedValue = "none",
|
||||
insideModal
|
||||
}: Props ): Node => {
|
||||
const { t } = useTranslation( );
|
||||
const [checked, setChecked] = useState( selectedValue );
|
||||
|
||||
const radioButtonRow = radioRow => (
|
||||
<RadioButtonRow
|
||||
key={radioRow}
|
||||
value={radioValues[radioRow].value}
|
||||
icon={radioValues[radioRow].icon}
|
||||
checked={checked === radioValues[radioRow].value}
|
||||
onPress={() => setChecked( radioValues[radioRow].value )}
|
||||
label={radioValues[radioRow].label}
|
||||
description={radioValues[radioRow].text}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<BottomSheet
|
||||
handleClose={handleClose}
|
||||
headerText={headerText}
|
||||
insideModal={insideModal}
|
||||
>
|
||||
<View className="p-5">
|
||||
{Object.keys( radioValues ).map( radioRow => radioButtonRow( radioRow ) )}
|
||||
<Button
|
||||
level="primary"
|
||||
onPress={( ) => confirm( checked )}
|
||||
text={radioValues[checked]?.buttonText ?? t( "CONFIRM" )}
|
||||
className="mt-[15px]"
|
||||
accessibilityLabel={radioValues[checked]?.buttonText ?? t( "CONFIRM" )}
|
||||
/>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButtonSheet;
|
||||
72
src/components/SharedComponents/Sheets/RadioButtonSheet.tsx
Normal file
72
src/components/SharedComponents/Sheets/RadioButtonSheet.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import {
|
||||
BottomSheet,
|
||||
Button,
|
||||
RadioButtonRow
|
||||
} from "components/SharedComponents";
|
||||
import { View } from "components/styledComponents";
|
||||
import React, { useState } from "react";
|
||||
import useTranslation from "sharedHooks/useTranslation";
|
||||
|
||||
interface Props {
|
||||
handleClose: Function,
|
||||
confirm: ( _checkedValue: string ) => void;
|
||||
headerText: string,
|
||||
radioValues: {
|
||||
[key: string]: {
|
||||
value: string,
|
||||
icon?: string,
|
||||
label: string,
|
||||
text?: string,
|
||||
buttonText?: string,
|
||||
}
|
||||
},
|
||||
selectedValue?: string,
|
||||
insideModal?: boolean
|
||||
}
|
||||
|
||||
const RadioButtonSheet = ( {
|
||||
handleClose,
|
||||
confirm,
|
||||
headerText,
|
||||
radioValues,
|
||||
selectedValue = "none",
|
||||
insideModal
|
||||
}: Props ) => {
|
||||
const { t } = useTranslation( );
|
||||
const [checkedValue, setCheckedValue] = useState( selectedValue );
|
||||
|
||||
const radioButtonRow = ( radioRow: string ) => (
|
||||
<View key={radioRow} className="pb-4">
|
||||
<RadioButtonRow
|
||||
value={radioValues[radioRow].value}
|
||||
icon={radioValues[radioRow].icon}
|
||||
checked={checkedValue === radioValues[radioRow].value}
|
||||
onPress={() => setCheckedValue( radioValues[radioRow].value )}
|
||||
label={radioValues[radioRow].label}
|
||||
description={radioValues[radioRow].text}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<BottomSheet
|
||||
handleClose={handleClose}
|
||||
headerText={headerText}
|
||||
insideModal={insideModal}
|
||||
>
|
||||
<View className="p-4 pt-2">
|
||||
<View className="p-3">
|
||||
{Object.keys( radioValues ).map( radioRow => radioButtonRow( radioRow ) )}
|
||||
</View>
|
||||
<Button
|
||||
level="primary"
|
||||
onPress={( ) => confirm( checkedValue )}
|
||||
text={radioValues[checkedValue]?.buttonText ?? t( "CONFIRM" )}
|
||||
accessibilityLabel={radioValues[checkedValue]?.buttonText ?? t( "CONFIRM" )}
|
||||
/>
|
||||
</View>
|
||||
</BottomSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default RadioButtonSheet;
|
||||
@@ -252,8 +252,21 @@ type Action = {type: EXPLORE_ACTION.RESET}
|
||||
type Dispatch = ( action: Action ) => void
|
||||
|
||||
const ExploreContext = React.createContext<
|
||||
{state: State; dispatch: Dispatch} | undefined
|
||||
>( undefined );
|
||||
{
|
||||
state: State;
|
||||
dispatch: Dispatch;
|
||||
makeSnapshot(): void;
|
||||
differsFromSnapshot: boolean;
|
||||
isNotInitialState: boolean;
|
||||
discardChanges(): void;
|
||||
numberOfFilters: number;
|
||||
defaultExploreLocation(): Promise<{
|
||||
place_guess: string;
|
||||
lat?: number;
|
||||
lng?: number;
|
||||
radius?: number;
|
||||
}>;
|
||||
} | undefined>( undefined );
|
||||
|
||||
// Every key in this object represents a numbered filter in the UI
|
||||
const calculatedFilters = {
|
||||
|
||||
Reference in New Issue
Block a user