diff --git a/package-lock.json b/package-lock.json index cacaeac..ec0f6d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,6 +19,7 @@ "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-icons": "^5.3.0", "react-router-dom": "^6.24.0", "react-toastify": "^10.0.5", "sass": "^1.77.6", @@ -9754,6 +9755,14 @@ "react": ">=16.3.0" } }, + "node_modules/react-icons": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz", + "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", diff --git a/package.json b/package.json index 0ff04ed..4659aff 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "prop-types": "^15.8.1", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-icons": "^5.3.0", "react-router-dom": "^6.24.0", "react-toastify": "^10.0.5", "sass": "^1.77.6", diff --git a/src/pages/ServerConsole/ServerConsole.jsx b/src/pages/ServerConsole/ServerConsole.jsx new file mode 100644 index 0000000..075eb56 --- /dev/null +++ b/src/pages/ServerConsole/ServerConsole.jsx @@ -0,0 +1,52 @@ +import { useEffect, useState } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import styles from './ServerConsole.module.scss'; +import serviiApi from "../../service/api.tsx"; +import Loading from '../Loading/loading.jsx'; +import PropTypes from "prop-types"; + +const ServerConsole = ({ user }) => { + const navigate = useNavigate(); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const [logs, setLogs] = useState(''); + + if (loading) { + return ; + } + + if (error) { + return ( +
+
+

{error}

+ +
+
+ ); + } + + return ( +
+
+

Console

+
+
+            {logs}
+          
+
+
+
+ ); +}; + +ServerConsole.propTypes = { + user: PropTypes.oneOfType([ + PropTypes.shape({ + uid: PropTypes.string.isRequired, + }), + ]), +}; + +export default ServerConsole; diff --git a/src/pages/ServerConsole/ServerConsole.module.scss b/src/pages/ServerConsole/ServerConsole.module.scss new file mode 100644 index 0000000..b68dd2b --- /dev/null +++ b/src/pages/ServerConsole/ServerConsole.module.scss @@ -0,0 +1,19 @@ +.container { + display: flex; + justify-content: center; + align-items: center; + margin-top: var(--navbar-height); + width: 60rem; + height: 90%; + margin-bottom: 1rem; + } + +.containerConsole { + display: flex; + justify-content: center; + align-items: center; + background-color: red; + width: 50rem; + height: 100%; + overflow: auto; + } \ No newline at end of file diff --git a/src/pages/ServerDetails/ServerDetails.jsx b/src/pages/ServerDetails/ServerDetails.jsx index 2f66608..dbd5e3c 100644 --- a/src/pages/ServerDetails/ServerDetails.jsx +++ b/src/pages/ServerDetails/ServerDetails.jsx @@ -1,155 +1,76 @@ -import { useEffect, useState } from 'react'; +import { useState } from 'react'; import { useParams, useNavigate } from 'react-router-dom'; import Navbar from '../../components/navbar/Navbar'; +import ServerProperties from '../ServerProperties/ServerProperties'; import styles from './ServerDetails.module.scss'; -import serviiApi from "../../service/api.tsx"; -import Loading from '../Loading/loading'; import PropTypes from "prop-types"; - +import { FaServer, FaCogs, FaUserFriends, FaGlobe, FaHistory, FaClipboardList, FaSave, FaLock } from 'react-icons/fa'; +import ServerConsole from '../ServerConsole/ServerConsole'; +// import ServerHistory from '../ServerHistory/ServerHistory'; +// import ServerPlayers from '../ServerPlayers/ServerPlayers'; +// import ServerWorlds from '../ServerWorlds/ServerWorlds'; +// import ServerBackups from '../ServerBackups/ServerBackups'; +// import ServerAccess from '../ServerAccess/ServerAccess'; const ServerDetails = ({ user }) => { - const { serverName } = useParams(); + const { serverName } = useParams(); const navigate = useNavigate(); - const [server, setServer] = useState(null); - const [loading, setLoading] = useState(true); - const [error, setError] = useState(null); - - useEffect(() => { - const fetchServer = async () => { - try { - const ApiResponse = await serviiApi.fetchServers(); - const data = ApiResponse.message; - const foundServer = data.find(server => server.name === serverName); - - if (foundServer) { - setServer(foundServer); - } else { - setError('Server not found'); - } - } catch (error) { - console.error('Error fetching server:', error); - setError('Error fetching server'); - } finally { - setLoading(false); - } - }; - - fetchServer(); - }, [serverName]); - - const validateInput = (input) => { - return input.replace(/[^a-zA-Z]/g, ''); - }; - - const handleChange = (e) => { - const { name, value } = e.target; - const validatedValue = name === 'motd' ? validateInput(value) : value; - setServer({ ...server, [name]: validatedValue }); - }; - - const handleSave = async () => { - try { - const props = [ - ['max-players', server.maxPlayers.toString()], - ['motd', server.motd], - ['difficulty', server.difficulty], - ['enable-command-block', server.enableCommandBlock.toString()], - ['gamemode', server.gamemode.toString()], - ['hardcore', server.hardcore.toString()], - ['online-mode', server.onlineMode.toString()], - ['pvp', server.pvp.toString()] - ]; - - await serviiApi.updateProperties(server.name, props); - } catch (error) { - console.error('Error updating server:', error); - alert('Error updating server'); - } - handleQuit(); - }; + const [selectedMenu, setSelectedMenu] = useState(''); const handleQuit = () => { navigate('/dashboard'); }; - if (loading) { - return ; - } - - if (error) { - return ( -
- -
-

{error}

- -
-
- ); - } + const renderContent = () => { + switch (selectedMenu) { + case 'options': + return ; + case 'console': + return ; + case 'history': + return

Cette fonctionnalité sera prochainement disponible.

; // + case 'players': + return

Cette fonctionnalité sera prochainement disponible.

; // + case 'worlds': + return

Cette fonctionnalité sera prochainement disponible.

; // + case 'backups': + return

Cette fonctionnalité sera prochainement disponible.

; // + case 'access': + return

Cette fonctionnalité sera prochainement disponible.

; // + default: + return

{serverName || 'Server name not available'}

; + } + }; return ( -
+ <> -
-

Détails du serveur {server.name}

-
- - +
+ -
- - +
+ {renderContent()}
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
-
- - -
- -
-
+ ); }; @@ -162,4 +83,5 @@ ServerDetails.propTypes = { }), ]), }; + export default ServerDetails; diff --git a/src/pages/ServerDetails/ServerDetails.module.scss b/src/pages/ServerDetails/ServerDetails.module.scss index 782bf06..065da33 100644 --- a/src/pages/ServerDetails/ServerDetails.module.scss +++ b/src/pages/ServerDetails/ServerDetails.module.scss @@ -1,133 +1,94 @@ +.container { + display: flex; + min-height: 100vh; +} + +.sidebar { + width: 20rem; + background-color: #100D25; + padding: 2rem; + box-sizing: border-box; + position: fixed; + height: 100vh; + top: 0; + color: white; +} + +.logo img { + width: 150px; + margin-bottom: 2rem; +} + +.user { + margin-bottom: 2rem; +} + +.user p { + font-size: 1.25rem; + font-weight: bold; +} + +.user small { + font-size: 0.875rem; + color: #9CA3AF; +} + +.menu { + display: flex; + flex-direction: column; +} + +.menuItem { + display: flex; + align-items: center; + padding: 1rem 0; + font-size: 1.5rem; + cursor: pointer; + color: #D1D5DB; + text-decoration: none; +} + +.menuItem:hover { + color: white; +} + +.menuItem svg { + margin-right: 1rem; + font-size: 1.25rem; +} + +.logoutButton { + margin-top: 2rem; + padding: 0.75rem 1.5rem; + background-color: #EF4444; + border: none; + color: white; + cursor: pointer; + width: 100%; + text-align: center; +} + +.logoutButton:hover { + background-color: #DC2626; +} + .serverDetailsContainer { + flex: 1; + margin-left: 20rem; padding-top: var(--navbar-height); background-color: var(--main-bg-color); display: flex; flex-direction: column; align-items: center; color: var(--text-color); - width: 100%; - box-sizing: border-box; -} - -.details { - margin-top: 5rem; - padding: 3rem; - padding-top: 0; - background-color: var(--card-bg-color); - width: 100%; - max-width: 60rem; - border-radius: 1.5rem; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); box-sizing: border-box; } -.formGroup { - margin-bottom: 2.5rem; - display: flex; - flex-direction: column; -} - -.formGroup label { - font-weight: 600; - margin-bottom: 1rem; - font-size: 1.4rem; - color: var(--label-color); -} - -.formGroup input, -.formGroup select { - width: 100%; - padding: 1.2rem; - height: auto; - background-color: var(--input-bg-color); - border: 1px solid var(--input-border-color); - border-radius: 0.75rem; - color: var(--text-color); - font-size: 1.2rem; - line-height: 1.5rem; - box-sizing: border-box; - transition: border-color 0.3s ease, box-shadow 0.3s ease; -} - -.formGroup input:focus, -.formGroup select:focus { - border-color: var(--focus-border-color); - box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); - outline: none; -} - -/* Chrome- styles */ -@supports (-webkit-appearance: none) { - .formGroup select { - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - background-image: url('data:image/svg+xml;utf8,'); - background-repeat: no-repeat; - background-position: right 1.2rem center; - background-size: 1rem; - padding-right: 3rem; - } -} - -.saveButton, -.quitButton { - padding: 1.2rem 2.5rem; - color: var(--button-text-color); - border: none; - border-radius: 0.75rem; - cursor: pointer; - transition: background-color 0.3s ease, transform 0.3s ease; - font-size: 1.2rem; - margin-top: 1rem; -} - -.saveButton { - background-color: #05a771; -} - -.saveButton:hover { - background-color: #05a77183; -} - -.quitButton { - background-color: gray; - margin-left: 1rem; -} - - -.error { - color: var(--error-color); - font-size: 1.2rem; -} - -.details h1 { - font-size: 2.5rem; - margin-bottom: 3rem; - color: var(--header-color); -} - -@media (max-width: 768px) { - .details { - width: 90%; - padding: 2rem; - } - - .formGroup input, - .formGroup select { - height: auto; - font-size: 1.1rem; - padding: 1rem; - } - - .saveButton, - .quitButton { - padding: 1rem 2rem; - font-size: 1.1rem; - } - - .details h1 { - font-size: 2rem; - margin-bottom: 2rem; - } +.navbar { + position: fixed; + top: 0; + width: 100%; + height: var(--navbar-height); + background-color: var(--navbar-bg-color); + z-index: 1000; } diff --git a/src/pages/ServerProperties/ServerProperties.jsx b/src/pages/ServerProperties/ServerProperties.jsx new file mode 100644 index 0000000..674360e --- /dev/null +++ b/src/pages/ServerProperties/ServerProperties.jsx @@ -0,0 +1,156 @@ +import { useEffect, useState } from 'react'; +import { useParams, useNavigate } from 'react-router-dom'; +import styles from './ServerProperties.module.scss'; +import serviiApi from "../../service/api.tsx"; +import Loading from '../Loading/loading'; +import PropTypes from "prop-types"; + +const ServerProprieties = ({ user }) => { + const { serverName } = useParams(); + const navigate = useNavigate(); + const [server, setServer] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(null); + + useEffect(() => { + const fetchServer = async () => { + try { + const ApiResponse = await serviiApi.fetchServers(); + const data = ApiResponse.message; + const foundServer = data.find(server => server.name === serverName); + + if (foundServer) { + setServer(foundServer); + } else { + setError('Server not found'); + } + } catch (error) { + console.error('Error fetching server:', error); + setError('Error fetching server'); + } finally { + setLoading(false); + } + }; + + fetchServer(); + }, [serverName]); + + const validateInput = (input) => { + return input.replace(/[^a-zA-Z]/g, ''); + }; + + const handleChange = (e) => { + const { name, value } = e.target; + const validatedValue = name === 'motd' ? validateInput(value) : value; + setServer({ ...server, [name]: validatedValue }); + }; + + const handleSave = async () => { + try { + const props = [ + ['max-players', server.maxPlayers.toString()], + ['motd', server.motd], + ['difficulty', server.difficulty], + ['enable-command-block', server.enableCommandBlock.toString()], + ['gamemode', server.gamemode.toString()], + ['hardcore', server.hardcore.toString()], + ['online-mode', server.onlineMode.toString()], + ['pvp', server.pvp.toString()] + ]; + + await serviiApi.updateProperties(server.name, props); + } catch (error) { + console.error('Error updating server:', error); + alert('Error updating server'); + } + }; + + if (loading) { + return ; + } + + if (error) { + return ( +
+
+

{error}

+ +
+
+ ); + } + + return ( +
+
+

Propriétés du serveur {server.name}

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+ ); +}; + +ServerProprieties.propTypes = { + user: PropTypes.oneOfType([ + PropTypes.shape({ + uid: PropTypes.string.isRequired, + displayName: PropTypes.string, + email: PropTypes.string, + }), + ]), +}; + +export default ServerProprieties; diff --git a/src/pages/ServerProperties/ServerProperties.module.scss b/src/pages/ServerProperties/ServerProperties.module.scss new file mode 100644 index 0000000..ccf14c8 --- /dev/null +++ b/src/pages/ServerProperties/ServerProperties.module.scss @@ -0,0 +1,133 @@ +.serverDetailsContainer { + padding-top: var(--navbar-height); + background-color: var(--main-bg-color); + display: flex; + flex-direction: column; + align-items: center; + color: var(--text-color); + width: 100%; + box-sizing: border-box; + } + + .details { + padding: 3rem; + padding-top: 0; + background-color: var(--card-bg-color); + width: 100%; + max-width: 60rem; + border-radius: 1.5rem; + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); + box-sizing: border-box; + } + + .formGroup { + margin-bottom: 2.5rem; + display: flex; + flex-direction: column; + } + + .formGroup label { + font-weight: 600; + margin-bottom: 1rem; + font-size: 1.4rem; + color: var(--label-color); + } + + .formGroup input, + .formGroup select { + width: 100%; + padding: 1.2rem; + height: auto; + background-color: var(--input-bg-color); + border: 1px solid var(--input-border-color); + border-radius: 0.75rem; + color: var(--text-color); + font-size: 1.2rem; + line-height: 1.5rem; + box-sizing: border-box; + transition: border-color 0.3s ease, box-shadow 0.3s ease; + } + + .formGroup input:focus, + .formGroup select:focus { + border-color: var(--focus-border-color); + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + outline: none; + } + + /* Chrome- styles */ + @supports (-webkit-appearance: none) { + .formGroup select { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: right 1.2rem center; + background-size: 1rem; + padding-right: 3rem; + } + } + + .saveButton, + .quitButton { + padding: 1.2rem 2.5rem; + color: var(--button-text-color); + border: none; + border-radius: 0.75rem; + cursor: pointer; + transition: background-color 0.3s ease, transform 0.3s ease; + font-size: 1.2rem; + margin-top: 1rem; + } + + .saveButton { + background-color: #05a771; + } + + .saveButton:hover { + background-color: #05a77183; + } + + .quitButton { + background-color: gray; + margin-left: 1rem; + } + + + .error { + color: var(--error-color); + font-size: 1.2rem; + } + + .details h1 { + font-size: 2.5rem; + margin-bottom: 3rem; + color: var(--header-color); + } + + @media (max-width: 768px) { + .details { + width: 90%; + padding: 2rem; + } + + .formGroup input, + .formGroup select { + height: auto; + font-size: 1.1rem; + padding: 1rem; + } + + .saveButton, + .quitButton { + padding: 1rem 2rem; + font-size: 1.1rem; + } + + .details h1 { + font-size: 2rem; + margin-bottom: 2rem; + } + } + \ No newline at end of file