Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
371 changes: 299 additions & 72 deletions greenscoutjs/bun.lock

Large diffs are not rendered by default.

39 changes: 17 additions & 22 deletions greenscoutjs/index.html
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
<!doctype html>
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Standard favicon -->
<link rel="icon" href="/src/assets/favicon/favicon.ico" sizes="any" />
<!-- For Apple devices -->
<link
rel="apple-touch-icon"
href="/src/assets/favicon/apple-touch-icon.png"
/>
<!-- General fallback for older browsers -->
<link
rel="icon"
type="image/png"
href="/src/assets/favicon/favicon-32x32.png"
sizes="32x32"
/>
</head>
<body style="padding: 0; margin: 0; color: var(--background-color)">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<title>Green Scout</title>
</body>
<head>
<!-- Standard favicon -->
<link rel="icon" href="/src/assets/favicon/favicon.ico" sizes="any">
<!-- For Apple devices -->
<link rel="apple-touch-icon" href="/src/assets/favicon/apple-touch-icon.png">
<!-- General fallback for older browsers -->
<link rel="icon" type="image/png" href="/src/assets/favicon/favicon-32x32.png" sizes="32x32">

<THEMEANCHOR/>

<title>Green Scout</title>
</head>
<body style="padding: 0; margin: 0; color: var(--background-color)">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
18 changes: 9 additions & 9 deletions greenscoutjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.13.5",
"axios": "1.14.0",
"gh-pages": "^6.3.0",
"react": "^19.2.4",
"react-dom": "^19.2.4",
"react-router-dom": "^7.13.1",
"styled-components": "^6.1.19"
"react-router-dom": "^7.14.0",
"styled-components": "^6.3.12"
},
"devDependencies": {
"@eslint/js": "^9.39.1",
"@types/react": "^19.2.5",
"@eslint/js": "^9.39.4",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react": "^5.1.1",
"@vitejs/plugin-react": "^5.2.0",
"connect-api-mocker": "^1.11.0",
"eslint": "^9.39.1",
"eslint": "^9.39.4",
"eslint-plugin-react-hooks": "^7.0.1",
"eslint-plugin-react-refresh": "^0.4.24",
"eslint-plugin-react-refresh": "^0.4.26",
"express": "^5.2.1",
"globals": "^16.5.0",
"vite": "^7.2.4"
"vite": "^7.3.1"
}
}
23 changes: 20 additions & 3 deletions greenscoutjs/src/api/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,27 @@ export const submitMatchform = async (formData) => {

export const getLeaderboard = async (scoreType) => {
const response = await axios.get(`${SERVER}/leaderboard`, {
headers: {
type: scoreType,
},
headers: { type: scoreType },
});

return response.data;
};

export const getThemeList = async () => {
const response = await axios.get(`${SERVER}/allThemes`);

return response.data.themes;
};

export const getCurrentTheme = async () => {
const response = await axios.get(`${SERVER}/currTheme`);
return response.data.theme;
};

export const setTheme = async (themeName) => {
await axios.post(`${SERVER}/setTheme`, { theme: themeName });
};

export const makeThemeLink = (themeName) => {
return `${SERVER}/getTheme?theme=${themeName}`;
};
4 changes: 4 additions & 0 deletions greenscoutjs/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@ export {
submitMatchform,
logoutUser,
getLeaderboard,
getThemeList,
getCurrentTheme,
setTheme,
makeThemeLink,
} from "@api";
12 changes: 12 additions & 0 deletions greenscoutjs/src/api/mockApi.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,15 @@ export const isAdmin = (userId) => {
};

export const logoutUser = async () => {};

export const getThemeList = async () => {
return ["Light", "Dark"];
};

export const getCurrentTheme = async () => {
return "Light";
};

export const setTheme = async (themeName) => {};

export const makeThemeLink = (themeName) => {};
6 changes: 3 additions & 3 deletions greenscoutjs/src/components/Settings.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ function Settings() {
<NavComponent />
<div id="settingsContainer">
<h1 className="settingsh1">Settings</h1>
{/* <button className="settingButton" onClick={navTheme}>
{<button className="settingButton" onClick={navTheme}>
<div className="image themeImage"></div>
Themes (Work In Progress)
</button> */}
Themes
</button>}
<button className="settingButton" onClick={navDebug}>
<div className="image debugImage"></div>
Debug Info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
.collapsibleDropdown__inner > p {
margin-top: 0.3rem;
margin-bottom: 0.2rem;
color: var(--font-color-prompt-title);
font-family: Arial, Helvetica, sans-serif;
font-size: var(--font-size-small);
}

.collapsibleDropdown__inner .child.notesdiv {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,67 @@
import { useEffect, useState } from "react";
import "../../settings.css";
import { useNavigate } from 'react-router-dom';
import { getThemeList, getCurrentTheme, setTheme, makeThemeLink } from "../../../api";

function ThemeDrop({ value, onChange, name = "theme" }) {
const [themes, setThemes] = useState([]);
const [selectedTheme, setSelectedTheme] = useState(value ?? "");
const navigate = useNavigate();

useEffect(() => {
let active = true;

async function loadThemes() {
try {
const [themeList, currentTheme] = await Promise.all([
getThemeList(),
getCurrentTheme(),
]);

if (!active) return;

setThemes(Array.isArray(themeList) ? themeList : []);
setSelectedTheme(value ?? currentTheme ?? "");
} catch (err) {
console.error("Failed to load themes:", err);
}
}

loadThemes();

return () => {
active = false;
};
}, [value]);

const handleChange = async (e) => {
const nextTheme = e.target.value;
setSelectedTheme(nextTheme);

try {
await setTheme(nextTheme);
onChange?.(e);
let themeLink = document.getElementById("themeLink");
themeLink.href = makeThemeLink(nextTheme);
} catch (err) {
console.error("Failed to set theme:", err);
}
};

function ThemeDrop({ value, onChange, name }) {
return (
<div className="themechild">
<p id="themedtext">Theme Palette</p>
<select id="themedropdown" name={name} value={value} onChange={onChange}>
<option>Light</option>
<option>Dark</option>
<select
id="themedropdown"
name={name}
value={selectedTheme}
onChange={handleChange}
>
{themes.map((theme) => (
<option key={theme} value={theme}>
{theme}
</option>
))}
</select>
</div>
);
Expand Down
19 changes: 17 additions & 2 deletions greenscoutjs/src/components/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,29 @@
background-size: calc(var(--settings-element-height) * 0.8)
calc(var(--settings-element-height) * 0.8);
flex-shrink: 0;


-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;

-webkit-mask-position: center;
mask-position: center;

-webkit-mask-size: contain;
mask-size: contain;
background-image: none;

background-color: var(--font-color-prompt-title);
}

.image.themeImage {
background-image: url("../assets/palette-solid-full.svg");
-webkit-mask-image: url("../assets/palette-solid-full.svg");
mask-image: url("../assets/palette-solid-full.svg");
}

.image.debugImage {
background-image: url("../assets/bug-solid-full.svg");
mask-image: url("../assets/bug-solid-full.svg");
-webkit-mask-image: url("../assets/bug-solid-full.svg");
}

.settingButtonDebug {
Expand Down
17 changes: 14 additions & 3 deletions greenscoutjs/vite.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,21 @@ import { log } from "console";
export default defineConfig(({ mode }) => {
const env = loadEnv(mode, process.cwd());
// Backend URL is defined in .env.production
// const useBackend = env.VITE_BACKEND_URL !== "";
const useBackend = true;
const useBackend = env.VITE_BACKEND_URL !== "";

return {
plugins: [react()],
plugins: [
react(),
{
name: "inject-html",
transformIndexHtml(html) {
return html.replace(
"<THEMEANCHOR/>",
`<link href="${env.VITE_BACKEND_URL}/getTheme" rel="stylesheet" id="themeLink">`,
);
},
},
],
base: "/GreenScoutJS/",
resolve: {
alias: {
Expand All @@ -21,6 +31,7 @@ export default defineConfig(({ mode }) => {
),
},
},

server: {
// List of specific hostnames allowed
allowedHosts: ["engelki.taild523d0.ts.net"],
Expand Down