Skip to content

Commit

Permalink
[Task] #77, enhance login, show pastUser if availabe, show user on ma…
Browse files Browse the repository at this point in the history
…inpage
  • Loading branch information
Type-Style committed Jul 5, 2024
1 parent 4b48089 commit d3a5bc7
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
"workbench.editor.enablePreview": false,
"editor.rename.enablePreview": false,
"typescript.tsdk": "node_modules\\typescript\\lib",
"html.format.wrapLineLength": 150
"html.format.wrapLineLength": 150,
"javascript.preferences.quoteStyle": "double",
"typescript.preferences.quoteStyle": "double"
}
9 changes: 9 additions & 0 deletions httpdocs/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,15 @@ Neutral: #131211
font-weight: calc(800 + var(--baseFontWeightModifier));
}

.fade { animation: fade 1s 1s forwards; }
.fadeIn { animation: reverse fade 1s forwards; }
@keyframes fade {
to {
font-size: 0;
opacity: 0;
}
}

@media screen and
(prefers-reduced-motion: reduce),
(update: slow) {
Expand Down
34 changes: 19 additions & 15 deletions src/client/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,24 @@ import Login from '../pages/Login';

export const LoginContext = createContext([]);

function loginDefault() {
const token = sessionStorage?.jwt;
let exp;

if (token) {
try {
exp = JSON.parse(window.atob(token.split('.')[1])).exp;
const date = new Date();
return date.getTime() / 1000 <= exp;
} catch (error) {
console.error("Unable to parse JWT Data, for login default state");
export function convertJwt() {
const token = localStorage?.jwt;
if (!token) { return false }
try {
const { user, exp } = JSON.parse(window.atob(token.split('.')[1]));
return { user, exp };
} catch (error) {
console.error("Unable to parse JWT Data");
return false;
}
}
return false;
}

function loginDefault(userInfo) {
if (!userInfo) { return false; }

const date = new Date();
const exp = userInfo.exp
return date.getTime() / 1000 <= exp;
}

const router = createBrowserRouter([
Expand All @@ -34,10 +37,11 @@ const router = createBrowserRouter([
]);

const App = () => {
const [isLoggedIn, setLogin] = useState(loginDefault());
const [userInfo, setUserInfo] = useState(convertJwt());
const [isLoggedIn, setLogin] = useState(loginDefault(userInfo));

return (
<LoginContext.Provider value={[isLoggedIn, setLogin]}>
<LoginContext.Provider value={[isLoggedIn, setLogin, userInfo, setUserInfo]}>
<RouterProvider router={router} />
</LoginContext.Provider>
);
Expand Down
2 changes: 1 addition & 1 deletion src/client/components/Map.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react'
import { MapContainer, Marker, Popup, TileLayer } from 'react-leaflet'
import 'leaflet/dist/leaflet.css';
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.webpack.css'; // Re-uses images from ~leaflet package
import L from 'leaflet';
// import L from 'leaflet';
import 'leaflet-defaulticon-compatibility';
import * as css from "../css/map.module.css";

Expand Down
4 changes: 4 additions & 0 deletions src/client/css/login.css
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@
padding-block: 1em;
text-align: center;
font-size: 3.5rem;

&.sub {
font-size: 2.1em;
}
}

form {
Expand Down
62 changes: 53 additions & 9 deletions src/client/css/start.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@
display: flex;
width: 100%;
justify-content: space-between;
padding: 0.7em 2em;
padding: 0.5em 0.8em;
@media (min-width: 30em) {
padding: 0.7em 2em;
}

}

Expand Down Expand Up @@ -60,8 +63,8 @@
display: grid;
}

image {
background-color: moccasin;
image {
background-color: moccasin;
}

.image+.image {
Expand All @@ -74,14 +77,24 @@
}
}

.error {
.message {
display: inline-flex;
flex-wrap: wrap;
align-content: center;
justify-content: center;
font-size: 1.3em;
font-size: 0.9em;

@media (min-width: 30em) {
font-size: 1.3em;
}

&.center {
margin-left: auto;
}

.statusCode {
.title {
font-size: 1.1em;
@media (min-width: 30em) { font-size: inherit; }
width: 100%;
text-align: center;
}
Expand All @@ -91,12 +104,43 @@
color: var(--bg);
margin-left: auto;
cursor: pointer;

white-space: nowrap;

font-size: 0;
padding: 0;

@media (min-width: 30em) {
/* reset to MUI default */
font-size: 1.3rem;
padding: 8px 22px;
}

.MuiButton-icon {
font-size: 1.3rem;
@media (min-width: 30em) {
font-size: inherit;
}
}
.MuiButton-startIcon {
margin-left: 6px;
@media (min-width: 30em) {
margin-left: 0px;
}
}
.MuiButton-endIcon {
margin-left: 0;
@media (min-width: 30em) {
margin-left: 4px;
}
}


&.loginButton--loggedIn {
svg {
position: relative;
top: -0.1em; right: 0.1em;
top: -0.1em;
right: 0.1em;
}
}
}
}
}
12 changes: 8 additions & 4 deletions src/client/pages/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import "../css/login.css";
import ModeSwitcher from '../components/ModeSwitcher';
import axios from 'axios';
import qs from 'qs';
import { LoginContext } from '../components/App';
import { LoginContext, convertJwt } from '../components/App';
import { useNavigate } from 'react-router-dom';
import LinearBuffer from '../components/LinearBuffer';

function Login() {
const [finish, setFinish] = useState(1);
const [start, setStart] = useState(1);
const navigate = useNavigate();
const [isLoggedIn, setLogin] = useContext(LoginContext);
const [isLoggedIn, setLogin, userInfo, setUserInfo] = useContext(LoginContext);
const [formInfo, updateFormInfo] = useState({
user: {
isError: false,
message: "Minimum 2",
value: ""
value: userInfo?.user || ""
},
password: {
isError: false,
Expand Down Expand Up @@ -87,14 +87,15 @@ function Login() {
headers: { "content-type": "application/x-www-form-urlencoded" }
})
const token = response.data.token;
sessionStorage.setItem("jwt", token);
localStorage.setItem("jwt", token);
setLogin(true);
setMessageObj({ isError: false, status: <Check />, message: "Success!" })

// update linearBar for delay until redirect
const date = new Date();
setStart(date.getTime());
setFinish(new Date(date.getTime() + 1000).getTime());
setUserInfo(convertJwt());

// redirect back to main page
setTimeout(() => { setLoading(false); navigate("/") }, 1000);
Expand All @@ -115,6 +116,9 @@ function Login() {
<h1 className="headline">
Login Page
</h1>
{isLoggedIn &&
<h2 className="headline sub">You are logged in</h2>
}
<form action="/login" method="post" onSubmit={submit}>
<TextField
label="Username"
Expand Down
19 changes: 12 additions & 7 deletions src/client/pages/Start.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import ModeSwitcher from '../components/ModeSwitcher';
import Map from '../components/Map';

function Start() {
const [isLoggedIn, setLogin] = useContext(LoginContext);
const [isLoggedIn, setLogin, userInfo] = useContext(LoginContext);
const [entries, setEntries] = useState<Models.IEntry[]>([]);
const [errorObj, setMessageObj] = React.useState({ isError: null, status: null, message: null });


useEffect(() => {
const token = sessionStorage.getItem("jwt");
const token = localStorage.getItem("jwt");
let response;

const getData = async () => {
Expand Down Expand Up @@ -52,15 +52,20 @@ function Start() {
<div className="start">
<div className="grid-item info">
{errorObj.isError &&
<div className="error">
<strong className="statusCode">{errorObj.status}</strong> <span>{errorObj.message} </span>
<div className="message center">
<strong className="title">{errorObj.status}</strong> <span className="fadeIn">{errorObj.message}</span>
</div>
}
{!errorObj.isError && userInfo &&
<div className="message">
<strong className="title">{userInfo.user}</strong> <span className="fade">Welcome back</span>
</div>
}
<Button
className={`loginButton ${isLoggedIn ? "loginButton--loggedIn" : ''} cut`}
variant="contained"
href={isLoggedIn ? null : "/login"}
onClick={isLoggedIn ? () => { setLogin(false); sessionStorage.clear(); } : null}
onClick={isLoggedIn ? () => { setLogin(false); localStorage.clear(); } : null}
endIcon={isLoggedIn ? <Check /> : null}
startIcon={isLoggedIn ? null : <HighlightOff />}
color={isLoggedIn ? "success" : "error"}
Expand All @@ -70,8 +75,8 @@ function Start() {
</Button>
</div>

<div className="grid-item map"><Map entries={entries}/></div>
<div className="grid-item theme"><ModeSwitcher/></div>
<div className="grid-item map"><Map entries={entries} /></div>
<div className="grid-item theme"><ModeSwitcher /></div>
<div className="grid-item status">status</div>
<div className="grid-item images">
<div className="image">image1</div>
Expand Down

0 comments on commit d3a5bc7

Please sign in to comment.