Skip to content

Commit

Permalink
Merge pull request #36 from chimobi-justice/ft/get-followers-users
Browse files Browse the repository at this point in the history
feat: get followers/followings users, clean up code
  • Loading branch information
chimobi-justice authored Oct 17, 2024
2 parents 5d88e41 + 191a8ea commit 1fb3100
Show file tree
Hide file tree
Showing 52 changed files with 967 additions and 568 deletions.
56 changes: 26 additions & 30 deletions src/Route/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FunctionComponent, Suspense, lazy } from 'react'
import { FunctionComponent } from 'react'
import {
createBrowserRouter,
createRoutesFromElements,
Expand All @@ -7,32 +7,31 @@ import {
} from 'react-router-dom'

import Layout from '@layout/index'
import { NotFound, Loading} from '@components/index'
import { NotFound } from '@components/index'

import AuthRoute from './AuthRoute'
import PrivateRoute from './privateRoute'

const Articles = lazy(() => import('@pages/Articles'));
const CreateArticle = lazy(() => import('@pages/Articles/create'));
const EditArticle = lazy(() => import('@pages/Articles/edit'));
const ShowArticle = lazy(() => import('@pages/Articles/show'));
const SavedArticles = lazy(() => import('@pages/Users/SavedArticles'));
const Home = lazy(() => import('@pages/Home'));
const Threads = lazy(() => import('@pages/Threads'));
const CreateThread = lazy(() => import('@pages/Threads/create'));
const EditThread = lazy(() => import('@pages/Threads/edit'));
const ShowThread = lazy(() => import('@pages/Threads/show'));
const ArthoredArticles = lazy(() => import('@pages/Users/AuthoredViews/Articles'));
const ArthoredThreads = lazy(() => import('@pages/Users/AuthoredViews/Threads'));
const Profile = lazy(() => import('@pages/Users/Profile'));
const ProfileEdit = lazy(() => import('@pages/Users/Settings'));
const ShowUserPublicPosts = lazy(() => import('@pages/Users/show'));
const Search = lazy(() => import('@pages/Search'));

const FollowPeople = lazy(() => import('@pages/FollowPeople'))

const Login = lazy(() => import('@pages/Auth/Login'));
const Register = lazy(() => import('@pages/Auth/Register'));
import Articles from '@pages/Articles'
import CreateArticle from '@pages/Articles/create'
import EditArticle from '@pages/Articles/edit'
import ShowArticle from '@pages/Articles/show'
import SavedArticles from '@pages/Users/SavedArticles'
import Home from '@pages/Home'
import Threads from '@pages/Threads'
import CreateThread from '@pages/Threads/create'
import EditThread from '@pages/Threads/edit'
import ShowThread from '@pages/Threads/show'
import ArthoredArticles from '@pages/Users/AuthoredViews/Articles'
import ArthoredThreads from '@pages/Users/AuthoredViews/Threads'
import Profile from '@pages/Users/Profile'
import ProfileEdit from '@pages/Users/Settings'
import FollowingUsers from '@pages/Users/FollowingUsers'
import ShowUserPublicPosts from '@pages/Users/show'
import Search from '@pages/Search'
import FollowPeople from '@pages/FollowPeople'

import Login from '@pages/Auth/Login'
import Register from '@pages/Auth/Register'

const routes = createBrowserRouter(
createRoutesFromElements(
Expand All @@ -48,7 +47,7 @@ const routes = createBrowserRouter(

<Route index path='/articles' element={<Articles />} />
<Route index path='/articles/:slug/:id' element={<ShowArticle />} />

<Route index path='/user/:username' element={<ShowUserPublicPosts />} />

{/* private route */}
Expand All @@ -64,6 +63,7 @@ const routes = createBrowserRouter(
<Route path="/:username" element={<Profile />} />
<Route path="/:username/reading-list" element={<SavedArticles />} />
<Route path="/me/settings/account/edit" element={<ProfileEdit />} />
<Route path="/me/users/:name" element={<FollowingUsers />} />
</Route>
{/* end private route */}

Expand All @@ -78,11 +78,7 @@ const routes = createBrowserRouter(
)

const AppRoutes: FunctionComponent = () => {
return (
<Suspense fallback={<Loading />}>
<RouterProvider router={routes} />
</Suspense>
)
return <RouterProvider router={routes} />;
}

export default AppRoutes;
47 changes: 21 additions & 26 deletions src/api/axiosInstance.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import axios from 'axios'

import { API_BASE_URL } from '@api/constant'

axios.defaults.baseURL = API_BASE_URL;

// Configure the base axios instance
export const axiosInstance = axios.create({
baseURL: API_BASE_URL,
headers: {
Expand All @@ -14,30 +12,27 @@ export const axiosInstance = axios.create({
withCredentials: true,
});

axiosInstance.interceptors.request.use(
(config) => {
const token = localStorage.getItem('ucType_');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => {
return Promise.reject(error);
// Request Interceptor to add Authorization header
const addAuthorizationHeader = (config: any) => {
const token = localStorage.getItem('ucType_');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
);

axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
if (axios.isAxiosError(error)) {
// Handle 401 (unauthorized) by removing token from localStorage
if (error.response?.status === 401 && localStorage.getItem('ucType_')) {
localStorage.removeItem('ucType_');
location.href = '/auth/login'
}
return Promise.reject(error);
return config;
}

// Response Interceptor to handle errors
const handleErrorResponse = (error: any) => {
if (axios.isAxiosError(error)) {
// Handle 401 (unauthorized) by removing token from localStorage
if (error.response?.status === 401 && localStorage.getItem('ucType_')) {
localStorage.removeItem('ucType_');
window.location.href = '/auth/login'
}
return Promise.reject(error);
}
);
}

// Apply interceptors
axiosInstance.interceptors.request.use(addAuthorizationHeader, (error) => Promise.reject(error));
axiosInstance.interceptors.response.use((response) => response, handleErrorResponse);
6 changes: 5 additions & 1 deletion src/api/endpoints/userEndpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,14 @@ export const PUBLIC_USER_ENDPOINT = `${API_BASE_URL}/users`;

export const GET_THREE_USERS_ENDPOINT = `${API_BASE_URL}/users/get-three-users`;

export const GET_ALL_USERS_ENDPOINT = `${API_BASE_URL}/users/all-users`;
export const GET_ALL_USERS_TO_FOLLOW_ENDPOINT = `${API_BASE_URL}/users/all-users`;

export const Get_FOLLOWING_USERS_ARTICLES_ENDPOINT = `${API_BASE_URL}/users/my-follow-users/articles`;

export const FOLLOW_USERS_ENDPOINT = `${API_BASE_URL}/users`;

export const ONFOLLOW_USERS_ENDPOINT = `${API_BASE_URL}/users`;

export const GET_FOLLOWING_USERS_ENDPOINT = `${API_BASE_URL}/users/followings`;

export const GET_FOLLOWERS_USERS_ENDPOINT = `${API_BASE_URL}/users/followers`;
2 changes: 1 addition & 1 deletion src/components/ArticleCard/Articles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const ArticlesCard: FunctionComponent<IProps> = ({
<Box width={{ base: "100%", md: "35%" }}>
<Image
src={articleImg}
alt={articleImg}
alt={title}
width={{ base: "100%", md: "50%" }}
height={{ base: "200px", md: "150px" }}
mx={{ base: "", md: "auto" }}
Expand Down
145 changes: 74 additions & 71 deletions src/components/FollowCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ import {
Heading,
Spinner,
Text,
useDisclosure,
} from '@chakra-ui/react'

import { colors } from '../../colors'
import { Button } from '@components/index'
import { Button, ShowLoginModal } from '@components/index'
import truncate from '@helpers/truncate'
import { useGetThreeCardUsers } from '@hooks/user/useGetFollowUsers'
import { useGetThreeCardUsers } from '@hooks/user/useGetAllUsersToFollow'
import { useUser } from '@context/userContext'
import { useCreateFollowUser } from '@hooks/user/useCreateFollowUser'
import { useCreateOnFollowUser } from '@hooks/user/useCreateUnFollowUser'
Expand All @@ -25,96 +26,98 @@ const FollowCard: FunctionComponent = () => {
const { data: people, isLoading } = useGetThreeCardUsers();
const { createFollowUserMutation } = useCreateFollowUser()
const { createOnFollowUserMutation } = useCreateOnFollowUser();
const { isOpen, onOpen, onClose } = useDisclosure();

const handleFollowUnfollow = (userId: string, following: boolean) => {
if (following) {
following ?
createOnFollowUserMutation.mutate(userId)
} else {
createFollowUserMutation.mutate(userId)
}
: createFollowUserMutation.mutate(userId)
}

return (
<Card>
{isLoading && (
<Box
textAlign={"center"}
height={"200px"}
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
>
<Spinner size={"xl"} thickness={"4px"} color={colors.primary} />
</Box>
)}
<>
<Card>
{isLoading && (
<Box
textAlign={"center"}
height={"200px"}
display="flex"
flexDirection="column"
justifyContent="center"
alignItems="center"
>
<Spinner size={"xl"} thickness={"4px"} color={colors.primary} />
</Box>
)}

{people && (
<>
<CardHeader pb={"4px"}>
<Heading size={"sm"}>People to follow</Heading>
</CardHeader>
{people && (
<>
<CardHeader pb={"4px"}>
<Heading size={"sm"}>People to follow</Heading>
</CardHeader>

<CardBody>
{people?.map((person: any, index: number) => (
<Flex key={index} mb={"8px"}>
<Flex flex="1" gap="4" alignItems="center" flexWrap="wrap">
<Link to={`/user/${person?.username}`}>
<Avatar size={"sm"} name={person?.fullname} src={person?.avatar} />
</Link>

<Box>
<CardBody>
{people?.data?.map((person, index: number) => (
<Flex key={index} mb={"8px"}>
<Flex flex="1" gap="4" alignItems="center" flexWrap="wrap">
<Link to={`/user/${person?.username}`}>
<Heading size="xs">{person?.fullname}</Heading>
<Avatar size={"sm"} name={person?.fullname} src={person?.avatar} />
</Link>
<Text fontSize={"13px"} color={"#0009"}>{truncate(person?.bio, 25)}</Text>
</Box>
</Flex>

{user && (
<Button
size="sm"
rounded="lg"
type="button"
variant={person?.is_following ? "solid" : "outline"}
onClick={() => handleFollowUnfollow(person?.id, person?.is_following)}
>
{person?.is_following ? "following" : "follow"}
</Button>
)}
<Box>
<Link to={`/user/${person?.username}`}>
<Heading size="xs">{person?.fullname}</Heading>
</Link>
<Text fontSize={"13px"} color={"#0009"}>{truncate(person?.bio, 25)}</Text>
</Box>
</Flex>

{!user && (
<Link to={"/auth/login"}>
{user && (
<Button
size="sm"
rounded="lg"
type="button"
variant={person?.is_following ? "solid" : "outline"}
onClick={() => handleFollowUnfollow(person?.id, person?.is_following)}
>
{person?.is_following ? "following" : "follow"}
</Button>
)}

{!user && (
<Button
size="sm"
rounded="lg"
type="button"
variant="outline"
onClick={onOpen}
>
follow
</Button>
</Link>
)}
</Flex>
))}
)}
</Flex>
))}

<Link to="/follow/people/suggestions">
<Text
fontSize={"13px"}
color={colors.primary}
mt={"20px"}
_hover={{
color: "#101828",
textDecoration: "underline"
}}
>
See more suggestions
</Text>
</Link>
</CardBody>
</>
)}
</Card>

<Link to="/follow/people/suggestions">
<Text
fontSize={"13px"}
color={colors.primary}
mt={"20px"}
_hover={{
color: "#101828",
textDecoration: "underline"
}}
>
See more suggestions
</Text>
</Link>
</CardBody>
</>
)}
</Card>
<ShowLoginModal isOpen={isOpen} onClose={onClose} />
</>
)
}

Expand Down
Loading

0 comments on commit 1fb3100

Please sign in to comment.