Skip to content

Commit

Permalink
feat: user ranking based on user points
Browse files Browse the repository at this point in the history
  • Loading branch information
lareii committed Sep 8, 2024
1 parent 1ae3524 commit 01fbe45
Show file tree
Hide file tree
Showing 14 changed files with 298 additions and 83 deletions.
10 changes: 9 additions & 1 deletion client/app/app/explore/page.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
'use client';

import PostList from '@/components/app/Post/List';
import UserList from '@/components/app/User/List';
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { getPosts } from '@/lib/api/posts';
import { getUsers } from '@/lib/api/users';

export default function Page() {
const fetchUsers = async (offset) => {
return await getUsers(11, offset);
};

const fetchPosts = async (offset) => {
return await getPosts(11, offset);
};
Expand All @@ -21,7 +27,9 @@ export default function Page() {
<PostList fetchPosts={fetchPosts} />
</TabsContent>
<TabsContent value='guilds'>2</TabsContent>
<TabsContent value='users'>3</TabsContent>
<TabsContent value='users'>
<UserList fetchUsers={fetchUsers} />
</TabsContent>
</Tabs>
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions client/components/app/Comment/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ import {
} from '@/components/ui/tooltip';
import Dropdown from '@/components/app/Comment/Dropdown';
import LikeButton from '@/components/app/Comment/LikeButton';
import UserCard from '@/components/app/UserCard';
import UserInfo from '@/components/app/User/Info';

export default function Comment({ comment: initialComment, onDelete }) {
const [comment, setComment] = useState(initialComment);

return (
<div>
<div className='flex items-center justify-between mb-3'>
<UserCard user={comment.author} />
<UserInfo user={comment.author} />
<Dropdown
comment={comment}
setComment={setComment}
Expand Down
4 changes: 2 additions & 2 deletions client/components/app/Navbar/Dropdown.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '@/components/ui/dropdown-menu';
import { Button } from '@/components/ui/button';
import { Skeleton } from '@/components/ui/skeleton';
import UserCard from '@/components/app/UserCard';
import UserInfo from '@/components/app/User/Info';
import { useAuthStore } from '@/stores/auth';
import { logout } from '@/lib/api/auth';

Expand Down Expand Up @@ -52,7 +52,7 @@ export default function Dropdown({ router, pathname }) {
<DropdownMenuContent>
<DropdownMenuLabel className='font-normal'>
{user != 'loading' ? (
<UserCard user={user} />
<UserInfo user={user} />
) : (
<div className='flex items-center'>
<div className='mr-3 w-10 h-10 rounded-lg bg-zinc-800'></div>
Expand Down
66 changes: 36 additions & 30 deletions client/components/app/Post/List.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useState, useEffect } from 'react';
import { LoaderCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
import Post from '@/components/app/Post';
Expand All @@ -7,6 +8,7 @@ export default function PostList({ fetchPosts }) {
const [posts, setPosts] = useState([]);
const [offset, setOffset] = useState(10);
const [hasMorePost, setHasMorePost] = useState(true);
const [loading, setLoading] = useState(false);
const { toast } = useToast();

const handleDelete = (postId) => {
Expand Down Expand Up @@ -39,39 +41,41 @@ export default function PostList({ fetchPosts }) {
setOffset((prevOffset) => prevOffset + 10);
};

useEffect(
() => {
const fetchInitialPosts = async () => {
const response = await fetchPosts(0);
if (!response) {
toast({
title: 'hay aksi, bir şeyler ters gitti!',
description:
'sunucudan yanıt alınamadı. lütfen daha sonra tekrar deneyin.',
duration: 3000
});
return;
}
useEffect(() => {
const fetchInitialPosts = async () => {
setLoading(true);
const response = await fetchPosts(0);
setLoading(false);

const initialPosts = response.data.posts || [];
if (!response) {
toast({
title: 'hay aksi, bir şeyler ters gitti!',
description:
'sunucudan yanıt alınamadı. Lütfen daha sonra tekrar deneyin.',
duration: 3000
});
return;
}

if (initialPosts.length > 10) {
setPosts(initialPosts.slice(0, 10));
} else {
setPosts(initialPosts);
setHasMorePost(false);
}
};
const initialPosts = response.data.posts || [];

fetchInitialPosts();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
if (initialPosts.length > 10) {
setPosts(initialPosts.slice(0, 10));
} else {
setPosts(initialPosts);
setHasMorePost(false);
}
};

fetchInitialPosts();
}, [fetchPosts, toast]);

return (
<div className='flex flex-col gap-2'>
{posts.length > 0 ? (
{loading && (
<LoaderCircle className='mt-3 w-4 h-4 animate-spin self-center' />
)}
{!loading && posts.length > 0 ? (
<>
{posts.map((post) => (
<Post key={post.id} post={post} onDelete={handleDelete} />
Expand All @@ -83,9 +87,11 @@ export default function PostList({ fetchPosts }) {
)}
</>
) : (
<div className='flex flex-col items-center justify-center text-sm'>
buralar şimdilik sessiz.
</div>
!loading && (
<div className='flex flex-col items-center justify-center text-sm'>
buralar şimdilik sessiz.
</div>
)
)}
</div>
);
Expand Down
4 changes: 2 additions & 2 deletions client/components/app/Post/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
import Dropdown from '@/components/app/Post/Dropdown';
import LikeButton from '@/components/app/Post/LikeButton';
import CommentButton from '@/components/app/Post/CommentButton';
import UserCard from '@/components/app/UserCard';
import UserInfo from '@/components/app/User/Info';

export default function Post({ post: initialPost, onDelete, onNewComment }) {
const [post, setPost] = useState(initialPost);
Expand All @@ -19,7 +19,7 @@ export default function Post({ post: initialPost, onDelete, onNewComment }) {
return (
<div className='p-5 bg-zinc-900 rounded-lg'>
<div className='flex items-center justify-between mb-3'>
<UserCard user={post.author} />
<UserInfo user={post.author} />
<Dropdown post={post} setPost={setPost} onDelete={onDelete} />
</div>
<div className='relative'>
Expand Down
53 changes: 53 additions & 0 deletions client/components/app/User/Card.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { CalendarFold, Trash, SquareArrowOutUpRight } from 'lucide-react';
import { Button } from '@/components/ui/button';
import Hover from '@/components/app/User/Hover';
import Link from 'next/link';

export default function Card({ index, user }) {
return (
<div
className={
index === 0
? 'p-[2px] rounded-lg bg-yellow-500'
: index === 1
? 'p-[2px] rounded-lg bg-zinc-400'
: index === 2
? 'p-[2px] rounded-lg bg-amber-700'
: ''
}
>
<div className='p-5 bg-zinc-900 opacity-85 rounded-lg'>
<div className='flex items-center justify-between'>
<div className='flex items-start'>
<div className='mr-3 w-10 h-10 rounded-lg bg-zinc-800'></div>
<div className='flex flex-col mr-2'>
<Hover user={user} />
<div className='text-xs text-zinc-400'>@{user.username}</div>
</div>
</div>
<Button variant='ghost' size='icon' asChild>
<Link href={`/app/users/${user.username}`}>
<SquareArrowOutUpRight className='w-4 h-4' />
</Link>
</Button>
</div>
<div className='mt-2 mb-3 text-sm'>{user.about}</div>
<div className='mt-2 flex items-center gap-2 text-xs text-zinc-400'>
<div className='flex'>
<CalendarFold className='w-4 h-4 mr-1' />
{new Date(user.created_at.T * 1000).toLocaleDateString('tr-TR', {
year: 'numeric',
month: 'long',
day: 'numeric'
})}
</div>
{' · '}
<div className='flex items-center'>
<Trash className='w-4 h-4 mr-1' />
<div className='static'>{user.points} çöp puanı</div>
</div>
</div>
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,4 @@ export default function Hover({ user }) {
</HoverCardContent>
</HoverCard>
);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Hover from '@/components/app/UserCard/Hover';
import Hover from '@/components/app/User/Hover';

export default function UserCard({ user }) {
export default function UserInfo({ user }) {
return (
<div className='flex items-start'>
<div className='mr-3 w-10 h-10 rounded-lg bg-zinc-800'></div>
Expand Down
87 changes: 87 additions & 0 deletions client/components/app/User/List.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { useState, useEffect } from 'react';
import { LoaderCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { useToast } from '@/components/ui/use-toast';
import Card from '@/components/app/User/Card';

export default function UserList({ fetchUsers }) {
const [users, setUsers] = useState([]);
const [offset, setOffset] = useState(10);
const [hasMoreUser, setHasMoreUser] = useState(true);
const { toast } = useToast();

const loadMoreUsers = async () => {
if (!hasMoreUser) return;

const response = await fetchUsers(offset);
if (!response) {
toast({
title: 'hay aksi, bir şeyler ters gitti!',
description:
'sunucudan yanıt alınamadı. lütfen daha sonra tekrar deneyin.',
duration: 3000
});
return;
}

const newUsers = response.data.users || [];

if (newUsers.length > 10) {
setUsers((prevUsers) => [...prevUsers, ...newUsers.slice(0, 10)]);
} else {
setUsers((prevUsers) => [...prevUsers, ...newUsers]);
setHasMoreUser(false);
}

setOffset((prevOffset) => prevOffset + 10);
};

useEffect(
() => {
const fetchInitialUsers = async () => {
const response = await fetchUsers(0);
if (!response) {
toast({
title: 'hay aksi, bir şeyler ters gitti!',
description:
'sunucudan yanıt alınamadı. lütfen daha sonra tekrar deneyin.',
duration: 3000
});
return;
}

const initialUsers = response.data.users || [];

if (initialUsers.length > 10) {
setUsers(initialUsers.slice(0, 10));
} else {
setUsers(initialUsers);
setHasMoreUser(false);
}
};

fetchInitialUsers();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);

return (
<div className='flex flex-col gap-2'>
{users.length > 0 ? (
<>
{users.map((user, index) => (
<Card key={user.id} index={index} user={user} />
))}
{hasMoreUser && (
<Button onClick={loadMoreUsers} className='w-full'>
daha fazla göster
</Button>
)}
</>
) : (
<LoaderCircle className='mt-3 w-4 h-4 animate-spin self-center' />
)}
</div>
);
}
9 changes: 9 additions & 0 deletions client/lib/api/users/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ export async function getUser({ slug }) {
}
}

export async function getUsers(limit, offset) {
try {
const response = await api.get('/users', { params: { limit, offset } });
return response;
} catch (error) {
return error.response;
}
}

export async function getUserPosts(slug, limit, offset) {
try {
const response = await api.get(`/users/${slug}/posts`, {
Expand Down
Loading

0 comments on commit 01fbe45

Please sign in to comment.