Skip to content

Instantly share code, notes, and snippets.

@jonasgroendahl
Last active December 28, 2020 21:00
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonasgroendahl/6f81b440edfe159932f2bcef2f06fbd5 to your computer and use it in GitHub Desktop.
Save jonasgroendahl/6f81b440edfe159932f2bcef2f06fbd5 to your computer and use it in GitHub Desktop.
Picker Modal Gist - React native
import React, {useState} from 'react';
import {View, StyleSheet, ScrollView, Image} from 'react-native';
import Container from '../components/Container';
import Typography from '../components/Typography';
import Paper from '../components/Paper';
import Icon from '../components/Icon';
import TextField from '../components/TextField';
import Spacer from '../components/Spacer';
import Button from '../components/Button';
import Center from '../components/Center';
import ThemeColors from '../utils/Colors';
import ExperienceList from '../components/ExperienceList';
import {StackNavigationProp} from '@react-navigation/stack';
import {RootStackProps} from '../router';
import ImagePicker from 'react-native-image-picker';
import IconButton from '../components/IconButton';
import {useMainContext} from '../hooks/useContext';
import {useFocusEffect} from '@react-navigation/native';
import LoginRequired from '../components/LoginRequired';
import {User} from '../types/types';
import {updateUserBackend} from '../firebase';
import PickerModal from '../components/PickerModal';
import {useTranslation} from '../context/Language';
import Snackbar from 'react-native-snackbar';
type Props = {
navigation: StackNavigationProp<RootStackProps, 'Profile'>;
};
const Profile: React.FC<Props> = () => {
const ctx = useMainContext();
const [user, setUser] = useState<any>({
id: '',
name: '',
age: '',
gender: '',
introduction: '',
experiences: [],
img: '',
});
const [editable, setEditable] = useState<boolean>(false);
const [showPicker, setShowPicker] = useState<string>('');
const {
titleMyProfile,
placeholderAge,
placeHolderGender,
placeholderName,
placeholderDescriptionProfile,
titleExperience,
btnSaveProfile,
genderFemale,
genderMale,
genderOther,
profileSaved,
} = useTranslation();
const pickerValue = {
age: [...new Array(100)].map((value, index) => index.toString()),
gender: [genderMale, genderFemale, genderOther],
};
useFocusEffect(
React.useCallback(() => {
if (ctx.user) {
setUser(ctx.user);
}
}, [ctx]),
);
const handleChange = (fieldName: string, value: string) => {
setUser((prevUser: User) => ({...prevUser, [fieldName]: value}));
};
const handleUpload = () => {
if (editable) {
ImagePicker.showImagePicker(
{maxHeight: 400, maxWidth: 500},
(response) => {
if (response.didCancel) {
return;
}
setUser((prev: User) => ({...prev, img: response.uri}));
},
);
}
};
const handleSubmit = async () => {
const newUser = await updateUserBackend(user);
ctx.setUser(newUser);
Snackbar.show({text: profileSaved, backgroundColor: ThemeColors.purple});
setEditable(false);
};
if (!ctx.isLoggedIn) {
return <LoginRequired />;
}
return (
<Container>
<ScrollView>
<Typography variant="largeTitle">{titleMyProfile}</Typography>
<Paper>
<View>
<View style={styles.abs}>
<IconButton
onPress={() => setEditable(!editable)}
variant="round"
style={{padding: 10}}>
{editable ? <Icon name="eye" /> : <Icon name="edit" />}
</IconButton>
</View>
</View>
<View style={styles.header}>
<View style={styles.profileImgContainer}>
<IconButton onPress={handleUpload}>
{user.img ? (
<Image source={{uri: user.img}} style={styles.profileImg} />
) : (
<Icon name="camera" size={30} color={ThemeColors.white} />
)}
</IconButton>
</View>
<View style={{flex: 1, marginLeft: 10}}>
<TextField
variant="contained"
placeholder={placeholderName}
value={user.name}
editable={editable}
onChangeText={(value: string) => handleChange('name', value)}
style={styles.headerSpacing}
/>
<Button
variant="input"
size="normal"
color="secondary"
onPress={() => setShowPicker('age')}
disabled={!editable}
style={styles.headerSpacing}>
{user.age || placeholderAge}
</Button>
<Button
variant="input"
color="secondary"
onPress={() => setShowPicker('gender')}
disabled={!editable}>
{user.gender || placeHolderGender}
</Button>
</View>
</View>
<Spacer />
<TextField
variant="contained"
multiline
placeholder={placeholderDescriptionProfile}
value={user.introduction}
editable={editable}
onChangeText={(value: string) =>
handleChange('introduction', value)
}
textAlignVertical="top"
/>
<Spacer />
<Center>
<Typography color="dark">{titleExperience}</Typography>
<Spacer />
</Center>
<ExperienceList
items={user.experiences}
editable={editable}
onAdd={(cat) => {
setUser((prev: User) => ({
...prev,
experiences: prev.experiences.concat(cat),
}));
}}
onDelete={(index: number) => {
setUser((prev: User) => ({
...prev,
experiences: prev.experiences.filter((_, i) => i !== index),
}));
}}
/>
<Spacer />
</Paper>
<Spacer />
<Center>
<View>
<Button onPress={handleSubmit} variant="outlined">
{btnSaveProfile}
</Button>
</View>
</Center>
<PickerModal
visible={Boolean(showPicker)}
title={showPicker}
items={showPicker ? pickerValue[showPicker] : []}
onClose={() => setShowPicker('')}
onSelect={(value) => handleChange(showPicker, value)}
value={showPicker ? user[showPicker] : ''}
/>
</ScrollView>
</Container>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: 'row',
},
profileImgContainer: {
borderRadius: 75,
width: 130,
height: 130,
backgroundColor: 'transparent',
borderWidth: 1,
borderColor: 'white',
justifyContent: 'center',
alignItems: 'center',
marginBottom: 10,
},
profileImg: {
width: 130,
height: 130,
borderRadius: 75,
},
header: {
flexDirection: 'row',
alignItems: 'center',
},
headerSpacing: {
marginBottom: 5,
},
abs: {
position: 'absolute',
top: -55,
right: 0,
},
});
export default Profile;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment