From ea3d9df0292ef0f8de740bf73adc12254b577468 Mon Sep 17 00:00:00 2001 From: ZainabImadulla Date: Mon, 2 Dec 2024 20:23:26 -0500 Subject: [PATCH 1/3] finished user profile --- frontend/api/user.ts | 4 + frontend/app/(app)/user/_layout.tsx | 15 ++- frontend/app/(app)/user/components/header.tsx | 5 +- .../app/(app)/user/follower_following.tsx | 118 ++++++++++++++++++ frontend/assets/search.svg | 4 +- frontend/components/profile.tsx | 1 + frontend/components/profile_tag.tsx | 47 +++++++ frontend/types/userProfile.ts | 6 + 8 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 frontend/app/(app)/user/follower_following.tsx create mode 100644 frontend/components/profile_tag.tsx diff --git a/frontend/api/user.ts b/frontend/api/user.ts index 55f1fd12..71eaea02 100644 --- a/frontend/api/user.ts +++ b/frontend/api/user.ts @@ -116,3 +116,7 @@ export async function updateProfilePhoto(photo: string): Promise { throw new Error(errorData.error || 'failed to change profile pic'); } } + +export function searchUserData(userlist: string[]): User[] { + +} diff --git a/frontend/app/(app)/user/_layout.tsx b/frontend/app/(app)/user/_layout.tsx index bdd8ea94..49f1de4e 100644 --- a/frontend/app/(app)/user/_layout.tsx +++ b/frontend/app/(app)/user/_layout.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import { Stack } from 'expo-router'; +import { Stack, router } from 'expo-router'; +import Arrow from '../../../components/arrow'; const Layout = () => { return ( @@ -11,6 +12,18 @@ const Layout = () => { headerShown: false, }} /> + ( + router.back()} /> + ), + }} + /> ); }; diff --git a/frontend/app/(app)/user/components/header.tsx b/frontend/app/(app)/user/components/header.tsx index 9a38be4d..9ab12659 100644 --- a/frontend/app/(app)/user/components/header.tsx +++ b/frontend/app/(app)/user/components/header.tsx @@ -8,6 +8,7 @@ import { PROFILE_PHOTO } from '../../../../consts/profile'; import { formatNumber } from '../../../../utils/profile'; import FollowButton from './follow-button'; import useFollow from '../../../../hooks/following'; +import { router } from 'expo-router'; const Header = ({ id }: { id: string }) => { const { mongoDBId } = useAuthStore(); @@ -37,7 +38,7 @@ const Header = ({ id }: { id: string }) => { image={data?.user.profilePicture || PROFILE_PHOTO} /> - + {router.push({pathname: "/user/follower_following", params: {id:id, option:"followers"}})}}> {formatNumber(data?.user.followers.length)} @@ -45,7 +46,7 @@ const Header = ({ id }: { id: string }) => { Followers - + {router.push({pathname: "/user/follower_following", params: {id:id, option:"following"}})}}> {formatNumber(data?.user.following.length)} diff --git a/frontend/app/(app)/user/follower_following.tsx b/frontend/app/(app)/user/follower_following.tsx new file mode 100644 index 00000000..9bce6f8e --- /dev/null +++ b/frontend/app/(app)/user/follower_following.tsx @@ -0,0 +1,118 @@ +import React, { useEffect, useState } from 'react'; +import { useLocalSearchParams } from 'expo-router'; +import { useUserById } from '../../../hooks/user'; +import { LinearGradient } from 'expo-linear-gradient'; +import { View, Text, Dimensions, TouchableOpacity, TextInput, Image, FlatList} from 'react-native'; +import Animated, { useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'; +import Fuse from 'fuse.js'; +import { UserType } from '../../../types/userProfile'; +import ProfileTags from '../../../components/profile_tag'; + + + +const FollowerFollowing = () => { + const { width } = Dimensions.get('window'); + const {id, option} = useLocalSearchParams<{ id: string, option: string}>(); + const {data, isError, isLoading } = useUserById(id); + const [category, setCategory] = option == "followers"? useState('Followers') : useState('Following'); + const [userData, setUserData] = useState([]); + + + useEffect(() => { + const findData = () => { + if(category == "Followers"){ + setUserData(data?.user.followers) + } else { + setUserData(data?.user.following) + } + } + findData(); + }, [category]) + + const renderUser = ({item}: { item: any;}) => ( + + + + ); + + const indicatorStyle = useAnimatedStyle(() => { + return { + transform: [ + { + translateX: withTiming( + category === 'Followers' ? 0 : (width / 2) , + { + duration: 300, + easing: Easing.bezier(0.25, 0.1, 0.25, 1), + }, + ), + }, + ], + }; + }, [category]); + + + + return ( + + + + {category === "Followers" ? "Followers" : "Following" } + + + @{data?.user.username} + + + + + setCategory('Followers')} + > + + {data.user.followers.length} Followers + + + setCategory('Following')} + > + + {data.user.following.length} Following + + + + + + + + + + + ) +}; + +export default FollowerFollowing; diff --git a/frontend/assets/search.svg b/frontend/assets/search.svg index 1d9bc08d..97403d32 100644 --- a/frontend/assets/search.svg +++ b/frontend/assets/search.svg @@ -1,4 +1,4 @@ - - + + diff --git a/frontend/components/profile.tsx b/frontend/components/profile.tsx index f2a26c3f..6189a136 100644 --- a/frontend/components/profile.tsx +++ b/frontend/components/profile.tsx @@ -32,6 +32,7 @@ const Profile: React.FC = ({ uri: image, }} /> + ); }; diff --git a/frontend/components/profile_tag.tsx b/frontend/components/profile_tag.tsx new file mode 100644 index 00000000..df364146 --- /dev/null +++ b/frontend/components/profile_tag.tsx @@ -0,0 +1,47 @@ +import { View, Text, TouchableOpacity } from 'react-native'; +import Profile from './profile'; +import { router } from 'expo-router'; +import { PROFILE_PHOTO } from '../consts/profile'; +import FollowButton from '../app/(app)/user/components/follow-button'; +import useFollow from '../hooks/following'; +import { UserType } from '../types/userProfile'; +import { useUserById } from '../hooks/user'; +import { useAuthStore } from '../auth/authStore'; + + +interface ProfileTagProps { + id : string +} +const ProfileTags: React.FC = ({ + id + }) => { + const {data, isLoading, isError} = useUserById(id); + const { handleFollowToggle, isFollowing, isPending } = useFollow(data?.user._id); + const uri = data?.user.profilePicture ? data?.user.profilePicture : PROFILE_PHOTO; + const { mongoDBId } = useAuthStore() + const isViewingOwnProfile = mongoDBId === id; + return ( + {router.push(`/user/${data?.user._id}`)}} + className="flex w-full flex-row items-center h-[8vh] bg-white shadow-sm rounded-lg pl-2" + > + + + {data?.user.username} + + + {isViewingOwnProfile? <>: + + } + + + + ) +} + +export default ProfileTags; \ No newline at end of file diff --git a/frontend/types/userProfile.ts b/frontend/types/userProfile.ts index 120575c4..27871785 100644 --- a/frontend/types/userProfile.ts +++ b/frontend/types/userProfile.ts @@ -1,3 +1,9 @@ export type UpdateProfileFields = { profilePicture: string; //String to the s3 }; + +export type UserType = { + _id: string; + profilePicture: string; + username: string +} From 4ded288d490c04e1a71902e5abd1e3f977a178d1 Mon Sep 17 00:00:00 2001 From: ZainabImadulla Date: Mon, 2 Dec 2024 21:24:13 -0500 Subject: [PATCH 2/3] fixed styled of user tag --- frontend/app/(app)/user/follower_following.tsx | 1 - frontend/components/profile_tag.tsx | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/frontend/app/(app)/user/follower_following.tsx b/frontend/app/(app)/user/follower_following.tsx index 9bce6f8e..b46280cc 100644 --- a/frontend/app/(app)/user/follower_following.tsx +++ b/frontend/app/(app)/user/follower_following.tsx @@ -4,7 +4,6 @@ import { useUserById } from '../../../hooks/user'; import { LinearGradient } from 'expo-linear-gradient'; import { View, Text, Dimensions, TouchableOpacity, TextInput, Image, FlatList} from 'react-native'; import Animated, { useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'; -import Fuse from 'fuse.js'; import { UserType } from '../../../types/userProfile'; import ProfileTags from '../../../components/profile_tag'; diff --git a/frontend/components/profile_tag.tsx b/frontend/components/profile_tag.tsx index df364146..dc3a0ee1 100644 --- a/frontend/components/profile_tag.tsx +++ b/frontend/components/profile_tag.tsx @@ -30,7 +30,7 @@ const ProfileTags: React.FC = ({ {data?.user.username} - {isViewingOwnProfile? <>: + {isViewingOwnProfile? <>: Date: Mon, 2 Dec 2024 21:24:41 -0500 Subject: [PATCH 3/3] fixed format --- frontend/api/user.ts | 4 +- frontend/app/(app)/(tabs)/index.tsx | 1 - frontend/app/(app)/user/components/header.tsx | 20 +- .../app/(app)/user/follower_following.tsx | 186 +++++++++--------- frontend/components/profile.tsx | 1 - frontend/components/profile_tag.tsx | 72 +++---- frontend/types/userProfile.ts | 4 +- 7 files changed, 151 insertions(+), 137 deletions(-) diff --git a/frontend/api/user.ts b/frontend/api/user.ts index 71eaea02..cd14fa14 100644 --- a/frontend/api/user.ts +++ b/frontend/api/user.ts @@ -117,6 +117,4 @@ export async function updateProfilePhoto(photo: string): Promise { } } -export function searchUserData(userlist: string[]): User[] { - -} +export function searchUserData(userlist: string[]): User[] {} diff --git a/frontend/app/(app)/(tabs)/index.tsx b/frontend/app/(app)/(tabs)/index.tsx index cffb4d31..32b1e164 100644 --- a/frontend/app/(app)/(tabs)/index.tsx +++ b/frontend/app/(app)/(tabs)/index.tsx @@ -245,7 +245,6 @@ const Home = () => { }} */ > - {split(nearbyPosts?.pages.flatMap((page) => page) || [])[0].map( diff --git a/frontend/app/(app)/user/components/header.tsx b/frontend/app/(app)/user/components/header.tsx index 9ab12659..bd637c9e 100644 --- a/frontend/app/(app)/user/components/header.tsx +++ b/frontend/app/(app)/user/components/header.tsx @@ -38,7 +38,15 @@ const Header = ({ id }: { id: string }) => { image={data?.user.profilePicture || PROFILE_PHOTO} /> - {router.push({pathname: "/user/follower_following", params: {id:id, option:"followers"}})}}> + { + router.push({ + pathname: '/user/follower_following', + params: { id: id, option: 'followers' }, + }); + }} + > {formatNumber(data?.user.followers.length)} @@ -46,7 +54,15 @@ const Header = ({ id }: { id: string }) => { Followers - {router.push({pathname: "/user/follower_following", params: {id:id, option:"following"}})}}> + { + router.push({ + pathname: '/user/follower_following', + params: { id: id, option: 'following' }, + }); + }} + > {formatNumber(data?.user.following.length)} diff --git a/frontend/app/(app)/user/follower_following.tsx b/frontend/app/(app)/user/follower_following.tsx index b46280cc..60e7c59a 100644 --- a/frontend/app/(app)/user/follower_following.tsx +++ b/frontend/app/(app)/user/follower_following.tsx @@ -2,116 +2,114 @@ import React, { useEffect, useState } from 'react'; import { useLocalSearchParams } from 'expo-router'; import { useUserById } from '../../../hooks/user'; import { LinearGradient } from 'expo-linear-gradient'; -import { View, Text, Dimensions, TouchableOpacity, TextInput, Image, FlatList} from 'react-native'; -import Animated, { useAnimatedStyle, withTiming, Easing } from 'react-native-reanimated'; +import { + View, + Text, + Dimensions, + TouchableOpacity, + TextInput, + Image, + FlatList, +} from 'react-native'; +import Animated, { + useAnimatedStyle, + withTiming, + Easing, +} from 'react-native-reanimated'; import { UserType } from '../../../types/userProfile'; import ProfileTags from '../../../components/profile_tag'; - - const FollowerFollowing = () => { - const { width } = Dimensions.get('window'); - const {id, option} = useLocalSearchParams<{ id: string, option: string}>(); - const {data, isError, isLoading } = useUserById(id); - const [category, setCategory] = option == "followers"? useState('Followers') : useState('Following'); - const [userData, setUserData] = useState([]); - - - useEffect(() => { - const findData = () => { - if(category == "Followers"){ - setUserData(data?.user.followers) - } else { - setUserData(data?.user.following) - } - } - findData(); - }, [category]) + const { width } = Dimensions.get('window'); + const { id, option } = useLocalSearchParams<{ id: string; option: string }>(); + const { data, isError, isLoading } = useUserById(id); + const [category, setCategory] = + option == 'followers' ? useState('Followers') : useState('Following'); + const [userData, setUserData] = useState([]); - const renderUser = ({item}: { item: any;}) => ( - - - - ); + useEffect(() => { + const findData = () => { + if (category == 'Followers') { + setUserData(data?.user.followers); + } else { + setUserData(data?.user.following); + } + }; + findData(); + }, [category]); - const indicatorStyle = useAnimatedStyle(() => { - return { - transform: [ - { - translateX: withTiming( - category === 'Followers' ? 0 : (width / 2) , - { - duration: 300, - easing: Easing.bezier(0.25, 0.1, 0.25, 1), - }, - ), - }, - ], - }; - }, [category]); + const renderUser = ({ item }: { item: any }) => ( + + + + ); - + const indicatorStyle = useAnimatedStyle(() => { + return { + transform: [ + { + translateX: withTiming(category === 'Followers' ? 0 : width / 2, { + duration: 300, + easing: Easing.bezier(0.25, 0.1, 0.25, 1), + }), + }, + ], + }; + }, [category]); - return ( + return ( - - - {category === "Followers" ? "Followers" : "Following" } + + + {category === 'Followers' ? 'Followers' : 'Following'} + + + @{data?.user.username} + + + + + setCategory('Followers')} + > + + {data.user.followers.length} Followers - - @{data?.user.username} + + setCategory('Following')} + > + + {data.user.following.length} Following + + - - - setCategory('Followers')} - > - - {data.user.followers.length} Followers - - - setCategory('Following')} - > - - {data.user.following.length} Following - - - - - - - - - + + - ) + ); }; export default FollowerFollowing; diff --git a/frontend/components/profile.tsx b/frontend/components/profile.tsx index 6189a136..f2a26c3f 100644 --- a/frontend/components/profile.tsx +++ b/frontend/components/profile.tsx @@ -32,7 +32,6 @@ const Profile: React.FC = ({ uri: image, }} /> - ); }; diff --git a/frontend/components/profile_tag.tsx b/frontend/components/profile_tag.tsx index dc3a0ee1..72fc4eef 100644 --- a/frontend/components/profile_tag.tsx +++ b/frontend/components/profile_tag.tsx @@ -8,40 +8,44 @@ import { UserType } from '../types/userProfile'; import { useUserById } from '../hooks/user'; import { useAuthStore } from '../auth/authStore'; - interface ProfileTagProps { - id : string -} -const ProfileTags: React.FC = ({ - id - }) => { - const {data, isLoading, isError} = useUserById(id); - const { handleFollowToggle, isFollowing, isPending } = useFollow(data?.user._id); - const uri = data?.user.profilePicture ? data?.user.profilePicture : PROFILE_PHOTO; - const { mongoDBId } = useAuthStore() - const isViewingOwnProfile = mongoDBId === id; - return ( - {router.push(`/user/${data?.user._id}`)}} - className="flex w-full flex-row items-center h-[8vh] bg-white shadow-sm rounded-lg pl-2" - > - - - {data?.user.username} - - - {isViewingOwnProfile? <>: - - } - - - - ) + id: string; } +const ProfileTags: React.FC = ({ id }) => { + const { data, isLoading, isError } = useUserById(id); + const { handleFollowToggle, isFollowing, isPending } = useFollow( + data?.user._id, + ); + const uri = data?.user.profilePicture + ? data?.user.profilePicture + : PROFILE_PHOTO; + const { mongoDBId } = useAuthStore(); + const isViewingOwnProfile = mongoDBId === id; + return ( + { + router.push(`/user/${data?.user._id}`); + }} + className="flex w-full flex-row items-center h-[8vh] bg-white shadow-sm rounded-lg pl-2" + > + + + {data?.user.username} + + + {isViewingOwnProfile ? ( + <> + ) : ( + + + + )} + + ); +}; -export default ProfileTags; \ No newline at end of file +export default ProfileTags; diff --git a/frontend/types/userProfile.ts b/frontend/types/userProfile.ts index 27871785..3052b06a 100644 --- a/frontend/types/userProfile.ts +++ b/frontend/types/userProfile.ts @@ -5,5 +5,5 @@ export type UpdateProfileFields = { export type UserType = { _id: string; profilePicture: string; - username: string -} + username: string; +};