Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
in-mai-space committed Dec 3, 2024
2 parents 3c9d4f0 + e29bc29 commit 8843b38
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 5 deletions.
2 changes: 2 additions & 0 deletions frontend/api/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,5 @@ export async function updateProfilePhoto(photo: string): Promise<void> {
throw new Error(errorData.error || 'failed to change profile pic');
}
}

export function searchUserData(userlist: string[]): User[] {}
15 changes: 14 additions & 1 deletion frontend/app/(app)/user/_layout.tsx
Original file line number Diff line number Diff line change
@@ -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 (
Expand All @@ -11,6 +12,18 @@ const Layout = () => {
headerShown: false,
}}
/>
<Stack.Screen
name="follower_following"
options={{
headerShown: true,
headerTitle: '',
headerTransparent: true,
gestureEnabled: false,
headerLeft: () => (
<Arrow direction="left" onPress={() => router.back()} />
),
}}
/>
</Stack>
);
};
Expand Down
21 changes: 19 additions & 2 deletions frontend/app/(app)/user/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -37,15 +38,31 @@ const Header = ({ id }: { id: string }) => {
image={data?.user.profilePicture || PROFILE_PHOTO}
/>
<View className="flex flex-row ml-[5%] justify-around w-3/4">
<TouchableOpacity className="flex-col justify-center items-center flex-1">
<TouchableOpacity
className="flex-col justify-center items-center flex-1"
onPress={() => {
router.push({
pathname: '/user/follower_following',
params: { id: id, option: 'followers' },
});
}}
>
<Text className="font-bold text-darkblue text-md sm:text-lg md:text-xl">
{formatNumber(data?.user.followers.length)}
</Text>
<Text className="text-darkblue text-xs sm:text-base">
Followers
</Text>
</TouchableOpacity>
<TouchableOpacity className="flex-col justify-center items-center flex-1">
<TouchableOpacity
className="flex-col justify-center items-center flex-1"
onPress={() => {
router.push({
pathname: '/user/follower_following',
params: { id: id, option: 'following' },
});
}}
>
<Text className="font-bold text-darkblue text-md sm:text-lg md:text-xl">
{formatNumber(data?.user.following.length)}
</Text>
Expand Down
115 changes: 115 additions & 0 deletions frontend/app/(app)/user/follower_following.tsx
Original file line number Diff line number Diff line change
@@ -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<string[]>([]);

useEffect(() => {
const findData = () => {
if (category == 'Followers') {
setUserData(data?.user.followers);
} else {
setUserData(data?.user.following);
}
};
findData();
}, [category]);

const renderUser = ({ item }: { item: any }) => (
<View className="mb-2 w-[80vw]">
<ProfileTags id={item} />
</View>
);

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 (
<LinearGradient
colors={['#549ac7', '#ffffff', '#ffffff', '#ffffff']}
style={{ flex: 1 }}
>
<View className="flex flex-col items-center mt-[10vh] ">
<Text className="font-bold text-darkblue text-xl">
{category === 'Followers' ? 'Followers' : 'Following'}
</Text>
<Text className="font-bold text-darkblue text-md mt-[2vh]">
@{data?.user.username}
</Text>

<View className="flex w-100 flex-row pb-[5%] pt-[2vh]">
<Animated.View
className="bg-[#3788BE] absolute h-[1px] w-2/5 mx-5"
style={[
{
bottom: '30%',
},
indicatorStyle,
]}
/>
<TouchableOpacity
className="py-2 w-[50%] justify-center items-center"
onPress={() => setCategory('Followers')}
>
<Text
className={`font-bold text-base text-sm ${
category === 'Followers' ? 'text-[#3788BE]' : 'text-gray-400'
}`}
>
{data.user.followers.length} Followers
</Text>
</TouchableOpacity>
<TouchableOpacity
className="py-[3%] w-[50%] justify-center items-center"
onPress={() => setCategory('Following')}
>
<Text
className={`font-bold text-base text-sm ${
category === 'Following' ? 'text-[#3788BE]' : 'text-gray-400'
}`}
>
{data.user.following.length} Following
</Text>
</TouchableOpacity>
</View>

<FlatList data={userData} renderItem={renderUser}></FlatList>
</View>
</LinearGradient>
);
};

export default FollowerFollowing;
4 changes: 2 additions & 2 deletions frontend/assets/search.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions frontend/components/profile_tag.tsx
Original file line number Diff line number Diff line change
@@ -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<ProfileTagProps> = ({ 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 (
<TouchableOpacity
onPress={() => {
router.push(`/user/${data?.user._id}`);
}}
className="flex w-full flex-row items-center h-[8vh] bg-white shadow-sm rounded-lg pl-2"
>
<Profile image={uri} size="md" />
<View className="flex flex-col pl-2">
<Text>{data?.user.username}</Text>
</View>

{isViewingOwnProfile ? (
<></>
) : (
<View className="absolute left-[58vw] w-[60vw]">
<FollowButton
onPress={handleFollowToggle}
isPending={isPending!}
isFollowing={isFollowing}
/>
</View>
)}
</TouchableOpacity>
);
};

export default ProfileTags;
6 changes: 6 additions & 0 deletions frontend/types/userProfile.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export type UpdateProfileFields = {
profilePicture: string; //String to the s3
};

export type UserType = {
_id: string;
profilePicture: string;
username: string;
};

0 comments on commit 8843b38

Please sign in to comment.