Friends listing page

pull/4317/head
Kamran Ahmed 1 year ago
parent c3b34cde3f
commit fb3fe8be42
  1. 10
      src/components/Befriend.tsx
  2. 53
      src/components/Friends/FriendsPage.tsx
  3. 27
      src/components/ReactIcons/AddUserIcon.tsx

@ -1,6 +1,5 @@
import { useEffect, useState } from 'preact/hooks'; import { useEffect, useState } from 'preact/hooks';
import { httpDelete, httpGet, httpPatch, httpPost } from '../lib/http'; import { httpDelete, httpGet, httpPatch, httpPost } from '../lib/http';
import ErrorIcon from '../icons/error.svg';
import { pageProgressMessage } from '../stores/page'; import { pageProgressMessage } from '../stores/page';
import { isLoggedIn } from '../lib/jwt'; import { isLoggedIn } from '../lib/jwt';
import { showLoginPopup } from '../lib/popup'; import { showLoginPopup } from '../lib/popup';
@ -10,7 +9,8 @@ import { DeleteUserIcon } from './ReactIcons/DeleteUserIcon';
import { useToast } from '../hooks/use-toast'; import { useToast } from '../hooks/use-toast';
import { useAuth } from '../hooks/use-auth'; import { useAuth } from '../hooks/use-auth';
import { AddedUserIcon } from './ReactIcons/AddedUserIcon'; import { AddedUserIcon } from './ReactIcons/AddedUserIcon';
import {StopIcon} from "./ReactIcons/StopIcon"; import { StopIcon } from './ReactIcons/StopIcon';
import { ErrorIcon } from './ReactIcons/ErrorIcon';
export type FriendshipStatus = export type FriendshipStatus =
| 'none' | 'none'
@ -106,11 +106,7 @@ export function Befriend() {
if (!user) { if (!user) {
return ( return (
<div className="container text-center"> <div className="container text-center">
<img <ErrorIcon additionalClasses="mx-auto mb-4 mt-24 w-20 opacity-20" />
alt={'error'}
src={ErrorIcon}
className="mx-auto mb-4 mt-24 w-20 opacity-20"
/>
<h2 className={'mb-1 text-2xl font-bold'}>Error</h2> <h2 className={'mb-1 text-2xl font-bold'}>Error</h2>
<p class="mb-4 text-base leading-6 text-gray-600"> <p class="mb-4 text-base leading-6 text-gray-600">

@ -1,12 +1,53 @@
import { useEffect } from 'preact/hooks'; import { useEffect, useState } from 'preact/hooks';
import UserPlus from '../../icons/user-plus.svg';
import { pageProgressMessage } from '../../stores/page'; import { pageProgressMessage } from '../../stores/page';
import { useAuth } from '../../hooks/use-auth'; 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'; 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() { 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(() => { useEffect(() => {
loadFriends().finally(() => {
pageProgressMessage.set(''); pageProgressMessage.set('');
});
}, []); }, []);
const user = useAuth(); const user = useAuth();
@ -15,16 +56,18 @@ export function FriendsPage() {
: 'https://roadmap.sh'; : 'https://roadmap.sh';
const befriendUrl = `${baseUrl}/befriend?u=${user?.id}`; const befriendUrl = `${baseUrl}/befriend?u=${user?.id}`;
if (friends.length === 0) {
return <EmptyFriends befriendUrl={befriendUrl} />; return <EmptyFriends befriendUrl={befriendUrl} />;
}
return ( return (
<div> <div>
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
<span className={'text-sm text-gray-400'}> <span className={'text-sm text-gray-400'}>
You have 4 friends on Roadmap.sh You have 4 active friends
</span> </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"> <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">
<img src={UserPlus} className="h-4 w-4" alt="Invite Friends" /> <AddUserIcon additionalClasses="w-4 h-4" />
Invite Friends Invite Friends
</button> </button>
</div> </div>

@ -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>
);
}
Loading…
Cancel
Save