aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/components/common/BadgeDetailView.tsx231
-rw-r--r--src/components/profile/ProfileHeader.tsx69
-rw-r--r--src/constants/api.ts2
-rw-r--r--src/screens/badge/BadgeSelection.tsx2
-rw-r--r--src/services/SuggestedPeopleService.ts32
5 files changed, 331 insertions, 5 deletions
diff --git a/src/components/common/BadgeDetailView.tsx b/src/components/common/BadgeDetailView.tsx
new file mode 100644
index 00000000..1dc50c32
--- /dev/null
+++ b/src/components/common/BadgeDetailView.tsx
@@ -0,0 +1,231 @@
+import {useNavigation} from '@react-navigation/core';
+import React, {useState} from 'react';
+import {FlatList, Image, Modal, StyleSheet, Text, View} from 'react-native';
+import {TouchableOpacity} from 'react-native-gesture-handler';
+import LinearGradient from 'react-native-linear-gradient';
+import {BADGE_GRADIENT_FIRST} from '../../constants';
+import CloseIcon from '../../assets/ionicons/close-outline.svg';
+import {UniversityBadge, UniversityType} from '../../types';
+import {getUniversityBadge, normalize} from '../../utils';
+import {removeBadgesService} from '../../services';
+import {useSelector} from 'react-redux';
+import {RootState} from '../../store/rootreducer';
+
+interface BadgeDetailModalProps {
+ isEditable: boolean;
+ setBadgeViewVisible: Function;
+ selectedBadges: UniversityBadge[];
+ name?: string;
+ userId: string;
+}
+
+const BadgeDetailView: React.FC<BadgeDetailModalProps> = ({
+ name,
+ isEditable = true,
+ setBadgeViewVisible,
+ selectedBadges,
+}) => {
+ const navigation = useNavigation();
+ const [removableBadges, setRemovableBadges] = useState([]);
+
+ const {
+ user: {userId = ''},
+ } = useSelector((state: RootState) => state.user);
+
+ const removeBadgeCell = async () => {
+ await removeBadgesService(removableBadges, userId);
+ };
+
+ const badgeEditCell = ({item: {id, name, badgeImage}}) => {
+ return (
+ <TouchableOpacity
+ style={styles.badgeCellContainerStyles}
+ onPress={() => {
+ setBadgeViewVisible(false);
+ navigation.navigate('MutualBadgeHolders', {
+ badge_id: id,
+ badge_title: name,
+ badge_img: badgeImage,
+ });
+ }}>
+ <View
+ style={
+ isEditable
+ ? styles.badgeCellImageContainerStyles
+ : styles.badgeCellImageNoEditContainerStyles
+ }>
+ <LinearGradient
+ colors={BADGE_GRADIENT_FIRST}
+ useAngle={true}
+ style={styles.badgeCellImageStyles}
+ angle={136.69}>
+ <Image
+ resizeMode="cover"
+ style={{
+ width: 70,
+ height: 70,
+ alignSelf: 'center',
+ }}
+ source={badgeImage}
+ />
+ </LinearGradient>
+ {isEditable && (
+ <TouchableOpacity
+ onPress={() => {
+ selectedBadges = selectedBadges.filter((b) => b.id === id);
+ const obj = {id, name};
+ removableBadges.push(obj);
+ removeBadgeCell();
+ }}>
+ <CloseIcon height={25} width={25} color="gray" />
+ </TouchableOpacity>
+ )}
+ </View>
+ <View style={{marginTop: 10}}>
+ <Text style={styles.badgeCellTextStyles}>{name}</Text>
+ </View>
+ </TouchableOpacity>
+ );
+ };
+
+ const addButton = () => {
+ return (
+ <TouchableOpacity
+ onPress={() => {
+ setBadgeViewVisible(false);
+ navigation.navigate('BadgeSelection', {editing: true});
+ }}
+ style={styles.addButtonStyles}>
+ <Text style={styles.addButtonTextStyles}>Add Badges</Text>
+ </TouchableOpacity>
+ );
+ };
+
+ const modalHeader = () => {
+ const heading = isEditable ? 'Edit your badges!' : name;
+ const subheading = isEditable
+ ? 'Add or delete your badges'
+ : 'View badges to discover groups!';
+ return (
+ <View>
+ <Text style={styles.modalHeadingStyles}>{heading}</Text>
+ <Text style={styles.modalSubheadingStyles}>{subheading}</Text>
+ </View>
+ );
+ };
+
+ return (
+ <Modal
+ animationType="slide"
+ transparent
+ visible={true}
+ presentationStyle="overFullScreen">
+ <View style={styles.viewWrapper}>
+ <View style={styles.modalView}>
+ <View style={styles.modalUpperContainerStyles}>
+ <TouchableOpacity
+ style={{marginTop: 10, marginLeft: 10}}
+ onPress={() => setBadgeViewVisible(false)}>
+ <CloseIcon height={25} width={25} color="gray" />
+ </TouchableOpacity>
+ <View style={styles.modalImageContainerStyles}>
+ <Image
+ style={styles.modalImageStyles}
+ source={getUniversityBadge(UniversityType.Brown, 'Crest')}
+ />
+ </View>
+ </View>
+ {modalHeader()}
+ <View>
+ <FlatList
+ contentContainerStyle={styles.modalListStyles}
+ scrollEnabled={false}
+ data={selectedBadges}
+ numColumns={3}
+ renderItem={badgeEditCell}
+ keyExtractor={(item) => item.id.toString()}
+ />
+ </View>
+ {isEditable && addButton()}
+ </View>
+ </View>
+ </Modal>
+ );
+};
+
+const styles = StyleSheet.create({
+ badgeCellContainerStyles: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ paddingVertical: 10,
+ },
+ badgeCellImageContainerStyles: {
+ flexDirection: 'row',
+ marginLeft: 25,
+ },
+ badgeCellImageNoEditContainerStyles: {
+ flexDirection: 'row',
+ marginHorizontal: 25,
+ },
+ badgeCellImageStyles: {
+ borderRadius: 50,
+ },
+ badgeCellTextStyles: {
+ fontWeight: '600',
+ fontSize: normalize(12),
+ lineHeight: normalize(16),
+ textAlign: 'center',
+ },
+ addButtonStyles: {
+ height: 40,
+ borderRadius: 5,
+ marginBottom: 45,
+ width: '40%',
+ marginTop: 14,
+ alignItems: 'center',
+ justifyContent: 'center',
+ alignSelf: 'center',
+ backgroundColor: '#698DD3',
+ },
+ addButtonTextStyles: {color: 'white'},
+ modalHeadingStyles: {
+ fontWeight: '600',
+ fontSize: normalize(17),
+ lineHeight: normalize(20.29),
+ textAlign: 'center',
+ },
+ modalSubheadingStyles: {
+ fontWeight: '600',
+ fontSize: normalize(11),
+ lineHeight: normalize(15),
+ textAlign: 'center',
+ color: '#828282',
+ },
+ modalUpperContainerStyles: {
+ flexDirection: 'row',
+ alignItems: 'flex-start',
+ },
+ modalImageContainerStyles: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ modalImageStyles: {left: -15, top: -30},
+ modalListStyles: {
+ alignSelf: 'center',
+ marginVertical: 35,
+ },
+ viewWrapper: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: 'rgba(0, 0, 0, 0.2)',
+ },
+ modalView: {
+ width: '95%',
+ backgroundColor: '#fff',
+ borderRadius: 7,
+ },
+});
+
+export default BadgeDetailView;
diff --git a/src/components/profile/ProfileHeader.tsx b/src/components/profile/ProfileHeader.tsx
index 2c623c2b..a17d9f6f 100644
--- a/src/components/profile/ProfileHeader.tsx
+++ b/src/components/profile/ProfileHeader.tsx
@@ -1,10 +1,14 @@
-import React, {useState} from 'react';
+import React, {useEffect, useState} from 'react';
import {StyleSheet, Text, View} from 'react-native';
+import {TouchableOpacity} from 'react-native-gesture-handler';
import {useSelector} from 'react-redux';
import {PROFILE_CUTOUT_TOP_Y} from '../../constants';
+import {BADGE_DATA} from '../../constants/badges';
+import {getSuggestedPeopleProfile} from '../../services';
import {RootState} from '../../store/rootreducer';
-import {ScreenType} from '../../types';
+import {ScreenType, UniversityBadge} from '../../types';
import {normalize} from '../../utils';
+import BadgeDetailView from '../common/BadgeDetailView';
import Avatar from './Avatar';
import FriendsCount from './FriendsCount';
import ProfileMoreInfoDrawer from './ProfileMoreInfoDrawer';
@@ -25,12 +29,59 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
}) => {
const {
profile: {name = '', university_class = 2021, university},
- user: {username: userXName = ''},
+ user: {userId, username: userXName = ''},
} = useSelector((state: RootState) =>
userXId ? state.userX[screenType][userXId] : state.user,
);
+
+ const {
+ user: {username = ''},
+ } = useSelector((state: RootState) => state.user);
const [drawerVisible, setDrawerVisible] = useState(false);
+ const [showBadgeView, setBadgeViewVisible] = useState(false);
const [firstName, lastName] = [...name.split(' ')];
+ const [selectedBadges, setSelectedBadges] = useState<UniversityBadge[]>([]);
+ const [selectedBadgesWithImage, setSelectedBadgesWithImage] = useState<any[]>(
+ [],
+ );
+
+ const fetchBadges = async () => {
+ const uid = userXId ? userXId : userId;
+ if (uid) {
+ const response = await getSuggestedPeopleProfile(uid);
+ if (response) {
+ const data = response.badges;
+ let extractedBadgeNames: UniversityBadge[] = [];
+ data.forEach((badge) => {
+ extractedBadgeNames.push(badge);
+ });
+ setSelectedBadges(extractedBadgeNames);
+ }
+ }
+ };
+
+ useEffect(() => {
+ fetchBadges();
+ }, []);
+
+ useEffect(() => {
+ let badgesWithImage = [];
+ selectedBadges.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);
+ });
+ });
+ setSelectedBadgesWithImage(badgesWithImage);
+ }, [selectedBadges]);
+
return (
<View style={styles.container}>
<ProfileMoreInfoDrawer
@@ -59,7 +110,17 @@ const ProfileHeader: React.FC<ProfileHeaderProps> = ({
)}
<View style={styles.friendsAndUniversity}>
<FriendsCount screenType={screenType} userXId={userXId} />
- <UniversityIcon {...{university, university_class}} />
+ <TouchableOpacity onPress={() => setBadgeViewVisible(true)}>
+ <UniversityIcon {...{university, university_class}} />
+ </TouchableOpacity>
+ {showBadgeView && (
+ <BadgeDetailView
+ isEditable={userXName === username}
+ name={name}
+ selectedBadges={selectedBadgesWithImage}
+ setBadgeViewVisible={setBadgeViewVisible}
+ />
+ )}
</View>
</View>
</View>
diff --git a/src/constants/api.ts b/src/constants/api.ts
index dd934f0e..45b6e8ae 100644
--- a/src/constants/api.ts
+++ b/src/constants/api.ts
@@ -58,6 +58,8 @@ export const SP_MUTUAL_BADGE_HOLDERS_ENDPOINT: string =
export const ADD_BADGES_ENDPOINT: string = SP_USERS_ENDPOINT + 'add_badges/';
export const UPDATE_BADGES_ENDPOINT: string =
SP_USERS_ENDPOINT + 'update_badges/';
+ export const REMOVE_BADGES_ENDPOINT: string =
+ SP_USERS_ENDPOINT + 'remove_badges/';
// Register as FCM device
export const FCM_ENDPOINT: string = API_URL + 'fcm/';
diff --git a/src/screens/badge/BadgeSelection.tsx b/src/screens/badge/BadgeSelection.tsx
index 91617377..0284498d 100644
--- a/src/screens/badge/BadgeSelection.tsx
+++ b/src/screens/badge/BadgeSelection.tsx
@@ -66,7 +66,7 @@ const BadgeSelection: React.FC<BadgeSelectionProps> = ({route}) => {
style={styles.rightButtonContainer}
onPress={async () => {
if (editing) {
- updateBadgesService(selectedBadges, university);
+ await updateBadgesService(selectedBadges, university);
navigation.navigate('UpdateSPPicture', {
editing: true,
});
diff --git a/src/services/SuggestedPeopleService.ts b/src/services/SuggestedPeopleService.ts
index 617f3970..7f5b4b8c 100644
--- a/src/services/SuggestedPeopleService.ts
+++ b/src/services/SuggestedPeopleService.ts
@@ -7,6 +7,7 @@ import {
import {
ADD_BADGES_ENDPOINT,
EDIT_PROFILE_ENDPOINT,
+ REMOVE_BADGES_ENDPOINT,
SP_MUTUAL_BADGE_HOLDERS_ENDPOINT,
SP_UPDATE_PICTURE_ENDPOINT,
SP_USERS_ENDPOINT,
@@ -195,3 +196,34 @@ export const updateBadgesService = async (
Alert.alert(ERROR_UPLOAD_BADGES);
}
};
+
+export const removeBadgesService = async (
+ removableBadges: string[],
+ userId: string,
+) => {
+ try {
+ const token = await AsyncStorage.getItem('token');
+ const form = new FormData();
+ form.append('badges', JSON.stringify(removableBadges));
+ form.append('user', JSON.stringify(userId));
+ const response = await fetch(REMOVE_BADGES_ENDPOINT, {
+ method: 'DELETE',
+ headers: {
+ 'Content-Type': 'multipart/form-data',
+ Authorization: 'Token ' + token,
+ },
+ body: form,
+ });
+ if (response.status === 400) {
+ Alert.alert(ERROR_BADGES_EXCEED_LIMIT);
+ return;
+ }
+ if (response.status === 200) {
+ Alert.alert(SUCCESS_BADGES_UPDATE);
+ return;
+ }
+ } catch (error) {
+ console.log(error);
+ Alert.alert(ERROR_UPLOAD_BADGES);
+ }
+};