Added nav, finished login page, made logo

This commit is contained in:
Patrick Hatsune 2024-08-02 07:49:07 -07:00
parent db3a18eda0
commit 865917f8b5
Signed by: keyemail
GPG key ID: 6FD1A0FDB0D914C2
18 changed files with 324 additions and 45 deletions

View file

@ -3,6 +3,7 @@
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="icon" type="image/x-icon" href="./logo.ico"/>
<title>Wifi Extender</title> <title>Wifi Extender</title>
</head> </head>
<body> <body>

65
package-lock.json generated
View file

@ -9,6 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "^18.3.1",
"react-cookie": "^7.2.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.25.1" "react-router-dom": "^6.25.1"
}, },
@ -1193,23 +1194,35 @@
"@babel/types": "^7.20.7" "@babel/types": "^7.20.7"
} }
}, },
"node_modules/@types/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
"integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==",
"dev": true "dev": true
}, },
"node_modules/@types/hoist-non-react-statics": {
"version": "3.3.5",
"resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
"integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
"dependencies": {
"@types/react": "*",
"hoist-non-react-statics": "^3.3.0"
}
},
"node_modules/@types/prop-types": { "node_modules/@types/prop-types": {
"version": "15.7.12", "version": "15.7.12",
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.12.tgz",
"integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==", "integrity": "sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q=="
"dev": true
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.3.3", "version": "18.3.3",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.3.tgz",
"integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==", "integrity": "sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==",
"dev": true,
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"csstype": "^3.0.2" "csstype": "^3.0.2"
@ -1653,8 +1666,7 @@
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
"dev": true
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.6", "version": "4.3.6",
@ -2290,6 +2302,14 @@
"node": ">=4" "node": ">=4"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.3.1", "version": "5.3.1",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz",
@ -2780,6 +2800,19 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-cookie": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-7.2.0.tgz",
"integrity": "sha512-mqhPERUyfOljq5yJ4woDFI33bjEtigsl8JDJdPPeNhr0eSVZmBc/2Vdf8mFxOUktQxhxTR1T+uF0/FRTZyBEgw==",
"dependencies": {
"@types/hoist-non-react-statics": "^3.3.5",
"hoist-non-react-statics": "^3.3.2",
"universal-cookie": "^7.0.0"
},
"peerDependencies": {
"react": ">= 16.3.0"
}
},
"node_modules/react-dom": { "node_modules/react-dom": {
"version": "18.3.1", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
@ -2792,6 +2825,11 @@
"react": "^18.3.1" "react": "^18.3.1"
} }
}, },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-refresh": { "node_modules/react-refresh": {
"version": "0.14.2", "version": "0.14.2",
"resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
@ -3095,6 +3133,23 @@
"node": ">=14.17" "node": ">=14.17"
} }
}, },
"node_modules/universal-cookie": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-7.2.0.tgz",
"integrity": "sha512-PvcyflJAYACJKr28HABxkGemML5vafHmiL4ICe3e+BEKXRMt0GaFLZhAwgv637kFFnnfiSJ8e6jknrKkMrU+PQ==",
"dependencies": {
"@types/cookie": "^0.6.0",
"cookie": "^0.6.0"
}
},
"node_modules/universal-cookie/node_modules/cookie": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz",

View file

@ -11,6 +11,7 @@
}, },
"dependencies": { "dependencies": {
"react": "^18.3.1", "react": "^18.3.1",
"react-cookie": "^7.2.0",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.25.1" "react-router-dom": "^6.25.1"
}, },

BIN
public/logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -1,9 +1,45 @@
import { useState, useEffect } from 'react'
import { Routes, Route, useNavigate } from 'react-router-dom';
import Dashboard from './pages/Dashboard'
import Devices from './pages/DeviceList.tsx'
import Extend from './pages/ExtendWirelessNetwork.tsx'
import WirelessSettings from './pages/SystemSettings.tsx'
import SystemSettings from './pages/WirelessSettings.tsx'
import Login from './pages/Login'
import Register from './pages/Register'
import Navbar from './components/Navbar'
import './styles/Main.css'
function Index() { function Index() {
return ( let [loginState, setLoginState] = useState(false);
let [loggedUser, setLoggedUser] = useState('')
const navigate = useNavigate();
useEffect(() => {
if(!loginState) {
navigate("/login");
}
if(loggedUser === '') {
setLoggedUser('Not Logged In')
}
}, [loginState, setLoggedUser]);
return(
<> <>
<p>hi</p> <p>{ loginState }</p>
<Navbar LoggedUser={ loggedUser } />
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/devices" element={<Devices />} />
<Route path="/extend" element={<Extend />} />
<Route path="/wireless" element={<WirelessSettings />} />
<Route path="/settings" element={<SystemSettings />} />
<Route path="/login" element={<Login setLogin={setLoginState} setUser={setLoggedUser} />} />
<Route path="/register" element={<Register />} />
</Routes>
</> </>
) )
} }
export default Index export default Index;

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

14
src/components/Navbar.tsx Normal file
View file

@ -0,0 +1,14 @@
interface Props {
LoggedUser: string;
}
function Navbar({ LoggedUser }: Props) {
return (
<nav>
<h1>Wifi Extender Hub</h1>
<p>{ LoggedUser }</p>
</nav>
)
}
export default Navbar;

0
src/data/login.json Normal file
View file

View file

@ -1,38 +1,12 @@
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import { RouterProvider, createBrowserRouter } from 'react-router-dom' import { BrowserRouter as Router } from 'react-router-dom';
import Index from './Index.tsx' import Index from './Index'
import Devices from './pages/DeviceList.tsx'
import Extend from './pages/ExtendWirelessNetwork.tsx'
import WirelessSettings from './pages/SystemSettings.tsx'
import SystemSettings from './pages/WirelessSettings.tsx'
import './styles/Main.css'
const router = createBrowserRouter([
{
path: "/",
element: <Index />
},
{
path: "/devices",
element: <Devices />
},
{
path: "/extend",
element: <Extend />
},
{
path: "/wireless",
element: <WirelessSettings />
},
{
path: "/settings",
element: <SystemSettings />
}
]);
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
<RouterProvider router={router} /> <Router>
<Index />
</Router>
</React.StrictMode>, </React.StrictMode>,
) )

9
src/pages/Dashboard.tsx Normal file
View file

@ -0,0 +1,9 @@
function Dashboard() {
return (
<>
<a href="/wireless"><p>hi</p></a>
</>
)
}
export default Dashboard

View file

@ -2,4 +2,4 @@ function DeviceList() {
return <p>device list</p> return <p>device list</p>
} }
export default DeviceList export default DeviceList;

View file

@ -2,4 +2,4 @@ function ExtendWirelessNetwork() {
return <p>Extend Wireless Network</p> return <p>Extend Wireless Network</p>
} }
export default ExtendWirelessNetwork export default ExtendWirelessNetwork;

View file

@ -0,0 +1,68 @@
import { Dispatch, SetStateAction, useState } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import '../styles/Login.css'
let usernames = ['root'];
let passwords = ['123', 'hello'];
interface Props {
setLogin: Dispatch<SetStateAction<boolean>>;
setUser: Dispatch<SetStateAction<string>>;
}
function Login({ setLogin, setUser }: Props) {
const navigate = useNavigate();
let [usernameError, setUsernameError] = useState(false);
let [passwordError, setPasswordError] = useState(false);
const handleLogin = (e: React.FormEvent) => {
e.preventDefault();
const userElement = document.getElementById('username') as HTMLInputElement | null;
const passwordElement = document.getElementById('password') as HTMLInputElement | null;
if(!userElement || !passwordElement) return;
let user = userElement?.value;
let password = passwordElement?.value;
for (let i = 0; i < usernames.length; i++) {
if(user === usernames[i] && password === passwords[i]) {
setLogin(true);
setUser(user);
return navigate("/");
}
}
setUsernameError(true);
setPasswordError(true);
};
return (
<div className="center">
<div id="login">
<h1>Welcome back!</h1>
<p>Enter your username and password.</p>
<form>
<h2>Username</h2>
<input type="text" id="username" />
{ passwordError &&
<p id="noinput">Wrong username.</p> }
<h2>Password</h2>
<input type="password" id="password" />
{ usernameError &&
<p id="noinput">Wrong password.</p> }
<p>Forgot password? <Link to="/reset">Reset it</Link></p>
<button onClick={handleLogin}>Login</button>
</form>
</div>
</div>
)
}
export default Login;

View file

@ -0,0 +1,5 @@
function Register() {
return <p>register</p>
}
export default Register;

View file

@ -2,4 +2,4 @@ function SystemSettings() {
return <p></p> return <p></p>
} }
export default SystemSettings export default SystemSettings;

View file

@ -2,4 +2,4 @@ function WirelessName() {
return <p>Wireless Name</p> return <p>Wireless Name</p>
} }
export default WirelessName export default WirelessName;

View file

@ -0,0 +1,80 @@
body {
height: 100vh;
}
#root {
height: 100%;
}
#login {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #071e42;
max-width: 500px;
height: 600px;
border-radius: 20px;
font-size: 1.5rem;
padding: 50px;
h1 {
text-align: center;
font-weight: normal;
}
p {
color: #ffffffd5;
}
}
#noinput {
color: red !important;
}
form {
display: flex;
flex-direction: inherit;
margin-top: 20px;
max-width: 360px;
font-weight: normal;
gap: 5px;
h2 {
font-size: 1.5rem;
font-weight: normal;
color: #ffffffd5;
}
input {
color: #ffffffb4;
border: none;
background-color: #071436;
height: 40px;
width: 360px;
border-radius: 10px;
padding: 5px;
font-size: 1rem;
}
p {
font-size: 0.8rem;
color: #ffffffd5;
max-width: fit-content;
}
a {
color: cyan;
}
button {
background-color: #071436;
border: none;
color: #fff;
margin-top: 20px;
height: 50px;
width: 100%;
border-radius: 10px;
font-size: 1.3rem;
cursor: pointer;
transition: 0.3s background-color;
}
button:hover {
background-color: #0069ff;
}
}

View file

@ -1,3 +1,15 @@
@font-face {
font-family: Poppins;
src: url(../fonts/Poppins/Poppins-Bold.ttf);
font-weight: bold;
}
@font-face {
font-family: Poppins;
src: url(../fonts/Poppins/Poppins-Regular.ttf);
font-weight: normal;
}
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -5,6 +17,30 @@
} }
body { body {
background-color: #121212; background-color: #071935;
color: #fff; color: #fff;
padding: 20px;
font-family: 'Poppins', sans-serif;
}
a {
color: inherit;
text-decoration: none;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
p {
float: right;
}
}
.center {
display: flex;
align-items: center;
justify-content: center;
height: calc(100% - 40px);
} }