🐛 Fix Android display bug

by not inserting MultiSelect (which uses a VirtualizedList)
into a ScrollView anymore
pull/21/head
Alexis Drai 2 years ago
parent 1b41495222
commit 866b3406bd

@ -86,6 +86,22 @@ The updating screen provides a form for updating an existing `Move`.
<img src="./docs/update.png" width="410" style="margin:20px" alt="">>
## Some business logic
While the back end doesn't forbid a `Move` from being both weak against and effective against the same one type,
it should. That's one of the flaws of that API.
In this app, we did implement the business logic described above in our callbacks for our `MultiSelect` elements, like
so:
```typescript
const handleSelectType = (selectedTypes: string[], setTypes: React.Dispatch<React.SetStateAction<string[]>>, otherSelectedTypes: string[]) => {
const uniqueSelectedTypes = Array.from(new Set(selectedTypes));
const withoutDuplicatesFromOtherColumn = uniqueSelectedTypes.filter(type => !otherSelectedTypes.includes(type));
setTypes(withoutDuplicatesFromOtherColumn);
};
```
## Using the app
### Running the backend

@ -1,7 +1,17 @@
// screens/moves/MoveFormScreen.tsx
import React, { useEffect, useState } from 'react';
import { Button, StyleSheet, Text, TextInput } from 'react-native';
import {
Button,
KeyboardAvoidingView,
Modal,
Platform,
ScrollView,
StyleSheet,
Text,
TextInput,
View
} from 'react-native';
import { StackNavigationProp } from '@react-navigation/stack';
import { RootStackParamList } from "../../navigation/navigationTypes";
import { useDispatch, useSelector } from 'react-redux';
@ -15,7 +25,6 @@ import { ItemValue } from "@react-native-community/pic
import { MoveCategoryName } from "../../entities/MoveCategoryName";
import { TypeName } from "../../entities/TypeName";
import MultiSelect from "react-native-multiple-select";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import AlertModal from "../../components/AlertModal";
import { MOVE_ERROR } from "../../redux/constants";
@ -50,6 +59,14 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
});
}, [navigation, route.params?.move]);
const [isModalVisible, setModalVisible] = useState(false);
const [currentMultiSelect, setCurrentMultiSelect] = useState<'weakAgainst' | 'effectiveAgainst'>('weakAgainst');
const handleOpenModal = (multiSelect: 'weakAgainst' | 'effectiveAgainst') => {
setCurrentMultiSelect(multiSelect);
setModalVisible(true);
};
const [selectedWeakAgainst, setSelectedWeakAgainst] = useState<string[]>(move.type.weakAgainst);
const [selectedEffectiveAgainst, setSelectedEffectiveAgainst] = useState<string[]>(move.type.effectiveAgainst);
@ -76,18 +93,25 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
};
return (
<KeyboardAwareScrollView style={styles.container}>
<KeyboardAvoidingView
style={styles.container}
behavior={Platform.OS === "ios" ? "padding" : "height"}
>
<ScrollView contentContainerStyle={{ paddingBottom: 20 }}>
<AlertModal
visible={!!error}
message={error || ''}
onClose={() => dispatch({ type: MOVE_ERROR, payload: null })}
/>
<View style={styles.row}>
<Text style={styles.label}>Name: </Text>
<TextInput
value={move.name}
onChangeText={(text) => setMove({ ...move, name: text })}
style={styles.input}
/>
</View>
<View style={styles.row}>
<Text style={styles.label}>Category: </Text>
<Picker
selectedValue={move.category}
@ -99,6 +123,8 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
<Picker.Item key={value} label={value} value={value}/>
)}
</Picker>
</View>
<View style={styles.row}>
<Text style={styles.label}>Power: </Text>
<TextInput
value={move.power.toString()}
@ -110,6 +136,8 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
style={styles.input}
keyboardType="numeric"
/>
</View>
<View style={styles.row}>
<Text style={styles.label}>Accuracy: </Text>
<TextInput
value={move.accuracy.toString()}
@ -121,6 +149,8 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
style={styles.input}
keyboardType="numeric"
/>
</View>
<View style={styles.row}>
<Text style={styles.label}>Type: </Text>
<Picker
selectedValue={move.type.name}
@ -132,33 +162,44 @@ const MoveFormScreen = ({ navigation, route }: Props) => {
<Picker.Item key={value} label={value} value={value}/>
)}
</Picker>
<Text style={styles.label}>Weak Against: </Text>
</View>
<Text>Weak Against: {selectedWeakAgainst.join(', ')}</Text>
<View style={styles.buttonContainer}>
<Button title="Select Weak Against" onPress={() => handleOpenModal('weakAgainst')}/>
</View>
<Text>Effective Against: {selectedEffectiveAgainst.join(', ')}</Text>
<View style={styles.buttonContainer}>
<Button title="Select Effective Against" onPress={() => handleOpenModal('effectiveAgainst')}/>
</View>
<View style={styles.buttonContainer}>
<Button title="Save" onPress={handleSave} color={styles.saveButton.backgroundColor}/>
</View>
</ScrollView>
<Modal
animationType="slide"
transparent={true}
visible={isModalVisible}
onRequestClose={() => {
setModalVisible(!isModalVisible);
}}>
<View style={styles.centeredView}>
<View style={styles.modalView}>
<MultiSelect
items={
Object.values(TypeName).map((value) => ({ id: value, name: value }))
}
uniqueKey="id"
onSelectedItemsChange={
(selectedItems) => handleSelectType(selectedItems, setSelectedWeakAgainst, selectedEffectiveAgainst)
(selectedItems) => handleSelectType(selectedItems, currentMultiSelect === 'weakAgainst' ? setSelectedWeakAgainst : setSelectedEffectiveAgainst, currentMultiSelect === 'weakAgainst' ? selectedEffectiveAgainst : selectedWeakAgainst)
}
selectedItems={selectedWeakAgainst}
selectedItems={currentMultiSelect === 'weakAgainst' ? selectedWeakAgainst : selectedEffectiveAgainst}
displayKey="name"
/>
<Text style={styles.label}>Effective Against: </Text>
<MultiSelect
items={
Object.values(TypeName).map((value) => ({ id: value, name: value }))
}
uniqueKey="id"
onSelectedItemsChange={
(selectedItems) => handleSelectType(selectedItems, setSelectedEffectiveAgainst, selectedWeakAgainst)
}
selectedItems={selectedEffectiveAgainst}
displayKey="name"
/>
<Button title="Save" onPress={handleSave}/>
</KeyboardAwareScrollView>
<Button title="Close" onPress={() => setModalVisible(false)}/>
</View>
</View>
</Modal>
</KeyboardAvoidingView>
);
};
@ -167,14 +208,49 @@ const styles = StyleSheet.create({
flex: 1,
padding: 16,
},
label: {
marginRight: 8,
},
input: {
backgroundColor: '#CEC',
borderRadius: 8,
height: 32,
minHeight: 32,
flex: 1,
},
label: {
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'flex-start',
margin: 8,
}
flexWrap: 'wrap',
},
centeredView: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 22
},
modalView: {
margin: 20,
backgroundColor: "white",
borderRadius: 20,
padding: 35,
alignItems: "center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 2
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5
},
buttonContainer: {
margin: 8,
},
saveButton: {
backgroundColor: '#BADA55',
},
});
export default MoveFormScreen;

Loading…
Cancel
Save