diff --git a/.DS_Store b/.DS_Store
index b370c47..4ecb4d9 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/backend/code/prisma/migrations/20231024181019_anme/migration.sql b/backend/code/prisma/migrations/20231024181019_anme/migration.sql
new file mode 100644
index 0000000..8b5fd5f
--- /dev/null
+++ b/backend/code/prisma/migrations/20231024181019_anme/migration.sql
@@ -0,0 +1,46 @@
+/*
+ Warnings:
+
+ - A unique constraint covering the columns `[createdAt]` on the table `messages` will be added. If there are existing duplicate values, this will fail.
+ - A unique constraint covering the columns `[Username]` on the table `users` will be added. If there are existing duplicate values, this will fail.
+
+*/
+-- CreateEnum
+CREATE TYPE "NotifType" AS ENUM ('addFriend');
+
+-- DropForeignKey
+ALTER TABLE "messages" DROP CONSTRAINT "messages_roomId_fkey";
+
+-- AlterTable
+ALTER TABLE "blocked_friends" ADD COLUMN "dmRoomId" TEXT;
+
+-- AlterTable
+ALTER TABLE "room_members" ADD COLUMN "bannedAt" TIMESTAMP(3);
+
+-- AlterTable
+ALTER TABLE "users" ADD COLUMN "tfaSecret" TEXT,
+ADD COLUMN "tfaStatus" BOOLEAN NOT NULL DEFAULT false;
+
+-- CreateTable
+CREATE TABLE "notifications" (
+ "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ "id" TEXT NOT NULL,
+ "recipientId" TEXT NOT NULL,
+ "content" "NotifType" NOT NULL,
+ "is_read" BOOLEAN NOT NULL DEFAULT false,
+ "readAt" TIMESTAMP(3),
+
+ CONSTRAINT "notifications_pkey" PRIMARY KEY ("id")
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "notifications_createdAt_key" ON "notifications"("createdAt");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "messages_createdAt_key" ON "messages"("createdAt");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_Username_key" ON "users"("Username");
+
+-- AddForeignKey
+ALTER TABLE "messages" ADD CONSTRAINT "messages_roomId_fkey" FOREIGN KEY ("roomId") REFERENCES "rooms"("id") ON DELETE CASCADE ON UPDATE CASCADE;
diff --git a/backend/code/src/game/game.controller.ts b/backend/code/src/game/game.controller.ts
index 4387ede..26dab0b 100644
--- a/backend/code/src/game/game.controller.ts
+++ b/backend/code/src/game/game.controller.ts
@@ -1,4 +1,4 @@
-import { Controller, Get, Post, Query, UseGuards } from '@nestjs/common';
+import { Controller, Get, Post, Query, UseGuards, Param } from '@nestjs/common';
import { GameService } from './game.service';
import { AtGuard } from 'src/auth/guards/at.guard';
import { GetCurrentUser } from 'src/auth/decorator/get_current_user.decorator';
@@ -21,4 +21,13 @@ export class GameController {
) {
return this.gameService.getHistory(userId, offset, limit);
}
+
+ @Get('history/:id')
+ @UseGuards(AtGuard)
+ getHistoryId(
+ @Param('id') userId: string,
+ @Query() { offset, limit }: QueryOffsetDto,
+ ) {
+ return this.gameService.getHistory(userId, offset, limit);
+ }
}
diff --git a/backend/code/src/game/game.service.ts b/backend/code/src/game/game.service.ts
index 28a3c4a..06b3cc2 100644
--- a/backend/code/src/game/game.service.ts
+++ b/backend/code/src/game/game.service.ts
@@ -51,12 +51,14 @@ export class GameService {
score2: true,
participant1: {
select: {
+ userId:true,
Username: true,
avatar: true,
},
},
participant2: {
select: {
+ userId:true,
Username: true,
avatar: true,
},
@@ -78,11 +80,13 @@ export class GameService {
match: {
createdAt: match.createdAt,
Player1: {
+ id:match.participant1.userId,
username: match.participant1.Username,
score: match.score1,
avatar: avatar1,
},
Player2: {
+ id:match.participant2.userId,
username: match.participant2.Username,
score: match.score2,
avatar: avatar2,
diff --git a/backend/code/src/leaderboard/leaderboard.service.ts b/backend/code/src/leaderboard/leaderboard.service.ts
index aaa2f75..cf9dfb4 100644
--- a/backend/code/src/leaderboard/leaderboard.service.ts
+++ b/backend/code/src/leaderboard/leaderboard.service.ts
@@ -16,9 +16,25 @@ export class LeaderBoardService {
},
},
});
- return leaderboard.map((user) => ({
- userId: user.winner_id,
- wins: user._count.id,
- }));
+ const leaderboardsPromises = leaderboard.map(async (user ) => {
+ const lead = await this.prisma.user.findUnique({
+ where: {
+ userId: user.winner_id,
+ },
+ select: {
+ Username: true,
+ firstName: true,
+ lastName: true,
+ avatar: true,
+ userId: true,
+ },
+ },
+ )
+ return {
+ ...lead,
+ wins: user._count.id
+ }
+ });
+ return await Promise.all(leaderboardsPromises);
}
}
diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev
index 0789330..a8ebb4c 100644
--- a/frontend/Dockerfile.dev
+++ b/frontend/Dockerfile.dev
@@ -1,4 +1,4 @@
-FROM node:20
+FROM node:18
WORKDIR /app
diff --git a/frontend/code/package-lock.json b/frontend/code/package-lock.json
index 219bfb2..3534222 100644
--- a/frontend/code/package-lock.json
+++ b/frontend/code/package-lock.json
@@ -30,6 +30,7 @@
"react-hook-form": "^7.46.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.10.1",
+ "react-infinite-scroll-component": "^6.1.0",
"react-konva": "^18.2.10",
"react-scripts": "^5.0.1",
"socket.io-client": "^4.7.2",
@@ -14606,6 +14607,17 @@
"react": "*"
}
},
+ "node_modules/react-infinite-scroll-component": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-infinite-scroll-component/-/react-infinite-scroll-component-6.1.0.tgz",
+ "integrity": "sha512-SQu5nCqy8DxQWpnUVLx7V7b7LcA37aM7tvoWjTLZp1dk6EJibM5/4EJKzOnl07/BsM1Y40sKLuqjCwwH/xV0TQ==",
+ "dependencies": {
+ "throttle-debounce": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.0.0"
+ }
+ },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -16560,6 +16572,14 @@
"resolved": "https://registry.npmjs.org/throat/-/throat-6.0.2.tgz",
"integrity": "sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ=="
},
+ "node_modules/throttle-debounce": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz",
+ "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/thunky": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
diff --git a/frontend/code/package.json b/frontend/code/package.json
index 11c8b68..395a475 100644
--- a/frontend/code/package.json
+++ b/frontend/code/package.json
@@ -25,9 +25,11 @@
"react-hook-form": "^7.46.1",
"react-hot-toast": "^2.4.1",
"react-icons": "^4.10.1",
+ "react-infinite-scroll-component": "^6.1.0",
"react-konva": "^18.2.10",
"socket.io-client": "^4.7.2",
"react-scripts": "^5.0.1",
+ "socket.io-client": "^4.7.2",
"typescript": "^4.9.5",
"web-vitals": "^2.1.4",
"zustand": "^4.4.1"
diff --git a/frontend/code/src/Components/Home/LeaderBoard.tsx b/frontend/code/src/Components/Home/LeaderBoard.tsx
index c13f38f..3a32832 100644
--- a/frontend/code/src/Components/Home/LeaderBoard.tsx
+++ b/frontend/code/src/Components/Home/LeaderBoard.tsx
@@ -1,12 +1,15 @@
import { Chart } from './assets/Chart'
import { Table } from './assets/Table'
-export const LeaderBoard = () => {
+
+
+export const LeaderBoard = () => {
return (
-
+
)
diff --git a/frontend/code/src/Components/Home/assets/Table.tsx b/frontend/code/src/Components/Home/assets/Table.tsx
index fcfc7ff..6ff5e5f 100644
--- a/frontend/code/src/Components/Home/assets/Table.tsx
+++ b/frontend/code/src/Components/Home/assets/Table.tsx
@@ -1,50 +1,91 @@
import { Trophy } from './Trophy'
-import { useState,useEffect } from 'react'
+import { useState,useEffect, useCallback, useRef, FC } from 'react'
import { Daimond } from './Daimond'
import { Loading } from '../../Loading'
import { Link } from 'react-router-dom'
-// import { useLoaderData } from 'react-router'
+import { NullPlaceHolder } from '../../Chat/Components/RoomChatHelpers'
+import { Logo } from '../../Layout/Assets/Logo'
+import InfiniteScroll from 'react-infinite-scroll-component';
+import api from '../../../Api/base'
+import toast from 'react-hot-toast'
-// export const dataLoader = async() => {
-
-// var users :any[] = [];
-// for (let i = 0 ; i < 10 ; ++i)
-// {
-// let response = await fetch(`https://randomuser.me/api/`)
-// let data = await response.json()
-// if (data.results && data.results.length > 0) {
-// const newUser = data.results[0];
-// users.push(newUser)
-// }
-// }
-// return users;
-
-
-// }
-export const Table = () =>
+export const Table: FC = () =>
{
- const [users, setUsers] = useState
([])
- // const users : any = useLoaderData();
+ const [users, setUsers] = useState([])
+ const [loading , setLoading] = useState(true)
+ const page = useRef(0);
+ const hasMoreItems = useRef(true)
+ const [nextPageUrl, setNextPageUrl] : any = useState(
+ "/leaderboard?offset=0&limit=20"
+
+ );
+
+ const [fetching, setFetching] = useState(false);
- const [loading , setLoading] = useState(true)
- useEffect( () => {
- const fetchdata = async() =>{
- for (let i = 0 ; i < 10 ; ++i)
- {
- let response = await fetch(`https://randomuser.me/api/`)
- let data = await response.json()
- if (data.results && data.results.length > 0) {
- const newUser = data.results[0];
- setUsers((oldUsers : any) => [...oldUsers, newUser]);
- }
- }
- setLoading(false)
+ const fetchItems = useCallback(
+ async () => {
+ if (fetching) {
+ return;
}
- fetchdata().catch(console.error)
- },[])
-
+
+ setFetching(true);
+
+ try {
+ const newdata : any = await api.get(nextPageUrl);
+ if (newdata.data.length < 20) {
+ setUsers([...users, ...newdata.data]);
+ setNextPageUrl(null);
+ return;
+ }
+ console.log(newdata.data.length)
+ if (!newdata.data || newdata.data.length === 0)
+ {
+ setNextPageUrl(null)
+ return ;
+ }
+ else
+ {
+ console.log(newdata.data)
+ console.log("here")
+ setUsers([...users, ...newdata.data]);
+ setNextPageUrl(`/leaderboard?offset=${page.current}&limit=20`);
+ page.current += 20;
+ }
+
+
+ }
+ catch(e)
+ {
+ toast.error("Can't get leadeboard");
+ }
+ finally {
+ setLoading(false)
+
+ setFetching(false);
+ }
+ },
+ [users, fetching, nextPageUrl]
+ );
+
+ useEffect(() => {
+ fetchItems()
+ page.current += 20;
+ //eslint-disable-next-line
+ },[])
+ hasMoreItems.current = !!nextPageUrl;
+
return (
-
+ users?.length > 0 || loading ? (
+
+
}
+ endMessage={
No more results!
}
+ hasMore={hasMoreItems.current}
+ scrollableTarget="scrollTarget"
+ style={{overflow:"auto", height:"100%"}}
+ >
@@ -53,11 +94,13 @@ export const Table = () =>
Score |
-
- { !loading && users.map((x: any, index: number) => (
+
+
+
+ {!loading && users.map((x: any, index: number) => (
@@ -67,22 +110,30 @@ export const Table = () =>
|
-
-
+
+
-
+
-
- {x.name.first}
+ {x?.Username}
|
- {index + 123} |
+ {x?.wins} |
- ))}
+
+
+ ))}
{loading && ()}
+
+
+ ):(
+
+
+ )
+
);
}
\ No newline at end of file
diff --git a/frontend/code/src/Components/Home/index.tsx b/frontend/code/src/Components/Home/index.tsx
index de90d59..808709d 100644
--- a/frontend/code/src/Components/Home/index.tsx
+++ b/frontend/code/src/Components/Home/index.tsx
@@ -1,10 +1,10 @@
-import { FC } from 'react'
import { Button } from './assets/Button'
import { LeaderBoard } from './LeaderBoard'
import { Link } from 'react-router-dom'
import herosvg from './assets/Hero.png'
-export const Home : FC = () : JSX.Element =>{
+export const Home = () : JSX.Element =>{
+
return (
<>
@@ -16,10 +16,12 @@ export const Home : FC = () : JSX.Element =>{
READY TO PLAY A GAME?
-
>
diff --git a/frontend/code/src/Components/Layout/Assets/Profile.tsx b/frontend/code/src/Components/Layout/Assets/Profile.tsx
index 459f37f..ea2e64b 100644
--- a/frontend/code/src/Components/Layout/Assets/Profile.tsx
+++ b/frontend/code/src/Components/Layout/Assets/Profile.tsx
@@ -1,34 +1,14 @@
-import { Link } from "react-router-dom";
-import { classNames } from "../../../Utils/helpers";
-
-type ProfileProps = React.HTMLAttributes & {
- selected?: boolean;
-};
-
-export const Profile = ({ selected, className, ...props }: ProfileProps) => {
- return (
-
-
+import {Link} from 'react-router-dom'
+import { useUserStore } from '../../../Stores/stores'
+export const Profile = ({selected} : boolean | any) => {
+ const userStore = useUserStore();
+ return (
+
+
);
};
diff --git a/frontend/code/src/Components/Layout/index.tsx b/frontend/code/src/Components/Layout/index.tsx
index ae9767e..494f263 100644
--- a/frontend/code/src/Components/Layout/index.tsx
+++ b/frontend/code/src/Components/Layout/index.tsx
@@ -8,7 +8,7 @@ import { Message } from "./Assets/Message";
import { Profile } from "./Assets/Profile";
import { Settings } from "./Assets/Settings";
import { Out } from "./Assets/Out";
-import { FC, PropsWithChildren, useLayoutEffect } from "react";
+import { FC, PropsWithChildren, useLayoutEffect} from "react";
import { Outlet } from "react-router";
import { matchRoutes, useLocation } from "react-router-dom";
import { useUserStore } from "../../Stores/stores";
@@ -37,6 +37,7 @@ function onConnect() {
console.log("hello");
}
export const Layout: FC = (): JSX.Element => {
+
const user = useUserStore();
const navigate = useNavigate();
@@ -44,10 +45,16 @@ export const Layout: FC = (): JSX.Element => {
const log = async () => {
try {
await user.login();
- } catch (e) {
- navigate("/");
- user.logout();
+ }
+ catch(e:any){
+ if (e?.response?.status !== 403 && e?.response?.data?.message !== "Please complete your profile")
+ {
+ navigate("/");
+ user.logout();
+ }
}
+
+
};
socket.on("connect", onConnect);
@@ -111,8 +118,9 @@ export const Layout: FC = (): JSX.Element => {
-
diff --git a/frontend/code/src/Components/Profile/History.tsx b/frontend/code/src/Components/Profile/History.tsx
index be724bc..5c39112 100644
--- a/frontend/code/src/Components/Profile/History.tsx
+++ b/frontend/code/src/Components/Profile/History.tsx
@@ -2,7 +2,7 @@ import { Chart } from './assets/Chart'
import { Table } from './assets/Table'
export const History = (props:any) => {
return (
-
+
Matches History
diff --git a/frontend/code/src/Components/Profile/assets/MessageB.tsx b/frontend/code/src/Components/Profile/assets/MessageB.tsx
index 7afb618..04b910d 100644
--- a/frontend/code/src/Components/Profile/assets/MessageB.tsx
+++ b/frontend/code/src/Components/Profile/assets/MessageB.tsx
@@ -1,14 +1,22 @@
-export const Message = () => {
+import { toast } from "react-hot-toast"
+import api from "../../../Api/base"
+export const Message = (props:any) => {
+ const handleSendReq = async() => {
+ toast.promise(api.post("friends/add",{friendId:props.profile.id}),{loading:`Sending friend request`,success:`request sent to ${props.profile.name.first}`,error:"could not send friend request"})
+ }
+
return (
-
+ //
+
+ //
)
}
\ No newline at end of file
diff --git a/frontend/code/src/Components/Profile/assets/Table.tsx b/frontend/code/src/Components/Profile/assets/Table.tsx
index 389a5ec..7634253 100644
--- a/frontend/code/src/Components/Profile/assets/Table.tsx
+++ b/frontend/code/src/Components/Profile/assets/Table.tsx
@@ -1,80 +1,114 @@
-import { useState,useEffect } from 'react'
+import { useState,useEffect, useRef } from 'react'
import { Link } from 'react-router-dom'
import { Load , Loading} from '../../Loading/';
-import { useParams } from 'react-router-dom';
+import { Logo } from '../../Layout/Assets/Logo';
+import InfiniteScroll from 'react-infinite-scroll-component';
+import api from '../../../Api/base';
+import toast from 'react-hot-toast';
+
+const getColor = (v1 : number , v2:number) => {
+ if (v1 > v2) return "text-lime-400";
+ if (v1 < v2) return "text-red-400";
+ return "text-gray-400";
+
+}
+
+const getTime = (value: string) => {
+ const date = new Date(value);
+ const today = new Date()
+ console.log(date);
+ if (date.getDate() === today.getDate() && date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth())
+ return `Today ${date.getHours()}:${date.getMinutes()}`
+ else if (date.getDate() === today.getDate() - 1 && date.getFullYear() === today.getFullYear() && date.getMonth() === today.getMonth())
+ return `Yestrday ${date.getHours()}:${date.getMinutes()}`
+ return `${date.getDate()}-${date.getMonth()}-${date.getFullYear()}`
+}
export const Table = (props:any) =>
{
- const param = useParams();
- const [users, setUsers] = useState
([]);
- const [enemys , setEnemys] = useState([]);
- const [loading , setLoading] = useState(true);
- useEffect( () => {
- setLoading(true)
- setUsers([])
- setEnemys([])
- const fetchdata = async() =>{
- for (let i = 0 ; i < 5 ; ++i){
- let response = await fetch(`https://randomuser.me/api/`)
- let data = await response.json()
- if (data.results && data.results.length > 0) {
- const newUser = data.results[0];
- newUser.seed = data.info.seed;
- setEnemys((oldUsers : any) => [...oldUsers, newUser]);
- }
- }
- for (let i = 0 ; i < 5 ; ++i){
- let response = await fetch(`https://randomuser.me/api/`)
- let data = await response.json()
- if (data.results && data.results.length > 0) {
- const newUser = data.results[0];
- newUser.seed = data.info.seed;
- setUsers((oldUsers : any) => [...oldUsers, newUser]);
- }
- }
- setLoading(false)
+ const [history, setHistory] = useState([]);
+ const [loading, setLoading] = useState(true);
+ const [hasMore, setHasMore] = useState(true);
+ // const [nextPage , setNextPage] = useState(`/game/history/${param.id}?offset=${0}&limit=20`)
+ const offset = useRef(0);
+
+ const fetchData = async() => {
+ try{
+
+ const history:any = await api.get(`/game/history/${props.props.props}`,{params:{offset:offset.current,limit:20}});
+ offset.current += 20;
+ setHistory((prev:any) => [...prev , ...history.data]);
+ setLoading(false);
+ if (history.data.length < 20)
+ setHasMore(false)
+ }catch{
+ toast.error("Error on loading match history")
}
- fetchdata().catch(console.error)
- },[param])
+
+
+ }
+ // useEffect(() => {
+ // fetchData();
+ // offset.current += 20;
+ // },[])
+ useEffect(() => {
+ offset.current = 0;
+ setHistory([]);
+ setLoading(true);
+ setHasMore(true)
+ fetchData(); offset.current += 20;
+ //eslint-disable-next-line
+ },[props.props.props])
+ console.log(props)
return (
-
-
-
-
- {!loading && users.map((x: any ,index:number) => (
-
-
-
-
- today 17:45
-
-
- |
-
-
- {x?.name?.first ? {x.name.first} : }
- {x?.seed ? : }
-
- 1 : 1
-
+
+ }
+ dataLength={history.length}
+ next={fetchData}
+ className='overflow-auto'
+ scrollableTarget="scrollTarget"
+ endMessage={ No more history}
+ >
+
+
+
+ {!loading && history.map((x: any ,index:number) => (
+
+
- {enemys[index]?.seed ? : }
- {enemys[index]?.name?.first ? enemys[index].name.first : }
-
- |
- + 1 |
-
- ))}
- { loading && (
-
- )
+
+ {getTime(x.match.createdAt)}
+
+
+
+
+ {x?.match?.Player1?.username ? {x.match.Player1.username} : }
+ {x?.match ? : }
+
+ {x.match.Player1.score} : {x.match.Player2.score}
+
+
+ {x?.match?.Player2?.id ? : }
+ {x?.match?.Player2?.username ? x.match.Player2.username : }
+
+ |
+ {x.match.Player1.score > x.match.Player2.score && "+1"} {x.match.Player1.score < x.match.Player2.score && "-1"}{x.match.Player1.score === x.match.Player2.score && "0"} |
+
+ ))}
+ { loading && (
+
+ )
+
+ }
+
+
- }
- |
-
+
)
diff --git a/frontend/code/src/Components/Profile/index.tsx b/frontend/code/src/Components/Profile/index.tsx
index fa844c4..f9cdfd6 100644
--- a/frontend/code/src/Components/Profile/index.tsx
+++ b/frontend/code/src/Components/Profile/index.tsx
@@ -1,186 +1,168 @@
-import { Pong } from "./assets/Pong";
-import { File } from "./assets/File";
-import { Share } from "./assets/ShareB";
-import { Message } from "./assets/MessageB";
-import { History } from "./History";
-import Hero from "./assets/Hero.gif";
-import { useState, useEffect } from "react";
-import { Link, useNavigate, useParams } from "react-router-dom";
-import { Load } from "../Loading/";
-import Newbie from "../Badges/Newbie.svg";
-import Master from "../Badges/Master.svg";
-import Ultimate from "../Badges/Ultimate.svg";
-import { Edit } from "./assets/Edit";
-import { useUserStore } from "../../Stores/stores";
-import dots from "./assets/svg/threedots.svg";
-import api from "../../Api/base";
-import { BlockedUsersModal } from "../Chat/Components/RoomChatHelpers";
-import { useModalStore } from "../Chat/Controllers/LayoutControllers";
-import { createNewRoomCall } from "../Chat/Services/ChatServices";
-import toast from "react-hot-toast";
-import {
- ChatType,
- useChatStore,
-} from "../Chat/Controllers/RoomChatControllers";
-// import toast from 'react-hot-toast'
-export const Profile = () => {
- const user = useUserStore();
- const params = useParams();
- const LayoutState = useModalStore((state) => state);
- const navigate = useNavigate();
- const ChatState = useChatStore((state) => state);
- console.log(`params : ${params.id} type ${typeof params.id}`);
- const [users, setUsers] = useState(undefined);
+import { Pong } from './assets/Pong'
+import { File } from './assets/File'
- useEffect(() => {
- const fetchUser = async () => {
- try {
- const res = await api.get(`profile/${params.id}`);
- setUsers(res.data);
- } catch (error) {
- navigate("/NotFound");
- }
- };
- if (params.id !== user.id || params.id !== "me") fetchUser();
- else setUsers(user);
- //eslint-disable-next-line
- }, [params, user]);
- // console.log(users)
- // const handleSendReq = async() => {
- // toast.promise(api.post("friend/add",{friendId:users.id}),{loading:`Sending friend request`,success:`request sent to ${users.name.first}`,error:"could not send friend request"})
- // }
- return (
- <>
-
-
-
-
-
-
-
-
+import { History } from './History'
+import Hero from './assets/Hero.gif'
+import { useState , useEffect } from 'react'
+import { Link, useNavigate, useParams} from 'react-router-dom'
+import { Load } from '../Loading/'
+import Newbie from '../Badges/Newbie.svg'
+import Master from '../Badges/Master.svg'
+import Ultimate from '../Badges/Ultimate.svg'
+import { Edit } from './assets/Edit'
+import { useUserStore } from '../../Stores/stores'
+import { VscChromeClose , VscAdd , VscCheck , VscComment} from "react-icons/vsc";
+import api from '../../Api/base'
+import toast from 'react-hot-toast'
+type FRIENDSHIP = 'none' | 'friend' | 'sent' | 'recive' | 'blocked' | undefined;
+export const Profile = () =>{
+ const user = useUserStore();
+ const params = useParams();
+ const navigate = useNavigate();
+ const [status , setStatus] = useState
(undefined)
+ const [disabled , setDisbaled] = useState("");
+ console.log(`params : ${params.id} type ${typeof(params.id)}`)
+ const [profile, setProfile] = useState(undefined);
+
+ useEffect(() => {
+ const fetchUser = async() => {
+ try {
+ const res = await api.get(`profile/${params.id}`)
+ setProfile(res.data)
+ res.data.friendship.length === 0 && setStatus('none');
+ res.data.friendship.length > 0 && res.data.friendship[0].accepted && setStatus('friend');
+ res.data.friendship.length > 0 && !res.data.friendship[0].accepted && res.data.friendship[0].fromId === user.id && setStatus('sent')
+ res.data.friendship.length > 0 && !res.data.friendship[0].accepted && res.data.friendship[0].fromId !== user.id && setStatus('recive')
+ console.log(res.data)
+ } catch (error) {
+
+ navigate("/NotFound")
+ }
+ }
+ if (params.id !== user.id || params.id !== "me")
+ fetchUser();
+ else
+ setProfile(user)
-
-
- {users?.picture?.large ? (
-
- ) : (
-
- )}
+ //eslint-disable-next-line
+ },[params, user])
+ console.log(status)
+ const sendRequest = async() => {
+ setDisbaled("btn-disabled")
+ const fetchFunc = async () => {await api.post("friends/add",{friendId:profile.id}) ; setStatus('sent'); setDisbaled("")}
+ toast.promise(fetchFunc(),{loading:`Sending friend request`,success:`request sent to ${profile.name.first}`,error:"could not send friend request"})
+ // setDisbaled("")
+
+
+ }
+ const cancelRequest = async() => {
+ setDisbaled("btn-disabled")
+ const fetchFunc = async () => {await api.post("friends/unfriend",{friendId:profile.id}) ; setStatus('none');setDisbaled("")}
+ toast.promise(fetchFunc(),{loading:`Cancling friend request`,success:`cancel ${profile.name.first} friend request`,error:"could not cancel friend request"})
+ }
+ const acceptRequest = async() => {
+ setDisbaled("btn-disabled")
+ const fetchFunc = async () => {await api.post("/friends/accept",{friendId:profile.id}) ; setStatus('none');setDisbaled("")}
+ toast.promise(fetchFunc(),{loading:`Accepting friend request`,success:`${profile.name.first} friend request accepted`,error:"could not accept friend request"})
+ }
+ const rejectRequest = async() => {
+ setDisbaled("btn-disabled")
+ const fetchFunc = async () => {await api.post("/friends/reject",{friendId:profile.id}) ; setStatus('none');setDisbaled("")}
+ toast.promise(fetchFunc(),{loading:`rejecting friend request`,success:`${profile.name.first} friend request rejected`,error:"could not reject friend request"})
+ }
+
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ {
+ profile?.picture?.large ?
:
+ }
+
+
+
-
-
-
- {users?.name?.first ? (
-
- {users?.name?.first} {users.name.last}{" "}
-
- ) : (
-
- )}{" "}
-
-
- {users?.bio}
-
-
-
- {params.id !== "me" ? (
- <>
-
{
- await createNewRoomCall(
- "",
- "dm",
- undefined,
- params.id
- ).then((res) => {
- if (res?.status === 200 || res?.status === 201) {
- ChatState.changeChatType(ChatType.Chat);
- ChatState.selectNewChatID(res?.data?.id);
- ChatState.setCurrentDmUser({
- id: users?.id,
- firstname: users?.name.first,
- lastname: users?.name.last,
- avatar: {
- thumbnail: users?.picture.thumbnail,
- medium: users?.picture.medium,
- large: users?.picture.large,
- },
- bio: users?.bio,
- });
- navigate(`/Dm/${params.id}`);
- } else {
- toast.error(
- "You Can't Send Message To this User For Now, try Again later"
- );
+
+ {
+ profile?.name?.first ?
{profile?.name?.first} {profile.name.last}
:
+ }
+
+ {profile?.bio}
+
+
+
+ {
+ params.id !== "me" && params.id !== user.id && status === 'none' &&
+
+ }
+ {
+ params.id !== "me" && params.id !== user.id && status === 'sent' &&
+
}
- });
- }}
- >
-
-
-
- >
- ) : (
-
-
-
- )}
+ {
+ params.id !== "me" && params.id !== user.id && status === 'recive' &&
+
+
+
+
+ }
+ {
+ params.id !== "me" && params.id !== user.id && status === 'friend' &&
+
+
+
+
+ }
+ {
+ (params.id === "me" || params.id === user.id) &&
+
+
+ }
+
+
+
+
+
+ {/*
+
+
+ Block
+ Send friend request
+
+
*/}
+
+
-
-
-
-
-
-
-
- -
-
Block
-
- -
-
Send friend request
-
- - {
- LayoutState.setShowBlockedList(
- !LayoutState.showBlockedLIstModal
- );
- }}
- >
-
-
See Blocked List
-
-
-
-
+
+
-
-
-
-
-
>
- );
-};
+ )
+}
\ No newline at end of file
diff --git a/frontend/code/src/index.css b/frontend/code/src/index.css
index dec01b2..2b6bc93 100644
--- a/frontend/code/src/index.css
+++ b/frontend/code/src/index.css
@@ -3,8 +3,8 @@
@tailwind utilities;
@layer utilities
{
- @variants responsive {
- /* Hide scrollbar for Chrome, Safari and Opera */
+ @variants responsive {
+ /* Hide scrollbar for Chrome, Safari and Opera */
.no-scrollbar::-webkit-scrollbar {
display: none;
}
@@ -13,8 +13,34 @@
.no-scrollbar {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
- }
+ }
+ .customScroll {
+ --sb-track-color: #353135;
+ --sb-thumb-color: #7940CF;
+ --sb-size: 8px;
+
+ scrollbar-color: var(--sb-thumb-color)
+ var(--sb-track-color);
+ }
+
+ .customScroll::-webkit-scrollbar {
+ width: var(--sb-size)
+ }
+
+ .customScroll::-webkit-scrollbar-track {
+ background: var(--sb-track-color);
+ border-radius: 8px;
+ }
+
+ .customScroll::-webkit-scrollbar-thumb {
+ background: var(--sb-thumb-color);
+ border-radius: 8px;
+ border: 2px solid #7940CF;
+ }
}
+
+
+
}
@import url('https://fonts.googleapis.com/css2?family=Lexend+Peta:wght@400;700;800&family=Montserrat:ital,wght@0,700;1,500&family=Poppins:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap');
@layer base {
@@ -22,4 +48,7 @@
@apply no-scrollbar;
@apply font-montserrat;
}
+ *{
+ @apply customScroll
+ }
}