Takipleşme sistemi eklendi.

This commit is contained in:
Batuhan 2025-03-04 08:55:24 +03:00
parent 9ff88ebc32
commit 0c9683cb60
10 changed files with 330 additions and 12 deletions

View File

@ -15,6 +15,11 @@ import Services from '../pages/Services';
import Settings from '../pages/Settings';
import SettingsProfile from './profiles/settings/Profile';
import Password from './profiles/settings/Password';
import Follow from './profiles/Follow/Follow';
import Follower from './profiles/Follow/Follower';
import Following from './profiles/Follow/Following';
import Request from './profiles/Follow/Request';
import Default from './profiles/Follow/Default';
export default function Pages(props) {
const importData = {
@ -30,12 +35,25 @@ export default function Pages(props) {
<Route path='/peoples' element={<Peoples importData={importData}/>}></Route>
<Route path='/services' element={<Services importData={importData}/>}></Route>
<Route path={'/profile/:username'} element={<Profile selectedMenu={props.selectedMenu} setSelectedMenu={props.setSelectedMenu}></Profile>}>
<Route path='' element={<Posts uid={"posts"}/>}>
<Route path=':cate' element={<Posts/>}></Route>
</Route>
{/* <Route path='' element={<Overview/>}></Route> */}
<Route path='posts' element={<Posts uid={"posts"}/>}>
<Route path=':cate' element={<Posts/>}></Route>
</Route>
{/* <Route path='about' element={<About/>}></Route> */}
</Route>
<Route path='/profile/:username/follow' element={<Follow importData={importData}/>}>
<Route path='following' element={<Following importData={importData}/>}>
<Route path='' element={<Default importData={importData}/>}/>
<Route path='requests' element={<Request/>}></Route>
</Route>
<Route path='follower' element={<Follower importData={importData}/>}>
<Route path='' element={<Default importData={importData}/>}/>
<Route path='requests' element={<Request/>}></Route>
</Route>
</Route>
<Route path='/profile/settings' element={<Settings uid={"settings"}/>}>
<Route path='profile' element={<SettingsProfile/>}/>
<Route path='password' element={<Password/>}/>

View File

@ -0,0 +1,36 @@
import React, { useEffect, useState } from 'react'
import { Link, Outlet, useOutletContext, useParams } from 'react-router-dom'
import User from './components/User';
import { FetchPOST } from '../../../middlewares/Fetch';
export default function Default() {
const {setSelectedMenu, buttonAction, data, username} = useOutletContext();
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log(data, 5)
setLoading(false);
},[]);
if(loading){ return (<></>) };
return (
<div className='flex flex-col w-full gap-4'>
<Link to={"requests"} className='flex gap-2 p-2 rounded-lg bg-pb'>
<p className='flex items-center'>Gönderdiğim İstekler ({data.requests.length})</p>
</Link>
<div className='flex flex-col'>
{
(data.isNull === 0) ?
<div className='flex items-center justify-center'>
<p className='font-bold'>Hiçbir Takipçiniz yok</p>
</div>
:
data.current.map(get =>
<User key={get.id} data={get.following || get.follower} button={get.button} buttonAction={buttonAction}/>
)
}
</div>
</div>
);
};

View File

@ -0,0 +1,49 @@
import React, { useState } from 'react'
import { Link, Outlet } from 'react-router-dom'
import { FetchPOST } from '../../../middlewares/Fetch';
export default function Follow() {
const [selectedMenu, setSelectedMenu] = useState(1);
return (
<div className='flex flex-col gap-4 h-full'>
<div className='grid grid-cols-2 gap-2'>
<div className='flex items-center justify-center'>
<Link className={'w-full text-center p-4 rounded-md hover:bg-pc ' + ((selectedMenu === 1) && "bg-pc font-bold")} to={"following"}>Takip Edilen</Link>
</div>
<div className='flex items-center justify-center'>
<Link className={'w-full text-center p-4 rounded-md hover:bg-pc ' + ((selectedMenu === 2) && "bg-pc font-bold")} to={"follower"}>Takipçiler</Link>
</div>
</div>
<div className='flex overflow-hidden overflow-y-scroll'>
<Outlet context={{ selectedMenu, setSelectedMenu, followPOST: friendPOST }}/>
</div>
</div>
);
};
const friendPOST = (e, userId) => {
FetchPOST({
port: 3001,
pathname: "/post/follow",
fetchData:{
method: "POST",
credentials: 'include',
headers: {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify({
userId: userId
})
}
}).then(res => {
if(res.follow){
e.target.innerText = res.follow.title;
console.log(res)
if(res.follow.statu === true){
e.target.classList.add("bg-pc", "bg-opacity-40")
}
};
});
};

View File

@ -0,0 +1,84 @@
import React, { useEffect, useState } from 'react'
import { Link, Outlet, useOutletContext, useParams } from 'react-router-dom';
import User from './components/User';
import { FetchPOST } from '../../../middlewares/Fetch';
import Loading from '../../Loading';
export default function Follower() {
const {setSelectedMenu, buttonAction} = useOutletContext();
const [followers, setFollowers] = useState([]);
const [loading, setLoading] = useState(true);
const { username } = useParams();
useEffect(() => {
setSelectedMenu(2);
FetchPOST({
port: 3001,
pathname: "/get/follow/followers/" + username,
fetchData: {
method: "GET"
}
})
.then(res => {
setFollowers(res.data);
setLoading(false);
});
},[]);
if(loading) { return (<></>) };
return (
<div className='flex flex-col w-full gap-4'>
<Outlet context={{data:followers, username, setSelectedMenu, buttonAction: destroyFollowerPOST, uid:"me-request"}}/>
</div>
);
};
// const followPOST = (e, userId) => {
// FetchPOST({
// port: 3001,
// pathname: "/post/follow",
// fetchData:{
// method: "POST",
// credentials: 'include',
// headers: {
// 'Accept' : 'application/json',
// 'Content-Type' : 'application/json'
// },
// body: JSON.stringify({
// userId: userId
// })
// }
// }).then(res => {
// if(res.follow){
// e.target.innerText = res.follow.title;
// console.log(res)
// if(res.follow.statu === true){
// e.target.classList.add("bg-pc", "bg-opacity-40")
// }
// };
// });
// };
const destroyFollowerPOST = (e, userId) => {
FetchPOST({
port: 3001,
pathname: "/post/follow/follower/destroy",
fetchData:{
method: "POST",
credentials: 'include',
headers: {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify({
userId: userId
})
}
})
.then(res => {
if(res.process === true){
e.target.parentElement.parentElement.remove();
};
});
};

View File

@ -0,0 +1,33 @@
import React, { useEffect, useState } from 'react';
import { Outlet, useOutletContext, useParams } from 'react-router-dom';
import { FetchPOST } from '../../../middlewares/Fetch';
export default function Following() {
const { selectedMenu, setSelectedMenu, followPOST } = useOutletContext();
const {username} = useParams();
const [loading, setLoading] = useState(true);
const [followings, setFollowings] = useState();
useEffect(()=>{
setSelectedMenu(1);
FetchPOST({
port: 3001,
pathname: "/get/follow/followings/" + username,
fetchData: {
method: "GET"
}
})
.then(res => {
setFollowings(res.data);
setLoading(false);
});
},[window.location.pathname]);
if(loading) { return (<></>) };
return (
<div className='flex flex-col w-full gap-4'>
<Outlet context={{data:followings, username, setSelectedMenu, buttonAction: followPOST, uid:"default"}}/>
</div>
);
};

View File

@ -0,0 +1,55 @@
import React, { useEffect, useState } from 'react'
import { Link, useOutletContext } from 'react-router-dom';
import User from './components/User';
import { FetchPOST } from '../../../middlewares/Fetch';
export default function Request() {
const { data, buttonAction, uid } = useOutletContext();
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log(data, uid)
setLoading(false);
},[]);
if(loading){
return(<></>);
};
return (
<div className='flex flex-col gap-4'>
<div className='flex items-center jus'>
<Link to={'..'} className='flex w-full p-2 bg-pc rounded-lg'>
Geri Git
</Link>
</div>
<div className='flex flex-col'>
{
data.requests.map(get =>
<User key={get.id} data={get.follower || get.following} button={get.button} buttonAction={requestPOST} uid={uid}/>
)
}
</div>
</div>
);
};
const requestPOST = (e, userId, svar) => {
FetchPOST({
port: 3001,
pathname: "/post/follow/request",
fetchData:{
method: "POST",
credentials: 'include',
headers: {
'Accept' : 'application/json',
'Content-Type' : 'application/json'
},
body: JSON.stringify({
userId: userId,
svar: svar
})
}
})
.then(res => console.log(res));
};

View File

@ -0,0 +1,35 @@
import React, { useEffect } from 'react'
import { Link } from 'react-router-dom';
export default function User({data, button, buttonAction, uid="default"}) {
console.log(uid)
if(uid === "default"){
return (
<div className='flex border-b-2 justify-between'>
<Link to={"/profile/" + data.username} className='flex flex-col flex-1 p-4'>
<p className='font-bold'>{data.first_name} {data.second_name}</p>
<p>@{data.username}</p>
</Link>
{
(button.isMy === false) &&
<div className='flex items-center justify-center'>
<a className='cursor-pointer p-2 rounded-lg ml-auto hover:bg-pc' onClick={(e) => {buttonAction(e, data.id)}}>{button.text}</a>
</div>
}
</div>
);
}else if(uid === "me-request"){
return (
<div className='flex border-b-2 justify-between'>
<Link to={"/profile/" + data.username} className='flex flex-col flex-1 p-4'>
<p className='font-bold'>{data.first_name} {data.second_name}</p>
<p>@{data.username}</p>
</Link>
<div className='grid grid-cols-2 items-center justify-center gap-2 px-2'>
<a className='rounded-lg text-center p-2 cursor-pointer bg-green-400 hover:bg-green-300' onClick={(e) => {buttonAction(e, data.id, "accept")}}>Kabul Et</a>
<a className='rounded-lg text-center p-2 cursor-pointer bg-red-400 hover:bg-red-300' onClick={(e) => {buttonAction(e, data.id, "reject")}}>Reddet</a>
</div>
</div>
);
}
};

View File

@ -1,7 +1,9 @@
import React from 'react'
import { FetchPOST } from '../../../middlewares/Fetch';
import { Link, useParams } from 'react-router-dom';
export default function Header({data}) {
const {username} = useParams();
const friendPOST = (e) => {
FetchPOST({
port: 3001,
@ -36,28 +38,31 @@ export default function Header({data}) {
<h2 className='col-span-3 font-bold text-center text-3xl'>{data.user.first_name} {data.user.second_name}</h2>
</div>
<div className='grid grid-cols-5 col-span-5 gap-4 p-2 rounded-2xl'>
<div className='flex flex-col rounded-2xl bg-pc p-2 gap-2'>
<Link to={"/profile/" + username + "/follow/follower"} className='flex flex-col rounded-2xl bg-pc p-2 gap-2'>
<div className='flex items-center justify-center'>
<p className='font-bold'>Takipçi</p>
</div>
<div className='flex items-center justify-center'>
<p>50</p>
<p>{data.user.followers.length}</p>
</div>
</div>
</Link>
<div className='col-span-3 bg-pc p-2 rounded-2xl'>
<p>{data.user.about}</p>
</div>
<div className='flex flex-col rounded-2xl bg-pc p-2 gap-2'>
<Link to={"/profile/" + username + "/follow/following"} className='flex flex-col rounded-2xl bg-pc p-2 gap-2'>
<div className='flex items-center justify-center'>
<p className='font-bold'>Takip Edilen</p>
</div>
<div className='flex items-center justify-center'>
<p>50</p>
<p>{data.user.followings.length}</p>
</div>
</div>
<div className='flex col-start-5 col-end-6 items-center justify-end'>
<a className='rounded-2xl select-none cursor-pointer p-2 shadow-md hover:bg-pc hover:bg-opacity-70' onClick={friendPOST}>Arkadaş Ekle</a>
</div>
</Link>
{
(data.isMy === false) &&
<div className='flex col-start-5 col-end-6 items-center justify-end'>
<a className='rounded-2xl select-none cursor-pointer p-2 shadow-md hover:bg-pc hover:bg-opacity-70' onClick={friendPOST}>{(data.user.follows.length > 0) ? data.user.follows[0].button.text : data.user.button.text}</a>
</div>
}
</div>
</div>
</div>

View File

@ -1,6 +1,7 @@
import React, { useEffect, useState } from 'react'
import { FetchPOST } from '../../../middlewares/Fetch'
import { useOutletContext } from 'react-router-dom';
import Loading from '../../Loading';
export default function Profile(props) {
const { selectedMenu, setSelectedMenu } = useOutletContext();
@ -83,7 +84,9 @@ export default function Profile(props) {
},[]);
if(loading){
return (<></>);
return (
<Loading/>
);
}
return (

View File

@ -22,5 +22,5 @@ export default function Profile({selectedMenu, setSelectedMenu, uid}) {
<div className='flex flex-col w-full h-full overflow-y-scroll'>
<ProfileDetail/>
</div>
)
}
);
};