diff options
author | Shravya Ramesh <37447613+shravyaramesh@users.noreply.github.com> | 2020-11-17 18:06:14 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-17 21:06:14 -0500 |
commit | 713d169915a82edfcfe4b44622e3dce8c6adaf0c (patch) | |
tree | 3f0a0a9ef86e80442c4cc5b6b89be24cf1526268 /src/components | |
parent | 9b4ba92df514ca8c5c92c4f9279144e2c9d49e36 (diff) |
[TMA-382] Edit profile screen (#121)
* added more icon
* a less fat icon
* and the actual icon asset
* bottom drawer skeleton done
* removed warning, better code
* a more completed skeleton done
* bottom drawer done!
* Added content container, sent birthday picker props, minor styling
* differenciating defined and undefined birthdate in birthdate, datepicker
* removed restricting width for TaggDropDown
* Added edit profile screen to navigator stack
* Add EditProfile view, refresh profile view on save
* Removes unnecessary import
* Stores gender and birthdate as part of ProfileType
* Added gender, birthdate, isEditProfile to AuthProv
* Conditional view applied for edit profile button
* Includes discarded changes in previous merge- BD
* removed unused icon
* resolved scary warnings
* added icon to drawer
* Small fix
* minor code improvement
* sc
* fixed birthday bug
* custom gender updation fixed
* small change to birthday default value
* missed something
* cleaned up types! Warnings gone!
* fixed another gender picker bug
* fixed gender bug and cleaned up logic
* removed warning, MUCH better code now
Co-authored-by: Ivan Chen <ivan@thetaggid.com>
Co-authored-by: Ashm Walia <ashmwalia@outlook.com>
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/common/BottomDrawer.tsx | 118 | ||||
-rw-r--r-- | src/components/common/SocialLinkModal.tsx | 3 | ||||
-rw-r--r-- | src/components/common/TaggDatePicker.tsx | 22 | ||||
-rw-r--r-- | src/components/common/index.ts | 1 | ||||
-rw-r--r-- | src/components/moments/Moment.tsx | 4 | ||||
-rw-r--r-- | src/components/onboarding/BirthDatePicker.tsx | 9 | ||||
-rw-r--r-- | src/components/onboarding/TaggDropDown.tsx | 7 | ||||
-rw-r--r-- | src/components/profile/MoreInfoDrawer.tsx | 88 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 4 | ||||
-rw-r--r-- | src/components/profile/ProfileHeader.tsx | 39 | ||||
-rw-r--r-- | src/components/profile/ToggleButton.tsx | 5 | ||||
-rw-r--r-- | src/components/profile/index.ts | 5 | ||||
-rw-r--r-- | src/components/search/RecentSearches.tsx | 3 | ||||
-rw-r--r-- | src/components/taggs/TwitterTaggPost.tsx | 4 |
14 files changed, 277 insertions, 35 deletions
diff --git a/src/components/common/BottomDrawer.tsx b/src/components/common/BottomDrawer.tsx new file mode 100644 index 00000000..bef9434a --- /dev/null +++ b/src/components/common/BottomDrawer.tsx @@ -0,0 +1,118 @@ +import React, {Fragment, ReactText, useEffect, useRef, useState} from 'react'; +import { + Modal, + StyleSheet, + TouchableWithoutFeedback, + View, + ViewProps, +} from 'react-native'; +import Animated from 'react-native-reanimated'; +import BottomSheet from 'reanimated-bottom-sheet'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; + +interface BottomDrawerProps extends ViewProps { + initialSnapPosition?: ReactText; + isOpen: boolean; + setIsOpen: (open: boolean) => void; + showHeader: boolean; +} + +// More examples here: +// https://github.com/osdnk/react-native-reanimated-bottom-sheet/tree/master/Example +const BottomDrawer: React.FC<BottomDrawerProps> = (props) => { + const {isOpen, setIsOpen, showHeader, initialSnapPosition} = props; + const drawerRef = useRef<BottomSheet>(null); + const [modalVisible, setModalVisible] = useState(isOpen); + const bgAlpha = new Animated.Value(isOpen ? 1 : 0); + + useEffect(() => { + if (isOpen) { + setModalVisible(true); + } else { + bgAlpha.setValue(0); + drawerRef.current && drawerRef.current.snapTo(1); + } + }, [isOpen]); + + const renderContent = () => { + return <View>{props.children}</View>; + }; + + const renderHeader = () => { + return showHeader ? ( + <View style={styles.header}> + <View style={styles.panelHeader}> + <View style={styles.panelHandle} /> + </View> + </View> + ) : ( + <Fragment /> + ); + }; + + return ( + <Modal + transparent + visible={modalVisible} + onShow={() => { + drawerRef.current && drawerRef.current.snapTo(0); + }}> + <BottomSheet + ref={drawerRef} + snapPoints={[initialSnapPosition ?? '30%', 0]} + initialSnap={1} + renderContent={renderContent} + renderHeader={renderHeader} + enabledContentGestureInteraction={false} + callbackNode={bgAlpha} + onCloseEnd={() => { + setModalVisible(false); + setIsOpen(false); + }} + /> + + <TouchableWithoutFeedback + onPress={() => { + setIsOpen(false); + }}> + <Animated.View + style={[ + styles.backgroundView, + { + backgroundColor: Animated.interpolateColors(bgAlpha, { + inputRange: [0, 1], + outputColorRange: ['rgba(0,0,0,0.3)', 'rgba(0,0,0,0)'], + }), + }, + ]} + /> + </TouchableWithoutFeedback> + </Modal> + ); +}; + +const styles = StyleSheet.create({ + header: { + backgroundColor: '#f7f5eee8', + shadowColor: '#000000', + paddingTop: 20, + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + }, + panelHeader: { + alignItems: 'center', + }, + panelHandle: { + width: 40, + height: 8, + borderRadius: 4, + backgroundColor: '#00000040', + marginBottom: 10, + }, + backgroundView: { + height: SCREEN_HEIGHT, + width: SCREEN_WIDTH, + }, +}); + +export default BottomDrawer; diff --git a/src/components/common/SocialLinkModal.tsx b/src/components/common/SocialLinkModal.tsx index 3cea2567..b307a62c 100644 --- a/src/components/common/SocialLinkModal.tsx +++ b/src/components/common/SocialLinkModal.tsx @@ -1,6 +1,7 @@ import React from 'react'; import {Modal, StyleSheet, Text, TouchableHighlight, View} from 'react-native'; import {TextInput} from 'react-native-gesture-handler'; +import { TAGG_TEXT_LIGHT_BLUE } from '../../constants'; import {SCREEN_WIDTH} from '../../utils'; interface SocialLinkModalProps { @@ -104,7 +105,7 @@ const styles = StyleSheet.create({ fontSize: 14, /* identical to box height */ textAlign: 'center', - color: '#698DD3', + color: TAGG_TEXT_LIGHT_BLUE, }, textInput: { height: 20, diff --git a/src/components/common/TaggDatePicker.tsx b/src/components/common/TaggDatePicker.tsx index d8010251..059bf620 100644 --- a/src/components/common/TaggDatePicker.tsx +++ b/src/components/common/TaggDatePicker.tsx @@ -1,3 +1,4 @@ +import moment from 'moment'; import React, {useState} from 'react'; import DatePicker from 'react-native-date-picker'; @@ -5,23 +6,24 @@ interface TaggDatePickerProps { handleDateUpdate: (_: Date) => void; maxDate: Date; textColor: string; + date: Date | undefined; } -const TaggDatePicker: React.FC<TaggDatePickerProps> = ({ - handleDateUpdate, - maxDate, - textColor, -}) => { - const [date, setDate] = useState(new Date()); +const TaggDatePicker: React.FC<TaggDatePickerProps> = (props) => { + const [date, setDate] = useState( + props.date + ? new Date(moment(props.date).add(1, 'day').format('YYYY-MM-DD')) + : undefined, + ); return ( <DatePicker - date={date} - textColor={textColor} + date={date ? date : props.maxDate} + textColor={props.textColor} mode={'date'} - maximumDate={maxDate} + maximumDate={props.maxDate} onDateChange={(newDate) => { setDate(newDate); - handleDateUpdate(newDate); + props.handleDateUpdate(newDate); }} /> ); diff --git a/src/components/common/index.ts b/src/components/common/index.ts index c7ed13cd..883dae61 100644 --- a/src/components/common/index.ts +++ b/src/components/common/index.ts @@ -13,4 +13,5 @@ export {default as SocialLinkModal} from './SocialLinkModal'; export {default as ComingSoon} from './ComingSoon'; export {default as PostCarousel} from './PostCarousel'; export {default as TaggDatePicker} from './TaggDatePicker'; +export {default as BottomDrawer} from './BottomDrawer'; export * from './post'; diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index f905bfe3..9e138ef3 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -6,7 +6,7 @@ import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; import PlusIcon from '../../assets/icons/plus_icon-01.svg'; import BigPlusIcon from '../../assets/icons/plus_icon-02.svg'; -import {MOMENTS_TITLE_COLOR} from '../../constants'; +import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {SCREEN_WIDTH} from '../../utils'; import ImagePicker from 'react-native-image-crop-picker'; import MomentTile from './MomentTile'; @@ -104,7 +104,7 @@ const styles = StyleSheet.create({ titleText: { fontSize: 16, fontWeight: 'bold', - color: MOMENTS_TITLE_COLOR, + color: TAGG_TEXT_LIGHT_BLUE, }, scrollContainer: { height: SCREEN_WIDTH / 2, diff --git a/src/components/onboarding/BirthDatePicker.tsx b/src/components/onboarding/BirthDatePicker.tsx index f97f1a72..0fc597c3 100644 --- a/src/components/onboarding/BirthDatePicker.tsx +++ b/src/components/onboarding/BirthDatePicker.tsx @@ -15,6 +15,8 @@ import {TaggDatePicker} from '../common'; interface BirthDatePickerProps extends TextInputProps { handleBDUpdate: (_: Date) => void; width?: number | string; + date: Date | undefined; + showPresetdate: boolean; } const BirthDatePicker = React.forwardRef( @@ -23,7 +25,7 @@ const BirthDatePicker = React.forwardRef( const maxDate = moment().subtract(13, 'y').subtract(1, 'd'); return maxDate.toDate(); }; - const [date, setDate] = useState(new Date(0)); + const [date, setDate] = useState(props.date); const [hidden, setHidden] = useState(true); const [updated, setUpdated] = useState(false); const textColor = updated ? 'white' : '#ddd'; @@ -42,7 +44,9 @@ const BirthDatePicker = React.forwardRef( style={[styles.input, {width: props.width}, {color: textColor}]} ref={ref} {...props}> - {updated ? moment(date).format('YYYY-MM-DD') : 'Date of Birth'} + {(updated || props.showPresetdate) && date + ? moment(date).format('YYYY-MM-DD') + : 'Date of Birth'} </Text> </TouchableOpacity> <Modal visible={!hidden} transparent={true} animationType="fade"> @@ -67,6 +71,7 @@ const BirthDatePicker = React.forwardRef( handleDateUpdate={updateDate} maxDate={getMaxDate()} textColor={'black'} + date={date} /> </View> </TouchableWithoutFeedback> diff --git a/src/components/onboarding/TaggDropDown.tsx b/src/components/onboarding/TaggDropDown.tsx index a45426ca..db531cc4 100644 --- a/src/components/onboarding/TaggDropDown.tsx +++ b/src/components/onboarding/TaggDropDown.tsx @@ -1,8 +1,8 @@ import React from 'react'; -import RNSelectPicker from 'react-native-picker-select'; -import {View, StyleSheet, TextInputProps} from 'react-native'; +import {StyleSheet, View} from 'react-native'; +import RNSelectPicker, {PickerSelectProps} from 'react-native-picker-select'; -interface TaggDropDownProps extends TextInputProps { +interface TaggDropDownProps extends PickerSelectProps { width?: number | string; } @@ -19,7 +19,6 @@ const TaggDropDown = React.forwardRef((props: TaggDropDownProps, ref: any) => { const styles = StyleSheet.create({ container: { - width: '66.67%', alignItems: 'center', marginVertical: 11, }, diff --git a/src/components/profile/MoreInfoDrawer.tsx b/src/components/profile/MoreInfoDrawer.tsx new file mode 100644 index 00000000..719c1894 --- /dev/null +++ b/src/components/profile/MoreInfoDrawer.tsx @@ -0,0 +1,88 @@ +import {useNavigation} from '@react-navigation/native'; +import React, {useContext} from 'react'; +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; +import {useSafeAreaInsets} from 'react-native-safe-area-context'; +import {TAGG_TEXT_LIGHT_BLUE} from '../../constants'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; +import {AuthContext} from '../../routes'; +import {BottomDrawer} from '../common'; +import PersonOutline from '../../assets/ionicons/person-outline.svg'; + +interface MoreInfoDrawerProps { + isOpen: boolean; + setIsOpen: (visible: boolean) => void; + isProfileView: boolean; +} + +const MoreInfoDrawer: React.FC<MoreInfoDrawerProps> = (props) => { + const insets = useSafeAreaInsets(); + const initialSnapPosition = 160 + insets.bottom; + const navigation = useNavigation(); + const { + user: {userId, username}, + } = useContext(AuthContext); + + const goToEditProfile = () => { + navigation.push('EditProfile', { + userId: userId, + username: username, + }); + props.setIsOpen(false); + }; + + return ( + <BottomDrawer + {...props} + showHeader={false} + initialSnapPosition={initialSnapPosition}> + <View style={styles.panel}> + <TouchableOpacity style={styles.panelButton} onPress={goToEditProfile}> + <PersonOutline style={styles.icon} /> + <Text style={styles.panelButtonTitle}>Edit Profile</Text> + </TouchableOpacity> + <View style={styles.divider} /> + <TouchableOpacity + style={styles.panelButton} + onPress={() => props.setIsOpen(false)}> + {/* Just a placeholder "icon" for easier alignment */} + <View style={styles.icon} /> + <Text style={styles.panelButtonTitleCancel}>Cancel</Text> + </TouchableOpacity> + </View> + </BottomDrawer> + ); +}; + +const styles = StyleSheet.create({ + panel: { + height: SCREEN_HEIGHT, + backgroundColor: 'white', + borderTopLeftRadius: 20, + borderTopRightRadius: 20, + }, + panelButton: { + height: 80, + flexDirection: 'row', + alignItems: 'center', + }, + panelButtonTitle: { + fontSize: 18, + fontWeight: 'bold', + color: 'black', + }, + icon: { + height: 25, + width: 25, + color: 'black', + marginLeft: SCREEN_WIDTH * 0.3, + marginRight: 25, + }, + panelButtonTitleCancel: { + fontSize: 18, + fontWeight: 'bold', + color: TAGG_TEXT_LIGHT_BLUE, + }, + divider: {height: 1, borderWidth: 1, borderColor: '#e7e7e7'}, +}); + +export default MoreInfoDrawer; diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index db8c6e0b..c0253533 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -1,6 +1,6 @@ import React from 'react'; import {StyleSheet, View, Text, LayoutChangeEvent} from 'react-native'; -import {TOGGLE_BUTTON_TYPE} from '../../constants'; +import {TAGG_DARK_BLUE, TOGGLE_BUTTON_TYPE} from '../../constants'; import {AuthContext, ProfileContext} from '../../routes/'; import ToggleButton from './ToggleButton'; @@ -80,7 +80,7 @@ const styles = StyleSheet.create({ }, website: { fontSize: 16, - color: '#4E699C', + color: TAGG_DARK_BLUE, marginBottom: 5, }, }); diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx index 6f11e806..62949746 100644 --- a/src/components/profile/ProfileHeader.tsx +++ b/src/components/profile/ProfileHeader.tsx @@ -1,10 +1,12 @@ -import React from 'react'; - +import React, {useState} from 'react'; +import {StyleSheet, Text, TouchableOpacity, View} from 'react-native'; +import MoreIcon from '../../assets/icons/more_horiz-24px.svg'; +import {TAGG_DARK_BLUE} from '../../constants'; +import {AuthContext, ProfileContext} from '../../routes/'; +import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; import Avatar from './Avatar'; +import MoreInfoDrawer from './MoreInfoDrawer'; import FollowCount from './FollowCount'; -import {View, Text, StyleSheet} from 'react-native'; -import {SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; -import {AuthContext, ProfileContext} from '../../routes/'; type ProfileHeaderProps = { isProfileView: boolean; @@ -22,8 +24,26 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({ } = isProfileView ? React.useContext(ProfileContext) : React.useContext(AuthContext); + const [drawerVisible, setDrawerVisible] = useState(false); + return ( <View style={styles.container}> + {!isProfileView && ( + <> + <TouchableOpacity + style={styles.more} + onPress={() => { + setDrawerVisible(true); + }}> + <MoreIcon height={30} width={30} color={TAGG_DARK_BLUE} /> + </TouchableOpacity> + <MoreInfoDrawer + isOpen={drawerVisible} + setIsOpen={setDrawerVisible} + isProfileView={isProfileView} + /> + </> + )} <View style={styles.row}> <Avatar style={styles.avatar} isProfileView={isProfileView} /> <View style={styles.header}> @@ -51,8 +71,7 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({ const styles = StyleSheet.create({ container: { top: SCREEN_HEIGHT / 2.4, - paddingHorizontal: SCREEN_WIDTH / 20, - marginBottom: SCREEN_HEIGHT / 10, + width: '100%', position: 'absolute', }, row: { @@ -76,6 +95,12 @@ const styles = StyleSheet.create({ follows: { marginHorizontal: SCREEN_HEIGHT / 50, }, + more: { + position: 'absolute', + right: '5%', + marginTop: '4%', + zIndex: 1, + }, }); export default ProfileHeader; diff --git a/src/components/profile/ToggleButton.tsx b/src/components/profile/ToggleButton.tsx index ff14cdde..4c8cb5b9 100644 --- a/src/components/profile/ToggleButton.tsx +++ b/src/components/profile/ToggleButton.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import {StyleSheet, Text} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; +import { TAGG_TEXT_LIGHT_BLUE } from '../../constants'; import {getToggleButtonText, SCREEN_HEIGHT, SCREEN_WIDTH} from '../../utils'; type ToggleButtonProps = { @@ -31,14 +32,14 @@ const styles = StyleSheet.create({ height: SCREEN_WIDTH * 0.1, borderRadius: 8, marginTop: '3%', - borderColor: '#698dd3', + borderColor: TAGG_TEXT_LIGHT_BLUE, backgroundColor: 'white', borderWidth: 3, marginHorizontal: '1%', }, text: { fontWeight: 'bold', - color: '#698dd3', + color: TAGG_TEXT_LIGHT_BLUE, }, }); export default ToggleButton; diff --git a/src/components/profile/index.ts b/src/components/profile/index.ts index 2e9c23ea..0f57347b 100644 --- a/src/components/profile/index.ts +++ b/src/components/profile/index.ts @@ -3,5 +3,6 @@ export {default as Content} from './Content'; export {default as ProfileCutout} from './ProfileCutout'; export {default as ProfileBody} from './ProfileBody'; export {default as ProfileHeader} from './ProfileHeader'; -export {default as ProfilePreview} from '../profile/ProfilePreview'; -export {default as Followers} from '../profile/Followers'; +export {default as ProfilePreview} from './ProfilePreview'; +export {default as Followers} from './Followers'; +export {default as MoreInfoDrawer} from './MoreInfoDrawer'; diff --git a/src/components/search/RecentSearches.tsx b/src/components/search/RecentSearches.tsx index a5c08984..f47f8879 100644 --- a/src/components/search/RecentSearches.tsx +++ b/src/components/search/RecentSearches.tsx @@ -7,6 +7,7 @@ import { TouchableOpacityProps, } from 'react-native'; import {ProfilePreviewType} from 'src/types'; +import { TAGG_TEXT_LIGHT_BLUE } from '../../constants'; import SearchResults from './SearchResults'; interface RecentSearchesProps extends TouchableOpacityProps { @@ -45,7 +46,7 @@ const styles = StyleSheet.create({ clear: { fontSize: 17, fontWeight: 'bold', - color: '#698DD3', + color: TAGG_TEXT_LIGHT_BLUE, }, }); diff --git a/src/components/taggs/TwitterTaggPost.tsx b/src/components/taggs/TwitterTaggPost.tsx index 158b5995..fb4cbd0f 100644 --- a/src/components/taggs/TwitterTaggPost.tsx +++ b/src/components/taggs/TwitterTaggPost.tsx @@ -3,7 +3,7 @@ import {Image, Linking, StyleSheet, View} from 'react-native'; import {Text} from 'react-native-animatable'; import Hyperlink from 'react-native-hyperlink'; import LinearGradient from 'react-native-linear-gradient'; -import {AVATAR_DIM, TAGGS_GRADIENT} from '../../constants'; +import {AVATAR_DIM, TAGGS_GRADIENT, TAGG_TEXT_LIGHT_BLUE} from '../../constants'; import {TwitterPostType} from '../../types'; import {SCREEN_WIDTH} from '../../utils'; import {DateLabel, PostCarousel} from '../common'; @@ -238,7 +238,7 @@ const styles = StyleSheet.create({ }, replyShowThisThread: { fontSize: 15, - color: '#698dd3', + color: TAGG_TEXT_LIGHT_BLUE, }, }); |