Create base webui

This commit is contained in:
Mathias Wagner
2025-09-09 12:00:12 +02:00
parent 439578434e
commit 0eb7e9d4ca
13 changed files with 741 additions and 16 deletions

View File

@@ -1,10 +1,18 @@
import { createBrowserRouter, Navigate, RouterProvider } from "react-router-dom";
import "@/common/styles/main.sass";
import Root from "@/common/layouts/Root.jsx";
const App = () => {
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
children: [
{ path: "/", element: <Navigate to="/servers" /> },
],
},
]);
return (
<>
<h1>vite init</h1>
</>
)
}
return <RouterProvider router={router}/>;
};
export default App;

View File

@@ -0,0 +1,68 @@
import { createContext, useEffect, useState } from "react";
import { getRequest, postRequest } from "@/common/utils/RequestUtil.js";
import Login from "@/pages/Login/index.js";
export const UserContext = createContext({});
export const UserProvider = ({ children }) => {
const [sessionToken, setSessionToken] = useState(localStorage.getItem("sessionToken"));
const [firstTimeSetup, setFirstTimeSetup] = useState(false);
const [user, setUser] = useState(null);
const updateSessionToken = (sessionToken) => {
setSessionToken(sessionToken);
localStorage.setItem("sessionToken", sessionToken);
login();
};
const checkFirstTimeSetup = async () => {
try {
const response = await getRequest("setup/status");
setFirstTimeSetup(response?.first_user_exists);
} catch (error) {
console.error(error);
}
};
const login = async () => {
try {
const userObj = await getRequest("accounts/me");
setUser(userObj);
} catch (error) {
if (error.message === "Unauthorized") {
setSessionToken(null);
localStorage.removeItem("sessionToken");
}
}
};
const logout = async () => {
await postRequest("auth/logout", { token: sessionToken });
window.location.reload();
};
useEffect(() => {
const searchParams = new URLSearchParams(location.search);
const tokenFromUrl = searchParams.get('token');
const error = searchParams.get('error');
if (tokenFromUrl) {
updateSessionToken(tokenFromUrl);
} else if (error) {
console.log(error)
}
}, [location]);
useEffect(() => {
sessionToken ? login() : checkFirstTimeSetup();
}, []);
return (
<UserContext.Provider value={{ updateSessionToken, user, sessionToken, firstTimeSetup, login, logout }}>
{user == null && <Login />}
{user !== null && children}
</UserContext.Provider>
);
};

View File

@@ -0,0 +1,7 @@
export default () => {
return (
<>
Root
</>
)
}

View File

View File

@@ -0,0 +1,48 @@
export const request = async (url, method, body, headers) => {
url = url.startsWith("/") ? url.substring(1) : url;
const response = await fetch(`/api/${url}`, {
method: method,
headers: {...headers, "Content-Type": "application/json"},
body: JSON.stringify(body)
});
if (response.status === 401) throw new Error("Unauthorized");
const rawData = await response.text();
const data = rawData ? JSON.parse(rawData) : rawData.toString();
if (data.code >= 300) throw data;
if (!response.ok) throw data;
return data;
}
const getToken = () => {
return localStorage.getItem("sessionToken");
}
export const sessionRequest = (url, method, token, body) => {
return request(url, method, body, {"Authorization": `Bearer ${token}`});
}
export const getRequest = (url) => {
return sessionRequest(url, "GET", getToken());
}
export const postRequest = (url, body) => {
return sessionRequest(url, "POST", getToken(), body);
}
export const putRequest = (url, body) => {
return sessionRequest(url, "PUT", getToken(), body);
}
export const deleteRequest = (url) => {
return sessionRequest(url, "DELETE", getToken());
}
export const patchRequest = (url, body) => {
return sessionRequest(url, "PATCH", getToken(), body);
}

View File

@@ -1,9 +1,12 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import {UserProvider} from "@/common/contexts/UserContext.jsx";
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
<UserProvider>
<App />
</UserProvider>
</StrictMode>,
)

View File

@@ -0,0 +1,6 @@
import "./styles.sass";
export const Login = () => {
return (
<div>Login Page</div>
)
}

View File

@@ -0,0 +1 @@
export {Login as default} from "./Login";

View File