diff --git a/arma/client/addons/org/ui/_site/base.css b/arma/client/addons/org/ui/_site/base.css new file mode 100644 index 0000000..a05b977 --- /dev/null +++ b/arma/client/addons/org/ui/_site/base.css @@ -0,0 +1,175 @@ +:root { + --bg-app: #fdfcf8; + --bg-surface: #ffffff; + --bg-surface-hover: #f1f5f9; + --primary: #475569; + --primary-hover: #1e293b; + --text-main: #1f2937; + --text-muted: #64748b; + --text-inverse: #f8fafc; + --border: #e2e8f0; + --radius: 8px; + --shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); + --footer-bg: #1e293b; +} + +body { + font-family: + "Inter", + system-ui, + -apple-system, + sans-serif; + margin: 0; + padding: 0; + background: var(--bg-app); + color: var(--text-main); + line-height: 1.6; +} + +#app { + min-height: 100vh; +} + +main { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.container { + max-width: 1200px; + width: 100%; + margin: 0 auto; + padding: 2rem; + flex: 1; + display: flex; + flex-direction: column; + box-sizing: border-box; +} + +.header { + text-align: center; + margin-bottom: 3rem; + padding-bottom: 2rem; + border-bottom: 1px solid var(--border); + + h1 { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 0.5rem; + letter-spacing: -0.025em; + color: var(--primary-hover); + } + + p { + color: var(--text-muted); + font-size: 1.1rem; + } +} + +.card { + background: var(--bg-surface); + border: 1px solid var(--border); + border-radius: var(--radius); + padding: 2rem; + box-shadow: var(--shadow); + text-align: center; + + h2 { + margin-top: 0; + font-size: 1.8rem; + color: var(--primary-hover); + } +} + +button { + background: var(--primary); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: var(--radius); + cursor: pointer; + font-size: 1rem; + font-weight: 500; + transition: all 0.2s ease; + + &:hover { + background: var(--primary-hover); + transform: translateY(-1px); + box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1); + } + + &:disabled { + cursor: not-allowed; + opacity: 0.65; + transform: none; + box-shadow: none; + } + + & + & { + margin-left: 1rem; + } +} + +.footer { + margin-top: auto; + background: var(--footer-bg); + color: var(--text-inverse); + display: block; + + .wrapper { + max-width: 1200px; + width: 100%; + margin: 0 auto; + padding: 3rem 2rem; + box-sizing: border-box; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 4rem; + } + + h3 { + color: var(--text-inverse); + font-size: 0.85rem; + text-transform: uppercase; + letter-spacing: 0.1em; + font-weight: 700; + margin-bottom: 1.5rem; + border-bottom: 1px solid #475569; + padding-bottom: 0.5rem; + margin-right: 1rem; + } + + ul { + li { + color: #cbd5e1; + font-size: 0.95rem; + margin-bottom: 0.75rem; + cursor: pointer; + transition: color 0.2s; + + &:hover { + color: white; + } + } + } +} + +@media (max-width: 960px) { + .container { + padding: 1.5rem; + } + + .header { + margin-bottom: 2rem; + padding-bottom: 1.5rem; + + h1 { + font-size: 2rem; + } + } + + .footer .wrapper { + grid-template-columns: 1fr; + } +} diff --git a/arma/client/addons/org/ui/_site/bootstrap.js b/arma/client/addons/org/ui/_site/bootstrap.js new file mode 100644 index 0000000..663a0b3 --- /dev/null +++ b/arma/client/addons/org/ui/_site/bootstrap.js @@ -0,0 +1,6 @@ +/** + * Registry app bootstrap + */ + +const root = document.getElementById("app"); +window.RegistryApp.runtime.render(window.RegistryApp.components.App, root); diff --git a/arma/client/addons/org/ui/_site/components/createOrgForm.js b/arma/client/addons/org/ui/_site/components/createOrgForm.js new file mode 100644 index 0000000..2541103 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/createOrgForm.js @@ -0,0 +1,168 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + RegistryApp.componentFns.CreateOrgForm = function CreateOrgForm() { + const handleCreate = () => { + const data = { + orgName: String( + document.getElementById("org-create-name")?.value || "", + ), + type: String( + document.getElementById("org-create-type")?.value || "", + ), + }; + console.log("Org Registration:", data); + }; + + return h( + "div", + { className: "split-container" }, + h( + "div", + { className: "info-panel" }, + h("h2", null, "Registration Details"), + h( + "p", + null, + "Complete the form to add your organization to the Global Organization Registry.", + ), + h( + "ul", + { + style: { + textAlign: "left", + marginTop: "1.5rem", + listStyleType: "none", + padding: 0, + }, + }, + h( + "li", + { style: { marginBottom: "0.5rem" } }, + "✅ Official Organization Designator", + ), + h( + "li", + { style: { marginBottom: "0.5rem" } }, + "✅ Secure Comms Channel", + ), + h( + "li", + { style: { marginBottom: "0.5rem" } }, + "✅ Deployment Roster Access", + ), + h( + "li", + { style: { marginBottom: "0.5rem" } }, + "✅ After-Action Report Tools", + ), + ), + h( + "div", + { + className: "price-tag", + style: { + marginTop: "2rem", + padding: "1rem", + background: "var(--bg-app)", + borderRadius: "var(--radius)", + border: "1px solid var(--border)", + }, + }, + h( + "span", + { + style: { + display: "block", + fontSize: "0.9rem", + color: "var(--text-muted)", + }, + }, + "Registration Fee", + ), + h( + "span", + { + style: { + display: "block", + fontSize: "2rem", + fontWeight: "700", + color: "var(--primary)", + }, + }, + "$50,000", + ), + ), + ), + h( + "div", + { className: "form-panel card", style: { margin: 0 } }, + h("h2", null, "Organization Registration"), + h( + "div", + { className: "app-form" }, + h( + "div", + null, + h("label", null, "Organization Name"), + h("input", { + id: "org-create-name", + type: "text", + placeholder: "e.g. Task Force 141", + }), + ), + h( + "div", + null, + h("label", null, "Organization Type"), + h( + "select", + { id: "org-create-type" }, + h( + "option", + { value: "infantry" }, + "Infantry / Milsim", + ), + h("option", { value: "aviation" }, "Aviation Wing"), + h( + "option", + { value: "pmc" }, + "Private Military Company", + ), + h( + "option", + { value: "support" }, + "Logistics & Support", + ), + ), + ), + h( + "div", + { className: "form-actions" }, + h( + "button", + { + type: "button", + style: { width: "100%" }, + onClick: handleCreate, + }, + "Submit Registration", + ), + h( + "span", + { + className: "cancel-link", + onClick: () => store.setView("home"), + }, + "Cancel / Return to Main", + ), + ), + ), + ), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/footer.js b/arma/client/addons/org/ui/_site/components/footer.js new file mode 100644 index 0000000..76f53c4 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/footer.js @@ -0,0 +1,43 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + RegistryApp.componentFns.Footer = function Footer() { + return h( + "div", + { className: "footer" }, + h( + "div", + { className: "wrapper" }, + h( + "div", + null, + h("h3", null, "Registry Resources"), + h( + "ul", + { style: { listStyleType: "none", padding: 0 } }, + h("li", null, "Registration Guidelines"), + h("li", null, "Tax & Fee Schedule"), + h("li", null, "Legal Compliance"), + h("li", null, "Trademark Database"), + ), + ), + h( + "div", + null, + h("h3", null, "Bureau Support"), + h( + "ul", + { style: { listStyleType: "none", padding: 0 } }, + h("li", null, "Office: Sector 7 Admin Block"), + h("li", null, "Hours: 0800 - 1600 (GST)"), + h("li", null, "Helpdesk: 555-01-REGISTRY"), + h("li", null, "support@org-bureau.gov"), + ), + ), + ), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/forms.css b/arma/client/addons/org/ui/_site/components/forms.css new file mode 100644 index 0000000..8364d77 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/forms.css @@ -0,0 +1,72 @@ +.split-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + align-items: center; + width: 100%; +} + +.info-panel { + text-align: left; + padding: 1rem; +} + +.app-form { + display: flex; + flex-direction: column; + gap: 1rem; + text-align: left; + + label { + display: block; + margin-bottom: 0.5rem; + color: var(--text-muted); + font-weight: 500; + font-size: 0.9rem; + } + + input, + select { + width: 100%; + padding: 0.75rem; + border-radius: var(--radius); + border: 1px solid var(--border); + background: var(--bg-app); + color: var(--text-main); + font-family: inherit; + font-size: 1rem; + box-sizing: border-box; + transition: border-color 0.2s; + + &:focus { + outline: none; + border-color: var(--primary); + box-shadow: 0 0 0 2px rgb(59 130 246 / 0.1); + } + } +} + +.form-actions { + margin-top: 1rem; + display: flex; + flex-direction: column; + gap: 1rem; + align-items: center; +} + +.cancel-link { + font-size: 0.9rem; + color: var(--text-muted); + cursor: pointer; + text-decoration: underline; + + &:hover { + color: var(--primary); + } +} + +@media (max-width: 960px) { + .split-container { + grid-template-columns: 1fr; + } +} diff --git a/arma/client/addons/org/ui/_site/components/header.js b/arma/client/addons/org/ui/_site/components/header.js new file mode 100644 index 0000000..bfb199c --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/header.js @@ -0,0 +1,23 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + RegistryApp.componentFns.Header = function Header({ title }) { + return h( + "div", + { className: "header" }, + h( + "h1", + { + style: { cursor: "pointer" }, + onClick: () => store.setView("home"), + }, + title, + ), + h("p", null, "Organization Registration & Management Portal"), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/homeView.css b/arma/client/addons/org/ui/_site/components/homeView.css new file mode 100644 index 0000000..fb1fd66 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/homeView.css @@ -0,0 +1,12 @@ +.content { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 2rem; + margin-bottom: 2rem; +} + +@media (max-width: 960px) { + .content { + grid-template-columns: 1fr; + } +} diff --git a/arma/client/addons/org/ui/_site/components/homeView.js b/arma/client/addons/org/ui/_site/components/homeView.js new file mode 100644 index 0000000..5342229 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/homeView.js @@ -0,0 +1,57 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + RegistryApp.componentFns.HomeView = function HomeView() { + return h( + "div", + { className: "content" }, + h( + "div", + { className: "card" }, + h("h2", null, "Create Organization"), + h( + "p", + null, + "Establish your Task Force, PMC, or Milsim unit with the Global Organization Network. Receive your official unit designator and TO&E authorization instantly.", + ), + h( + "button", + { onClick: () => store.setView("create") }, + "Register", + ), + ), + h( + "div", + { className: "card" }, + h("h2", null, "Organization Portal"), + h( + "p", + null, + "Access your unit dashboard to modify rosters, adjust active deployments, and submit after-action reports through the secure field uplink.", + ), + h("button", { onClick: () => store.setView("login") }, "Login"), + ), + h( + "div", + { className: "card", style: { gridColumn: "span 2" } }, + h("h2", null, "Organization Portal Preview"), + h( + "p", + null, + "Review the refactor direction for a player organization portal with fleet, assets, treasury, reputation, roster management, and reserved space for future modules.", + ), + h( + "button", + { + onClick: () => store.setView("portal"), + }, + "Open Portal Preview", + ), + ), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/index.js b/arma/client/addons/org/ui/_site/components/index.js new file mode 100644 index 0000000..8b63cea --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/index.js @@ -0,0 +1,48 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.components = RegistryApp.components || {}; + + RegistryApp.components.App = function App() { + const Navbar = RegistryApp.componentFns.Navbar; + const Header = RegistryApp.componentFns.Header; + const HomeView = RegistryApp.componentFns.HomeView; + const LoginForm = RegistryApp.componentFns.LoginForm; + const CreateOrgForm = RegistryApp.componentFns.CreateOrgForm; + const Footer = RegistryApp.componentFns.Footer; + const PortalApp = + window.OrgPortal && window.OrgPortal.components + ? window.OrgPortal.components.App + : null; + + const view = store.getView(); + + if (view === "portal" && PortalApp) { + return h("div", null, Navbar(), PortalApp()); + } + + let mainContent; + if (view === "home") { + mainContent = HomeView(); + } else if (view === "login") { + mainContent = LoginForm(); + } else if (view === "create") { + mainContent = CreateOrgForm(); + } + + return h( + "main", + null, + Navbar(), + h( + "div", + { className: "container" }, + Header({ title: "Global Organization Network" }), + mainContent, + ), + Footer(), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/loginForm.js b/arma/client/addons/org/ui/_site/components/loginForm.js new file mode 100644 index 0000000..82e87a3 --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/loginForm.js @@ -0,0 +1,76 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + RegistryApp.componentFns.LoginForm = function LoginForm() { + const handleLogin = () => { + const data = { + email: String( + document.getElementById("org-login-email")?.value || "", + ), + password: String( + document.getElementById("org-login-password")?.value || "", + ), + }; + console.log("Login Attempt:", data); + store.setView("portal"); + }; + + return h( + "div", + { + className: "card", + style: { maxWidth: "400px", margin: "0 auto" }, + }, + h("h2", null, "Organization Login"), + h( + "div", + { className: "app-form" }, + h( + "div", + null, + h("label", null, "Email"), + h("input", { + id: "org-login-email", + type: "text", + placeholder: "admin@spearnet.mil", + }), + ), + h( + "div", + null, + h("label", null, "Password"), + h("input", { + id: "org-login-password", + type: "password", + placeholder: "********", + }), + ), + h( + "div", + { className: "form-actions" }, + h( + "button", + { + type: "button", + style: { width: "100%" }, + onClick: handleLogin, + }, + "Access Authenticator", + ), + h( + "span", + { + className: "cancel-link", + onClick: () => store.setView("home"), + }, + "Cancel / Return to Main", + ), + ), + ), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/components/navbar.css b/arma/client/addons/org/ui/_site/components/navbar.css new file mode 100644 index 0000000..9a6478e --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/navbar.css @@ -0,0 +1,79 @@ +.app-navbar { + background: var(--bg-surface); + border-bottom: 1px solid var(--border); + box-shadow: var(--shadow); +} + +.app-navbar-inner { + display: flex; + justify-content: space-between; + align-items: center; + max-width: 1200px; + width: 100%; + margin: 0 auto; + padding: 1rem 2rem; + box-sizing: border-box; +} + +.app-navbar-brand { + display: flex; + flex-direction: column; + gap: 0.125rem; +} + +.app-navbar-kicker { + font-size: 0.7rem; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--text-muted); + font-weight: 600; +} + +.app-navbar-title { + font-size: 1.25rem; + font-weight: 700; + color: var(--primary-hover); + letter-spacing: -0.025em; +} + +.app-navbar-actions { + display: flex; + align-items: center; + gap: 1.5rem; +} + +.app-navbar-view { + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--text-muted); + font-weight: 600; +} + +.app-close-btn { + background: transparent; + color: var(--text-muted); + border: 1px solid var(--border); + padding: 0.5rem 1rem; + font-size: 0.85rem; + + &:hover { + background: var(--bg-surface-hover); + color: var(--primary-hover); + border-color: var(--primary); + transform: none; + box-shadow: none; + } +} + +@media (max-width: 960px) { + .app-navbar-inner { + flex-direction: column; + align-items: flex-start; + padding: 1rem 1.5rem; + } + + .app-navbar-actions { + align-items: flex-start; + } +} diff --git a/arma/client/addons/org/ui/_site/components/navbar.js b/arma/client/addons/org/ui/_site/components/navbar.js new file mode 100644 index 0000000..53a7b5a --- /dev/null +++ b/arma/client/addons/org/ui/_site/components/navbar.js @@ -0,0 +1,70 @@ +(function () { + const RegistryApp = (window.RegistryApp = window.RegistryApp || {}); + const { h } = RegistryApp.runtime; + const store = RegistryApp.store; + + RegistryApp.componentFns = RegistryApp.componentFns || {}; + + function closeRegistry() { + if ( + typeof A3API !== "undefined" && + typeof A3API.SendAlert === "function" + ) { + A3API.SendAlert( + JSON.stringify({ + event: "org::close", + data: {}, + }), + ); + return; + } + + store.setView("home"); + } + + RegistryApp.componentFns.Navbar = function Navbar() { + const view = store.getView(); + const viewLabel = + view === "login" + ? "Organization Login" + : view === "create" + ? "Organization Registration" + : view === "portal" + ? "Organization Portal" + : "Entry Hub"; + const actionLabel = view === "portal" ? "Sign Out" : "Close"; + + return h( + "nav", + { className: "app-navbar" }, + h( + "div", + { className: "app-navbar-inner" }, + h( + "div", + { className: "app-navbar-brand" }, + h("span", { className: "app-navbar-kicker" }, "ORBIS"), + h( + "span", + { className: "app-navbar-title" }, + "Global Organization Network", + ), + ), + h( + "div", + { className: "app-navbar-actions" }, + h("span", { className: "app-navbar-view" }, viewLabel), + h( + "button", + { + type: "button", + className: "app-close-btn", + onClick: closeRegistry, + }, + actionLabel, + ), + ), + ), + ); + }; +})(); diff --git a/arma/client/addons/org/ui/_site/index.html b/arma/client/addons/org/ui/_site/index.html index cdb8685..94cdd9d 100644 --- a/arma/client/addons/org/ui/_site/index.html +++ b/arma/client/addons/org/ui/_site/index.html @@ -1,243 +1,109 @@ +
+ + +FACTION-001
-