Last Updated: January 21, 2025
Project Status: Production Ready
Live Demo: GitHub Pages
cd python-forms
python3 regenerate_complete_form.py
This creates a production-ready medical screening form at surveys/weightloss/GLP1-screener-live.html
.
<!-- Copy the entire HTML content from the generated file -->
<!-- Paste into your GHL custom HTML widget or any website -->
This is a complete medical form generation system for GHL (GoHighLevel) white-label healthcare businesses. The system generates dynamic, responsive medical screening forms from JSON data with advanced conditional logic, real-time BMI calculation, and comprehensive API integration. Itβs designed specifically for telemedicine patient screening and integrates with n8n webhooks for data processing.
ltGlobalWidgets/
βββ README.md # This file - Main documentation
βββ python-forms/ # Core form generation system
β βββ enhanced_form_generator.py # Main form generation engine
β βββ form_data_loader.py # JSON data parser
β βββ regenerate_complete_form.py # Form generation script
β βββ surveys/all-forms/ # Shared form sections
β βββ components/ # Universal form components
βββ surveys/ # Generated forms and form data
β βββ weightloss/GLP1-screener-live.html # Production form
β βββ weightloss/GLP1-screener.json # Form data
β βββ hormone/Sermorelin-screener.json # Hormone form data
β βββ antiaging/NAD-screener.json # Anti-aging form data
βββ docs/ # Documentation and assets
β βββ api/ # API documentation
β βββ brand/ # Brand assets and CSS
β βββ widgets/ # Widget dashboard docs
βββ widget-dashboard.html # Widget management interface
βββ forms-dashboard.html # Forms management & embed code library
βββ api-dashboard.html # API integration dashboard
βββ archive-ignore/ # Outdated files and old systems
enhanced_form_generator.py
)Purpose: Main form generation engine Key Features:
Critical Methods:
generate_notion_form()
: Main form generation entry pointgenerate_all_sections()
: Creates all form sectionsgenerate_form_javascript()
: Creates interactive JavaScriptgenerate_height_weight_group()
: Special 3-column layout with BMI displayform_data_loader.py
)Purpose: Intelligent JSON parser and data combiner Key Features:
surveys/all-forms/
directory/surveys/{category}/
Critical Methods:
generate_complete_form_data()
: Combines all data sourcesload_general_sections()
: Loads shared form sectionsload_form_assessment()
: Loads form-specific questions_convert_questions()
: Converts Notion format to internal formatPurpose: Dynamic question visibility based on user answers Implementation: JavaScript functions within generated forms
Available Conditions:
always
: Question always visibleif_gender_female
: Shows for female patients (pregnancy questions)if_allergies_yes
: Shows when allergies are indicatedif_other_glp1s_yes
: Shows for patients taking other GLP-1 medicationsif_tobacco_yes
/ if_tobacco_use_yes
: Shows tobacco follow-up questionsJSON Data Sources β Form Data Loader β Enhanced Form Generator β HTML Form
β β β β
surveys/all-forms/ Combines sections Generates UI User fills form
surveys/{category}/ Sorts questions Adds JavaScript JavaScript validates
Creates IDs Applies styling Sends to webhook
Webhook Endpoint: https://locumtele.app.n8n.cloud/webhook/patient-screener
Data Structure Sent:
{
"contact": {
"name": "Patient Name",
"email": "patient@email.com",
"phone": "(555) 123-4567",
"address": "123 Main St",
"address2": "Apt 1",
"city": "City",
"state": "CA",
"postalCode": "12345",
"type": "patient"
},
"patient": {
"rxRequested": "GLP1",
"height": "5'10\"",
"weight": "180",
"BMI": "25.8"
},
"form": {
"formType": "screener",
"category": "Weightloss",
"screener": "GLP1",
"timestamp": "2025-01-21T...",
"formVersion": "1.0",
"answers": {
"What is your exercise level?": "moderate",
"Do you have any allergies?": "no",
"Do you currently use tobacco or vape?": "no"
},
"consultType": "async"
},
"clinic": {
"name": "",
"id": "",
"type": "healthcare"
}
}
property_order
field(555) 123-4567
surveys/all-forms/
or surveys/{category}/
enhanced_form_generator.py
for UI/logic changespython3 regenerate_complete_form.py
surveys/weightloss/GLP1-screener-live.html
in browsersurveys/all-forms/
and surveys/{category}/
filesenhanced_form_generator.py
form_data_loader.py
regenerate_complete_form.py
forms-dashboard.html
- Live embed code librarywidget-dashboard.html
- Internal management interfaceapi-dashboard.html
- API integration dashboardThe system uses string matching in JavaScript to implement conditional logic:
// Example: Tobacco follow-up
if (condition === 'if_tobacco_yes' || condition === 'if_tobacco_use_yes') {
const tobaccoInputs = document.querySelectorAll('input[type="radio"][value="yes"]:checked');
for (let input of tobaccoInputs) {
const questionText = input.closest('.question-container').querySelector('label[class*="question-label"]')?.textContent;
if (questionText && (questionText.toLowerCase().includes('tobacco') || questionText.toLowerCase().includes('vape'))) {
shouldShow = true;
break;
}
}
}
BMI is calculated in real-time and displayed in the Patient Profile section. Disqualification logic is form-specific:
// BMI calculation
function calculateBMI() {
const feet = parseInt(feetInput.value) || 0;
const inches = parseInt(inchesInput.value) || 0;
const weight = parseFloat(weightInput.value) || 0;
if (feet > 0 && weight > 0) {
const totalInches = (feet * 12) + inches;
const heightInMeters = totalInches * 0.0254;
const weightInKg = weight * 0.453592;
const bmi = weightInKg / (heightInMeters * heightInMeters);
// Display BMI
bmiValueElement.textContent = bmi.toFixed(1);
// Check disqualification (only for GLP1 forms)
if (category === 'Weightloss' && form_name === 'GLP1' && bmi < 25) {
// Show disqualification message
}
}
}
The webhook data building function dynamically finds form inputs and structures data:
// Build comprehensive form answers object with question text as keys
const formAnswers = {};
const contactFields = ['name', 'email', 'phone', 'address', 'city', 'state', 'postal'];
const allInputs = document.querySelectorAll('input, select, textarea');
allInputs.forEach(input => {
if (input.name && input.value) {
// Get question text
const questionWrapper = input.closest('.question-wrapper');
let questionText = questionWrapper?.querySelector('label')?.textContent?.trim() || input.name;
// Remove asterisk from required fields
questionText = questionText.replace('*', '').trim();
// Skip contact info fields - they're already in contact section
const isContactField = contactFields.some(field =>
questionText.toLowerCase().includes(field) ||
(field === 'name' && questionText.toLowerCase().includes('full name'))
);
if (!isContactField) {
// Add to answers object
formAnswers[questionText] = input.value;
}
}
});
Certain states only support synchronous consultations:
const syncOnlyStates = ['AL', 'AK', 'AR', 'ID', 'IA', 'KS', 'KY', 'LA', 'ME', 'MS', 'MO', 'MT', 'NE', 'NV', 'NH', 'NM', 'ND', 'OK', 'SC', 'SD', 'TN', 'UT', 'VT', 'WV', 'WY'];
if (syncOnlyStates.includes(selectedState)) {
finalConsultType = 'sync';
} else {
finalConsultType = consultType; // Use original consult type
}
The Forms Dashboard (forms-dashboard.html
) provides a comprehensive management interface for medical forms:
β οΈ Note: HTML generation and embed code creation buttons were removed due to JavaScript template literal syntax issues. HTML files must be generated manually using the Python scripts in the python-forms/
directory.
π§ JavaScript Issue: Template literals (backticks with ${}
) cause severe syntax errors when used within HTML content. Always use string concatenation ('string' + variable + 'string'
) instead of template literals when building HTML content or complex strings within HTML files.
cd python-forms && python3 regenerate_complete_form.py
surveys/weightloss/GLP1-screener-live.html
https://locumtele.app.n8n.cloud/webhook/patient-screener
forms-dashboard.html
# Navigate to project
cd /Users/tatyanagomez/Projects/ltGlobalWidgets/python-forms/
# Generate latest form
python3 regenerate_complete_form.py
# Open for testing
open surveys/weightloss/GLP1-screener-live.html
# Monitor network tab in browser dev tools to verify API calls
const response = await fetch('https://locumtele.app.n8n.cloud/webhook/patient-screener', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data)
});
const storageKey = `medicalForm_${form_name}_${category}`;
// Example: "medicalForm_GLP1_Weightloss"
// Only applies to GLP1 Weightloss forms with BMI < 25
if (category === 'Weightloss' && form_name === 'GLP1' && bmi < 25) {
// Show disqualification
}
/* Main theme colors */
:root {
--primary-color: #333;
--secondary-color: #555;
--accent-color: #e74c3c;
--background-gradient: linear-gradient(135deg, #fff 0%, #fef7f7 100%);
}
Issue: Radio buttons showing as selected on page load Solution: Clear localStorage for the form
localStorage.removeItem('medicalForm_GLP1_Weightloss');
Issue: Phone field accepting letters or not validating
Solution: Check formatPhoneInput()
function and validation logic
Issue: Follow-up questions not appearing Solution:
property_show_condition
in JSON datacheckQuestionVisibility()
functionIssue: Webhook not receiving expected data Solution:
buildWebhookData()
functionIssue: BMI not calculating or displaying Solution:
calculateBMI()
is called on input changes/Users/tatyanagomez/Projects/ltGlobalWidgets/python-forms/README-Python-Form-Generator.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/python-forms/README-Quick-Start-Guide.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/python-forms/README-Integration-Guide.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/python-forms/README-Conditional-Logic-Reference.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/docs/widgets/README-Forms-Dashboard.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/docs/brand/README-CSS-Framework.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/docs/api/README-Patient-Screening-API.md
/Users/tatyanagomez/Projects/ltGlobalWidgets/
python-forms/README.md
for detailed instructionsdocs/api/api-screeners.md
for API documentationdocs/widgets/README_widget.md
for dashboard usagepython-forms/README.md
docs/api/api-screeners.md
docs/widgets/README_widget.md
python-forms/SHOW_CONDITION_PATTERNS.md
git checkout -b feature/amazing-feature
)git commit -m 'Add amazing feature'
)git push origin feature/amazing-feature
)This project is part of the LocumTele GHL widget system for white-label healthcare businesses.
Document Status: β
Complete and Current
Next Review Date: [To be scheduled]
Version: 1.0 (January 21, 2025)
This document serves as the definitive reference for the LocumTele Medical Form System project. It should be updated whenever significant changes are made to the system architecture, features, or configuration.
Built with β€οΈ for healthcare providers