forge/arma/ui/app.js
2026-02-13 19:10:23 -06:00

236 lines
8.9 KiB
JavaScript

/**
* Simple React-like Vanilla JS Implementation
*/
// --- 1. The "Library" Logic ---
// Helper to create DOM elements (like React.createElement)
function h(tag, props = {}, ...children) {
const el = document.createElement(tag);
// Handle props
if (props) {
Object.entries(props).forEach(([key, value]) => {
if (key.startsWith('on') && typeof value === 'function') {
el.addEventListener(key.substring(2).toLowerCase(), value);
} else if (key === 'className') {
el.className = value;
} else if (key === 'style' && typeof value === 'object') {
Object.assign(el.style, value);
} else {
el.setAttribute(key, value);
}
});
}
// Handle children
children.forEach(child => {
if (typeof child === 'string' || typeof child === 'number') {
el.appendChild(document.createTextNode(child));
} else if (child instanceof Node) {
el.appendChild(child);
} else if (Array.isArray(child)) {
child.forEach(c => el.appendChild(c));
}
});
return el;
}
// Simple Rendering Logic
let _rootContainer = null;
let _rootComponent = null;
function render(component, container) {
_rootContainer = container;
_rootComponent = component;
_render();
}
function _render() {
_rootContainer.innerHTML = ''; // Clear previous tree (simple re-render)
_rootContainer.appendChild(_rootComponent());
}
// Simple State Hook (Global for simplicity, or localized using closures)
// Note: In a real app this would be more complex to handle multiple components.
// For this demo, we'll re-render the whole app on state change.
const createSignal = (initialValue) => {
let _val = initialValue;
const getValue = () => _val;
const setValue = (newValue) => {
_val = typeof newValue === 'function' ? newValue(_val) : newValue;
_render(); // Trigger re-render
};
return [getValue, setValue];
};
// --- 2. The Application Components ---
// Global View State: 'home', 'login', 'create'
const [getView, setView] = createSignal('home');
// Header Component
function Header({ title }) {
return h('div', { className: 'header' },
h('h1', {
style: { cursor: 'pointer' },
onClick: () => setView('home')
}, title),
h('p', null, 'Organization Registration & Management Portal')
);
}
// Login Form Component
function LoginForm() {
const handleSubmit = (e) => {
e.preventDefault(); // Critical for strict sandbox
const formData = new FormData(e.target);
const data = Object.fromEntries(formData.entries());
console.log('Login Attempt:', data);
// TODO: Handle authentication logic here
};
return h('div', { className: 'card', style: { maxWidth: '400px', margin: '0 auto' } },
h('h2', null, 'Organization Login'),
h('form', { onSubmit: handleSubmit },
h('div', null,
h('label', null, 'Email'),
h('input', { name: 'email', type: 'text', placeholder: 'admin@spearnet.mil' })
),
h('div', null,
h('label', null, 'Password'),
h('input', { name: 'password', type: 'password', placeholder: '••••••••' })
),
h('div', { className: 'form-actions' },
h('button', { type: 'submit', style: { width: '100%' } }, 'Access Authenticator'),
h('span', {
className: 'cancel-link',
onClick: () => setView('home')
}, 'Cancel / Return to Main')
)
)
);
}
// Create Org Form Component
function CreateOrgForm() {
const handleSubmit = (e) => {
e.preventDefault(); // Critical for strict sandbox
const formData = new FormData(e.target);
const data = Object.fromEntries(formData.entries());
console.log('Org Registration:', data);
// TODO: Handle registration logic here
};
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('form', { onSubmit: handleSubmit },
h('div', null,
h('label', null, 'Organization Name'),
h('input', { name: 'orgName', type: 'text', placeholder: 'e.g. Task Force 141' })
),
h('div', null,
h('label', null, 'Organization Type'),
h('select', { name: '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: 'submit', style: { width: '100%' } }, 'Submit Registration'),
h('span', {
className: 'cancel-link',
onClick: () => setView('home')
}, 'Cancel / Return to Main')
)
)
)
);
}
// Home View Component
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: () => setView('create') }, 'Register')
),
h('div', { className: 'card' },
h('h2', null, 'Organization Dashboard'),
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: () => setView('login') }, 'Login')
)
);
}
// Footer Component (unchanged)
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')
)
)
)
);
}
// Main App Component
function App() {
const view = getView();
let mainContent;
if (view === 'home') {
mainContent = HomeView();
} else if (view === 'login') {
mainContent = LoginForm();
} else if (view === 'create') {
mainContent = CreateOrgForm();
}
return h('main', null,
h('div', { className: 'container' },
Header({ title: 'Global Organization Network' }),
mainContent
),
Footer()
);
}
// --- 3. Mount Application ---
const root = document.getElementById('app');
render(App, root);