new-site/site/src/components/intake/steps/BundledServiceStep.astro
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
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>
2026-04-27 06:54:22 -05:00

98 lines
4.3 KiB
Text

---
// BundledServiceStep — local+toll bundle revenue allocation methodology.
// Only asked if the filer offers bundled local + toll service at a
// single price.
---
<div class="pw-step">
<h2>Bundled service allocation</h2>
<p class="pw-help">
If you offer bundled local + toll service at a single price, the FCC
requires you to allocate the bundle revenue between local (Line 404)
and toll (Line 414) based on your supporting books and records.
</p>
<label>
<input type="checkbox" id="pw-bs-has-bundle" />
We offer bundled local + toll service at a single price
</label>
<div id="pw-bs-details" hidden>
<label class="pw-field">Annual bundle revenue (USD)</label>
<input type="number" step="0.01" id="pw-bs-bundle-rev" class="pw-input" min="0" />
<div class="pw-row">
<div><label class="pw-field">% allocated to local (Line 404)</label>
<input type="number" step="0.1" min="0" max="100" id="pw-bs-local-pct" class="pw-input" /></div>
<div><label class="pw-field">% allocated to toll (Line 414)</label>
<input type="number" step="0.1" min="0" max="100" id="pw-bs-toll-pct" class="pw-input" /></div>
</div>
<label class="pw-field">Allocation methodology (required for audit defense)</label>
<textarea id="pw-bs-method" class="pw-input" rows="3"
placeholder="e.g., 'Based on our billing records, the toll component is priced at X/minute; with 700 average monthly minutes at a $50 bundle price, toll is ~$14 or 28% of the bundle.'"></textarea>
</div>
<div id="pw-bs-err" class="pw-err" hidden></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; }
.pw-err { color: #b91c1c; margin-top: 0.75rem; font-size: 0.9rem; }
</style>
<script>
const hasBundle = document.getElementById("pw-bs-has-bundle") as HTMLInputElement;
const details = document.getElementById("pw-bs-details") as HTMLElement;
const bundleRev = document.getElementById("pw-bs-bundle-rev") as HTMLInputElement;
const localPct = document.getElementById("pw-bs-local-pct") as HTMLInputElement;
const tollPct = document.getElementById("pw-bs-toll-pct") as HTMLInputElement;
const method = document.getElementById("pw-bs-method") as HTMLTextAreaElement;
const err = document.getElementById("pw-bs-err") as HTMLDivElement;
hasBundle.addEventListener("change", () => { details.hidden = !hasBundle.checked; });
window.addEventListener("pw:step-shown", (evt: any) => {
if (evt.detail.step !== "bundled_service") return;
const s = (window as any).PWIntake.get();
const b = s.intake_data?.bundled_service || {};
hasBundle.checked = !!b.has_bundle;
details.hidden = !hasBundle.checked;
bundleRev.value = b.bundle_revenue_usd ?? "";
localPct.value = b.local_allocation_pct ?? "";
tollPct.value = b.toll_allocation_pct ?? "";
method.value = b.methodology || "";
});
window.addEventListener("pw:step-next", (evt: any) => {
const PW = (window as any).PWIntake;
if (PW.steps[PW.get().step_index] !== "bundled_service") return;
if (hasBundle.checked) {
const lp = Number(localPct.value) || 0;
const tp = Number(tollPct.value) || 0;
if (Math.abs((lp + tp) - 100) > 0.01) {
err.hidden = false; err.textContent = `Local + Toll must sum to 100% (got ${(lp+tp).toFixed(2)}%).`;
evt.preventDefault(); return;
}
if (!method.value.trim()) {
err.hidden = false; err.textContent = "Allocation methodology is required — the FCC needs to see your basis for the split.";
evt.preventDefault(); return;
}
}
err.hidden = true;
PW.patchIntakeData({
bundled_service: hasBundle.checked ? {
has_bundle: true,
bundle_revenue_usd: Number(bundleRev.value) || 0,
local_allocation_pct: Number(localPct.value) || 0,
toll_allocation_pct: Number(tollPct.value) || 0,
methodology: method.value.trim(),
} : { has_bundle: false },
});
});
</script>