diff options
Diffstat (limited to 'src/components')
-rw-r--r-- | src/components/common/BadgeDetailView.tsx | 71 | ||||
-rw-r--r-- | src/components/moments/Moment.tsx | 4 | ||||
-rw-r--r-- | src/components/profile/ProfileBadges.tsx | 148 | ||||
-rw-r--r-- | src/components/profile/ProfileBody.tsx | 3 | ||||
-rw-r--r-- | src/components/profile/index.ts | 1 | ||||
-rw-r--r-- | src/components/suggestedPeople/BadgeIcon.tsx | 19 | ||||
-rw-r--r-- | src/components/suggestedPeople/legacy/BadgesDropdown.tsx | 13 |
7 files changed, 202 insertions, 57 deletions
diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx index 6504300c..19f1e74d 100644 --- a/src/components/common/BadgeDetailView.tsx +++ b/src/components/common/BadgeDetailView.tsx @@ -5,11 +5,15 @@ import {TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; import {useDispatch, useSelector} from 'react-redux'; import CloseIcon from '../../assets/ionicons/close-outline.svg'; -import {BADGE_GRADIENT_FIRST} from '../../constants'; -import {BADGE_DATA} from '../../constants/badges'; +import {BADGE_GRADIENT_FIRST, BADGE_LIMIT} from '../../constants'; +import {removeUserBadge} from '../../store/actions'; import {RootState} from '../../store/rootreducer'; -import {ScreenType} from '../../types'; -import {getUniversityBadge, normalize, removeUserBadge} from '../../utils'; +import {ScreenType, UniversityBadgeDisplayType} from '../../types'; +import { + badgesToDisplayBadges, + getUniversityBadge, + normalize, +} from '../../utils'; interface BadgeDetailModalProps { userXId: string | undefined; @@ -34,35 +38,24 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({ userXId ? state.userX[screenType][userXId] : state.user, ); const navigation = useNavigation(); - const [selectedBadgesWithImage, setSelectedBadgesWithImage] = useState<any[]>( - [], - ); + const [displayBadges, setDisplayBadges] = useState< + UniversityBadgeDisplayType[] + >([]); + const atLimit = badges.length >= BADGE_LIMIT; useEffect(() => { - let badgesWithImage = []; - badges.forEach((e) => { - const uniData = BADGE_DATA[e.university]; - const categoryData = uniData.filter((u) => { - return u.title === e.category; - }); - const badgeData = categoryData[0].data.filter((c) => { - return c.badgeName === e.name; - }); - badgeData.forEach((c) => { - const obj = {...e, badgeImage: c.badgeImage}; - badgesWithImage.push(obj); - }); - }); - setTimeout(() => { - setSelectedBadgesWithImage(badgesWithImage); - }, 250); + setDisplayBadges(badgesToDisplayBadges(badges, university)); }, [badges]); const removeBadgeCell = async (badgeName: string) => { - await removeUserBadge(badges, badgeName, user.userId, dispatch); + dispatch(removeUserBadge(badgeName, user.userId)); }; - const badgeEditCell = ({item: {id, name, badgeImage}}) => { + const badgeEditCell = ({ + item: {id, name, img}, + }: { + item: UniversityBadgeDisplayType; + }) => { return ( <TouchableOpacity style={styles.badgeCellContainerStyles} @@ -71,7 +64,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({ navigation.navigate('MutualBadgeHolders', { badge_id: id, badge_title: name, - badge_img: badgeImage, + badge_img: img, }); }}> <View @@ -88,7 +81,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({ <Image resizeMode="cover" style={styles.badgeImageStyles} - source={badgeImage} + source={img} /> </LinearGradient> {isEditable && ( @@ -121,10 +114,20 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({ }; const modalHeader = () => { - const heading = isEditable ? 'Edit your badges!' : userFullName; - const subheading = isEditable - ? 'Add or delete your badges' - : 'View badges to discover groups!'; + let heading = ''; + let subheading = ''; + if (isEditable) { + if (atLimit) { + heading = 'You have reached your badge limit'; + subheading = 'Remove a badge if you wish to add more'; + } else { + heading = 'Edit your badges!'; + subheading = 'Add or delete your badges'; + } + } else { + heading = userFullName!; + subheading = 'View badges to discover groups!'; + } return ( <View> <Text style={styles.modalHeadingStyles}>{heading}</Text> @@ -155,7 +158,7 @@ const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({ <FlatList contentContainerStyle={styles.modalListStyles} scrollEnabled={false} - data={selectedBadgesWithImage} + data={displayBadges} numColumns={3} renderItem={badgeEditCell} keyExtractor={(item) => item.id.toString()} @@ -228,6 +231,8 @@ const styles = StyleSheet.create({ fontSize: normalize(17), lineHeight: normalize(20.29), textAlign: 'center', + marginVertical: normalize(10), + marginTop: normalize(20), }, modalSubheadingStyles: { fontWeight: '600', diff --git a/src/components/moments/Moment.tsx b/src/components/moments/Moment.tsx index 0ceb8542..cde5b2e0 100644 --- a/src/components/moments/Moment.tsx +++ b/src/components/moments/Moment.tsx @@ -7,8 +7,8 @@ import ImagePicker from 'react-native-image-crop-picker'; import LinearGradient from 'react-native-linear-gradient'; import DeleteIcon from '../../assets/icons/delete-logo.svg'; import DownIcon from '../../assets/icons/down_icon.svg'; -import PlusIcon from '../../assets/icons/plus_icon-01.svg'; -import BigPlusIcon from '../../assets/icons/plus_icon-02.svg'; +import PlusIcon from '../../assets/icons/plus-icon.svg'; +import BigPlusIcon from '../../assets/icons/plus-icon-white.svg'; import UpIcon from '../../assets/icons/up_icon.svg'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {ERROR_UPLOAD} from '../../constants/strings'; diff --git a/src/components/profile/ProfileBadges.tsx b/src/components/profile/ProfileBadges.tsx new file mode 100644 index 00000000..8e68dc46 --- /dev/null +++ b/src/components/profile/ProfileBadges.tsx @@ -0,0 +1,148 @@ +import {useNavigation} from '@react-navigation/core'; +import React, {FC, useEffect, useState} from 'react'; +import {StyleSheet, Text, View} from 'react-native'; +import {ScrollView, TouchableOpacity} from 'react-native-gesture-handler'; +import {useSelector} from 'react-redux'; +import {BadgeIcon} from '..'; +import PlusIconImage from '../../assets/icons/plus-icon-thin.svg'; +import {BADGE_LIMIT} from '../../constants'; +import {RootState} from '../../store/rootReducer'; +import {ScreenType, UniversityBadgeDisplayType} from '../../types'; +import {badgesToDisplayBadges, normalize} from '../../utils'; +import BadgeDetailView from '../common/BadgeDetailView'; + +interface ProfileBadgesProps { + userXId: string | undefined; + screenType: ScreenType; +} + +const ProfileBadges: React.FC<ProfileBadgesProps> = ({userXId, screenType}) => { + const navigation = useNavigation(); + const {badges, name, university} = useSelector((state: RootState) => + userXId ? state.userX[screenType][userXId].profile : state.user.profile, + ); + const [displayBadges, setDisplayBadges] = useState< + UniversityBadgeDisplayType[] + >([]); + const [isEditBadgeModalVisible, setIsEditBadgeModalVisible] = useState(false); + const isOwnProfile = userXId === undefined; + + useEffect(() => { + setDisplayBadges(badgesToDisplayBadges(badges, university)); + }, [badges]); + + const PlusIcon: FC = () => ( + <TouchableOpacity + onPress={() => navigation.navigate('BadgeSelection', {editing: true})}> + <PlusIconImage style={styles.plus} /> + </TouchableOpacity> + ); + + const CloseIcon: FC = () => ( + <TouchableOpacity onPress={() => setIsEditBadgeModalVisible(true)}> + <PlusIconImage style={styles.close} /> + </TouchableOpacity> + ); + + return ( + <> + {/* Tutorial text */} + {displayBadges.length === 0 && isOwnProfile && ( + <> + <Text style={styles.title}>Badges</Text> + <Text style={styles.body}> + Proudly represent your team, club, or organization! + </Text> + </> + )} + {displayBadges.length === 0 && isOwnProfile && ( + // Grey circle placeholders + <ScrollView + contentContainerStyle={styles.badgeContainer} + scrollEnabled={false} + horizontal> + <PlusIcon /> + {Array(BADGE_LIMIT) + .fill(0) + .map(() => ( + <View style={[styles.grey, styles.circle]} /> + ))} + </ScrollView> + )} + {displayBadges.length !== 0 && ( + // Populating actual badges + <ScrollView + contentContainerStyle={styles.badgeContainer} + scrollEnabled={false} + horizontal> + {/* Actual badges */} + {displayBadges.map((displayBadge) => ( + <BadgeIcon key={displayBadge.id} badge={displayBadge} /> + ))} + {/* Plus icon */} + {displayBadges.length < BADGE_LIMIT && isOwnProfile && <PlusIcon />} + {/* Empty placeholders for space-between styling */} + {Array(BADGE_LIMIT + 1) + .fill(0) + .splice(displayBadges.length + 1, BADGE_LIMIT) + .map(() => ( + <View style={styles.circle} /> + ))} + {/* X button */} + {displayBadges.length === BADGE_LIMIT && isOwnProfile && ( + <CloseIcon /> + )} + </ScrollView> + )} + {isEditBadgeModalVisible && ( + <BadgeDetailView + userXId={userXId} + screenType={screenType} + isEditable={isOwnProfile} + userFullName={name} + setBadgeViewVisible={setIsEditBadgeModalVisible} + /> + )} + </> + ); +}; + +const styles = StyleSheet.create({ + title: { + fontWeight: '600', + fontSize: normalize(13.5), + lineHeight: normalize(18), + }, + body: { + fontSize: normalize(13.5), + lineHeight: normalize(17), + marginBottom: 10, + }, + badgeContainer: { + width: '100%', + justifyContent: 'space-between', + marginTop: 10, + marginBottom: 15, + }, + circle: { + width: normalize(31), + height: normalize(31), + borderRadius: normalize(31) / 2, + }, + grey: { + backgroundColor: '#c4c4c4', + }, + plus: { + width: normalize(31), + height: normalize(31), + color: 'black', + }, + close: { + width: normalize(31), + height: normalize(31), + color: 'grey', + transform: [{rotate: '45deg'}], + }, +}); + +export default ProfileBadges; diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 8743acfb..c0ee508a 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -20,6 +20,7 @@ import { import {canViewProfile} from '../../utils/users'; import {FriendsButton} from '../common'; import {MessageButton} from '../messages'; +import ProfileBadges from './ProfileBadges'; import ToggleButton from './ToggleButton'; interface ProfileBodyProps { @@ -65,6 +66,7 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ return ( <View onLayout={onLayout} style={styles.container}> + <ProfileBadges {...{userXId, screenType}} /> <Text style={styles.username}>{`@${username}`}</Text> {biography.length > 0 && ( <Text style={styles.biography}>{`${biography}`}</Text> @@ -137,7 +139,6 @@ const styles = StyleSheet.create({ justifyContent: 'space-between', }, container: { - paddingVertical: '1%', paddingHorizontal: 18, backgroundColor: 'white', }, diff --git a/src/components/profile/index.ts b/src/components/profile/index.ts index c544c3f2..faf273d9 100644 --- a/src/components/profile/index.ts +++ b/src/components/profile/index.ts @@ -9,3 +9,4 @@ export {default as ProfileMoreInfoDrawer} from './ProfileMoreInfoDrawer'; export {default as MomentMoreInfoDrawer} from './MomentMoreInfoDrawer'; export {default as UniversityIcon} from './UniversityIcon'; export {default as TaggAvatar} from './TaggAvatar'; +export {default as ProfileBadges} from './ProfileBadges'; diff --git a/src/components/suggestedPeople/BadgeIcon.tsx b/src/components/suggestedPeople/BadgeIcon.tsx index 8f576a43..616bac93 100644 --- a/src/components/suggestedPeople/BadgeIcon.tsx +++ b/src/components/suggestedPeople/BadgeIcon.tsx @@ -1,24 +1,17 @@ import {useNavigation} from '@react-navigation/core'; import React from 'react'; -import { - Image, - ImageSourcePropType, - StyleProp, - StyleSheet, - ViewStyle, -} from 'react-native'; +import {Image, StyleProp, StyleSheet, ViewStyle} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import LinearGradient from 'react-native-linear-gradient'; -import {UniversityBadge} from '../../types'; +import {UniversityBadgeDisplayType} from '../../types'; import {normalize} from '../../utils'; interface BadgeIconProps { - badge: UniversityBadge; - img: ImageSourcePropType; + badge: UniversityBadgeDisplayType; style?: StyleProp<ViewStyle>; } -const BadgeIcon: React.FC<BadgeIconProps> = ({badge, img, style}) => { +const BadgeIcon: React.FC<BadgeIconProps> = ({badge, style}) => { const navigation = useNavigation(); return ( <TouchableOpacity @@ -27,7 +20,7 @@ const BadgeIcon: React.FC<BadgeIconProps> = ({badge, img, style}) => { navigation.navigate('MutualBadgeHolders', { badge_id: badge.id, badge_title: badge.name, - badge_img: img, + badge_img: badge.img, }); }}> <LinearGradient @@ -36,7 +29,7 @@ const BadgeIcon: React.FC<BadgeIconProps> = ({badge, img, style}) => { angle={154.72} angleCenter={{x: 0.5, y: 0.5}} style={styles.badgeBackground}> - <Image source={img} style={styles.icon} /> + <Image source={badge.img} style={styles.icon} /> </LinearGradient> </TouchableOpacity> ); diff --git a/src/components/suggestedPeople/legacy/BadgesDropdown.tsx b/src/components/suggestedPeople/legacy/BadgesDropdown.tsx index 267355f3..2c177e69 100644 --- a/src/components/suggestedPeople/legacy/BadgesDropdown.tsx +++ b/src/components/suggestedPeople/legacy/BadgesDropdown.tsx @@ -1,18 +1,15 @@ import React, {useEffect, useState} from 'react'; -import {ImageSourcePropType, StyleSheet} from 'react-native'; +import {StyleSheet} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import Animated, {Easing} from 'react-native-reanimated'; import {BadgeIcon, UniversityIcon} from '../..'; -import {UniversityBadge, UniversityType} from '../../../types'; +import {UniversityBadgeDisplayType, UniversityType} from '../../../types'; import {normalize} from '../../../utils'; import UniversityIconClicked from '../UniversityIconClicked'; interface BadgesDropdownProps { university: UniversityType; - localBadges: { - badge: UniversityBadge; - img: ImageSourcePropType; - }[]; + localBadges: UniversityBadgeDisplayType[]; } const BadgesDropdown: React.FC<BadgesDropdownProps> = ({ @@ -92,7 +89,7 @@ const BadgesDropdown: React.FC<BadgesDropdownProps> = ({ )} </TouchableOpacity> {localBadges && - localBadges.map(({badge, img}, index) => ( + localBadges.map((badge, index) => ( <Animated.View key={badge.id} style={[ @@ -102,7 +99,7 @@ const BadgesDropdown: React.FC<BadgesDropdownProps> = ({ zIndex: -1 * badge.id, }, ]}> - <BadgeIcon badge={badge} img={img} /> + <BadgeIcon badge={badge} /> </Animated.View> ))} </Animated.View> |