Includes: API (Express/TypeScript), Astro site, Python workers, document generators, FCC compliance tools, Canada CRTC formation, Ansible infrastructure, and deployment scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
112 lines
4.8 KiB
Text
112 lines
4.8 KiB
Text
---
|
|
// WirelessStep — spectrum / MVNO host / subscriber counts / roaming.
|
|
// Inserted into the wizard when line_105_categories contains 'wireless'.
|
|
---
|
|
|
|
<div class="pw-step">
|
|
<h2>Wireless carrier details</h2>
|
|
<p class="pw-help">
|
|
Wireless-specific intake for Form 499-A Lines 309 / 409 / 410 (mobile
|
|
revenue to resellers, end-user mobile monthly, roaming + usage) and
|
|
for the wireless CPNI template.
|
|
</p>
|
|
|
|
<label class="pw-field">Infrastructure</label>
|
|
<select id="pw-wl-infra" class="pw-input">
|
|
<option value="facilities">Facilities-based (own spectrum / towers)</option>
|
|
<option value="mvno">MVNO (use another carrier's network)</option>
|
|
</select>
|
|
|
|
<div id="pw-wl-mvno-wrap" hidden>
|
|
<label class="pw-field">Host MNO</label>
|
|
<select id="pw-wl-host" class="pw-input">
|
|
<option value="">—</option>
|
|
<option value="T-Mobile">T-Mobile</option>
|
|
<option value="Verizon">Verizon</option>
|
|
<option value="AT&T">AT&T</option>
|
|
<option value="Dish">Dish / Boost</option>
|
|
<option value="US Cellular">US Cellular</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div id="pw-wl-fac-wrap">
|
|
<label class="pw-field">Spectrum bands (one per line)</label>
|
|
<textarea id="pw-wl-bands" class="pw-input" rows="3"
|
|
placeholder="e.g., Lower 700 MHz PCS 1900 CBRS 3.5 GHz"></textarea>
|
|
<label class="pw-field">Cell site count</label>
|
|
<input type="number" id="pw-wl-sites" class="pw-input" min="0" />
|
|
</div>
|
|
|
|
<div class="pw-row">
|
|
<div><label class="pw-field">Post-paid subscribers</label>
|
|
<input type="number" id="pw-wl-post" class="pw-input" min="0" /></div>
|
|
<div><label class="pw-field">Pre-paid subscribers</label>
|
|
<input type="number" id="pw-wl-pre" class="pw-input" min="0" /></div>
|
|
</div>
|
|
|
|
<div class="pw-row">
|
|
<div><label class="pw-field">Inbound roaming MOUs</label>
|
|
<input type="number" id="pw-wl-roam-mou" class="pw-input" min="0" /></div>
|
|
<div><label class="pw-field">Inbound roaming revenue (USD)</label>
|
|
<input type="number" step="0.01" id="pw-wl-roam-rev" class="pw-input" min="0" /></div>
|
|
</div>
|
|
</div>
|
|
|
|
<style>
|
|
.pw-step h2 { margin: 0 0 0.5rem; color: #1a2744; }
|
|
.pw-help { color: #64748b; font-size: 0.9rem; margin-bottom: 1rem; }
|
|
.pw-field { display: block; font-weight: 600; color: #1f2937; margin: 0.6rem 0 0.2rem; font-size: 0.88rem; }
|
|
.pw-input { width: 100%; padding: 0.5rem 0.7rem; border: 1px solid #cbd5e1; border-radius: 6px; font-size: 0.93rem; font-family: inherit; }
|
|
.pw-row { display: flex; gap: 1rem; flex-wrap: wrap; }
|
|
.pw-row > * { flex: 1 1 140px; }
|
|
</style>
|
|
|
|
<script>
|
|
const infra = document.getElementById("pw-wl-infra") as HTMLSelectElement;
|
|
const mvnoWrap = document.getElementById("pw-wl-mvno-wrap") as HTMLElement;
|
|
const facWrap = document.getElementById("pw-wl-fac-wrap") as HTMLElement;
|
|
const hostSel = document.getElementById("pw-wl-host") as HTMLSelectElement;
|
|
const bands = document.getElementById("pw-wl-bands") as HTMLTextAreaElement;
|
|
const sites = document.getElementById("pw-wl-sites") as HTMLInputElement;
|
|
const post = document.getElementById("pw-wl-post") as HTMLInputElement;
|
|
const pre = document.getElementById("pw-wl-pre") as HTMLInputElement;
|
|
const roamMou = document.getElementById("pw-wl-roam-mou") as HTMLInputElement;
|
|
const roamRev = document.getElementById("pw-wl-roam-rev") as HTMLInputElement;
|
|
|
|
function syncInfra() {
|
|
mvnoWrap.hidden = infra.value !== "mvno";
|
|
facWrap.hidden = infra.value === "mvno";
|
|
}
|
|
infra.addEventListener("change", syncInfra);
|
|
|
|
window.addEventListener("pw:step-shown", (evt: any) => {
|
|
if (evt.detail.step !== "wireless") return;
|
|
const s = (window as any).PWIntake.get();
|
|
const m = s.intake_data?.wireless_meta || {};
|
|
infra.value = m.infra_type || "facilities";
|
|
hostSel.value = m.host_mno || "";
|
|
bands.value = (m.spectrum_bands || []).join("\n");
|
|
sites.value = m.cell_site_count ?? "";
|
|
post.value = m.post_paid_subs ?? "";
|
|
pre.value = m.pre_paid_subs ?? "";
|
|
roamMou.value = m.roaming_mou ?? "";
|
|
roamRev.value = m.roaming_revenue_usd ?? "";
|
|
syncInfra();
|
|
});
|
|
|
|
window.addEventListener("pw:step-next", (evt: any) => {
|
|
const PW = (window as any).PWIntake;
|
|
if (PW.steps[PW.get().step_index] !== "wireless") return;
|
|
const meta: Record<string, any> = {
|
|
infra_type: infra.value,
|
|
host_mno: infra.value === "mvno" ? hostSel.value || null : null,
|
|
spectrum_bands: bands.value.split("\n").map((b) => b.trim()).filter(Boolean),
|
|
cell_site_count: Number(sites.value) || null,
|
|
post_paid_subs: Number(post.value) || 0,
|
|
pre_paid_subs: Number(pre.value) || 0,
|
|
roaming_mou: Number(roamMou.value) || 0,
|
|
roaming_revenue_usd: Number(roamRev.value) || 0,
|
|
};
|
|
PW.patchIntakeData({ wireless_meta: meta });
|
|
});
|
|
</script>
|