fix docker, add base routing, header + drawer

This commit is contained in:
Marcus Almert
2025-10-28 17:33:39 +01:00
parent dbf54f59ef
commit b0a42de301
18 changed files with 1461 additions and 214 deletions

View File

@@ -4,39 +4,3 @@
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

View File

@@ -1,13 +0,0 @@
import "./App.css";
function App() {
return (
<>
<div>
<h1>MitM Webserver</h1>
</div>
</>
);
}
export default App;

15
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,15 @@
import { Routes, Route } from "react-router-dom";
import "./App.css";
import Header from "./header/Header";
import Home from "./pages/Home";
export default function App() {
return (
<>
<Header />
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</>
);
}

View File

@@ -0,0 +1,93 @@
import React from "react";
import {
AppBar,
Toolbar,
Typography,
IconButton,
Drawer,
List,
ListItem,
ListItemButton,
ListItemText,
Box,
useTheme,
} from "@mui/material";
import MenuIcon from "@mui/icons-material/Menu";
import { useNavigate, useLocation, To } from "react-router-dom";
const pages = [{ name: "Home", path: "/" }];
export default function Header() {
const [drawerOpen, setDrawerOpen] = React.useState(false);
const theme = useTheme();
const navigate = useNavigate();
const location = useLocation();
const toggleDrawer = (open: boolean) => () => setDrawerOpen(open);
const handleNavigate = (path: To) => {
navigate(path);
setDrawerOpen(false);
};
const drawerList = (
<Box
sx={{
width: 250,
height: "100%",
bgcolor: theme.palette.background.default,
color: theme.palette.text.primary,
}}
role="presentation"
onKeyDown={toggleDrawer(false)}
>
<Typography
variant="h6"
sx={{
textAlign: "center",
my: 2,
fontWeight: "bold",
color: theme.palette.primary.main,
}}
>
MitM Webserver
</Typography>
<List>
{pages.map(({ name, path }) => (
<ListItem key={name} disablePadding>
<ListItemButton
onClick={() => handleNavigate(path)}
selected={location.pathname === path}
>
<ListItemText primary={name} />
</ListItemButton>
</ListItem>
))}
</List>
</Box>
);
return (
<>
<AppBar position="fixed" color="primary" elevation={2}>
<Toolbar>
<IconButton color="inherit" edge="start" onClick={toggleDrawer(true)}>
<MenuIcon />
</IconButton>
<Typography
variant="h6"
component="div"
sx={{ flexGrow: 1, fontWeight: "bold", cursor: "pointer" }}
onClick={() => handleNavigate("/")}
>
MitM Webserver
</Typography>
</Toolbar>
</AppBar>
<Toolbar /> {/* spacing */}
<Drawer anchor="left" open={drawerOpen} onClose={toggleDrawer(false)}>
{drawerList}
</Drawer>
</>
);
}

View File

@@ -1,68 +1,89 @@
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
/* === Reset & base === */
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
/* Smooth scrolling */
html {
scroll-behavior: smooth;
}
font-synthesis: none;
text-rendering: optimizeLegibility;
/* Root background and typography (matches theme background + font) */
body {
font-family: "Inter", "Roboto", "Helvetica", "Arial", sans-serif;
background-color: #f9f9f9; /* matches theme.palette.background.default */
color: #262626; /* matches theme.palette.text.primary */
line-height: 1.6;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
/* Anchor defaults */
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
color: #1976d2; /* primary main */
text-decoration: none;
transition: color 0.2s ease-in-out;
}
a:hover {
color: #535bf2;
color: #004ba0; /* primary dark */
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
/* === Scrollbar styling (WebKit browsers) === */
::-webkit-scrollbar {
width: 10px;
height: 10px;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
::-webkit-scrollbar-track {
background: #f0f0f0;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
::-webkit-scrollbar-thumb {
background: #bfbfbf;
border-radius: 5px;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
::-webkit-scrollbar-thumb:hover {
background: #737373;
}
/* === Utility classes === */
/* Center container with padding */
.container {
max-width: 1200px;
margin: 0 auto;
padding: 1rem;
}
/* Add subtle fade animation for route transitions */
.fade-enter {
opacity: 0;
transform: translateY(10px);
}
.fade-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity 0.3s, transform 0.3s;
}
/* === Code blocks / preformatted text === */
pre,
code {
background-color: #f0f0f0;
color: #262626;
padding: 0.25rem 0.5rem;
border-radius: 4px;
font-family: "JetBrains Mono", "Fira Code", monospace;
}
/* === App container fix for fixed header === */
main {
padding-top: 64px; /* matches MUI AppBar height */
}

View File

@@ -1,10 +0,0 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)

21
frontend/src/main.tsx Normal file
View File

@@ -0,0 +1,21 @@
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.js";
import { ThemeProvider, createTheme } from "@mui/material/styles";
import { BrowserRouter } from "react-router-dom";
import theme from "./theme";
const rootElement = document.getElementById("root");
if (rootElement) {
createRoot(rootElement).render(
<StrictMode>
<ThemeProvider theme={theme}>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>
</StrictMode>
);
}

View File

@@ -0,0 +1,14 @@
import { Container, Typography, Button } from "@mui/material";
export default function Home() {
return (
<Container style={{ textAlign: "center", marginTop: "4rem" }}>
<Typography variant="h4" gutterBottom>
🚀 Hello MUI + React!
</Typography>
<Button variant="contained" color="primary">
Klick mich!
</Button>
</Container>
);
}

111
frontend/src/theme.tsx Normal file
View File

@@ -0,0 +1,111 @@
import { createTheme } from "@mui/material/styles";
const theme = createTheme({
palette: {
mode: "light",
// === Primary colors (blue shades) ===
primary: {
main: "#1976d2", // medium blue
light: "#63a4ff", // light blue
dark: "#004ba0", // deep blue
contrastText: "#ffffff",
},
// === Secondary colors (gray shades) ===
secondary: {
main: "#737373", // neutral medium gray
light: "#bfbfbf", // lighter gray
dark: "#404040", // darker gray
contrastText: "#ffffff",
},
// === Background colors ===
background: {
default: "#f9f9f9", // soft gray-white for page background
paper: "#ffffff", // white for cards, modals, etc.
},
// === Text colors ===
text: {
primary: "#262626", // almost black
secondary: "#737373", // muted gray
},
// === Divider ===
divider: "#d9d9d9",
},
typography: {
fontFamily: '"Inter", "Roboto", "Helvetica", "Arial", sans-serif',
h1: { fontWeight: 700, fontSize: "2.5rem", color: "#262626" },
h2: { fontWeight: 600, fontSize: "2rem", color: "#262626" },
h3: { fontWeight: 600, fontSize: "1.75rem", color: "#262626" },
body1: { fontSize: "1rem", lineHeight: 1.6, color: "#262626" },
button: {
textTransform: "none",
fontWeight: 500,
color: "#ffffff",
},
},
shape: {
borderRadius: 10,
},
components: {
MuiAppBar: {
styleOverrides: {
root: {
backgroundColor: "#1976d2", // primary main
color: "#ffffff",
},
},
},
MuiButton: {
styleOverrides: {
root: {
borderRadius: 8,
textTransform: "none",
fontWeight: 500,
"&:hover": {
backgroundColor: "#004ba0", // darker blue
},
},
},
},
MuiPaper: {
styleOverrides: {
root: {
borderRadius: 0,
backgroundColor: "#ffffff",
color: "#262626",
boxShadow:
"0px 2px 8px rgba(0, 0, 0, 0.05), 0px 1px 2px rgba(0, 0, 0, 0.1)",
},
},
},
MuiDrawer: {
styleOverrides: {
paper: {
backgroundColor: "#f0f0f0", // subtle gray drawer background
color: "#262626",
},
},
},
MuiListItemButton: {
styleOverrides: {
root: {
"&.Mui-selected": {
backgroundColor: "#e0e0e0",
"&:hover": {
backgroundColor: "#d0d0d0",
},
},
},
},
},
},
});
export default theme;