mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-02 05:42:41 +02:00
Friends listing page
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { httpDelete, httpGet, httpPatch, httpPost } from '../lib/http';
|
||||
import ErrorIcon from '../icons/error.svg';
|
||||
import { pageProgressMessage } from '../stores/page';
|
||||
import { isLoggedIn } from '../lib/jwt';
|
||||
import { showLoginPopup } from '../lib/popup';
|
||||
@@ -10,7 +9,8 @@ import { DeleteUserIcon } from './ReactIcons/DeleteUserIcon';
|
||||
import { useToast } from '../hooks/use-toast';
|
||||
import { useAuth } from '../hooks/use-auth';
|
||||
import { AddedUserIcon } from './ReactIcons/AddedUserIcon';
|
||||
import {StopIcon} from "./ReactIcons/StopIcon";
|
||||
import { StopIcon } from './ReactIcons/StopIcon';
|
||||
import { ErrorIcon } from './ReactIcons/ErrorIcon';
|
||||
|
||||
export type FriendshipStatus =
|
||||
| 'none'
|
||||
@@ -106,11 +106,7 @@ export function Befriend() {
|
||||
if (!user) {
|
||||
return (
|
||||
<div className="container text-center">
|
||||
<img
|
||||
alt={'error'}
|
||||
src={ErrorIcon}
|
||||
className="mx-auto mb-4 mt-24 w-20 opacity-20"
|
||||
/>
|
||||
<ErrorIcon additionalClasses="mx-auto mb-4 mt-24 w-20 opacity-20" />
|
||||
|
||||
<h2 className={'mb-1 text-2xl font-bold'}>Error</h2>
|
||||
<p class="mb-4 text-base leading-6 text-gray-600">
|
||||
|
@@ -1,12 +1,53 @@
|
||||
import { useEffect } from 'preact/hooks';
|
||||
import UserPlus from '../../icons/user-plus.svg';
|
||||
import { useEffect, useState } from 'preact/hooks';
|
||||
import { pageProgressMessage } from '../../stores/page';
|
||||
import { useAuth } from '../../hooks/use-auth';
|
||||
import { AddUserIcon } from '../ReactIcons/AddUserIcon';
|
||||
import { httpGet } from '../../lib/http';
|
||||
import type { FriendshipStatus } from '../Befriend';
|
||||
import { useToast } from '../../hooks/use-toast';
|
||||
import { EmptyFriends } from './EmptyFriends';
|
||||
|
||||
type FriendResourceProgress = {
|
||||
updatedAt: string;
|
||||
title: string;
|
||||
resourceId: string;
|
||||
resourceType: string;
|
||||
learning: number;
|
||||
skipped: number;
|
||||
done: number;
|
||||
total: number;
|
||||
};
|
||||
|
||||
type ListFriendsResponse = {
|
||||
userId: string;
|
||||
name: string;
|
||||
avatar: string;
|
||||
status: FriendshipStatus;
|
||||
roadmaps: FriendResourceProgress[];
|
||||
bestPractices: FriendResourceProgress[];
|
||||
}[];
|
||||
|
||||
export function FriendsPage() {
|
||||
const toast = useToast();
|
||||
const [friends, setFriends] = useState<ListFriendsResponse>([]);
|
||||
|
||||
async function loadFriends() {
|
||||
const { response, error } = await httpGet<ListFriendsResponse>(
|
||||
`${import.meta.env.PUBLIC_API_URL}/v1-list-friends`
|
||||
);
|
||||
|
||||
if (error || !response) {
|
||||
toast.error(error?.message || 'Something went wrong');
|
||||
return;
|
||||
}
|
||||
|
||||
setFriends(response);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
loadFriends().finally(() => {
|
||||
pageProgressMessage.set('');
|
||||
});
|
||||
}, []);
|
||||
|
||||
const user = useAuth();
|
||||
@@ -15,16 +56,18 @@ export function FriendsPage() {
|
||||
: 'https://roadmap.sh';
|
||||
const befriendUrl = `${baseUrl}/befriend?u=${user?.id}`;
|
||||
|
||||
if (friends.length === 0) {
|
||||
return <EmptyFriends befriendUrl={befriendUrl} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-4 flex items-center justify-between">
|
||||
<span className={'text-sm text-gray-400'}>
|
||||
You have 4 friends on Roadmap.sh
|
||||
You have 4 active friends
|
||||
</span>
|
||||
<button class="flex items-center justify-center gap-2 rounded-md border border-gray-400 bg-gray-50 p-1 px-2 text-sm hover:border-gray-500 hover:bg-gray-100">
|
||||
<img src={UserPlus} className="h-4 w-4" alt="Invite Friends" />
|
||||
<button class="flex items-center justify-center gap-1.5 rounded-md border border-gray-400 bg-gray-50 p-1 px-2 text-sm hover:border-gray-500 hover:bg-gray-100">
|
||||
<AddUserIcon additionalClasses="w-4 h-4" />
|
||||
Invite Friends
|
||||
</button>
|
||||
</div>
|
||||
|
27
src/components/ReactIcons/AddUserIcon.tsx
Normal file
27
src/components/ReactIcons/AddUserIcon.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
type CheckIconProps = {
|
||||
additionalClasses?: string;
|
||||
};
|
||||
|
||||
export function AddUserIcon(props: CheckIconProps) {
|
||||
const { additionalClasses = 'mr-2 w-[20px] h-[20px]' } = props;
|
||||
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
className={`relative ${additionalClasses}`}
|
||||
>
|
||||
<path d="M14 19a6 6 0 0 0-12 0" />
|
||||
<circle cx="8" cy="9" r="4" />
|
||||
<line x1="19" x2="19" y1="8" y2="14" />
|
||||
<line x1="22" x2="16" y1="11" y2="11" />
|
||||
</svg>
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user