Add OpenAI-compatible AI investment advisor to benefit calculator

- server.js: add /api/calculate endpoint using openai SDK with configurable
  AI_API_URL, AI_API_KEY, AI_MODEL, AI_DEBUG env vars (works with any
  OpenAI-compatible provider: NVIDIA NIM, Together AI, Groq, Ollama, etc.)
- app.js: make calculator submit handler async; call /api/calculate with
  graceful fallback to client-side generated text if AI is unavailable
- package.json: add openai and dotenv dependencies
- AI_SETUP.md: rewrite to document new unified env var config with provider examples

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 10:05:36 -04:00
parent c95fd7d424
commit bf70efc0d7
5 changed files with 1423 additions and 156 deletions

19
app.js
View File

@@ -52,7 +52,7 @@
close();
});
submitBtn?.addEventListener('click', () => {
submitBtn?.addEventListener('click', async () => {
const homesites = parseFloat(document.getElementById('calcHomesites').value) || 0;
const propertyType = document.getElementById('calcPropertyType').value;
const annualIncome = parseFloat(document.getElementById('calcAnnualIncome').value) || 0;
@@ -116,7 +116,22 @@
ai += `This would represent entirely new interest income for your community at no additional risk.`;
}
document.getElementById('calcAiText').textContent = ai;
// ── AI recommendation — call server; fall back to client-side text ──
try {
const aiRes = await fetch('/api/calculate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ homesites, propertyType, annualIncome, paymentFreq, reserveFunds, interest2025 }),
});
if (aiRes.ok) {
const { recommendation } = await aiRes.json();
document.getElementById('calcAiText').textContent = recommendation;
} else {
document.getElementById('calcAiText').textContent = ai;
}
} catch (_) {
document.getElementById('calcAiText').textContent = ai;
}
// ── Animate the main number ──
animateValue(document.getElementById('resultAmount'), 0, totalPotential);