diff --git a/frontend/api/user.ts b/frontend/api/user.ts index 55f1fd1..cd14fa1 100644 --- a/frontend/api/user.ts +++ b/frontend/api/user.ts @@ -116,3 +116,5 @@ 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)/(tabs)/index.tsx b/frontend/app/(app)/(tabs)/index.tsx index cffb4d3..32b1e16 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/_layout.tsx b/frontend/app/(app)/user/_layout.tsx index bdd8ea9..49f1de4 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 9a38be4..bd637c9 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,15 @@ 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 +54,15 @@ 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 0000000..60e7c59 --- /dev/null +++ b/frontend/app/(app)/user/follower_following.tsx @@ -0,0 +1,115 @@ +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 { 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 1d9bc08..97403d3 100644 --- a/frontend/assets/search.svg +++ b/frontend/assets/search.svg @@ -1,4 +1,4 @@ - - + + diff --git a/frontend/components/profile_tag.tsx b/frontend/components/profile_tag.tsx new file mode 100644 index 0000000..72fc4ee --- /dev/null +++ b/frontend/components/profile_tag.tsx @@ -0,0 +1,51 @@ +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; diff --git a/frontend/types/userProfile.ts b/frontend/types/userProfile.ts index 120575c..3052b06 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; +};