diff options
Diffstat (limited to 'src/screens')
-rw-r--r-- | src/screens/badge/BadgeItem.tsx | 84 | ||||
-rw-r--r-- | src/screens/badge/BadgeList.tsx | 57 | ||||
-rw-r--r-- | src/screens/badge/BadgeListHeader.tsx | 33 | ||||
-rw-r--r-- | src/screens/badge/BadgeScreenHeader.tsx | 42 | ||||
-rw-r--r-- | src/screens/badge/BadgeSelection.tsx | 266 | ||||
-rw-r--r-- | src/screens/badge/index.ts | 5 | ||||
-rw-r--r-- | src/screens/index.ts | 1 | ||||
-rw-r--r-- | src/screens/profile/SocialMediaTaggs.tsx | 7 | ||||
-rw-r--r-- | src/screens/suggestedPeopleOnboarding/SuggestedPeopleUploadPictureScreen.tsx | 1 |
9 files changed, 495 insertions, 1 deletions
diff --git a/src/screens/badge/BadgeItem.tsx b/src/screens/badge/BadgeItem.tsx new file mode 100644 index 00000000..d7c0b74a --- /dev/null +++ b/src/screens/badge/BadgeItem.tsx @@ -0,0 +1,84 @@ +import React from 'react'; +import {View, Text, StyleSheet, Image, ImageSourcePropType} from 'react-native'; +import {SCREEN_WIDTH, normalize} from '../../utils'; +import LinearGradient from 'react-native-linear-gradient'; +import {BADGE_GRADIENT_FIRST, BADGE_GRADIENT_REST} from '../../constants'; +import {TouchableOpacity} from 'react-native-gesture-handler'; + +interface BadgeItemProps { + title: string; + resourcePath: ImageSourcePropType; + index: Number; + selected: boolean; + onSelection: (ikey: string) => void; +} + +const BadgeItem: React.FC<BadgeItemProps> = ({ + title, + resourcePath, + selected, + index, + onSelection, +}) => { + return ( + <TouchableOpacity onPress={() => onSelection(title)}> + <LinearGradient + colors={index === 0 ? BADGE_GRADIENT_FIRST : BADGE_GRADIENT_REST} + useAngle={true} + angle={136.69} + style={styles.item}> + <View + style={ + selected ? styles.selectedDetailContainer : styles.detailContainer + }> + <Image source={resourcePath} style={styles.imageStyles} /> + <View style={styles.textContainer}> + <Text style={styles.title}>{title}</Text> + </View> + </View> + </LinearGradient> + </TouchableOpacity> + ); +}; + +const styles = StyleSheet.create({ + item: { + width: SCREEN_WIDTH / 3 - 20, + height: SCREEN_WIDTH / 3 - 20, + marginLeft: 15, + marginBottom: 12, + borderRadius: 8, + }, + detailContainer: { + flexGrow: 1, + justifyContent: 'center', + alignItems: 'center', + borderWidth: 3, + borderRadius: 8, + borderColor: 'transparent', + }, + selectedDetailContainer: { + flexGrow: 1, + justifyContent: 'center', + alignItems: 'center', + borderWidth: 3, + borderColor: 'white', + borderRadius: 8, + }, + imageStyles: { + width: '31%', + height: '31%', + marginTop: '11%', + }, + textContainer: {marginTop: '16%'}, + title: { + fontSize: normalize(15), + fontWeight: '500', + lineHeight: normalize(17.9), + textAlign: 'center', + color: 'white', + marginHorizontal: '2%', + }, +}); + +export default BadgeItem; diff --git a/src/screens/badge/BadgeList.tsx b/src/screens/badge/BadgeList.tsx new file mode 100644 index 00000000..f3e96d60 --- /dev/null +++ b/src/screens/badge/BadgeList.tsx @@ -0,0 +1,57 @@ +import React from 'react'; +import {SectionList, StyleSheet} from 'react-native'; +import {SCREEN_HEIGHT} from '../../utils'; +import BadgeItem from './BadgeItem'; +import BadgeHeader from './BadgeListHeader'; + +interface BadgeListProps { + data: any[]; + selectedBadges: any[]; + selectKey: (ikey: string) => void; +} + +const BadgeList: React.FC<BadgeListProps> = ({ + data, + selectedBadges, + selectKey, +}) => { + return ( + <SectionList + stickySectionHeadersEnabled={false} + style={{height: SCREEN_HEIGHT * 0.8}} + contentContainerStyle={styles.listContainer} + sections={data} + keyExtractor={(item, index) => item + index} + extraData={selectedBadges} + renderItem={({item: {badgeName, badgeImage}, index}) => { + return ( + <BadgeItem + selected={selectedBadges.includes(badgeName)} + onSelection={selectKey} + title={badgeName} + resourcePath={badgeImage} + index={index} + /> + ); + }} + renderSectionHeader={({section: {title}}) => ( + <BadgeHeader title={title} /> + )} + /> + ); +}; + +const styles = StyleSheet.create({ + listContainer: { + flexDirection: 'row', + flexWrap: 'wrap', + alignItems: 'center', + flexGrow: 1, + paddingBottom: SCREEN_HEIGHT * 0.1, + }, + scrollViewStyles: { + paddingBottom: SCREEN_HEIGHT * 0.5, + }, +}); + +export default BadgeList; diff --git a/src/screens/badge/BadgeListHeader.tsx b/src/screens/badge/BadgeListHeader.tsx new file mode 100644 index 00000000..27335dfb --- /dev/null +++ b/src/screens/badge/BadgeListHeader.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import {View, Text, StyleSheet} from 'react-native'; +import {SCREEN_WIDTH, normalize} from '../../utils'; + +interface BadgeHeaderProps { + title: String; +} + +const BadgeListHeader: React.FC<BadgeHeaderProps> = ({title}) => { + return ( + <View style={styles.headerContainer}> + <Text style={styles.header}>{title}</Text> + </View> + ); +}; + +const styles = StyleSheet.create({ + headerContainer: { + width: SCREEN_WIDTH * 0.75, + marginHorizontal: SCREEN_WIDTH * 0.125, + marginBottom: '2%', + marginTop: '4%', + }, + header: { + fontSize: normalize(20), + fontWeight: '700', + lineHeight: normalize(23.87), + color: '#fff', + textAlign: 'center', + }, +}); + +export default BadgeListHeader; diff --git a/src/screens/badge/BadgeScreenHeader.tsx b/src/screens/badge/BadgeScreenHeader.tsx new file mode 100644 index 00000000..fd250585 --- /dev/null +++ b/src/screens/badge/BadgeScreenHeader.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import {Image, StyleSheet, Text, View} from 'react-native'; +import {normalize} from '../../utils'; + +const BadgeScreenHeader: React.FC = () => { + return ( + <View style={styles.container}> + <Image source={require('../../assets/images/badges/brown_badge.png')} /> + <View style={styles.universityTextContainer}> + <Text style={styles.universityText}>Brown University Badges</Text> + </View> + <View style={styles.searchTextContainer}> + <Text style={styles.searchText}> + Search for organizations you are a part of! + </Text> + </View> + </View> + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: 'center', + marginBottom: '1%', + }, + universityTextContainer: {marginTop: 12}, + universityText: { + fontSize: normalize(20), + fontWeight: '700', + lineHeight: normalize(23.87), + color: 'white', + }, + searchTextContainer: {marginTop: 6}, + searchText: { + fontSize: normalize(15), + fontWeight: '500', + lineHeight: normalize(17.9), + color: 'white', + }, +}); + +export default BadgeScreenHeader; diff --git a/src/screens/badge/BadgeSelection.tsx b/src/screens/badge/BadgeSelection.tsx new file mode 100644 index 00000000..4754960b --- /dev/null +++ b/src/screens/badge/BadgeSelection.tsx @@ -0,0 +1,266 @@ +import AsyncStorage from '@react-native-community/async-storage'; +import {StackNavigationProp} from '@react-navigation/stack'; +import React, {useEffect, useState} from 'react'; +import {Alert, SafeAreaView, StatusBar, StyleSheet, View} from 'react-native'; +import {Text} from 'react-native-animatable'; +import {TouchableOpacity} from 'react-native-gesture-handler'; +import LinearGradient from 'react-native-linear-gradient'; +import {useDispatch} from 'react-redux'; +import {ADD_USER_BADGES, BACKGROUND_GRADIENT_MAP} from '../../constants'; +import { + ERROR_BADGES_EXCEED_LIMIT, + ERROR_UPLOAD_BADGES, +} from '../../constants/strings'; +import {suggestedPeopleBadgesFinished} from '../../store/actions'; +import {BackgroundGradientType} from '../../types'; +import {SCREEN_HEIGHT, StatusBarHeight} from '../../utils'; +import BadgeList from './BadgeList'; +import BadgeScreenHeader from './BadgeScreenHeader'; + +/** + * Home Screen for displaying Tagg Badge Selections + **/ + +const BadgeImages = { + football: require('../../assets/images/badges/football.png'), + track: require('../../assets/images/badges/track.png'), + volleyball: require('../../assets/images/badges/volleyball.png'), + lax: require('../../assets/images/badges/brown_badge.png'), + fieldHockey: require('../../assets/images/badges/field_hockey.png'), + gymnastics: require('../../assets/images/badges/gymnastics.png'), + hockey: require('../../assets/images/badges/hockey.png'), + baseball: require('../../assets/images/badges/baseball.png'), + basketball: require('../../assets/images/badges/basketball.png'), + kappadelta: require('../../assets/images/badges/kappa_delta.png'), + alphachiomega: require('../../assets/images/badges/alpha_chi_omega.png'), + deltagamma: require('../../assets/images/badges/delta_gamma.png'), + sigma: require('../../assets/images/badges/sigma.png'), + thetaalpha: require('../../assets/images/badges/theta_alpha.png'), + deltaphi: require('../../assets/images/badges/delta_phi.png'), + kappaalphapsi: require('../../assets/images/badges/kappa_alpha_psi.png'), + alphaphialpha: require('../../assets/images/badges/alpha_phi_alpha.png'), + betaomegachi: require('../../assets/images/badges/beta_omega_chi.png'), +}; + +const DATA = [ + { + title: 'Athletics', + data: [ + { + badgeName: 'Brown Football', + badgeImage: BadgeImages.football, + }, + { + badgeName: 'Brown Track', + badgeImage: BadgeImages.track, + }, + { + badgeName: 'Brown Volleyball', + badgeImage: BadgeImages.volleyball, + }, + { + badgeName: 'Brown LAX', + badgeImage: BadgeImages.lax, + }, + { + badgeName: 'Brown Field Hockey', + badgeImage: BadgeImages.fieldHockey, + }, + { + badgeName: 'Brown Gymnastics', + badgeImage: BadgeImages.gymnastics, + }, + { + badgeName: 'Brown Hockey', + badgeImage: BadgeImages.hockey, + }, + { + badgeName: 'Brown Baseball', + badgeImage: BadgeImages.baseball, + }, + { + badgeName: 'Brown Basketball', + badgeImage: BadgeImages.basketball, + }, + ], + }, + + { + title: 'Sorority', + data: [ + { + badgeName: 'Kappa Delta', + badgeImage: BadgeImages.kappadelta, + }, + { + badgeName: 'Alpha Chi Omega', + badgeImage: BadgeImages.alphachiomega, + }, + { + badgeName: 'Delta Gamma', + badgeImage: BadgeImages.deltagamma, + }, + ], + }, + + { + title: 'Fraternity', + data: [ + { + badgeName: 'Sigma', + badgeImage: BadgeImages.sigma, + }, + { + badgeName: 'Theta Alpha', + badgeImage: BadgeImages.thetaalpha, + }, + { + badgeName: 'Delta Phi', + badgeImage: BadgeImages.deltaphi, + }, + ], + }, + { + title: 'Historically Black Fraternities', + data: [ + { + badgeName: 'Kappa Alpha Psi', + badgeImage: BadgeImages.kappadelta, + }, + { + badgeName: 'Alpha Phi Alpha', + badgeImage: BadgeImages.alphaphialpha, + }, + { + badgeName: 'Beta Omega Chi', + badgeImage: BadgeImages.betaomegachi, + }, + ], + }, +]; + +type BadgeSelectionParamList = { + BadgeList: any[]; +}; + +type BadgeSelectionScreenNavigationProp = StackNavigationProp< + BadgeSelectionParamList, + 'BadgeList' +>; + +type BadgeSelectionProps = { + navigation: BadgeSelectionScreenNavigationProp; +}; + +const BadgeSelection: React.FC<BadgeSelectionProps> = ({navigation}) => { + const [canSubmit, setCanSubmit] = useState(false); + navigation.setOptions({ + headerRight: () => ( + <TouchableOpacity + style={styles.rightButtonContainer} + onPress={() => { + if (canSubmit) { + uploadUserSelection(); + } + }}> + <Text style={styles.rightButton}>{canSubmit ? 'Done' : 'Skip'}</Text> + </TouchableOpacity> + ), + }); + + const [selectedBadges, setSelectedBadges] = useState<string[]>([]); + const selectKey = (key: string) => { + if (selectedBadges.includes(key)) { + const selectedBadgesArray = [...selectedBadges]; + const itemIndex = selectedBadgesArray.indexOf(key); + if (itemIndex > -1) { + selectedBadgesArray.splice(itemIndex, 1); + } + setSelectedBadges(selectedBadgesArray); + } else { + const selectedBadgesArray = [...selectedBadges, key]; + setSelectedBadges(selectedBadgesArray); + } + }; + const dispatch = useDispatch(); + useEffect(() => { + setCanSubmit(selectedBadges.length !== 0); + }, [selectedBadges]); + + const uploadUserSelection = async () => { + try { + const token = await AsyncStorage.getItem('token'); + const form = new FormData(); + form.append('badges', JSON.stringify(selectedBadges)); + const response = await fetch(ADD_USER_BADGES, { + method: 'POST', + headers: { + 'Content-Type': 'multipart/form-data', + Authorization: 'Token ' + token, + }, + body: form, + }); + if (response.status === 400) { + Alert.alert(ERROR_BADGES_EXCEED_LIMIT); + return; + } + dispatch(suggestedPeopleBadgesFinished()); + } catch (error) { + console.log(error); + Alert.alert(ERROR_UPLOAD_BADGES); + } + }; + + return ( + <LinearGradient + colors={BACKGROUND_GRADIENT_MAP[BackgroundGradientType.Dark]} + style={styles.container}> + <StatusBar barStyle={'light-content'} /> + <SafeAreaView> + <View style={styles.listContainer}> + <BadgeScreenHeader /> + {/* filter not working, comment out for now */} + {/* <SearchBar + style={styles.searchBarStyle} + onCancel={() => {}} + top={Animated.useValue(0)} + /> */} + <BadgeList + data={DATA} + selectedBadges={selectedBadges} + selectKey={selectKey} + /> + </View> + </SafeAreaView> + </LinearGradient> + ); +}; + +const styles = StyleSheet.create({ + container: { + flex: 1, + }, + searchBarStyle: { + width: '95%', + alignSelf: 'center', + marginTop: SCREEN_HEIGHT * 0.05, + }, + viewContainer: {marginTop: StatusBarHeight}, + listContainer: {marginTop: SCREEN_HEIGHT * 0.05}, + rightButtonContainer: {marginRight: 24}, + rightButton: { + color: '#FFFFFF', + fontWeight: 'bold', + fontSize: 15, + lineHeight: 18, + }, + leftButtonContainer: {marginLeft: 24}, + leftButton: { + color: '#FFFFFF', + fontWeight: '500', + fontSize: 15, + lineHeight: 18, + }, +}); + +export default BadgeSelection; diff --git a/src/screens/badge/index.ts b/src/screens/badge/index.ts new file mode 100644 index 00000000..217aa7e8 --- /dev/null +++ b/src/screens/badge/index.ts @@ -0,0 +1,5 @@ +export {default as BadgeSelection} from './BadgeSelection'; +export {default as BadgeItem} from './BadgeItem'; +export {default as BadgeListHeader} from './BadgeListHeader'; +export {default as BadgeList} from './BadgeList'; +export {default as BadgeScreenHeader} from './BadgeScreenHeader'; diff --git a/src/screens/index.ts b/src/screens/index.ts index faf3d0b7..50ada3d1 100644 --- a/src/screens/index.ts +++ b/src/screens/index.ts @@ -4,3 +4,4 @@ export * from './profile'; export * from './search'; export * from './suggestedPeople'; export * from './suggestedPeopleOnboarding'; +export * from './badge'; diff --git a/src/screens/profile/SocialMediaTaggs.tsx b/src/screens/profile/SocialMediaTaggs.tsx index 45d417a6..466ba509 100644 --- a/src/screens/profile/SocialMediaTaggs.tsx +++ b/src/screens/profile/SocialMediaTaggs.tsx @@ -12,7 +12,12 @@ import { } from '../../components'; import {AVATAR_GRADIENT} from '../../constants'; import {ProfileStackParams} from '../../routes'; -import {SimplePostType, TwitterPostType, SocialAccountType, ScreenType} from '../../types'; +import { + SimplePostType, + TwitterPostType, + SocialAccountType, + ScreenType, +} from '../../types'; import {AvatarHeaderHeight, SCREEN_HEIGHT} from '../../utils'; import {useSelector} from 'react-redux'; import {RootState} from '../../store/rootReducer'; diff --git a/src/screens/suggestedPeopleOnboarding/SuggestedPeopleUploadPictureScreen.tsx b/src/screens/suggestedPeopleOnboarding/SuggestedPeopleUploadPictureScreen.tsx index c587e930..bb8aaccf 100644 --- a/src/screens/suggestedPeopleOnboarding/SuggestedPeopleUploadPictureScreen.tsx +++ b/src/screens/suggestedPeopleOnboarding/SuggestedPeopleUploadPictureScreen.tsx @@ -76,6 +76,7 @@ const SuggestedPeopleUploadPictureScreen: React.FC = ({route}) => { const success = await sendSuggestedPeoplePhoto(image); if (success) { dispatch(uploadedSuggestedPeoplePhoto(image)); + navigation.push('BadgeSelection'); } else { Alert.alert(ERROR_UPLOAD); } |