From 50f5ac247e009980d6434b325abef864dd2b5f7a Mon Sep 17 00:00:00 2001 From: Stanleyowskiki Date: Tue, 14 May 2024 07:42:31 +0200 Subject: [PATCH] user-view --- package.json | 1 + src/User/ProfileView/ProfileInfoTable.js | 44 ++-- .../ProfileInfoTableAchievements.css | 80 +++++++ .../ProfileInfoTableAchievements.js | 81 ++++++- .../ProfileView/ProfileInfoTableButtons.js | 6 +- src/User/ProfileView/ProfileView.css | 51 ++++- src/User/ProfileView/ProfileView.js | 66 ++++-- src/User/Settings/SettingPopup.js | 2 +- src/User/User.js | 18 +- src/User/store.js | 8 +- src/forms/LoginForm.js | 15 +- src/index.js | 2 +- src/resources/ban.svg | 8 + src/resources/icon1.svg | 2 + src/resources/icon2.svg | 18 ++ src/resources/icon3.svg | 2 + src/resources/tour1.svg | 200 +++++++++++++++++ src/resources/tour3.svg | 202 ++++++++++++++++++ src/resources/tour5.svg | 200 +++++++++++++++++ src/services/ServiceUtils.js | 26 +++ 20 files changed, 948 insertions(+), 84 deletions(-) create mode 100644 src/User/ProfileView/ProfileInfoTableAchievements.css create mode 100644 src/resources/ban.svg create mode 100644 src/resources/icon1.svg create mode 100644 src/resources/icon2.svg create mode 100644 src/resources/icon3.svg create mode 100644 src/resources/tour1.svg create mode 100644 src/resources/tour3.svg create mode 100644 src/resources/tour5.svg create mode 100644 src/services/ServiceUtils.js diff --git a/package.json b/package.json index 6b41de6..4bb5936 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", "axios": "^1.6.5", + "buffer": "^6.0.3", "jwt-decode": "^4.0.0", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/User/ProfileView/ProfileInfoTable.js b/src/User/ProfileView/ProfileInfoTable.js index a9cacb3..5ef38d1 100644 --- a/src/User/ProfileView/ProfileInfoTable.js +++ b/src/User/ProfileView/ProfileInfoTable.js @@ -1,23 +1,7 @@ import { useEffect, useState } from "react"; import {PointsService} from "../../services/PointsService"; -import {XAxis, YAxis, CartesianGrid, Tooltip, LineChart, Line } from 'recharts'; +import {XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip, LineChart, Line } from 'recharts'; -function StatsTable(props) { - return ( - - - - - - - - - - - -
WinsLossesDraws
{props.wins}{props.losses}{props.draws}
- ); -} function RatingTable(props) { const [history, setHistory] = useState([{id: 0, logDate: "", points: 0, playerId: 0}]); @@ -26,17 +10,17 @@ function RatingTable(props) { setHistory(PointsService.getPointsHistoryForPlayer(props.playerid)["data"]); }, [props.playerid]); + var ticksize = 20; const chart = - - - - - - - ; - - console.log(history); - + + + + + + + + + return ( <> {chart} @@ -85,8 +69,6 @@ function TournamentsPlayedTable(props) { function changeState(newState) { switch (newState) { - case "stats": - return ; case "rating": return ; case "bots": @@ -101,10 +83,10 @@ function changeState(newState) { } function ProfileInfoTable(props) { - const { state } = props; + const { state, user } = props; const [content, setContent] = useState(null); useEffect(() => { - const con = changeState(state); + var con = changeState(state); setContent(con); }, [state]); diff --git a/src/User/ProfileView/ProfileInfoTableAchievements.css b/src/User/ProfileView/ProfileInfoTableAchievements.css new file mode 100644 index 0000000..028e35b --- /dev/null +++ b/src/User/ProfileView/ProfileInfoTableAchievements.css @@ -0,0 +1,80 @@ +.user-achivments-container { + position: relative; + margin-bottom: 10px; + vertical-align: middle; +} + +.user-achivments-container-content { + position: relative; + z-index: 100; + height: 100%; + padding: 10px; +} + +.user-achivments-background { + color:#222222; + background-color: #111111; + position: absolute; + z-index: 10; + width: 100%; + top: 0; + left: 0; + padding: 10px; +} + +.user-achivments-background-text { + text-shadow: 0px 0px 10px #000000; + float: right; + user-select: none; +} + +.user-achivments-scroll { + overflow-x: scroll; + overflow-y: hidden; + height: 100%; + user-select: none; + display: flex; + flex-wrap: nowrap; + justify-content: flex-start; + flex-shrink: 0; +} + + +.user-achivments-container-content > ::-webkit-scrollbar { + background: #222222; + height: 5px; +} + +.user-achivments-container-content > ::-webkit-scrollbar-track { + background: #090909; +} + +.user-achivments-container-content > ::-webkit-scrollbar-thumb { + background: #002200; + border-radius: 5px; +} + +.user-achivments-container-content > ::-webkit-scrollbar-thumb:hover { + background: #006000; +} + +.user-achivments-icon { + height: 30px; + width: auto; + + min-width: 30px; +} + +.user-achivments-icon-container { + margin: 5px; + padding: 0px 10px 0px 10px; + width: fit-content; + border-radius: 50%; + display: inline-block; + transition: all 0.3s ease; +} + +.user-achivments-icon-container:hover { + cursor: pointer; + background: rgb(170, 170, 170, 0.5); +} \ No newline at end of file diff --git a/src/User/ProfileView/ProfileInfoTableAchievements.js b/src/User/ProfileView/ProfileInfoTableAchievements.js index a57f5e9..90e5871 100644 --- a/src/User/ProfileView/ProfileInfoTableAchievements.js +++ b/src/User/ProfileView/ProfileInfoTableAchievements.js @@ -1,17 +1,82 @@ +import './ProfileInfoTableAchievements.css'; +import icon1 from '../../resources/icon1.svg' +import icon2 from '../../resources/icon2.svg' +import icon3 from '../../resources/icon3.svg' +import { useEffect, useState } from 'react'; +import { Tooltip } from '@mui/material'; +function getAchievements(playerId) { + return [ + {'achiv': 'achiv1', 'description': 'very good description', 'icon': icon1, 'value': '1000', 'achived': true}, + {'achiv': 'achiv2', 'description': 'very bad description', 'icon': icon2, 'value': '2000', 'achived': true}, + {'achiv': 'achiv3', 'description': 'very ugly description', 'icon': icon3, 'value': '3000', 'achived': false}, + {'achiv': 'achiv4', 'description': 'very beautiful description', 'icon': icon2, 'value': '4000', 'achived': true}, + {'achiv': 'achiv5', 'description': 'very descriptive description', 'icon': icon1, 'value': '5000', 'achived':false}, + {'achiv': 'achiv6', 'description': 'very good description', 'icon': icon2, 'value': '1000', 'achived': false}, + {'achiv': 'achiv7', 'description': 'very bad description', 'icon': icon3, 'value': '2000', 'achived': true}, + {'achiv': 'achiv8', 'description': 'very ugly description', 'icon': icon2, 'value': '3000','achived': false}, + {'achiv': 'achiv9', 'description': 'very beautiful description', 'icon': icon1, 'value': '4000', 'achived': true}, + {'achiv': 'achiv10', 'description': 'very descriptive description', 'icon': icon3, 'value': '5000', 'achived': false}, + {'achiv': 'achiv11', 'description': 'very good description', 'icon': icon1, 'value': '1000', 'achived': false}, + {'achiv': 'achiv12', 'description': 'very bad description', 'icon': icon2, 'value': '2000', 'achived': true}, + {'achiv': 'achiv13', 'description': 'very ugly description', 'icon': icon3, 'value': '3000', 'achived': false}, + {'achiv': 'achiv7', 'description': 'very bad description', 'icon': icon1, 'value': '2000', 'achived': true}, + {'achiv': 'achiv8', 'description': 'very ugly description', 'icon': icon3, 'value': '3000', 'achived':false}, + {'achiv': 'achiv9', 'description': 'very beautiful description', 'icon': icon1, 'value': '4000','achived': true}, + {'achiv': 'achiv10', 'description': 'very descriptive description', 'icon': icon2, 'value': '5000','achived': false}, + {'achiv': 'achiv11', 'description': 'very good description', 'icon': icon1, 'value': '1000','achived': true}, + {'achiv': 'achiv12', 'description': 'very bad description', 'icon': icon2, 'value': '2000','achived': false}, + {'achiv': 'achiv13', 'description': 'very ugly description', 'icon': icon3, 'value': '3000','achived': true}, + ] +} function ProfileInfoTableAchievements(props) { const {playerId} = props; + const [achievements, setAchievements] = useState([{'achiv':'', 'description':'', 'icon':'', 'value':'', 'achived':false}]); + + useEffect(() => { + setAchievements(getAchievements(playerId)); + }, [playerId]); + let content = achievements.map((achiv) => { + let tooltipcontent = <> +

{achiv.achiv}

+

{achiv.description}

+

Current value: {achiv.value}

+ + return ( + +
+ +
+
+ ); + }); + return ( - - - - - - - -
achievements
{playerId}
+ <> +
+
+
+ {content} +
+
+
+

Achivments

+
+
+ ); } diff --git a/src/User/ProfileView/ProfileInfoTableButtons.js b/src/User/ProfileView/ProfileInfoTableButtons.js index a001db9..7d5dd0f 100644 --- a/src/User/ProfileView/ProfileInfoTableButtons.js +++ b/src/User/ProfileView/ProfileInfoTableButtons.js @@ -1,15 +1,15 @@ import "./ProfileView.css"; + function ProfileInfoTableButtons(props) { const { setState } = props; return (
- - - + +
); } diff --git a/src/User/ProfileView/ProfileView.css b/src/User/ProfileView/ProfileView.css index 4a45203..0981970 100644 --- a/src/User/ProfileView/ProfileView.css +++ b/src/User/ProfileView/ProfileView.css @@ -7,7 +7,7 @@ justify-items: stretch; align-content: stretch; - height: 100%; + height: 100hw; } .user-photo { @@ -19,6 +19,11 @@ .profile-image { border: 3px solid black; border-radius: 1px; + + width: 100%; + aspect-ratio: 1/1; + + object-fit: cover; } .change-photo { @@ -28,12 +33,16 @@ } .user-info { - font-size: 20px; + font-size: 30%; border: 3px solid black; padding: 10px; height: 100%; } +.user-info .user-info-text { + color: aqua; +} + .user-info-table-container { border: 3px solid black; padding: 20px; @@ -53,10 +62,38 @@ } .user-info-table-buttons-container { - display: flex; + display: grid; + grid-template-columns: 1fr 1fr 1fr 1fr; justify-content:space-evenly; } +@media (max-aspect-ratio: 1){ + .user-info-table-buttons-container { + grid-template-columns: 1fr 1fr; + } +} + +@media (max-aspect-ratio: 5/6) { + /*Handling collapse*/ + .main-container { + grid-template-columns: 0% 100%; + } + + .notcollapse { + background-color: red; + visibility: collapse; + width: 0; + } + + .collapse { + visibility: visible; + } +} + +.collapse { + visibility: collapse; +} + .user-overview { height: 100%; } @@ -74,8 +111,6 @@ .settings-button { width: 100%; align-self: flex-end; - - bottom: 0; } .cell { @@ -104,3 +139,9 @@ button { width: 100%; padding: 10px; } + +.user-ban-icon { + position: absolute; + width: 50px; + padding: 10px; +} diff --git a/src/User/ProfileView/ProfileView.js b/src/User/ProfileView/ProfileView.js index 049680d..8f0ea92 100644 --- a/src/User/ProfileView/ProfileView.js +++ b/src/User/ProfileView/ProfileView.js @@ -3,42 +3,74 @@ import React, { useState, useEffect } from 'react'; import { UserService } from '../../services/UserService' import ProfileInfoTable from './ProfileInfoTable'; import ProfileInfoTableAchievements from './ProfileInfoTableAchievements'; - +import { Buffer } from 'buffer'; import './ProfileView.css'; import ProfileInfoTableButtons from './ProfileInfoTableButtons'; +import { Tooltip } from '@mui/material'; +import { dateToResponse } from '../../services/ServiceUtils'; + +import defIcon from "../../resources/user.svg"; +import banIcon from "../../resources/ban.svg"; function ProfileView() { - const { id } = useParams(); + const { name } = useParams(); const [user, setUser] = useState({}); const [state, setState] = useState("stats"); + const [image, setImage] = useState(""); const myID = 1; - useEffect(() => { - setUser(UserService.getPlayerInfo(id)); - }, [id]); + UserService.getPlayerInfo(name).then((data) => { + setUser(data.data.data); + }).catch((error) => { + console.log(error); + }); + }, [name]); + useEffect(() => { + if (user.id === undefined) return; + UserService.getImageForPlayer(user.id).then((data) => { + setImage(Buffer.from(data.data.data, "base64").toString()); + }).catch((error) => { + console.log(error); + }); + }, [user]); return (<>
-
+
- user + {image === "" ? + user + : + + }
-
+
+ {user.isBanned && <> +
+ + ban + +
}

{user.login}

-

{user.rating}

+

{user.point}

-
+
-
- {id === myID ? +
+ {user.id === myID ? Change photo : <> @@ -49,12 +81,12 @@ function ProfileView() {
-
+
-

Member since: {user.joined}

-

Last seen: {user.lastseen}

-

Bots added: #TODO#

-

Tournaments created: #TODO#

+

Member since: {dateToResponse("2024-04-26T11:13:01.8196733")}

+

Last seen: {user.lastSeen}

+

Bots added: {user.botsNumber}

+

Tournaments created: {user.tournamentNumber}

diff --git a/src/User/Settings/SettingPopup.js b/src/User/Settings/SettingPopup.js index b7b3685..bea659e 100644 --- a/src/User/Settings/SettingPopup.js +++ b/src/User/Settings/SettingPopup.js @@ -36,7 +36,7 @@ export default function SettingPopup(props) { return null; } - var but = + const but = return (<> {close => diff --git a/src/User/User.js b/src/User/User.js index 10544ca..f695d36 100644 --- a/src/User/User.js +++ b/src/User/User.js @@ -9,13 +9,21 @@ function User({ isAuthenticated, user, login, logout }) { {isAuthenticated ? ( ) : ( - <> - - + <> + + + + + )} diff --git a/src/User/store.js b/src/User/store.js index c27deb0..94a3ee9 100644 --- a/src/User/store.js +++ b/src/User/store.js @@ -26,13 +26,19 @@ const authReducer = (state = initialState, action) => { } }; +// Configuration for redux-persist using sessionStorage const persistConfig = { key: 'root', - storage, + storage, // Use sessionStorage }; +// Wrap the reducer with redux-persist const persistedReducer = persistReducer(persistConfig, authReducer); + +// Create store with persisted reducer const store = createStore(persistedReducer); + +// Create a persistor object export const persistor = persistStore(store); export default store; diff --git a/src/forms/LoginForm.js b/src/forms/LoginForm.js index 8c8fe21..715153b 100644 --- a/src/forms/LoginForm.js +++ b/src/forms/LoginForm.js @@ -5,8 +5,7 @@ import {UserService} from "../services/UserService"; import { connect } from 'react-redux'; import { login, logout } from '../User/store'; -function LoginForm({isAuthenticated, user, login, logout}) { - +function RegisterForm() { const [email, setEmail] = useState(''); const [password, setPassword] = useState(''); const [message, setMessage] = useState(true); @@ -18,7 +17,7 @@ function LoginForm({isAuthenticated, user, login, logout}) { await UserService.loginUser(email, password) setMessage('Login succesful.') } catch (e) { - setMessage('There was a problem with login.') + setMessage('There was a problem with the registration.') } }; @@ -65,12 +64,4 @@ function LoginForm({isAuthenticated, user, login, logout}) { ) } -const mapStateToProps = (state) => ({ - isAuthenticated: state.isAuthenticated, - user: state.user, - }); - -const mapDispatchToProps = {login,logout,}; - -export default connect(mapStateToProps, mapDispatchToProps)(LoginForm); - +export default RegisterForm diff --git a/src/index.js b/src/index.js index 9ce2e5e..9d6a10f 100644 --- a/src/index.js +++ b/src/index.js @@ -40,7 +40,7 @@ const router = createBrowserRouter([ element: , }, { - path: "/player/:id", + path: "/player/:name", element: , }, { diff --git a/src/resources/ban.svg b/src/resources/ban.svg new file mode 100644 index 0000000..023ae92 --- /dev/null +++ b/src/resources/ban.svg @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/src/resources/icon1.svg b/src/resources/icon1.svg new file mode 100644 index 0000000..16971c5 --- /dev/null +++ b/src/resources/icon1.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/resources/icon2.svg b/src/resources/icon2.svg new file mode 100644 index 0000000..ea57344 --- /dev/null +++ b/src/resources/icon2.svg @@ -0,0 +1,18 @@ + + + \ No newline at end of file diff --git a/src/resources/icon3.svg b/src/resources/icon3.svg new file mode 100644 index 0000000..8e86823 --- /dev/null +++ b/src/resources/icon3.svg @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/src/resources/tour1.svg b/src/resources/tour1.svg new file mode 100644 index 0000000..78dc738 --- /dev/null +++ b/src/resources/tour1.svg @@ -0,0 +1,200 @@ + + + +I diff --git a/src/resources/tour3.svg b/src/resources/tour3.svg new file mode 100644 index 0000000..4b3f3b6 --- /dev/null +++ b/src/resources/tour3.svg @@ -0,0 +1,202 @@ + + + +III diff --git a/src/resources/tour5.svg b/src/resources/tour5.svg new file mode 100644 index 0000000..919b651 --- /dev/null +++ b/src/resources/tour5.svg @@ -0,0 +1,200 @@ + + + +V diff --git a/src/services/ServiceUtils.js b/src/services/ServiceUtils.js new file mode 100644 index 0000000..28dca6b --- /dev/null +++ b/src/services/ServiceUtils.js @@ -0,0 +1,26 @@ + + +function dateToRequest(date){ + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + const hours = String(date.getHours()).padStart(2, '0'); + const minutes = String(date.getMinutes()).padStart(2, '0'); + const seconds = String(date.getSeconds()).padStart(2, '0'); + const milliseconds = String(date.getMilliseconds()).padStart(3, '0'); + return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${milliseconds}Z`; +} + +// 2024-04-26T11:13:01.8196733 +// YYYY-MM-DDTHH:MM:SS.MMMZ +function dateToResponse(date){ + const dateObj = new Date(Date.parse(date)); + return `${dateObj.getFullYear()}-${dateObj.getMonth()}-${dateObj.getDate()}`; +} + +function getCurrentTimeRequest(){ + const now = new Date(); + return dateToRequest(now); +} + +export { dateToRequest, dateToResponse, getCurrentTimeRequest } \ No newline at end of file