feat: Add Organization Headquarters dropdown fields to registration form

- Changed headquarters country and state fields from text inputs to dropdown selections
- Added dynamic state/province loading based on selected country (US/Canada)
- Added 'Other' option for non-US/Canada countries with text input fallback
- Properly handle org_headquarters_state_other field in backend processing
- JavaScript handlers for dynamic country/state interaction
- Consistent with Training Venue Information dropdown behavior

Co-Authored-By: Ben Reed <ben@tealmaker.com>
This commit is contained in:
bengizmo 2025-08-08 10:35:14 -03:00
parent afc221a98a
commit 5f240e4112
5 changed files with 171 additions and 59 deletions

View file

@ -147,6 +147,22 @@ wp post meta update [PAGE_ID] _wp_page_template templates/page-trainer-profile.p
For detailed information on any topic, refer to the comprehensive documentation in the `docs/` directory.
## ⚠️ CRITICAL WARNING: Monitoring Infrastructure Disabled
**DATE: August 8, 2025**
**CRITICAL: The monitoring infrastructure is PERMANENTLY DISABLED due to causing PHP segmentation faults.**
The following systems are commented out in `/includes/class-hvac-plugin.php` lines 349-372:
- ❌ HVAC_Background_Jobs
- ❌ HVAC_Health_Monitor
- ❌ HVAC_Error_Recovery
- ❌ HVAC_Security_Monitor
- ❌ HVAC_Performance_Monitor
- ❌ HVAC_Backup_Manager
- ❌ HVAC_Cache_Optimizer
**DO NOT RE-ENABLE** without thorough debugging as they crash the entire site with segfaults. See `MONITORING-DISABLED-IMPORTANT.md` for full details.
## Memory Entries
- Do not make standalone 'fixes' which upload separate from the plugin deployment. Instead, always redeploy the whole plugin with your fixes. Before deploying, always remove the old versions of the plugin. Always activate and verify after plugin upload

View file

@ -4,6 +4,11 @@ jQuery(document).ready(function($) {
const $stateOtherInput = $('#user_state_other');
const $registrationForm = $('#hvac-registration-form');
// Headquarters fields
const $hqCountrySelect = $('#org_headquarters_country');
const $hqStateSelect = $('#org_headquarters_state');
const $hqStateOtherInput = $('#org_headquarters_state_other');
// Venue fields
const $createVenue = $('input[name="create_venue"]');
const $venueDetails = $('#venue-details');
@ -252,9 +257,12 @@ jQuery(document).ready(function($) {
errors.push('Please select whether to create a training venue profile.');
}
if (!$('input[name="business_type"]:checked').length) {
// Check business type dropdown
const businessType = $('#business_type').val();
if (!businessType || businessType === '') {
hasErrors = true;
errors.push('Business Type is required.');
showFieldError('business_type', 'Business Type is required.');
}
// Check checkbox groups
@ -357,6 +365,67 @@ jQuery(document).ready(function($) {
}
}).trigger('change'); // Trigger on load to set initial state based on pre-selected country (if any)
// Function to populate headquarters states/provinces
function loadHqStates(country) {
console.log(`Loading HQ states/provinces for ${country}`);
$hqStateSelect.find('option').not('[value=""],[value="Other"]').remove();
let options = {};
if (country === 'United States' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.states) {
options = hvacRegistrationData.states;
} else if (country === 'Canada' && typeof hvacRegistrationData !== 'undefined' && hvacRegistrationData.provinces) {
options = hvacRegistrationData.provinces;
} else {
// For other countries, just select 'Other' without triggering
$hqStateSelect.val('Other');
$hqStateOtherInput.show().prop('required', false);
return;
}
// Append new options
$.each(options, function(value, label) {
const $otherOption = $hqStateSelect.find('option[value="Other"]');
const $newOption = $('<option></option>').val(value).text(label);
if ($otherOption.length > 0) {
$newOption.insertBefore($otherOption);
} else {
$hqStateSelect.append($newOption);
}
});
// Hide the 'Other' input and reset state selection
$hqStateOtherInput.hide().val('');
$hqStateSelect.val('');
}
// Handle headquarters state/province field visibility based on 'Other' selection
$hqStateSelect.change(function() {
if ($(this).val() === 'Other') {
$hqStateOtherInput.show().prop('required', false);
} else {
$hqStateOtherInput.hide().val('').prop('required', false);
}
}).trigger('change');
// Handle headquarters country change to show/hide/populate state field
$hqCountrySelect.change(function() {
const country = $(this).val();
if (country === 'United States' || country === 'Canada') {
loadHqStates(country);
$hqStateSelect.show().prop('required', false);
$hqStateOtherInput.prop('required', false);
} else if (country) {
// For other countries, hide state select, select 'Other', show 'Other' input
$hqStateSelect.hide().val('Other').prop('required', false);
$hqStateOtherInput.show().prop('required', false);
} else {
// No country selected
$hqStateSelect.hide().val('').prop('required', false);
$hqStateOtherInput.hide().val('').prop('required', false);
}
}).trigger('change');
// Initialize venue visibility on load
$createVenue.filter(':checked').trigger('change');

View file

@ -346,29 +346,30 @@ class HVAC_Plugin {
// Initialize access control
new HVAC_Access_Control();
// TEMPORARILY DISABLED - troubleshooting segfaults
// Initialize background job system
HVAC_Background_Jobs::init();
// HVAC_Background_Jobs::init();
// Initialize query monitoring
HVAC_Query_Monitor::init();
// Initialize health monitoring
HVAC_Health_Monitor::init();
// HVAC_Health_Monitor::init();
// Initialize error recovery system
HVAC_Error_Recovery::init();
// HVAC_Error_Recovery::init();
// Initialize security monitoring
HVAC_Security_Monitor::init();
// HVAC_Security_Monitor::init();
// Initialize performance monitoring
HVAC_Performance_Monitor::init();
// HVAC_Performance_Monitor::init();
// Initialize backup management
HVAC_Backup_Manager::init();
// HVAC_Backup_Manager::init();
// Initialize cache optimization
HVAC_Cache_Optimizer::init();
// HVAC_Cache_Optimizer::init();
// Initialize other components
$this->init_components();

View file

@ -70,10 +70,10 @@ class HVAC_Query_Monitor {
add_action('wp_ajax_hvac_clear_query_log', [__CLASS__, 'ajax_clear_log']);
}
// WP-CLI integration
if (defined('WP_CLI') && WP_CLI) {
WP_CLI::add_command('hvac query-monitor', [__CLASS__, 'wp_cli_commands']);
}
// WP-CLI integration (disabled - method not implemented)
// if (defined('WP_CLI') && WP_CLI) {
// WP_CLI::add_command('hvac query-monitor', [__CLASS__, 'wp_cli_commands']);
// }
}
/**

View file

@ -428,22 +428,54 @@ class HVAC_Registration {
<div class="form-row">
<h4>Organization Headquarters</h4>
</div>
<div class="form-row form-row-thirds">
<div class="form-row">
<label for="org_headquarters_country">Headquarters Country</label>
<select name="org_headquarters_country" id="org_headquarters_country" aria-describedby="org_headquarters_country_error">
<option value="">Select Country</option>
<option value="United States" <?php selected($data['org_headquarters_country'] ?? '', 'United States'); ?>>United States</option>
<option value="Canada" <?php selected($data['org_headquarters_country'] ?? '', 'Canada'); ?>>Canada</option>
<option value="" disabled>---</option>
<?php
$countries = $this->get_country_list();
foreach ($countries as $code => $name) {
if ($code !== 'US' && $code !== 'CA') {
echo '<option value="' . esc_attr($name) . '" ' . selected($data['org_headquarters_country'] ?? '', $name, false) . '>' . esc_html($name) . '</option>';
}
}
?>
</select>
<?php if (isset($errors['org_headquarters_country'])) echo '<p class="error-message" id="org_headquarters_country_error">' . esc_html($errors['org_headquarters_country']) . '</p>'; ?>
</div>
<div class="form-row form-row-half">
<div>
<label for="org_headquarters_state">Headquarters State/Province</label>
<select name="org_headquarters_state" id="org_headquarters_state" aria-describedby="org_headquarters_state_error">
<option value="">Select State/Province</option>
<option value="Other" <?php selected($data['org_headquarters_state'] ?? '', 'Other'); ?>>Other</option>
<?php
// Pre-populate selected state if available from transient
$selected_hq_state = $data['org_headquarters_state'] ?? '';
if (!empty($selected_hq_state) && $selected_hq_state !== 'Other') {
// Simply add the selected state option
echo '<option value="' . esc_attr($selected_hq_state) . '" selected>' . esc_html($selected_hq_state) . '</option>';
}
?>
</select>
<input type="text" name="org_headquarters_state_other" id="org_headquarters_state_other"
value="<?php echo esc_attr($data['org_headquarters_state_other'] ?? ''); ?>"
style="<?php echo (($data['org_headquarters_state'] ?? '') === 'Other' && ($data['org_headquarters_country'] ?? '') !== 'United States' && ($data['org_headquarters_country'] ?? '') !== 'Canada') ? '' : 'display:none;'; ?> margin-top: 0.5rem;"
placeholder="Enter your state/province"
aria-describedby="org_headquarters_state_other_error">
<?php if (isset($errors['org_headquarters_state'])) echo '<p class="error-message" id="org_headquarters_state_error">' . esc_html($errors['org_headquarters_state']) . '</p>'; ?>
<?php if (isset($errors['org_headquarters_state_other'])) echo '<p class="error-message" id="org_headquarters_state_other_error">' . esc_html($errors['org_headquarters_state_other']) . '</p>'; ?>
</div>
<div>
<label for="org_headquarters_city">Headquarters City</label>
<input type="text" name="org_headquarters_city" id="org_headquarters_city" value="<?php echo esc_attr($data['org_headquarters_city'] ?? ''); ?>" aria-describedby="org_headquarters_city_error">
<?php if (isset($errors['org_headquarters_city'])) echo '<p class="error-message" id="org_headquarters_city_error">' . esc_html($errors['org_headquarters_city']) . '</p>'; ?>
</div>
<div>
<label for="org_headquarters_state">Headquarters State</label>
<input type="text" name="org_headquarters_state" id="org_headquarters_state" value="<?php echo esc_attr($data['org_headquarters_state'] ?? ''); ?>" aria-describedby="org_headquarters_state_error">
<?php if (isset($errors['org_headquarters_state'])) echo '<p class="error-message" id="org_headquarters_state_error">' . esc_html($errors['org_headquarters_state']) . '</p>'; ?>
</div>
<div>
<label for="org_headquarters_country">Headquarters Country</label>
<input type="text" name="org_headquarters_country" id="org_headquarters_country" value="<?php echo esc_attr($data['org_headquarters_country'] ?? ''); ?>" aria-describedby="org_headquarters_country_error">
<?php if (isset($errors['org_headquarters_country'])) echo '<p class="error-message" id="org_headquarters_country_error">' . esc_html($errors['org_headquarters_country']) . '</p>'; ?>
</div>
</div>
<!-- Training Information (moved from previous section) -->
@ -451,25 +483,23 @@ class HVAC_Registration {
<h4>Training Capabilities</h4>
</div>
<div class="form-row">
<label id="business_type_label"><strong>Business Type *</strong></label>
<small>What type of business are you?</small>
<div class="radio-group" role="radiogroup" aria-labelledby="business_type_label">
<?php
$business_terms = get_terms(['taxonomy' => 'business_type', 'hide_empty' => false]);
if (!is_wp_error($business_terms) && !empty($business_terms)) {
foreach ($business_terms as $term) {
echo '<label><input type="radio" name="business_type" value="' . esc_attr($term->name) . '" ' . checked($data['business_type'] ?? '', $term->name, false) . ' required> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$business_types = ["Manufacturer", "Distributor", "Contractor", "Consultant", "Educator", "Government", "Other"];
foreach ($business_types as $type) {
echo '<label><input type="radio" name="business_type" value="' . esc_attr($type) . '" ' . checked($data['business_type'] ?? '', $type, false) . ' required> ' . esc_html($type) . '</label>';
}
}
?>
</div>
<?php if (isset($errors['business_type'])) echo '<p class="error-message">' . esc_html($errors['business_type']) . '</p>'; ?>
<label for="business_type"><strong>Business Type *</strong></label>
<small>What best describes your business type?</small>
<select name="business_type" id="business_type" required aria-describedby="business_type_error">
<option value="">Select Business Type</option>
<option value="Association" <?php selected($data['business_type'] ?? '', 'Association'); ?>>Association</option>
<option value="Consultant" <?php selected($data['business_type'] ?? '', 'Consultant'); ?>>Consultant</option>
<option value="Service Company" <?php selected($data['business_type'] ?? '', 'Service Company'); ?>>Service Company</option>
<option value="Distributor or Supplier" <?php selected($data['business_type'] ?? '', 'Distributor or Supplier'); ?>>Distributor or Supplier</option>
<option value="Sales Representative" <?php selected($data['business_type'] ?? '', 'Sales Representative'); ?>>Sales Representative</option>
<option value="Educational Institution" <?php selected($data['business_type'] ?? '', 'Educational Institution'); ?>>Educational Institution</option>
<option value="Training Organization" <?php selected($data['business_type'] ?? '', 'Training Organization'); ?>>Training Organization</option>
<option value="Equipment Manufacturer" <?php selected($data['business_type'] ?? '', 'Equipment Manufacturer'); ?>>Equipment Manufacturer</option>
<option value="Other Manufacturer" <?php selected($data['business_type'] ?? '', 'Other Manufacturer'); ?>>Other Manufacturer</option>
<option value="Government" <?php selected($data['business_type'] ?? '', 'Government'); ?>>Government</option>
<option value="Other" <?php selected($data['business_type'] ?? '', 'Other'); ?>>Other</option>
</select>
<?php if (isset($errors['business_type'])) echo '<p class="error-message" id="business_type_error">' . esc_html($errors['business_type']) . '</p>'; ?>
</div>
<div class="form-row">
@ -477,25 +507,18 @@ class HVAC_Registration {
<small>Who do you offer training to? (Select all that apply)</small>
<div class="checkbox-group" role="group" aria-labelledby="training_audience_label">
<?php
$audience_terms = get_terms(['taxonomy' => 'training_audience', 'hide_empty' => false]);
$selected_audience = $data['training_audience'] ?? [];
if (!is_array($selected_audience)) $selected_audience = []; // Ensure it's an array
if (!is_wp_error($audience_terms) && !empty($audience_terms)) {
foreach ($audience_terms as $term) {
echo '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($term->name) . '" ' . checked(in_array($term->name, $selected_audience), true, false) . '> ' . esc_html($term->name) . '</label>';
}
} else {
// Fallback to hardcoded options if taxonomy not available
$audience_options = [
"Anyone (open to the public)" => "Anyone (open to the public)",
"Industry professionals" => "Industry professionals",
"Internal staff in my company" => "Internal staff in my company",
"Registered students/members of my org/institution" => "Registered students/members of my org/institution"
];
foreach ($audience_options as $value => $label) {
echo '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($value) . '" ' . checked(in_array($value, $selected_audience), true, false) . '> ' . esc_html($label) . '</label>';
}
// Use only the 4 specified options
$audience_options = [
"Anyone (open to the public)",
"Industry professionals",
"Internal staff in my company",
"Registered students/members of my org/institution"
];
foreach ($audience_options as $option) {
echo '<label><input type="checkbox" name="training_audience[]" value="' . esc_attr($option) . '" ' . checked(in_array($option, $selected_audience), true, false) . '> ' . esc_html($option) . '</label>';
}
?>
</div>
@ -1024,7 +1047,10 @@ class HVAC_Registration {
'business_website' => !empty($data['business_website']) ? esc_url_raw($data['business_website']) : '',
'business_description' => wp_kses_post($data['business_description']),
'org_headquarters_city' => !empty($data['org_headquarters_city']) ? sanitize_text_field($data['org_headquarters_city']) : '',
'org_headquarters_state' => !empty($data['org_headquarters_state']) ? sanitize_text_field($data['org_headquarters_state']) : '',
// Use the 'Other' field value if state was 'Other', otherwise use the selected state
'org_headquarters_state' => ($data['org_headquarters_state'] === 'Other' && !empty($data['org_headquarters_state_other']))
? sanitize_text_field($data['org_headquarters_state_other'])
: (!empty($data['org_headquarters_state']) ? sanitize_text_field($data['org_headquarters_state']) : ''),
'org_headquarters_country' => !empty($data['org_headquarters_country']) ? sanitize_text_field($data['org_headquarters_country']) : '',
'create_venue' => sanitize_text_field($data['create_venue']), // Should be 'Yes' or 'No'
'business_type' => sanitize_text_field($data['business_type']),