feat: playing with colours

This commit is contained in:
julius 2025-03-14 11:55:21 +01:00
parent 953a166ec5
commit 9ec457bb7a
Signed by: julius
GPG Key ID: C80A63E6A5FD7092
5 changed files with 84 additions and 47 deletions

View File

@ -1,7 +1,3 @@
* {
border-radius: 16px;
}
body { body {
background-color: aliceblue; background-color: aliceblue;
position: relative; position: relative;
@ -46,6 +42,7 @@ footer {
.controls { .controls {
z-index: 9; z-index: 9;
position: absolute; position: absolute;
color: black;
top: 1vh; top: 1vh;
right: 0px; right: 0px;
padding: 8px; padding: 8px;
@ -133,7 +130,7 @@ input:checked+.slider:before {
} }
.grey { .grey {
color: #444; opacity: 66%;
} }
@ -193,6 +190,7 @@ h3 {
.box { .box {
position: relative; position: relative;
flex: 1; flex: 1;
border-radius: 16px;
&.one { &.one {
max-width: min(96%, 768px); max-width: min(96%, 768px);
@ -265,6 +263,7 @@ button {
.control { .control {
display: flex; display: flex;
border-radius: 16px;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -418,6 +417,7 @@ button {
padding: 3px 8px; padding: 3px 8px;
width: fit-content; width: fit-content;
border: 3px solid black; border: 3px solid black;
border-radius: 16px;
margin: 0 auto 16px auto; margin: 0 auto 16px auto;
ul { ul {
@ -435,6 +435,31 @@ button {
} }
} }
/*=======CONTEXT MENU=======*/
.context-menu {
z-index: 3;
position: absolute;
background: aliceblue;
box-shadow: 4px 4px black;
color: black;
border: 3px solid black;
border-radius: 16px;
padding: 0;
margin: 0;
list-style: none;
li {
padding: 8px;
border-bottom: 2px solid #0008;
border-radius: 0;
cursor: pointer;
}
li:last-child {
border-bottom: none;
}
}
.networkroute { .networkroute {
z-index: 3; z-index: 3;

View File

@ -8,6 +8,7 @@ import { SessionProvider } from "./Session";
import { GraphComponent } from "./Network"; import { GraphComponent } from "./Network";
import MVPChart from "./MVPChart"; import MVPChart from "./MVPChart";
import { SetPassword } from "./SetPassword"; import { SetPassword } from "./SetPassword";
import { ThemeProvider } from "./ThemeProvider";
const Maintenance = () => { const Maintenance = () => {
return ( return (
@ -21,26 +22,28 @@ const Maintenance = () => {
function App() { function App() {
return ( return (
<BrowserRouter> <ThemeProvider>
<Routes> <BrowserRouter>
<Route path="/password" element={<SetPassword />} /> <Routes>
<Route <Route path="/password" element={<SetPassword />} />
path="/*" <Route
element={ path="/*"
<SessionProvider> element={
<Header /> <SessionProvider>
<Routes> <Header />
<Route index element={<Rankings />} /> <Routes>
<Route path="/network" element={<GraphComponent />} /> <Route index element={<Rankings />} />
<Route path="/analysis" element={<Analysis />} /> <Route path="/network" element={<GraphComponent />} />
<Route path="/mvp" element={<MVPChart />} /> <Route path="/analysis" element={<Analysis />} />
</Routes> <Route path="/mvp" element={<MVPChart />} />
<Footer /> </Routes>
</SessionProvider> <Footer />
} </SessionProvider>
/> }
</Routes> />
</BrowserRouter> </Routes>
</BrowserRouter>
</ThemeProvider>
); );
} }
export default App; export default App;

View File

@ -1,6 +1,8 @@
import { createRef, MouseEventHandler, useEffect, useState } from "react"; import { createRef, MouseEventHandler, useEffect, useState } from "react";
import { useSession } from "./Session"; import { useSession } from "./Session";
import { User } from "./api"; import { User } from "./api";
import { useTheme } from "./ThemeProvider";
import { colourTheme, darkTheme, normalTheme, rainbowTheme } from "./themes";
interface ContextMenuItem { interface ContextMenuItem {
label: string; label: string;
@ -32,6 +34,7 @@ const UserInfo = (user: User) => {
export default function Avatar() { export default function Avatar() {
const { user, onLogout } = useSession(); const { user, onLogout } = useSession();
const { theme, setTheme } = useTheme();
const [contextMenu, setContextMenu] = useState<{ const [contextMenu, setContextMenu] = useState<{
open: boolean; open: boolean;
allowOpen: boolean; allowOpen: boolean;
@ -42,8 +45,26 @@ export default function Avatar() {
const avatarRef = createRef<HTMLDivElement>(); const avatarRef = createRef<HTMLDivElement>();
const contextMenuItems: ContextMenuItem[] = [ const contextMenuItems: ContextMenuItem[] = [
{ label: "View Profile", onClick: handleViewProfile }, { label: "view Profile", onClick: handleViewProfile },
{ label: "Logout", onClick: onLogout }, {
label: "change theme",
onClick: () => {
switch (theme) {
case darkTheme:
setTheme(colourTheme);
break;
case colourTheme:
setTheme(rainbowTheme);
break;
case rainbowTheme:
setTheme(normalTheme);
break;
case normalTheme:
setTheme(darkTheme);
}
},
},
{ label: "logout", onClick: onLogout },
]; ];
const handleMenuClick: MouseEventHandler<HTMLDivElement> = (event) => { const handleMenuClick: MouseEventHandler<HTMLDivElement> = (event) => {
@ -94,7 +115,6 @@ export default function Avatar() {
const dialogRef = createRef<HTMLDialogElement>(); const dialogRef = createRef<HTMLDialogElement>();
function handleViewProfile() { function handleViewProfile() {
handleMenuClose();
if (user) { if (user) {
dialogRef.current?.showModal(); dialogRef.current?.showModal();
setDialog(UserInfo(user)); setDialog(UserInfo(user));
@ -105,7 +125,7 @@ export default function Avatar() {
<div <div
className="avatar" className="avatar"
onContextMenu={handleMenuClick} onContextMenu={handleMenuClick}
style={{ display: user ? "block" : "none" }} style={{ display: user ? "block" : "none", color: "black" }}
onClick={(event) => { onClick={(event) => {
if (contextMenu.open && event.target === avatarRef.current) { if (contextMenu.open && event.target === avatarRef.current) {
handleMenuClose(); handleMenuClose();
@ -121,25 +141,13 @@ export default function Avatar() {
className="context-menu" className="context-menu"
ref={contextMenuRef} ref={contextMenuRef}
style={{ style={{
zIndex: 3,
position: "absolute",
top: contextMenu.mouseY, top: contextMenu.mouseY,
left: contextMenu.mouseX, left: contextMenu.mouseX,
background: "white",
border: "1px solid #ddd",
padding: 0,
margin: 0,
listStyle: "none",
}} }}
> >
{contextMenuItems.map((item, index) => ( {contextMenuItems.map((item, index) => (
<li <li
key={index} key={index}
style={{
padding: "10px",
borderBottom: "1px solid #ddd",
cursor: "pointer",
}}
onClick={() => { onClick={() => {
item.onClick(); item.onClick();
handleMenuClose(); handleMenuClose();

View File

@ -1,6 +1,6 @@
import { Theme } from "reagraph"; import { Theme } from "reagraph";
export const customTheme: Theme = { export var customTheme: Theme = {
canvas: { canvas: {
background: "aliceblue", background: "aliceblue",
}, },

View File

@ -14,12 +14,10 @@ const determineNiceWidth = (width: number) => {
}; };
const RaceChart: FC<RaceChartProps> = ({ players, std }) => { const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
// State to store window's width and height
const [width, setWidth] = useState(determineNiceWidth(window.innerWidth)); const [width, setWidth] = useState(determineNiceWidth(window.innerWidth));
//const [height, setHeight] = useState(window.innerHeight); //const [height, setHeight] = useState(window.innerHeight);
const height = players.length * 40; const height = players.length * 40;
// Update state on resize
useEffect(() => { useEffect(() => {
const handleResize = () => { const handleResize = () => {
setWidth(determineNiceWidth(window.innerWidth)); setWidth(determineNiceWidth(window.innerWidth));
@ -41,11 +39,14 @@ const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
{players.map((player, index) => ( {players.map((player, index) => (
<rect <rect
key={String(index)} key={String(index)}
x={0} x={4}
y={index * barHeight + padding} y={index * barHeight + padding}
width={(1 - player.rank / maxValue) * width} width={(1 - player.rank / maxValue) * width}
height={barHeight - gap} // subtract 2 for some spacing between bars height={barHeight - gap} // subtract 2 for some spacing between bars
fill="#36c" fill="#36c"
stroke="aliceblue"
strokeWidth={4}
paintOrder={"stroke fill"}
/> />
))} ))}
@ -53,7 +54,7 @@ const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
<g key={"group" + index}> <g key={"group" + index}>
<text <text
key={index + "_name"} key={index + "_name"}
x={4} x={8}
y={index * barHeight + barHeight / 2 + padding + gap / 2} y={index * barHeight + barHeight / 2 + padding + gap / 2}
width={(1 - player.rank / maxValue) * width} width={(1 - player.rank / maxValue) * width}
height={barHeight - 8} // subtract 2 for some spacing between bars height={barHeight - 8} // subtract 2 for some spacing between bars
@ -71,7 +72,7 @@ const RaceChart: FC<RaceChartProps> = ({ players, std }) => {
<text <text
key={index + "_value"} key={index + "_value"}
x={ x={
4 + 8 +
(4 + Math.max(...players.map((p, _) => p.name.length))) * (4 + Math.max(...players.map((p, _) => p.name.length))) *
fontSize * fontSize *
0.66 0.66