feat: initial commit

This commit is contained in:
Iain Learmonth 2026-01-08 16:19:27 +00:00
commit 98355eceb5
18 changed files with 5416 additions and 0 deletions

19
app/app.css Normal file
View file

@ -0,0 +1,19 @@
html,
body {
margin: 0;
padding: 0;
}
.logo {
margin: 0;
padding: 5px;
color: white;
display: flex;
align-items: center;
font-size: large;
cursor: pointer;
img {
width: 48px;
padding: 5px 10px 5px 5px;
}
}

77
app/root.tsx Normal file
View file

@ -0,0 +1,77 @@
import {
isRouteErrorResponse,
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "react-router";
import { ConfigProvider } from 'antd';
import type { Route } from "./+types/root";
import "./app.css";
export function Layout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
export default function App() {
return <ConfigProvider
theme={{
token: {
// Seed Token
colorPrimary: "#00b353",
borderRadius: 2,
// Alias Token
// colorBgContainer: '#f6ffed',
},
}}
>
<Outlet />
</ConfigProvider>
}
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
let message = "Oops!";
let details = "An unexpected error occurred.";
let stack: string | undefined;
if (isRouteErrorResponse(error)) {
message = error.status === 404 ? "404" : "Error";
details =
error.status === 404
? "The requested page could not be found."
: error.statusText || details;
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message;
stack = error.stack;
}
return (
<>
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full p-4 overflow-x-auto">
<code>{stack}</code>
</pre>
)}
</>
);
}

12
app/routes.ts Normal file
View file

@ -0,0 +1,12 @@
import {type RouteConfig, index, layout, route} from "@react-router/dev/routes";
export default [
layout("routes/base_layout.tsx",
[
index("routes/home.tsx"),
route("proxy", "routes/proxy.tsx", [
index("routes/proxy/overview.tsx"),
route("origins", "routes/proxy/origins.tsx"),
])
]),
] satisfies RouteConfig;

View file

@ -0,0 +1,74 @@
import React from 'react';
import {CloudServerOutlined, DashboardOutlined, GlobalOutlined, HomeOutlined} from '@ant-design/icons';
import {Layout, Menu} from 'antd';
import {Outlet, useNavigate} from "react-router";
const {Content, Footer, Sider} = Layout;
const items = [{
key: "home", icon: React.createElement(HomeOutlined), label: "Home", "data-navigate": "/",
}, {
key: "proxy", icon: React.createElement(CloudServerOutlined), label: "Smart Proxy", children: [{
key: "proxy/overview",
icon: React.createElement(DashboardOutlined),
label: "Overview",
"data-navigate": "/proxy",
}, {
key: "proxy/origins",
icon: React.createElement(GlobalOutlined),
label: "Web Origins",
"data-navigate": "/proxy/origins",
}]
}];
export default function BaseLayout() {
const navigate = useNavigate();
// @ts-ignore TODO
const addOnClick = (items) => {
// @ts-ignore TODO
return items.map((item) => {
return item ? {
...item,
children: item.children ? addOnClick(item.children) : null,
onClick: item["data-navigate"] ? () => {
navigate(item["data-navigate"]);
} : undefined
} : null;
})
};
const menuItems = addOnClick(items);
return (<Layout>
<Sider
breakpoint="lg"
collapsedWidth="0"
onBreakpoint={(broken) => {
console.log(broken);
}}
onCollapse={(collapsed, type) => {
console.log(collapsed, type);
}}
style={{height: "100vh"}}
>
<h1 className="logo" onClick={() => navigate("/")}>
<img src="https://jasima.app/img/logo.png" alt=""/>
jasima.app
</h1>
<Menu theme="dark" mode="inline" defaultSelectedKeys={['a']} items={menuItems}/>
</Sider>
<Layout>
<Content style={{margin: '24px 16px 0'}}>
<div
style={{
padding: 24, minHeight: 360, background: "white",
}}
>
<Outlet/>
</div>
</Content>
<Footer style={{textAlign: 'center'}}>
Copyright © 2021-{new Date().getFullYear()} SR2 Communications Limited.
</Footer>
</Layout>
</Layout>)
}

7
app/routes/home.tsx Normal file
View file

@ -0,0 +1,7 @@
import {Typography} from "antd";
const {Paragraph} = Typography;
export default function Home() {
return <Paragraph>hi</Paragraph>;
}

21
app/routes/proxy.tsx Normal file
View file

@ -0,0 +1,21 @@
import type { Route } from "../+types/root";
import {CloudServerOutlined} from "@ant-design/icons";
import {Breadcrumb, Typography} from "antd";
import {Outlet} from "react-router";
const { Title } = Typography;
export function meta({}: Route.MetaArgs) {
return [
{ title: "Smart Proxy Administration" },
{ name: "description", content: "Hi!" },
];
}
export default function Proxy() {
return <>
<Title><CloudServerOutlined /> Smart Proxy</Title>
<Breadcrumb items={[{title: "Smart Proxy", href: "/proxy"}]} />
<Outlet />
</>;
}

View file

@ -0,0 +1,4 @@
export default function Origins() {
return "hello origins";
}

View file

@ -0,0 +1,7 @@
import {Typography} from "antd";
const {Paragraph} = Typography;
export default function Overview() {
return <Paragraph>hi</Paragraph>;
}