Lesss gooo claude

This commit is contained in:
2026-09-06 11:44:59 +02:00
parent 477db87363
commit 9362c9ac80
22 changed files with 3871 additions and 1 deletions
+101
View File
@@ -0,0 +1,101 @@
import { browser } from 'wxt/browser';
import { DEFAULT_LOCK_STATE, type LockScope, type LockState } from '@/shared/types';
import type { NexaMessage } from '@/shared/messaging';
const app = document.getElementById('app');
if (!app) throw new Error('Popup root element #app not found.');
app.innerHTML = `
<header>
<h1>Nexa</h1>
<p class="subtitle">Trading companion</p>
</header>
<section class="status" id="status"></section>
<section class="dev-controls">
<h2>Dev mock controls</h2>
<p class="hint">No backend connected yet — use this to simulate a lock signal.</p>
<label class="field">
<span>Locked</span>
<input type="checkbox" id="locked-toggle" />
</label>
<label class="field">
<span>Scope</span>
<select id="scope-select">
<option value="buy-only">buy-only</option>
<option value="full-block">full-block</option>
</select>
</label>
<label class="field">
<span>Reason</span>
<input type="text" id="reason-input" placeholder="e.g. -$62 loss crossed your $50 threshold" />
</label>
</section>
<a class="thresholds-link" id="thresholds-link" href="#" title="Threshold settings are not part of this milestone">
Adjust loss thresholds →
</a>
`;
const statusEl = document.getElementById('status') as HTMLElement;
const lockedToggle = document.getElementById('locked-toggle') as HTMLInputElement;
const scopeSelect = document.getElementById('scope-select') as HTMLSelectElement;
const reasonInput = document.getElementById('reason-input') as HTMLInputElement;
function escapeHtml(value: string): string {
const div = document.createElement('div');
div.textContent = value;
return div.innerHTML;
}
function renderStatus(state: LockState): void {
statusEl.innerHTML = state.locked
? `<div class="badge badge-locked">🔒 Locked</div>
<p class="reason">${escapeHtml(state.reason ?? 'No reason provided.')}</p>
<p class="scope">Scope: ${escapeHtml(state.scope)}</p>`
: `<div class="badge badge-unlocked">Unlocked</div>`;
}
function syncFormFromState(state: LockState): void {
lockedToggle.checked = state.locked;
scopeSelect.value = state.scope;
reasonInput.value = state.reason ?? '';
}
async function loadState(): Promise<LockState> {
const message: NexaMessage = { type: 'nexa:get-lock-state' };
const state = (await browser.runtime.sendMessage(message)) as LockState | undefined;
return state ?? DEFAULT_LOCK_STATE;
}
async function pushState(): Promise<void> {
const next: LockState = {
locked: lockedToggle.checked,
scope: scopeSelect.value as LockScope,
reason: reasonInput.value.trim() || undefined,
lockedAt: lockedToggle.checked ? Date.now() : undefined,
};
const message: NexaMessage = { type: 'nexa:set-lock-state', state: next };
await browser.runtime.sendMessage(message);
renderStatus(next);
}
for (const el of [lockedToggle, scopeSelect, reasonInput]) {
el.addEventListener('change', () => void pushState());
}
loadState().then((state) => {
syncFormFromState(state);
renderStatus(state);
});
browser.runtime.onMessage.addListener((message: NexaMessage) => {
if (message?.type === 'nexa:lock-state-changed') {
syncFormFromState(message.state);
renderStatus(message.state);
}
});