diff options
32 files changed, 367 insertions, 117 deletions
diff --git a/src/assets/badges/aap.png b/src/assets/badges/aap.png Binary files differnew file mode 100644 index 00000000..dd150b8f --- /dev/null +++ b/src/assets/badges/aap.png diff --git a/src/assets/badges/cals.png b/src/assets/badges/cals.png Binary files differnew file mode 100644 index 00000000..fbf0717b --- /dev/null +++ b/src/assets/badges/cals.png diff --git a/src/assets/badges/college_of_arts_and_sciences.png b/src/assets/badges/college_of_arts_and_sciences.png Binary files differnew file mode 100644 index 00000000..146a06ed --- /dev/null +++ b/src/assets/badges/college_of_arts_and_sciences.png diff --git a/src/assets/badges/college_of_engineering.png b/src/assets/badges/college_of_engineering.png Binary files differnew file mode 100644 index 00000000..c3f9e889 --- /dev/null +++ b/src/assets/badges/college_of_engineering.png diff --git a/src/assets/badges/college_of_human_ecology.png b/src/assets/badges/college_of_human_ecology.png Binary files differnew file mode 100644 index 00000000..14a9fd80 --- /dev/null +++ b/src/assets/badges/college_of_human_ecology.png diff --git a/src/assets/badges/college_of_veterinary_medicine.png b/src/assets/badges/college_of_veterinary_medicine.png Binary files differnew file mode 100644 index 00000000..1814aa97 --- /dev/null +++ b/src/assets/badges/college_of_veterinary_medicine.png diff --git a/src/assets/badges/cornell_law_school.png b/src/assets/badges/cornell_law_school.png Binary files differnew file mode 100644 index 00000000..43104e41 --- /dev/null +++ b/src/assets/badges/cornell_law_school.png diff --git a/src/assets/badges/cornell_tech.png b/src/assets/badges/cornell_tech.png Binary files differnew file mode 100644 index 00000000..c40d3889 --- /dev/null +++ b/src/assets/badges/cornell_tech.png diff --git a/src/assets/badges/dyson_school.png b/src/assets/badges/dyson_school.png Binary files differnew file mode 100644 index 00000000..d17663b7 --- /dev/null +++ b/src/assets/badges/dyson_school.png diff --git a/src/assets/badges/entrepreneurship_at_cornell.png b/src/assets/badges/entrepreneurship_at_cornell.png Binary files differnew file mode 100644 index 00000000..6b86abd4 --- /dev/null +++ b/src/assets/badges/entrepreneurship_at_cornell.png diff --git a/src/assets/badges/graduate_school.png b/src/assets/badges/graduate_school.png Binary files differnew file mode 100644 index 00000000..f1c4006e --- /dev/null +++ b/src/assets/badges/graduate_school.png diff --git a/src/assets/badges/hotel_administration.png b/src/assets/badges/hotel_administration.png Binary files differnew file mode 100644 index 00000000..a92cfa3d --- /dev/null +++ b/src/assets/badges/hotel_administration.png diff --git a/src/assets/badges/ilr.png b/src/assets/badges/ilr.png Binary files differnew file mode 100644 index 00000000..549d6955 --- /dev/null +++ b/src/assets/badges/ilr.png diff --git a/src/assets/badges/sc_johnson_school_of_management.png b/src/assets/badges/sc_johnson_school_of_management.png Binary files differnew file mode 100644 index 00000000..3fc24aa4 --- /dev/null +++ b/src/assets/badges/sc_johnson_school_of_management.png diff --git a/src/assets/badges/student_agencies.png b/src/assets/badges/student_agencies.png Binary files differnew file mode 100644 index 00000000..ac31a1ee --- /dev/null +++ b/src/assets/badges/student_agencies.png diff --git a/src/assets/badges/weill_cornell_medical_sciences.png b/src/assets/badges/weill_cornell_medical_sciences.png Binary files differnew file mode 100644 index 00000000..2167df79 --- /dev/null +++ b/src/assets/badges/weill_cornell_medical_sciences.png diff --git a/src/assets/badges/weill_cornell_medicine.png b/src/assets/badges/weill_cornell_medicine.png Binary files differnew file mode 100644 index 00000000..3e8a60b3 --- /dev/null +++ b/src/assets/badges/weill_cornell_medicine.png diff --git a/src/components/common/BasicButton.tsx b/src/components/common/BasicButton.tsx index 1fe29cd9..e2274dbd 100644 --- a/src/components/common/BasicButton.tsx +++ b/src/components/common/BasicButton.tsx @@ -1,5 +1,12 @@ import React from 'react'; -import {StyleProp, StyleSheet, Text, View, ViewStyle} from 'react-native'; +import { + StyleProp, + StyleSheet, + Text, + TextStyle, + View, + ViewStyle, +} from 'react-native'; import {TAGG_LIGHT_BLUE} from '../../constants'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {normalize} from '../../utils'; @@ -8,7 +15,7 @@ interface BasicButtonProps { title: string; onPress: () => void; solid?: boolean; - externalStyles?: Record<string, StyleProp<ViewStyle>>; + externalStyles?: Record<string, StyleProp<ViewStyle | TextStyle>>; } const BasicButton: React.FC<BasicButtonProps> = ({ title, @@ -27,6 +34,7 @@ const BasicButton: React.FC<BasicButtonProps> = ({ <Text style={[ styles.buttonTitle, + externalStyles?.buttonTitle, solid ? styles.solidButtonTitleColor : styles.outlineButtonTitleColor, diff --git a/src/components/friends/InviteFriendTile.tsx b/src/components/friends/InviteFriendTile.tsx index 5237389a..abd017d0 100644 --- a/src/components/friends/InviteFriendTile.tsx +++ b/src/components/friends/InviteFriendTile.tsx @@ -1,21 +1,30 @@ import React, {useEffect, useState} from 'react'; import { Alert, + Linking, StyleSheet, Text, TouchableOpacity, TouchableWithoutFeedback, View, } from 'react-native'; +import {useSelector} from 'react-redux'; +import {RootState} from 'src/store/rootReducer'; import {TAGG_LIGHT_BLUE} from '../../constants'; import { ERROR_NO_CONTACT_INVITE_LEFT, ERROR_SOMETHING_WENT_WRONG, - SUCCESS_INVITE_CONTACT, + INVITE_USER_SMS_BODY, + SUCCESS_CONFIRM_INVITE_CONTACT_MESSAGE, + SUCCESS_CONFIRM_INVITE_CONTACT_TITLE, SUCCESS_LAST_CONTACT_INVITE, } from '../../constants/strings'; import {InviteContactType} from '../../screens/profile/InviteFriendsScreen'; -import {inviteFriendService} from '../../services'; +import { + getRemainingInviteCount, + handleCreateInviteCode, + inviteFriendService, +} from '../../services'; import {normalize} from '../../utils'; interface InviteFriendTileProps { @@ -24,20 +33,41 @@ interface InviteFriendTileProps { const InviteFriendTile: React.FC<InviteFriendTileProps> = ({item}) => { const [invited, setInvited] = useState<boolean>(false); + const {name} = useSelector((state: RootState) => state.user.profile); const [formatedPhoneNumber, setFormattedPhoneNumber] = useState<string>(''); const handleInviteFriend = async () => { - const invites_left = await inviteFriendService( - item.phoneNumber, - item.firstName, - item.lastName, - ); + const invites_left = await getRemainingInviteCount(); if (invites_left > 0) { - setInvited(true); - Alert.alert(SUCCESS_INVITE_CONTACT(invites_left)); - } else if (invites_left === 0) { - setInvited(true); - Alert.alert(SUCCESS_LAST_CONTACT_INVITE); - } else if (invites_left === -1) { + Alert.alert( + SUCCESS_CONFIRM_INVITE_CONTACT_TITLE(invites_left), + SUCCESS_CONFIRM_INVITE_CONTACT_MESSAGE, + [ + {text: 'No!', style: 'cancel'}, + { + text: 'Yes!', + onPress: async () => { + setInvited(true); + const inviteCode = await handleCreateInviteCode(); + await inviteFriendService( + item.phoneNumber, + item.firstName, + item.lastName, + ); + Linking.openURL( + `sms:${item.phoneNumber}&body=${INVITE_USER_SMS_BODY( + item.firstName, + name, + inviteCode, + )}`, + ); + if (invites_left === 1) { + Alert.alert(SUCCESS_LAST_CONTACT_INVITE); + } + }, + }, + ], + ); + } else if (invites_left === -1 || invites_left === 0) { Alert.alert(ERROR_NO_CONTACT_INVITE_LEFT); } else { Alert.alert(ERROR_SOMETHING_WENT_WRONG); diff --git a/src/components/messages/MessageButton.tsx b/src/components/messages/MessageButton.tsx new file mode 100644 index 00000000..5ac42c4c --- /dev/null +++ b/src/components/messages/MessageButton.tsx @@ -0,0 +1,73 @@ +import React from 'react'; +import {Fragment, useContext} from 'react'; +import {useStore} from 'react-redux'; +import {ChatContext} from '../../App'; +import {RootState} from '../../store/rootReducer'; +import {FriendshipStatusType} from '../../types'; +import {createChannel} from '../../utils'; +import {Alert, StyleProp, TextStyle, ViewStyle} from 'react-native'; +import {BasicButton} from '../common'; +import {useNavigation} from '@react-navigation/native'; +import {ERROR_UNABLE_CONNECT_CHAT} from '../../constants/strings'; + +interface MessageButtonProps { + userXId: string; + isBlocked: boolean; + friendship_status: FriendshipStatusType; + friendship_requester_id?: string; + solid?: boolean; + externalStyles?: Record<string, StyleProp<ViewStyle | TextStyle>>; +} + +const MessageButton: React.FC<MessageButtonProps> = ({ + userXId, + isBlocked, + friendship_status, + friendship_requester_id, + solid, + externalStyles, +}) => { + const navigation = useNavigation(); + const {chatClient, setChannel} = useContext(ChatContext); + + const state: RootState = useStore().getState(); + const loggedInUserId = state.user.user.userId; + + const canMessage = () => { + if ( + userXId && + !isBlocked && + (friendship_status === 'no_record' || + friendship_status === 'friends' || + (friendship_status === 'requested' && + friendship_requester_id === loggedInUserId)) + ) { + return true; + } else { + return false; + } + }; + + const onPressMessage = async () => { + if (chatClient.user && userXId) { + const channel = await createChannel(loggedInUserId, userXId, chatClient); + setChannel(channel); + navigation.navigate('Chat'); + } else { + Alert.alert(ERROR_UNABLE_CONNECT_CHAT); + } + }; + + return canMessage() ? ( + <BasicButton + title={'Message'} + onPress={onPressMessage} + externalStyles={externalStyles} + solid={solid ? solid : false} + /> + ) : ( + <Fragment /> + ); +}; + +export default MessageButton; diff --git a/src/components/messages/index.ts b/src/components/messages/index.ts index b19067ca..7270e2e2 100644 --- a/src/components/messages/index.ts +++ b/src/components/messages/index.ts @@ -7,3 +7,4 @@ export {default as MessageAvatar} from './MessageAvatar'; export {default as TypingIndicator} from './TypingIndicator'; export {default as MessageFooter} from './MessageFooter'; export {default as DateHeader} from './DateHeader'; +export {default as MessageButton} from './MessageButton'; diff --git a/src/components/moments/MomentPostContent.tsx b/src/components/moments/MomentPostContent.tsx index 45186ba1..193bf40c 100644 --- a/src/components/moments/MomentPostContent.tsx +++ b/src/components/moments/MomentPostContent.tsx @@ -10,6 +10,7 @@ import { navigateToProfile, SCREEN_HEIGHT, SCREEN_WIDTH, + normalize, } from '../../utils'; import {mentionPartTypes, renderTextWithMentions} from '../../utils/comments'; import {CommentsCount} from '../comments'; @@ -103,6 +104,9 @@ const styles = StyleSheet.create({ marginRight: '5%', color: '#ffffff', fontWeight: '500', + fontSize: normalize(13), + lineHeight: normalize(15.51), + letterSpacing: normalize(0.6), }, }); export default MomentPostContent; diff --git a/src/components/notifications/Notification.tsx b/src/components/notifications/Notification.tsx index ae884b42..cb62047a 100644 --- a/src/components/notifications/Notification.tsx +++ b/src/components/notifications/Notification.tsx @@ -34,6 +34,7 @@ import { } from '../../utils'; import {Avatar} from '../common'; import AcceptDeclineButtons from '../common/AcceptDeclineButtons'; +import {MessageButton} from '../messages'; interface NotificationProps { item: NotificationType; @@ -61,6 +62,10 @@ const Notification: React.FC<NotificationProps> = (props) => { const [avatar, setAvatar] = useState<string | undefined>(undefined); const [momentURI, setMomentURI] = useState<string | undefined>(undefined); + const notification_title = + notification_type === 'FRD_ACPT' + ? `Say Hi to ${first_name}!` + : `${first_name} ${last_name}`; useEffect(() => { (async () => { @@ -246,9 +251,7 @@ const Notification: React.FC<NotificationProps> = (props) => { {/* Text content: Actor name and verbage*/} <View style={styles.contentContainer}> <TouchableWithoutFeedback onPress={navigateToProfile}> - <Text style={styles.actorName}> - {first_name} {last_name} - </Text> + <Text style={styles.actorName}>{notification_title}</Text> </TouchableWithoutFeedback> <TouchableWithoutFeedback style={styles.textContainerStyles} @@ -273,6 +276,30 @@ const Notification: React.FC<NotificationProps> = (props) => { /> </View> )} + {notification_type === 'FRD_ACPT' && ( + <View style={styles.buttonsContainer}> + <MessageButton + userXId={id} + isBlocked={false} + friendship_status={'friends'} + externalStyles={{ + container: { + width: normalize(63), + height: normalize(21), + marginTop: '7%', + }, + buttonTitle: { + fontSize: normalize(11), + lineHeight: normalize(13.13), + letterSpacing: normalize(0.5), + fontWeight: '700', + textAlign: 'center', + }, + }} + solid + /> + </View> + )} {/* Moment Image Preview */} {(notification_type === 'CMT' || notification_type === 'MOM_3+' || @@ -306,7 +333,7 @@ const styles = StyleSheet.create({ flex: 1, alignSelf: 'center', alignItems: 'center', - paddingHorizontal: '8%', + paddingHorizontal: '6.3%', }, avatarContainer: { height: 42, @@ -348,9 +375,9 @@ const styles = StyleSheet.create({ lineHeight: normalize(13.13), }, timeStampStyles: { - fontWeight: '700', - fontSize: normalize(12), - lineHeight: normalize(14.32), + fontWeight: '500', + fontSize: normalize(11), + lineHeight: normalize(13.13), marginHorizontal: 2, color: '#828282', textAlignVertical: 'center', diff --git a/src/components/profile/FriendsCount.tsx b/src/components/profile/FriendsCount.tsx index 8252266e..a299e9a1 100644 --- a/src/components/profile/FriendsCount.tsx +++ b/src/components/profile/FriendsCount.tsx @@ -37,7 +37,7 @@ const FriendsCount: React.FC<FriendsCountProps> = ({ return ( <TouchableOpacity onPress={() => - navigation.navigate('FriendsListScreen', { + navigation.push('FriendsListScreen', { userXId, screenType, }) diff --git a/src/components/profile/ProfileBody.tsx b/src/components/profile/ProfileBody.tsx index 3d654724..7557de00 100644 --- a/src/components/profile/ProfileBody.tsx +++ b/src/components/profile/ProfileBody.tsx @@ -1,17 +1,7 @@ -import {useNavigation} from '@react-navigation/core'; -import React, {useContext} from 'react'; -import { - Alert, - LayoutChangeEvent, - Linking, - StyleSheet, - Text, - View, -} from 'react-native'; +import React from 'react'; +import {LayoutChangeEvent, Linking, StyleSheet, Text, View} from 'react-native'; import {useDispatch, useSelector, useStore} from 'react-redux'; -import {ChatContext} from '../../App'; import {TAGG_DARK_BLUE, TOGGLE_BUTTON_TYPE} from '../../constants'; -import {ERROR_UNABLE_CONNECT_CHAT} from '../../constants/strings'; import { acceptFriendRequest, declineFriendRequest, @@ -22,14 +12,14 @@ import {NO_PROFILE} from '../../store/initialStates'; import {RootState} from '../../store/rootReducer'; import {ScreenType} from '../../types'; import { - createChannel, getUserAsProfilePreviewType, normalize, SCREEN_HEIGHT, SCREEN_WIDTH, } from '../../utils'; import {canViewProfile} from '../../utils/users'; -import {BasicButton, FriendsButton} from '../common'; +import {FriendsButton} from '../common'; +import {MessageButton} from '../messages'; import ToggleButton from './ToggleButton'; interface ProfileBodyProps { @@ -47,7 +37,6 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ screenType, }) => { const dispatch = useDispatch(); - const navigation = useNavigation(); const {profile = NO_PROFILE, user} = useSelector((state: RootState) => userXId ? state.userX[screenType][userXId] : state.user, @@ -65,10 +54,7 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ profile, ); - const {chatClient, setChannel} = useContext(ChatContext); - const state: RootState = useStore().getState(); - const loggedInUserId = state.user.user.userId; const handleAcceptRequest = async () => { await dispatch(acceptFriendRequest({id, username, first_name, last_name})); @@ -81,32 +67,6 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ dispatch(updateUserXProfileAllScreens(id, state)); }; - const canMessage = () => { - if ( - userXId && - !isBlocked && - (friendship_status === 'no_record' || - friendship_status === 'friends' || - (friendship_status === 'requested' && - friendship_requester_id === loggedInUserId)) && - canViewProfile(state, userXId, screenType) - ) { - return true; - } else { - return false; - } - }; - - const onPressMessage = async () => { - if (chatClient.user && userXId) { - const channel = await createChannel(loggedInUserId, userXId, chatClient); - setChannel(channel); - navigation.navigate('Chat'); - } else { - Alert.alert(ERROR_UNABLE_CONNECT_CHAT); - } - }; - return ( <View onLayout={onLayout} style={styles.container}> <Text style={styles.username}>{`@${username}`}</Text> @@ -142,10 +102,12 @@ const ProfileBody: React.FC<ProfileBodyProps> = ({ onAcceptRequest={handleAcceptRequest} onRejectRequest={handleDeclineFriendRequest} /> - {canMessage() && ( - <BasicButton - title={'Message'} - onPress={onPressMessage} + {canViewProfile(state, userXId, screenType) && ( + <MessageButton + userXId={userXId} + isBlocked={isBlocked} + friendship_status={friendship_status} + friendship_requester_id={friendship_requester_id} externalStyles={{ container: { width: SCREEN_WIDTH * 0.42, diff --git a/src/components/taggs/TaggsBar.tsx b/src/components/taggs/TaggsBar.tsx index 4d567b25..a7e8fc7a 100644 --- a/src/components/taggs/TaggsBar.tsx +++ b/src/components/taggs/TaggsBar.tsx @@ -113,13 +113,11 @@ const TaggsBar: React.FC<TaggsBarProps> = ({ loadData(); } }, [taggsNeedUpdate, user]); - const paddingTopStylesProgress = useDerivedValue(() => - interpolate( - y.value, - [PROFILE_CUTOUT_BOTTOM_Y, PROFILE_CUTOUT_BOTTOM_Y + profileBodyHeight], - [0, 1], - Extrapolate.CLAMP, - ), + const paddingTopStylesProgress = interpolate( + y.value, + [PROFILE_CUTOUT_BOTTOM_Y, PROFILE_CUTOUT_BOTTOM_Y + profileBodyHeight], + [0, 1], + Extrapolate.CLAMP, ); const shadowOpacityStylesProgress = useDerivedValue(() => interpolate( @@ -134,7 +132,7 @@ const TaggsBar: React.FC<TaggsBarProps> = ({ ); const animatedStyles = useAnimatedStyle(() => ({ shadowOpacity: shadowOpacityStylesProgress.value / 5, - paddingTop: paddingTopStylesProgress.value * insetTop, + paddingTop: paddingTopStylesProgress + insetTop, })); return taggs.length > 0 ? ( diff --git a/src/constants/api.ts b/src/constants/api.ts index 9d3f70c9..3c7e669e 100644 --- a/src/constants/api.ts +++ b/src/constants/api.ts @@ -51,7 +51,8 @@ export const USERS_FROM_CONTACTS_ENDPOINT: string = API_URL + 'user_contacts/find_friends/'; export const INVITE_FRIEND_ENDPOINT: string = API_URL + 'user_contacts/invite_friend/'; - +export const CREATE_INVITE_CODE = API_URL + 'create-code/'; +export const GET_REMAINING_INVITES = API_URL + 'user_contacts/check_invite_count/' // Suggested People export const SP_USERS_ENDPOINT: string = API_URL + 'suggested_people/'; export const SP_UPDATE_PICTURE_ENDPOINT: string = @@ -61,7 +62,7 @@ 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 = +export const REMOVE_BADGES_ENDPOINT: string = SP_USERS_ENDPOINT + 'remove_badges/'; export const GET_USER_BADGES_ENDPOINT: string = SP_USERS_ENDPOINT + 'get_badges/'; diff --git a/src/constants/badges.ts b/src/constants/badges.ts index aca53f26..54979ecd 100644 --- a/src/constants/badges.ts +++ b/src/constants/badges.ts @@ -1,7 +1,7 @@ import {BadgeDataType} from '../types'; export const _badgeImages = { - iff: require('../assets/badges/iff.png'), + aap: require('../assets/badges/aap.png'), acacia: require('../assets/badges/acacia.png'), acapella: require('../assets/badges/acapella.png'), alpha_chi_omega: require('../assets/badges/alpha_chi_omega.png'), @@ -26,8 +26,15 @@ export const _badgeImages = { brown_womens_collective: require('../assets/badges/brown_womens_collective.png'), bsu: require('../assets/badges/bsu.png'), buxton_international: require('../assets/badges/buxton_international.png'), + cals: require('../assets/badges/cals.png'), chi_phi: require('../assets/badges/chi_phi.png'), chi_psi: require('../assets/badges/chi_psi.png'), + college_of_arts_and_sciences: require('../assets/badges/college_of_arts_and_sciences.png'), + college_of_engineering: require('../assets/badges/college_of_engineering.png'), + college_of_human_ecology: require('../assets/badges/college_of_human_ecology.png'), + college_of_veterinary_medicine: require('../assets/badges/college_of_veterinary_medicine.png'), + cornell_law_school: require('../assets/badges/cornell_law_school.png'), + cornell_tech: require('../assets/badges/cornell_tech.png'), delta_chi: require('../assets/badges/delta_chi.png'), delta_delta_delta: require('../assets/badges/delta_delta_delta.png'), delta_gamma: require('../assets/badges/delta_gamma.png'), @@ -36,13 +43,19 @@ export const _badgeImages = { delta_tau: require('../assets/badges/delta_tau.png'), delta_tau_delta: require('../assets/badges/delta_tau_delta.png'), delta_upsilon: require('../assets/badges/delta_upsilon.png'), + dyson_school: require('../assets/badges/dyson_school.png'), + entrepreneurship_at_cornell: require('../assets/badges/entrepreneurship_at_cornell.png'), fashion_at_brown: require('../assets/badges/fashion_at_brown.png'), fencing: require('../assets/badges/fencing.png'), field_hockey: require('../assets/badges/field_hockey.png'), football: require('../assets/badges/football.png'), golf: require('../assets/badges/golf.png'), + graduate_school: require('../assets/badges/graduate_school.png'), gymnastics: require('../assets/badges/gymnastics.png'), hockey: require('../assets/badges/hockey.png'), + hotel_administration: require('../assets/badges/hotel_administration.png'), + iff: require('../assets/badges/iff.png'), + ilr: require('../assets/badges/ilr.png'), impulse_and_mezcla: require('../assets/badges/impulse_and_mezcla.png'), kappa_alpha_theta: require('../assets/badges/kappa_alpha_theta.png'), kappa_delta: require('../assets/badges/kappa_delta.png'), @@ -69,6 +82,7 @@ export const _badgeImages = { polo: require('../assets/badges/polo.png'), rowing: require('../assets/badges/rowing.png'), sailing: require('../assets/badges/sailing.png'), + sc_johnson_school_of_management: require('../assets/badges/sc_johnson_school_of_management.png'), sigma_alpha_mu: require('../assets/badges/sigma_alpha_mu.png'), sigma_chi: require('../assets/badges/sigma_chi.png'), sigma_delta_tau: require('../assets/badges/sigma_delta_tau.png'), @@ -77,6 +91,7 @@ export const _badgeImages = { soccer: require('../assets/badges/soccer.png'), softball: require('../assets/badges/softball.png'), squash: require('../assets/badges/squash.png'), + student_agencies: require('../assets/badges/student_agencies.png'), swimming_and_diving: require('../assets/badges/swimming_and_diving.png'), tap: require('../assets/badges/tap.png'), tennis: require('../assets/badges/tennis.png'), @@ -86,6 +101,8 @@ export const _badgeImages = { track_and_field: require('../assets/badges/track_and_field.png'), ucs: require('../assets/badges/ucs.png'), volleyball: require('../assets/badges/volleyball.png'), + weill_cornell_medical_sciences: require('../assets/badges/weill_cornell_medical_sciences.png'), + weill_cornell_medicine: require('../assets/badges/weill_cornell_medicine.png'), women_in_business: require('../assets/badges/women_in_business.png'), wrestling: require('../assets/badges/wrestling.png'), zeta_beta_tau: require('../assets/badges/zeta_beta_tau.png'), @@ -244,13 +261,13 @@ const _brownUniversityBadges = [ badgeImage: _badgeImages.fashion_at_brown, }, { - badgeName: 'Impulse', - badgeImage: _badgeImages.impulse_and_mezcla, - }, - { badgeName: 'Ivy Film Festival ', badgeImage: _badgeImages.iff, }, + { + badgeName: 'Impulse', + badgeImage: _badgeImages.impulse_and_mezcla, + }, ], }, { @@ -629,6 +646,89 @@ const _cornellUniversityBadges = [ }, ], }, + { + title: 'School', + data: [ + { + badgeName: 'College of Agriculture and Life Sciences or (CALS)', + badgeImage: _badgeImages.cals, + }, + { + badgeName: 'College of Architecture, Art and Planning or (AAP)', + badgeImage: _badgeImages.aap, + }, + { + badgeName: 'College of Arts and Sciences ', + badgeImage: _badgeImages.college_of_arts_and_sciences, + }, + { + badgeName: 'Hotel Administration ', + badgeImage: _badgeImages.hotel_administration, + }, + { + badgeName: 'Dyson School', + badgeImage: _badgeImages.dyson_school, + }, + { + badgeName: 'College of Engineering ', + badgeImage: _badgeImages.college_of_engineering, + }, + { + badgeName: 'College of Human Ecology', + badgeImage: _badgeImages.college_of_human_ecology, + }, + { + badgeName: 'School of Industrial and Labor Relations or ILR', + badgeImage: _badgeImages.ilr, + }, + ], + }, + { + title: 'Graduate Program', + data: [ + { + badgeName: 'SC Johnson School of Management', + badgeImage: _badgeImages.sc_johnson_school_of_management, + }, + { + badgeName: 'Conrell Tech (NYC)', + badgeImage: _badgeImages.cornell_tech, + }, + { + badgeName: 'Cornell Law School', + badgeImage: _badgeImages.cornell_law_school, + }, + { + badgeName: 'College of Veterinary Medicine', + badgeImage: _badgeImages.college_of_veterinary_medicine, + }, + { + badgeName: 'Graduate School', + badgeImage: _badgeImages.graduate_school, + }, + { + badgeName: 'Weill Cornell Medicine (NYC)', + badgeImage: _badgeImages.weill_cornell_medicine, + }, + { + badgeName: 'Weill Cornell Medical Sciences (NYC)', + badgeImage: _badgeImages.weill_cornell_medical_sciences, + }, + ], + }, + { + title: 'Network', + data: [ + { + badgeName: 'Entrepreneurship @ Cornell ', + badgeImage: _badgeImages.entrepreneurship_at_cornell, + }, + { + badgeName: 'Student Agencies, INC', + badgeImage: _badgeImages.student_agencies, + }, + ], + }, ]; export const BADGE_DATA: BadgeDataType = { diff --git a/src/constants/strings.ts b/src/constants/strings.ts index 56d54d39..2ce64aed 100644 --- a/src/constants/strings.ts +++ b/src/constants/strings.ts @@ -2,6 +2,7 @@ // Below is the regex to convert this into a csv for the Google Sheet // export const (.*) = .*?(['|"|`])(.*)\2; // replace with: $1\t$3 +export const APP_STORE_LINK = 'https://apps.apple.com/us/app/tagg-discover-your-community/id1537853613' export const ADD_COMMENT_TEXT = (username?: string) => username ? `Reply to ${username}` : 'Add a comment...' export const COMING_SOON_MSG = 'Creating more fun things for you, surprises coming soon 😉'; export const ERROR_ATTEMPT_EDIT_SP = 'Can\'t let you do that yet! Please onboard Suggested People first!'; @@ -68,6 +69,11 @@ export const SUCCESS_BADGES_UPDATE = 'Badges updated successfully!' export const SUCCESS_CATEGORY_DELETE = 'Category successfully deleted, but its memory will live on'; export const SUCCESS_INVITATION_CODE = 'Welcome to Tagg!'; export const SUCCESS_INVITE_CONTACT = (str: string) => `Success! You now have ${str} invites left!`; +export const SUCCESS_CONFIRM_INVITE_CONTACT_TITLE = (str: string) => `You have ${str} invites left!`; +export const SUCCESS_CONFIRM_INVITE_CONTACT_MESSAGE = 'Use one now?'; +export const INVITE_USER_SMS_BODY = (invitedUserName: string, invitee: string, inviteCode: string) => `Hey ${invitedUserName}!\n +You've been tagged by ${invitee}. Follow the instructions below to skip the line and join them on Tagg!\n +Sign up and use this code to get in: ${inviteCode}\n ${APP_STORE_LINK}`; export const SUCCESS_LAST_CONTACT_INVITE = 'Done! That was your last invite, hope you used it wisely!'; export const SUCCESS_LINK = (str: string) => `Successfully linked ${str} 🎉`; export const SUCCESS_PIC_UPLOAD = 'Beautiful, the picture was uploaded successfully!'; diff --git a/src/screens/badge/BadgeItem.tsx b/src/screens/badge/BadgeItem.tsx index 1051d4a7..e4f1b1da 100644 --- a/src/screens/badge/BadgeItem.tsx +++ b/src/screens/badge/BadgeItem.tsx @@ -43,9 +43,15 @@ const BadgeItem: React.FC<BadgeItemProps> = ({ style={styles.item}> <View style={styles.detailContainer}> <Image source={resourcePath} style={styles.imageStyles} /> - <View style={styles.textContainer}> - <Text style={styles.title}>{title}</Text> - </View> + <Text + style={[ + styles.title, + title.length > 30 + ? {fontSize: normalize(12), lineHeight: normalize(16)} + : {}, + ]}> + {title} + </Text> </View> </LinearGradient> </TouchableOpacity> @@ -53,33 +59,30 @@ const BadgeItem: React.FC<BadgeItemProps> = ({ ); }; +const ITEM_WIDTH = SCREEN_WIDTH / 3 - 20; + const styles = StyleSheet.create({ border: { - width: SCREEN_WIDTH / 3 - 20 + 6, - height: 146, + width: ITEM_WIDTH + 6, + height: 156, marginLeft: 10, marginBottom: 12, borderRadius: 8, }, item: { - width: SCREEN_WIDTH / 3 - 20, - height: 140, + width: ITEM_WIDTH, + height: 150, borderRadius: 8, }, detailContainer: { flexGrow: 1, - justifyContent: 'center', + justifyContent: 'space-evenly', alignItems: 'center', - borderWidth: 3, - borderRadius: 8, - borderColor: 'transparent', }, imageStyles: { - width: 40, - height: 40, - marginTop: '11%', + width: normalize(50), + height: normalize(50), }, - textContainer: {marginTop: '16%'}, title: { fontSize: normalize(15), fontWeight: '500', diff --git a/src/services/UserFriendsService.ts b/src/services/UserFriendsService.ts index deb3ec6d..453f35a5 100644 --- a/src/services/UserFriendsService.ts +++ b/src/services/UserFriendsService.ts @@ -1,7 +1,9 @@ import AsyncStorage from '@react-native-community/async-storage'; import {Alert} from 'react-native'; import { + CREATE_INVITE_CODE, FRIENDS_ENDPOINT, + GET_REMAINING_INVITES, INVITE_FRIEND_ENDPOINT, USERS_FROM_CONTACTS_ENDPOINT, } from '../constants'; @@ -220,23 +222,54 @@ export const inviteFriendService = async ( inviteeFirstName: string, inviteeLastName: string, ) => { - const token = await AsyncStorage.getItem('token'); - const response = await fetch(INVITE_FRIEND_ENDPOINT, { - method: 'POST', - headers: { - Authorization: 'Token ' + token, - }, - body: JSON.stringify({ - invitee_phone_number: phoneNumber, - invitee_first_name: inviteeFirstName, - invitee_last_name: inviteeLastName, - }), - }); - if (response.status === 201 || response.status === 200) { + try { + const token = await AsyncStorage.getItem('token'); + const response = await fetch(INVITE_FRIEND_ENDPOINT, { + method: 'POST', + headers: { + Authorization: 'Token ' + token, + }, + body: JSON.stringify({ + invitee_phone_number: phoneNumber, + invitee_first_name: inviteeFirstName, + invitee_last_name: inviteeLastName, + }), + }); + return response.status === 201 || response.status === 200; + } catch (error) { + console.log(error); + Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH); + return false; + } +}; + +export const handleCreateInviteCode = async () => { + const response = await fetch(CREATE_INVITE_CODE, {method: 'POST'}); + if (response.status === 200) { const data = await response.json(); - return data.invites_left; - } else if (response.status === 400) { + return data.code; + } else if (response.status === 500) { return -1; } - return false; +}; + +export const getRemainingInviteCount = async () => { + const token = await AsyncStorage.getItem('token'); + try { + const response = await fetch(GET_REMAINING_INVITES, { + method: 'GET', + headers: { + Authorization: 'Token ' + token, + }, + }); + if (response.status === 200) { + const data = await response.json(); + return data.invites_left; + } else if (response.status === 500) { + return -1; + } + } catch (error) { + console.log(error); + Alert.alert(ERROR_SOMETHING_WENT_WRONG_REFRESH); + } }; diff --git a/src/utils/users.ts b/src/utils/users.ts index 430c843f..8505cde2 100644 --- a/src/utils/users.ts +++ b/src/utils/users.ts @@ -244,6 +244,10 @@ export const navigateToProfile = async ( }); }; +/* Function to open imagepicker and + * select images, which are sent to + * the database to update the profile + */ export const patchProfile = async ( title: 'profile' | 'header', userId: string, |