Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/components/navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Overlay from 'react-bootstrap/Overlay';
import Tooltip from 'react-bootstrap/Tooltip';
import profile from "../image/107161_circle_github_icon.png";
import '../../styles/sass/main.scss'
import { useNavigate } from "react-router-dom";
import { useNavigate,Link } from "react-router-dom";

export const Navbar = () => {
const {userData} = useSelector((state) => state.user)
Expand Down Expand Up @@ -36,13 +36,13 @@ export const Navbar = () => {
</div>
<Button className="avatar" ref={target} onClick={() => setShow(!show)}>
{userData ? (
<img src={userData.avatar_url} alt="" />
<img src={userData?.avatar_url} alt="" />
) : (null)}
</Button>
<Overlay target={target.current} show={show} placement="bottom">
{(props) => (
<Tooltip id="overlay-example" {...props}>
<div> Your Profile </div>
<Link to={"/profile/"+userData?.login}><button className='your-profile'>Your Profile</button></Link>
</Tooltip>
)}
</Overlay>
Expand Down
161 changes: 161 additions & 0 deletions src/containers/profile/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import './style.scss';
import Container from 'react-bootstrap/Container';
import 'bootstrap/dist/css/bootstrap.css';
import Row from 'react-bootstrap/Row';
import Col from 'react-bootstrap/Col';
import 'bootstrap/dist/css/bootstrap.css';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import ReactPaginate from 'react-paginate';
import profile from "..//../component/image/PngItem_1280311.png";
import { useSelector, useDispatch } from '../../store/index';
import { useEffect, useState } from 'react';
import Popover from 'react-bootstrap/Popover'
import Button from 'react-bootstrap/Button';
import { useParams, Link } from 'react-router-dom';
import axios from 'axios';
import '../../styles/sass/main.scss'

export const ProfilePage = () => {
const {token, userData} = useSelector((state) => state.user)
const [userInfo,setUserInfo] = useState<any>();
const [followersInfo,setFollowersInfo] = useState<any[]>([]);
const [followingInfo,setFollowingInfo] = useState<any[]>([]);
const { profileId } = useParams();
const [currentPageForFollowers, setCurrentPageForFollowers] = useState(0);
const [currentPageForFollowing, setCurrentPageForFollowing] = useState(0);
const [loading, setLoading] = useState(false);
const [isFollowing, setIsFollowing] = useState(true);
const [ownProfile, setOwnProfile] = useState(false);
const PER_PAGE = 4;

const fetchUserInfo = async() =>{
setLoading(true);
if(userData?.login!==profileId) {
setOwnProfile(false);
isFollowingUser();
}
else {
setOwnProfile(true);
}
const response = await axios.get('https://api.github.com/users/'+profileId);
setUserInfo(response.data);
console.log(response.data);
}

useEffect(() =>{
fetchUserInfo();
},[profileId]);

const fetchFollowersInfo = async() =>{
const response = await axios.get('https://api.github.com/users/'+profileId+"/followers?page="+(currentPageForFollowers+1)+"&per_page="+PER_PAGE);
setFollowersInfo(response.data);
}

const fetchFollowingInfo = async() =>{
const response = await axios.get('https://api.github.com/users/'+profileId+"/following?page="+(currentPageForFollowing+1)+"&per_page="+PER_PAGE);
setFollowingInfo(response.data);
}

useEffect(() =>{
fetchFollowersInfo();
},[profileId,currentPageForFollowers]);

useEffect(() =>{
fetchFollowingInfo();
},[profileId,currentPageForFollowing]);

function handlePageClickForFollowers({selected} : {selected:number}) {
setCurrentPageForFollowers(selected)
}

function handlePageClickForFollowing({selected} : {selected:number}) {
setCurrentPageForFollowing(selected)
}

const isFollowingUser = async() =>{
try {
await axios({
method: 'get',
url: 'https://api.github.com/user/following/'+profileId,
headers: {
Authorization: 'Bearer ' + token
}
})
setIsFollowing(true);
} catch(error:any) {
setIsFollowing(false);
}
}
const followUser = async() =>{
await axios({
method: 'put',
url: 'https://api.github.com/user/following/'+profileId,
headers: {
Authorization: 'Bearer ' + token
}
})
setIsFollowing(true);
}

return(
<div>
{loading===false?
<div className="spinner-container">
<div className="loading-spinner"></div>
</div>:
<div className='profile-section'>
<div className='profile-section-bio'>
<img className='profile-section-pic' src={{userInfo}.userInfo?.avatar_url} alt="" />
<h3>{{userInfo}.userInfo?.name}</h3>
<p className='profile-section-name'>{profileId}</p>
{!ownProfile&&<div>
{isFollowing===true?
<button disabled={isFollowing}>Following</button>:
(<button onClick={(e)=>{
followUser();
}}>Follow</button>)
}
</div>}
<p className='profile-section-follows' >{{userInfo}.userInfo?.followers} Followers </p>
<p className='profile-section-follows'>{{userInfo}.userInfo?.following} Following </p>
</div>
<div className='profile-section-followers'>
<h3>Followers</h3>
<div className='info'>
{followersInfo.slice(0, PER_PAGE).map((res, index) => <> <div className='item'><Link to={"/profile/"+res.login}> <img src={res?.avatar_url} /></Link> <p>{res?.login}</p> </div> </> )}
</div>
<div className="paginate">
<ReactPaginate className='pagination location'
previousLabel = {"<- Previous"}
nextLabel = {"Next ->"}
pageCount = {Math.ceil({userInfo}.userInfo?.followers / PER_PAGE)}
onPageChange = {handlePageClickForFollowers}
containerClassName = {"pagination"}
previousLinkClassName = {"pagination__link"}
nextClassName = {"pagination__link"}
disabledClassName = {"pagination__link--disabled"}
activeClassName = {"pagination__link--active"}
/>
</div>
<h3>Following</h3>
<div className='info'>
{followingInfo.slice(0,PER_PAGE).map((res, index) => <> <div className='item'> <Link to={"/profile/"+res.login}> <img src={res?.avatar_url} /></Link> <p>{res?.login}</p> </div> </> )}
</div>
<div className="paginate">
<ReactPaginate className='pagination location'
previousLabel = {"<- Previous"}
nextLabel = {"Next ->"}
pageCount = {Math.ceil({userInfo}.userInfo?.following / PER_PAGE)}
onPageChange = {handlePageClickForFollowing}
containerClassName = {"pagination"}
previousLinkClassName = {"pagination__link"}
nextClassName = {"pagination__link"}
disabledClassName = {"pagination__link--disabled"}
activeClassName = {"pagination__link--active"}
/>
</div>
</div>
</div>}
</div>
)
}
17 changes: 7 additions & 10 deletions src/containers/search/index.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { useParams } from 'react-router-dom';
import { useParams, Link } from 'react-router-dom';
import { useEffect, useState } from 'react';
import ReactPaginate from 'react-paginate';
import React, { Component } from 'react';
import '../../styles/sass/main.scss'

import axios from 'axios';
import './style.scss';


export const SearchPage = () => {
const [users,setUsers] = useState<any>();
const { searchId } = useParams();
const [currentPage, setCurrentPage] = useState(0);
let pageCount;
const PER_PAGE = 10;
const fetchData = async() =>{
const response = await axios.get('https://api.github.com/search/users?per_page=10&page='+(currentPage+1)+'&q='+searchId)
setUsers(response.data);
Expand All @@ -21,24 +22,20 @@ export const SearchPage = () => {

function handlePageClick({selected} : {selected:number}) {
setCurrentPage(selected)
setUsers(undefined)
}
if (users!=undefined){
pageCount = users.total_count;
}

const pageCount = Math.ceil(users?.total_count/PER_PAGE);
return(
<div>
<div className='info'>
{users?.items?.map((res:any, index:any) =>
<> <div className='item'> <img src={res.avatar_url} />
<> <div className='item'> <Link to={"/profile/"+res.login}><img src={res.avatar_url} /> </Link>
<p>{res.login}</p> </div> </> )}
</div>
<div className="paginate">
<ReactPaginate
previousLabel = {"<- Previous"}
nextLabel = {"Next ->"}
pageCount = {pageCount}
pageCount = {pageCount===undefined?0:pageCount}
onPageChange = {handlePageClick}
containerClassName = {"pagination"}
previousLinkClassName = {"pagination__link"}
Expand Down
8 changes: 6 additions & 2 deletions src/routes/routesConfig.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { LoginPage } from '../containers/login'
import { HomePage } from '../containers/home'
import { SearchPage } from '../containers/search'
import React, { Component } from 'react';

import { ProfilePage } from '../containers/profile'
const routesConfig: RouteConfig[] = [
{
path: '/',
Expand All @@ -14,6 +13,11 @@ const routesConfig: RouteConfig[] = [
component: <SearchPage />,
private: true,
},
{
path: '/profile/:profileId',
component: <ProfilePage />,
private: true,
},
{
path: '/login',
component: <LoginPage />,
Expand Down
6 changes: 5 additions & 1 deletion src/styles/sass/components/_navbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,8 @@ nav {
box-shadow: none;
}
}

.your-profile {
background-color: #003865;
border: none;
color: white;
}
1 change: 1 addition & 0 deletions src/styles/sass/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
@import 'pages/login';
@import 'components/navbar';
@import 'pages/search';
@import 'pages/profile';
61 changes: 61 additions & 0 deletions src/styles/sass/pages/_profile.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
.profile-section-pic {
border-radius: 50%;
height: 300px;
margin-top: 40px;
margin-left: 40px;
}
.profile-section {
display: flex;
}

.profile-section-bio {
width: 30%;
}

.profile-section-bio h3{
margin-left: 80px;
margin-top: 10px;
}

.profile-section-name {
margin-left: 80px;
margin-top: -10px;
color: grey;
}
.profile-section-follows {
margin-left: 80px;
margin-top: 10px;
}
.profile-section button {
display: block;
width: 250px;
height: 36px;
margin-left: 80px;
color: white;
background-color: #003865;
}

.location{
margin-left: 42px;
}

.profile-section-followers h3 {
margin-left: 42px;
}

@keyframes spinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.loading-spinner {
width: 50px;
height: 50px;
border: 10px solid #f3f3f3;
border-top: 10px solid #383636;
border-radius: 50%;
animation: spinner 1.5s linear infinite;
}
1 change: 0 additions & 1 deletion src/styles/sass/pages/_search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,4 @@
background-color: transparent;
border: 1px solid transparent;
margin-right: 10px;
margin-bottom: 1px;
}