diff --git a/.env.development b/.env.development index 3b60c35..0a8dc40 100644 --- a/.env.development +++ b/.env.development @@ -1 +1 @@ -VITE_API_URL="http://localhost:8000" \ No newline at end of file +#VITE_API_URL="http://localhost:8000" \ No newline at end of file diff --git a/src/hooks/login.tsx b/src/hooks/login.tsx index e188f48..9269e63 100644 --- a/src/hooks/login.tsx +++ b/src/hooks/login.tsx @@ -16,6 +16,7 @@ export default function useLogin() { publicKey: session.publicKey, system, api: new LNVpsApi(ApiUrl, LoginState.getSigner()), + logout: () => LoginState.logout() } : undefined, [session, system]); } diff --git a/src/index.css b/src/index.css index 49d3b0d..db73177 100644 --- a/src/index.css +++ b/src/index.css @@ -4,6 +4,7 @@ :root { font-family: "Source Code Pro", monospace; + font-size: 15px; @apply bg-black text-white; } diff --git a/src/main.tsx b/src/main.tsx index da826d6..27b12aa 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -11,6 +11,8 @@ import VmPage from "./pages/vm.tsx"; import AccountPage from "./pages/account.tsx"; import SignUpPage from "./pages/sign-up.tsx"; import { TosPage } from "./pages/terms.tsx"; +import { StatusPage } from "./pages/status.tsx"; +import { AccountSettings } from "./pages/account-settings.tsx"; const system = new NostrSystem({ automaticOutboxModel: false, @@ -39,6 +41,10 @@ const router = createBrowserRouter([ path: "/account", element: , }, + { + path: "/account/settings", + element: + }, { path: "/order", element: , @@ -50,6 +56,10 @@ const router = createBrowserRouter([ { path: "/tos", element: , + }, + { + path: "/status", + element: , } ], }, diff --git a/src/pages/account-settings.tsx b/src/pages/account-settings.tsx new file mode 100644 index 0000000..31fb1f9 --- /dev/null +++ b/src/pages/account-settings.tsx @@ -0,0 +1,52 @@ +import useLogin from "../hooks/login"; +import { useEffect, useState } from "react"; +import { AccountDetail } from "../api"; +import { AsyncButton } from "../components/button"; +import { Icon } from "../components/icon"; + +export function AccountSettings() { + const login = useLogin(); + const [acc, setAcc] = useState(); + const [editEmail, setEditEmail] = useState(false); + + useEffect(() => { + login?.api.getAccount().then(setAcc); + }, [login]); + + function notifications() { + return <> +

Notification Settings

+
+ { + setAcc((s) => (s ? { ...s, contact_email: e.target.checked } : undefined)); + }} /> + Email + { + setAcc((s) => (s ? { ...s, contact_nip17: e.target.checked } : undefined)); + }} /> + Nostr DM +
+
+

Email

+ setAcc(s => (s ? { ...s, email: e.target.value } : undefined))} /> + {!editEmail && setEditEmail(true)} />} +
+
+ { + if (login?.api && acc) { + await login.api.updateAccount(acc); + const newAcc = await login.api.getAccount(); + setAcc(newAcc); + setEditEmail(false); + } + }}> + Save + +
+ + } + + return <> + {notifications()} + +} \ No newline at end of file diff --git a/src/pages/account.tsx b/src/pages/account.tsx index 177657e..d786dab 100644 --- a/src/pages/account.tsx +++ b/src/pages/account.tsx @@ -1,15 +1,14 @@ import { useEffect, useState } from "react"; -import { AccountDetail, LNVpsApi, VmInstance } from "../api"; +import { LNVpsApi, VmInstance } from "../api"; import useLogin from "../hooks/login"; import VpsInstanceRow from "../components/vps-instance"; import { hexToBech32 } from "@snort/shared"; -import { Icon } from "../components/icon"; import { AsyncButton } from "../components/button"; +import { useNavigate } from "react-router-dom"; export default function AccountPage() { const login = useLogin(); - const [acc, setAcc] = useState(); - const [editEmail, setEditEmail] = useState(false); + const navigate = useNavigate(); const [vms, setVms] = useState>([]); async function loadVms(api: LNVpsApi) { @@ -20,7 +19,6 @@ export default function AccountPage() { useEffect(() => { if (login?.api) { loadVms(login.api); - login.api.getAccount().then(setAcc); const t = setInterval(() => { loadVms(login.api); }, 5_000); @@ -28,38 +26,6 @@ export default function AccountPage() { } }, [login]); - function notifications() { - return <> -

Notification Settings

-
- { - setAcc((s) => (s ? { ...s, contact_email: e.target.checked } : undefined)); - }} /> - Email - { - setAcc((s) => (s ? { ...s, contact_nip17: e.target.checked } : undefined)); - }} /> - Nostr DM -
-
-

Email

- setAcc(s => (s ? { ...s, email: e.target.value } : undefined))} /> - {!editEmail && setEditEmail(true)} />} -
-
- { - if (login?.api && acc) { - await login.api.updateAccount(acc); - const newAcc = await login.api.getAccount(); - setAcc(newAcc); - setEditEmail(false); - } - }}> - Save - -
- - } const npub = hexToBech32("npub", login?.publicKey); const subjectLine = `[${npub}] Account Query`; @@ -67,7 +33,17 @@ export default function AccountPage() {
Your Public Key:
{npub}
- {notifications()} +
+ navigate("settings")}> + Settings + + { + login?.logout(); + navigate("/") + }}> + Logout + +

My Resources

Something doesnt look right?
diff --git a/src/pages/home.tsx b/src/pages/home.tsx index 03c33ed..eec3d1e 100644 --- a/src/pages/home.tsx +++ b/src/pages/home.tsx @@ -1,6 +1,5 @@ import { useState, useEffect } from "react"; import { VmTemplate, LNVpsApi } from "../api"; -import Profile from "../components/profile"; import VpsCard from "../components/vps-card"; import { ApiUrl, NostrProfile } from "../const"; import { Link } from "react-router-dom"; @@ -15,31 +14,39 @@ export default function HomePage() { return ( <> -

VPS Offers

-
+
+
VPS Offers
+
+ Virtual Private Server hosting with flexible plans, high uptime, and dedicated support, tailored to your needs. +
{offers.map((a) => ( ))}
- + All VPS come with 1x IPv4 and 1x IPv6 address and unmetered traffic
- - -
- - Speedtest - - {" | "} PGP {" | "} - Status + Status {" | "} Terms + {" | "} + + Nostr + + {" | "} + + Git + + {" | "} + + Speedtest +
LNVPS is a trading name of Apex Strata Ltd, a company registered in Ireland. diff --git a/src/pages/layout.tsx b/src/pages/layout.tsx index 1f70c73..75c6a64 100644 --- a/src/pages/layout.tsx +++ b/src/pages/layout.tsx @@ -5,7 +5,7 @@ export default function Layout() { return (
- LNVPS + LNVPS
diff --git a/src/pages/status.tsx b/src/pages/status.tsx new file mode 100644 index 0000000..aadedd2 --- /dev/null +++ b/src/pages/status.tsx @@ -0,0 +1,49 @@ + +import Markdown from "../components/markdown"; +import Status from "../status.json"; + +export function StatusPage() { + const totalDowntime = Status.events.reduce((acc, v) => { + if (v.end_time) { + const end = new Date(v.end_time); + const start = new Date(v.start_time); + const duration = end.getTime() - start.getTime(); + acc += duration; + } + return acc; + }, 0); + const birth = new Date(Status.birth); + const now = new Date(); + const age = now.getTime() - birth.getTime(); + const uptime = 1 - (totalDowntime / age); + + function formatDuration(n: number) { + if (n > 3600) { + return `${(n / 3600).toFixed(0)}h ${((n % 3600) / 60).toFixed(0)}m`; + } else if (n > 60) { + return `${(n % 60).toFixed(0)}m`; + } else { + return `${n.toFixed(0)}s`; + } + } + + return
+
Uptime: {(100 * uptime).toFixed(5)}%
+ +
Incidents:
+ {Status.events.map(e => { + const end = e.end_time ? new Date(e.end_time) : undefined; + const start = new Date(e.start_time); + const duration = end ? end.getTime() - start.getTime() : undefined; + + return
+
+
{e.title}
+
{new Date(e.start_time).toLocaleString()}
+
+ {duration &&
Duration: {formatDuration(duration / 1000)}
} + +
+ })} +
+} \ No newline at end of file diff --git a/src/pages/terms.tsx b/src/pages/terms.tsx index a2ea219..de1fee5 100644 --- a/src/pages/terms.tsx +++ b/src/pages/terms.tsx @@ -1,5 +1,5 @@ import Markdown from "../components/markdown"; -import TOS from "../../tos.md?raw"; +import TOS from "../tos.md?raw"; export function TosPage() { return diff --git a/src/status.json b/src/status.json new file mode 100644 index 0000000..af1ba8e --- /dev/null +++ b/src/status.json @@ -0,0 +1,11 @@ +{ + "birth": "2024-06-05T00:00:00Z", + "events":[ + { + "start_time": "2025-02-10T05:00:00Z", + "end_time": "2025-02-10T10:08:00Z", + "title": "VPS outage", + "description": "Primary disk full, causing system to halt" + } + ] +} \ No newline at end of file diff --git a/tos.md b/src/tos.md similarity index 100% rename from tos.md rename to src/tos.md