diff --git a/wordpress-dev/bin/create-communication-templates-page.sh b/wordpress-dev/bin/create-communication-templates-page.sh new file mode 100755 index 00000000..8f6528a9 --- /dev/null +++ b/wordpress-dev/bin/create-communication-templates-page.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Create Communication Templates page on staging server + +echo "Creating Communication Templates page on staging server..." + +# Check if the page already exists +PAGE_EXISTS=$(ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post list --post_type=page --title='Communication Templates' --field=ID") + +if [ -n "$PAGE_EXISTS" ]; then + echo "Communication Templates page already exists with ID: $PAGE_EXISTS" + exit 0 +fi + +# Create the page with the shortcode +PAGE_ID=$(ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post create --post_type=page --post_title='Communication Templates' --post_status=publish --post_content='[hvac_communication_templates]' --porcelain") + +if [ $? -eq 0 ] && [ -n "$PAGE_ID" ]; then + echo "✓ Communication Templates page created successfully" +else + echo "✗ Failed to create Communication Templates page" + exit 1 +fi + +# Verify the page was created +VERIFY_ID=$(ssh roodev@146.190.76.204 "cd /home/974670.cloudwaysapps.com/uberrxmprk/public_html && wp post list --post_type=page --name=communication-templates --field=ID") + +if [ -n "$VERIFY_ID" ]; then + echo "✓ Page created with ID: $PAGE_ID" + echo "✓ URL: https://upskill-staging.measurequick.com/communication-templates/" +else + echo "✗ Failed to verify page creation" + exit 1 +fi \ No newline at end of file diff --git a/wordpress-dev/tests/e2e/communication-templates.test.ts b/wordpress-dev/tests/e2e/communication-templates.test.ts new file mode 100644 index 00000000..fed3ca2e --- /dev/null +++ b/wordpress-dev/tests/e2e/communication-templates.test.ts @@ -0,0 +1,205 @@ +import { test, expect } from './fixtures/auth'; +import { CommonActions } from './utils/common-actions'; + +/** + * Communication Templates E2E Tests + * + * Tests the email template management system for trainers + */ + +test.describe('Communication Templates Tests', () => { + + test('Templates page loads and displays correctly', async ({ authenticatedPage: page }) => { + test.setTimeout(25000); + const actions = new CommonActions(page); + + // Navigate to communication templates page + await actions.navigateAndWait('/communication-templates/'); + await actions.screenshot('templates-page-loaded'); + + // Check page title and heading + await expect(page.locator('h1')).toContainText('Communication Templates'); + + // Verify main elements are present + await expect(page.locator('.hvac-templates-wrapper')).toBeVisible(); + await expect(page.locator('.hvac-templates-header')).toBeVisible(); + + console.log('✓ Communication Templates page loaded successfully'); + }); + + test('Template manager widget displays in email attendees page', async ({ authenticatedPage: page }) => { + test.setTimeout(30000); + const actions = new CommonActions(page); + + // First navigate to dashboard to get an event + await actions.navigateAndWait('/hvac-dashboard/'); + await actions.screenshot('dashboard-for-event-selection'); + + // Look for events with attendees + const eventLinks = page.locator('a[href*="email-attendees"]'); + const eventCount = await eventLinks.count(); + + if (eventCount > 0) { + // Navigate to email attendees page for first event + await eventLinks.first().click(); + await page.waitForLoadState('networkidle'); + await actions.screenshot('email-attendees-page-loaded'); + + // Check that template manager widget is present + await expect(page.locator('.hvac-template-manager')).toBeVisible(); + await expect(page.locator('.hvac-template-toggle')).toBeVisible(); + + // Check toggle functionality + const templateToggle = page.locator('.hvac-template-toggle'); + await templateToggle.click(); + await actions.screenshot('template-manager-opened'); + + // Template manager should now be visible + await expect(page.locator('.hvac-template-manager')).toBeVisible(); + + console.log('✓ Template manager widget working in email attendees page'); + } else { + console.log('⚠ No events with email functionality found - skipping widget test'); + } + }); + + test('Template creation functionality works', async ({ authenticatedPage: page }) => { + test.setTimeout(30000); + const actions = new CommonActions(page); + + // Navigate to templates page + await actions.navigateAndWait('/communication-templates/'); + await actions.screenshot('templates-page-for-creation'); + + // Look for create template button + const createButton = page.locator('button:has-text("Create New Template")'); + + if (await createButton.isVisible()) { + await createButton.click(); + await actions.screenshot('template-form-opened'); + + // Check form elements are present + await expect(page.locator('#hvac_template_title')).toBeVisible(); + await expect(page.locator('#hvac_template_content')).toBeVisible(); + await expect(page.locator('#hvac_template_category')).toBeVisible(); + + // Check placeholder helper is present + await expect(page.locator('.hvac-placeholder-helper')).toBeVisible(); + await expect(page.locator('.hvac-placeholder-grid')).toBeVisible(); + + console.log('✓ Template creation form displays correctly'); + } else { + console.log('⚠ Template creation interface not found - may need default templates'); + } + }); + + test('Default templates installation works for new trainers', async ({ authenticatedPage: page }) => { + test.setTimeout(25000); + const actions = new CommonActions(page); + + // Navigate to templates page + await actions.navigateAndWait('/communication-templates/'); + await actions.screenshot('templates-page-new-user'); + + // Check if this shows getting started section (for users without templates) + const gettingStarted = page.locator('.hvac-getting-started'); + + if (await gettingStarted.isVisible()) { + // New trainer setup detected + await expect(gettingStarted).toContainText('Welcome to Communication Templates'); + + // Check for install defaults button + const installButton = page.locator('a:has-text("Install Default Templates")'); + await expect(installButton).toBeVisible(); + + console.log('✓ Getting started interface displays for new trainers'); + } else { + // User already has templates + const templatesGrid = page.locator('.hvac-templates-grid'); + if (await templatesGrid.isVisible()) { + // Check template cards exist + const templateCards = page.locator('.hvac-template-card'); + const cardCount = await templateCards.count(); + + expect(cardCount).toBeGreaterThan(0); + + // Check template card structure + await expect(templateCards.first().locator('.hvac-template-card-title')).toBeVisible(); + await expect(templateCards.first().locator('.hvac-template-card-actions')).toBeVisible(); + + console.log(`✓ Templates display correctly (${cardCount} templates found)`); + } else { + console.log('⚠ No templates found and no getting started section'); + } + } + }); + + test('Template placeholders system works', async ({ authenticatedPage: page }) => { + test.setTimeout(20000); + const actions = new CommonActions(page); + + // Navigate to templates page + await actions.navigateAndWait('/communication-templates/'); + await actions.screenshot('templates-page-placeholders'); + + // Try to open template form to see placeholders + const createButton = page.locator('button:has-text("Create New Template")'); + + if (await createButton.isVisible()) { + await createButton.click(); + await page.waitForTimeout(1000); + + // Check placeholder helper is loaded + const placeholderHelper = page.locator('.hvac-placeholder-helper'); + await expect(placeholderHelper).toBeVisible(); + + // Check for some common placeholders + await expect(page.locator('.hvac-placeholder-item:has-text("{attendee_name}")')).toBeVisible(); + await expect(page.locator('.hvac-placeholder-item:has-text("{event_title}")')).toBeVisible(); + await expect(page.locator('.hvac-placeholder-item:has-text("{trainer_name}")')).toBeVisible(); + + console.log('✓ Template placeholders system working correctly'); + } else { + console.log('⚠ Cannot test placeholders - template form not accessible'); + } + }); + + test('JavaScript functionality loads without errors', async ({ authenticatedPage: page }) => { + test.setTimeout(20000); + const actions = new CommonActions(page); + + // Monitor console errors + const jsErrors: string[] = []; + page.on('console', (msg) => { + if (msg.type() === 'error') { + jsErrors.push(msg.text()); + } + }); + + // Navigate to templates page + await actions.navigateAndWait('/communication-templates/'); + await actions.screenshot('templates-page-js-check'); + + // Check that HVACTemplates object is available + const hvacTemplatesExists = await page.evaluate(() => { + return typeof window.HVACTemplates !== 'undefined'; + }); + + if (hvacTemplatesExists) { + console.log('✓ HVACTemplates JavaScript object loaded correctly'); + } else { + console.log('⚠ HVACTemplates JavaScript object not found'); + } + + // Check for critical JS errors + const criticalErrors = jsErrors.filter(error => + error.includes('HVACTemplates') || + error.includes('communication-templates') || + error.includes('Uncaught') + ); + + expect(criticalErrors.length).toBe(0); + console.log(`✓ No critical JavaScript errors found (${jsErrors.length} total console messages)`); + }); + +}); \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/css/communication-templates.css b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/css/communication-templates.css new file mode 100644 index 00000000..e086e70f --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/css/communication-templates.css @@ -0,0 +1,512 @@ +/** + * HVAC Communication Templates Styling + * + * Styles for the email template management system + * + * @version 1.0.0 + */ + +/* Template Management Container */ +.hvac-template-manager { + background: var(--hvac-background-white); + border-radius: var(--hvac-radius-lg); + box-shadow: var(--hvac-shadow-md); + padding: var(--hvac-spacing-6); + margin-bottom: var(--hvac-spacing-6); + border: 1px solid var(--hvac-border); +} + +.hvac-template-manager h3 { + color: var(--hvac-theme-text-dark); + font-size: var(--hvac-font-size-lg); + font-weight: var(--hvac-font-weight-semibold); + margin: 0 0 var(--hvac-spacing-4) 0; + display: flex; + align-items: center; + gap: var(--hvac-spacing-2); +} + +.hvac-template-manager h3::before { + content: '📝'; + font-size: var(--hvac-font-size-xl); +} + +/* Template Actions */ +.hvac-template-actions { + display: flex; + gap: var(--hvac-spacing-3); + margin-bottom: var(--hvac-spacing-4); + flex-wrap: wrap; + align-items: center; +} + +.hvac-template-toggle { + background: var(--hvac-primary); + color: white; + border: none; + padding: var(--hvac-spacing-2) var(--hvac-spacing-4); + border-radius: var(--hvac-radius-md); + font-size: var(--hvac-font-size-sm); + font-weight: var(--hvac-font-weight-medium); + cursor: pointer; + transition: all var(--hvac-transition-fast); + display: flex; + align-items: center; + gap: var(--hvac-spacing-1); +} + +.hvac-template-toggle:hover { + background: var(--hvac-primary-dark); + transform: translateY(-1px); +} + +.hvac-template-toggle.active { + background: var(--hvac-success); +} + +/* Template List */ +.hvac-template-list { + margin-bottom: var(--hvac-spacing-4); +} + +.hvac-template-selector { + display: flex; + gap: var(--hvac-spacing-3); + align-items: center; + flex-wrap: wrap; + margin-bottom: var(--hvac-spacing-4); +} + +.hvac-template-dropdown { + min-width: 200px; + padding: var(--hvac-spacing-2) var(--hvac-spacing-3); + border: 2px solid var(--hvac-border); + border-radius: var(--hvac-radius-md); + font-size: var(--hvac-font-size-sm); + background: var(--hvac-background-white); + cursor: pointer; + transition: border-color var(--hvac-transition-fast); +} + +.hvac-template-dropdown:focus { + border-color: var(--hvac-primary); + outline: none; + box-shadow: 0 0 0 3px var(--hvac-primary-light); +} + +.hvac-template-category-filter { + min-width: 150px; + padding: var(--hvac-spacing-2) var(--hvac-spacing-3); + border: 2px solid var(--hvac-border); + border-radius: var(--hvac-radius-md); + font-size: var(--hvac-font-size-sm); + background: var(--hvac-background-white); +} + +.hvac-template-actions-buttons { + display: flex; + gap: var(--hvac-spacing-2); +} + +.hvac-btn-load, .hvac-btn-edit, .hvac-btn-delete, .hvac-btn-save { + padding: var(--hvac-spacing-2) var(--hvac-spacing-3); + border: none; + border-radius: var(--hvac-radius-sm); + font-size: var(--hvac-font-size-sm); + font-weight: var(--hvac-font-weight-medium); + cursor: pointer; + transition: all var(--hvac-transition-fast); + display: flex; + align-items: center; + gap: var(--hvac-spacing-1); +} + +.hvac-btn-load { + background: var(--hvac-accent); + color: white; +} + +.hvac-btn-load:hover { + background: var(--hvac-accent-dark); +} + +.hvac-btn-edit { + background: var(--hvac-warning); + color: white; +} + +.hvac-btn-edit:hover { + background: var(--hvac-warning-dark); +} + +.hvac-btn-delete { + background: var(--hvac-error); + color: white; +} + +.hvac-btn-delete:hover { + background: var(--hvac-error-dark); +} + +.hvac-btn-save { + background: var(--hvac-success); + color: white; +} + +.hvac-btn-save:hover { + background: var(--hvac-success-dark); +} + +/* Template Form */ +.hvac-template-form { + background: var(--hvac-background-subtle); + padding: var(--hvac-spacing-5); + border-radius: var(--hvac-radius-md); + border: 1px solid var(--hvac-border-light); + margin-bottom: var(--hvac-spacing-4); + display: none; +} + +.hvac-template-form.active { + display: block; + animation: hvac-fadeIn 0.3s ease-out; +} + +@keyframes hvac-fadeIn { + from { opacity: 0; transform: translateY(-10px); } + to { opacity: 1; transform: translateY(0); } +} + +.hvac-template-form-row { + margin-bottom: var(--hvac-spacing-4); +} + +.hvac-template-form-row label { + display: block; + margin-bottom: var(--hvac-spacing-2); + font-weight: var(--hvac-font-weight-semibold); + color: var(--hvac-theme-text-dark); + font-size: var(--hvac-font-size-sm); +} + +.hvac-template-form-row input[type="text"], +.hvac-template-form-row select, +.hvac-template-form-row textarea { + width: 100%; + padding: var(--hvac-spacing-3); + border: 2px solid var(--hvac-border); + border-radius: var(--hvac-radius-md); + font-size: var(--hvac-font-size-md); + font-family: var(--hvac-font-family); + background: var(--hvac-background-white); + transition: border-color var(--hvac-transition-fast); + box-sizing: border-box; +} + +.hvac-template-form-row input[type="text"]:focus, +.hvac-template-form-row select:focus, +.hvac-template-form-row textarea:focus { + border-color: var(--hvac-primary); + outline: none; + box-shadow: 0 0 0 3px var(--hvac-primary-light); +} + +.hvac-template-form-row textarea { + min-height: 200px; + resize: vertical; + font-family: 'Courier New', monospace; + line-height: 1.6; +} + +/* Required field indicator */ +.hvac-required { + color: var(--hvac-error); + font-weight: bold; +} + +/* Placeholder Helper */ +.hvac-placeholder-helper { + background: var(--hvac-info-light); + border: 1px solid var(--hvac-accent); + border-radius: var(--hvac-radius-md); + padding: var(--hvac-spacing-4); + margin-bottom: var(--hvac-spacing-4); +} + +.hvac-placeholder-helper h4 { + color: var(--hvac-accent); + font-size: var(--hvac-font-size-md); + font-weight: var(--hvac-font-weight-semibold); + margin: 0 0 var(--hvac-spacing-3) 0; + display: flex; + align-items: center; + gap: var(--hvac-spacing-2); +} + +.hvac-placeholder-helper h4::before { + content: '💡'; +} + +.hvac-placeholder-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: var(--hvac-spacing-2); +} + +.hvac-placeholder-item { + background: var(--hvac-background-white); + border: 1px solid var(--hvac-border-light); + border-radius: var(--hvac-radius-sm); + padding: var(--hvac-spacing-2) var(--hvac-spacing-3); + cursor: pointer; + transition: all var(--hvac-transition-fast); + font-size: var(--hvac-font-size-sm); + display: flex; + justify-content: space-between; + align-items: center; +} + +.hvac-placeholder-item:hover { + background: var(--hvac-primary-light); + border-color: var(--hvac-primary); + transform: translateY(-1px); +} + +.hvac-placeholder-code { + font-family: 'Courier New', monospace; + font-weight: var(--hvac-font-weight-bold); + color: var(--hvac-primary); +} + +.hvac-placeholder-desc { + color: var(--hvac-theme-text-light); + font-size: var(--hvac-font-size-xs); +} + +/* Form Actions */ +.hvac-template-form-actions { + display: flex; + gap: var(--hvac-spacing-3); + justify-content: flex-end; + align-items: center; + margin-top: var(--hvac-spacing-5); + padding-top: var(--hvac-spacing-4); + border-top: 1px solid var(--hvac-border-light); +} + +.hvac-template-form-actions button { + padding: var(--hvac-spacing-3) var(--hvac-spacing-5); + border: none; + border-radius: var(--hvac-radius-md); + font-size: var(--hvac-font-size-md); + font-weight: var(--hvac-font-weight-semibold); + cursor: pointer; + transition: all var(--hvac-transition-fast); + min-width: 120px; +} + +.hvac-btn-primary { + background: var(--hvac-primary); + color: white; +} + +.hvac-btn-primary:hover { + background: var(--hvac-primary-dark); + transform: translateY(-2px); + box-shadow: var(--hvac-shadow-md); +} + +.hvac-btn-secondary { + background: var(--hvac-theme-text-light); + color: white; +} + +.hvac-btn-secondary:hover { + background: var(--hvac-theme-text); +} + +/* Loading State */ +.hvac-loading { + opacity: 0.6; + pointer-events: none; +} + +.hvac-spinner { + width: 20px; + height: 20px; + border: 2px solid rgba(255, 255, 255, 0.3); + border-top: 2px solid white; + border-radius: 50%; + animation: hvac-spin 1s linear infinite; + display: inline-block; + margin-right: var(--hvac-spacing-2); +} + +@keyframes hvac-spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Messages */ +.hvac-template-message { + padding: var(--hvac-spacing-3) var(--hvac-spacing-4); + border-radius: var(--hvac-radius-md); + margin-bottom: var(--hvac-spacing-4); + font-size: var(--hvac-font-size-sm); + font-weight: var(--hvac-font-weight-medium); + display: flex; + align-items: center; + gap: var(--hvac-spacing-2); +} + +.hvac-template-message.success { + background: var(--hvac-success-light); + color: var(--hvac-success-dark); + border: 1px solid var(--hvac-success); +} + +.hvac-template-message.success::before { + content: '✓'; + font-weight: bold; +} + +.hvac-template-message.error { + background: var(--hvac-error-light); + color: var(--hvac-error-dark); + border: 1px solid var(--hvac-error); +} + +.hvac-template-message.error::before { + content: '⚠'; + font-weight: bold; +} + +/* Empty State */ +.hvac-template-empty { + text-align: center; + padding: var(--hvac-spacing-8); + color: var(--hvac-theme-text-light); +} + +.hvac-template-empty-icon { + font-size: 3rem; + margin-bottom: var(--hvac-spacing-4); + opacity: 0.5; +} + +.hvac-template-empty h4 { + font-size: var(--hvac-font-size-lg); + margin-bottom: var(--hvac-spacing-2); + color: var(--hvac-theme-text); +} + +.hvac-template-empty p { + font-size: var(--hvac-font-size-md); + line-height: 1.6; +} + +/* Responsive Design */ +@media (max-width: 768px) { + .hvac-template-selector { + flex-direction: column; + align-items: stretch; + } + + .hvac-template-dropdown, + .hvac-template-category-filter { + min-width: auto; + width: 100%; + } + + .hvac-template-actions-buttons { + flex-wrap: wrap; + gap: var(--hvac-spacing-2); + } + + .hvac-template-actions-buttons button { + flex: 1; + min-width: auto; + } + + .hvac-placeholder-grid { + grid-template-columns: 1fr; + } + + .hvac-template-form-actions { + flex-direction: column; + align-items: stretch; + } + + .hvac-template-form-actions button { + width: 100%; + } +} + +@media (max-width: 480px) { + .hvac-template-manager { + padding: var(--hvac-spacing-4); + } + + .hvac-template-form { + padding: var(--hvac-spacing-4); + } + + .hvac-template-actions { + flex-direction: column; + align-items: stretch; + } + + .hvac-template-toggle { + width: 100%; + justify-content: center; + } +} + +/* Integration with Email Form */ +.hvac-email-form .hvac-template-manager { + margin-bottom: var(--hvac-spacing-6); + border: 2px solid var(--hvac-primary-light); +} + +.hvac-email-form .hvac-template-manager h3 { + color: var(--hvac-primary); +} + +/* WordPress Editor Integration */ +.hvac-template-content-wp-editor { + border: 2px solid var(--hvac-border); + border-radius: var(--hvac-radius-md); + overflow: hidden; +} + +.hvac-template-content-wp-editor iframe { + border: none; + width: 100%; + min-height: 200px; +} + +/* Accessibility Improvements */ +.hvac-template-manager button:focus, +.hvac-template-manager select:focus, +.hvac-template-manager input:focus { + outline: 2px solid var(--hvac-primary); + outline-offset: 2px; +} + +.hvac-template-manager [aria-disabled="true"] { + opacity: 0.6; + cursor: not-allowed; +} + +/* Print Styles */ +@media print { + .hvac-template-manager { + box-shadow: none; + border: 1px solid #000; + } + + .hvac-template-actions, + .hvac-template-form-actions { + display: none; + } +} \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/js/communication-templates.js b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/js/communication-templates.js new file mode 100644 index 00000000..0d4a71eb --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/assets/js/communication-templates.js @@ -0,0 +1,489 @@ +/** + * HVAC Communication Templates JavaScript + * + * Handles the frontend functionality for email template management + * + * @version 1.0.0 + */ + +(function($) { + 'use strict'; + + // Template Manager Object + const HVACTemplates = { + + // Configuration + config: { + ajaxUrl: hvacTemplates.ajaxUrl, + nonce: hvacTemplates.nonce, + placeholders: hvacTemplates.placeholders, + categories: hvacTemplates.categories, + strings: hvacTemplates.strings + }, + + // Current state + currentTemplateId: null, + isEditing: false, + templates: [], + + // Initialize + init: function() { + this.bindEvents(); + this.loadTemplates(); + this.setupPlaceholderHelper(); + }, + + // Bind event handlers + bindEvents: function() { + const self = this; + + // Toggle template manager + $(document).on('click', '.hvac-template-toggle', function(e) { + e.preventDefault(); + self.toggleTemplateManager(); + }); + + // Category filter change + $(document).on('change', '.hvac-template-category-filter', function() { + self.filterTemplatesByCategory($(this).val()); + }); + + // Template actions + $(document).on('click', '.hvac-btn-load', function(e) { + e.preventDefault(); + const templateId = $('.hvac-template-dropdown').val(); + if (templateId) { + self.loadTemplate(templateId); + } + }); + + $(document).on('click', '.hvac-btn-edit', function(e) { + e.preventDefault(); + const templateId = $('.hvac-template-dropdown').val(); + if (templateId) { + self.editTemplate(templateId); + } + }); + + $(document).on('click', '.hvac-btn-delete', function(e) { + e.preventDefault(); + const templateId = $('.hvac-template-dropdown').val(); + if (templateId && confirm(self.config.strings.confirmDelete)) { + self.deleteTemplate(templateId); + } + }); + + $(document).on('click', '.hvac-btn-save', function(e) { + e.preventDefault(); + self.saveTemplate(); + }); + + // Form actions + $(document).on('click', '.hvac-template-form-save', function(e) { + e.preventDefault(); + self.saveTemplate(); + }); + + $(document).on('click', '.hvac-template-form-cancel', function(e) { + e.preventDefault(); + self.cancelTemplateForm(); + }); + + // Placeholder insertion + $(document).on('click', '.hvac-placeholder-item', function(e) { + e.preventDefault(); + const placeholder = $(this).find('.hvac-placeholder-code').text(); + self.insertPlaceholder(placeholder); + }); + + // Auto-save prevention + $(document).on('beforeunload', function() { + if (self.isEditing && self.hasUnsavedChanges()) { + return 'You have unsaved changes. Are you sure you want to leave?'; + } + }); + }, + + // Toggle template manager visibility + toggleTemplateManager: function() { + const $manager = $('.hvac-template-manager'); + const $toggle = $('.hvac-template-toggle'); + + if ($manager.is(':visible')) { + $manager.slideUp(); + $toggle.removeClass('active').text('📝 Use Template'); + } else { + $manager.slideDown(); + $toggle.addClass('active').text('📝 Hide Templates'); + } + }, + + // Load user templates + loadTemplates: function(category = '') { + const self = this; + + $.ajax({ + url: this.config.ajaxUrl, + type: 'POST', + data: { + action: 'hvac_get_templates', + nonce: this.config.nonce, + category: category + }, + success: function(response) { + if (response.success) { + self.templates = response.data.templates; + self.populateTemplateDropdown(); + } else { + self.showMessage(response.data.message, 'error'); + } + }, + error: function() { + self.showMessage(self.config.strings.error, 'error'); + } + }); + }, + + // Filter templates by category + filterTemplatesByCategory: function(category) { + this.loadTemplates(category); + }, + + // Populate template dropdown + populateTemplateDropdown: function() { + const $dropdown = $('.hvac-template-dropdown'); + $dropdown.empty(); + + if (this.templates.length === 0) { + $dropdown.append(''); + $('.hvac-template-actions-buttons button').prop('disabled', true); + return; + } + + $dropdown.append(''); + + this.templates.forEach(function(template) { + $dropdown.append( + '' + ); + }); + + $('.hvac-template-actions-buttons button').prop('disabled', false); + }, + + // Load template content into email form + loadTemplate: function(templateId) { + const self = this; + + $.ajax({ + url: this.config.ajaxUrl, + type: 'POST', + data: { + action: 'hvac_load_template', + nonce: this.config.nonce, + template_id: templateId + }, + beforeSend: function() { + $('.hvac-btn-load').addClass('hvac-loading'); + }, + success: function(response) { + if (response.success) { + const template = response.data; + + // Populate email form fields + $('#email_subject').val(template.title); + + // Handle different content areas (WordPress editor or textarea) + if (typeof tinyMCE !== 'undefined' && tinyMCE.get('email_message')) { + tinyMCE.get('email_message').setContent(template.content); + } else { + $('#email_message').val(template.content); + } + + self.showMessage('Template loaded successfully', 'success'); + + // Optionally hide template manager after loading + // self.toggleTemplateManager(); + + } else { + self.showMessage(response.data.message, 'error'); + } + }, + complete: function() { + $('.hvac-btn-load').removeClass('hvac-loading'); + } + }); + }, + + // Edit template + editTemplate: function(templateId) { + const self = this; + + $.ajax({ + url: this.config.ajaxUrl, + type: 'POST', + data: { + action: 'hvac_load_template', + nonce: this.config.nonce, + template_id: templateId + }, + beforeSend: function() { + $('.hvac-btn-edit').addClass('hvac-loading'); + }, + success: function(response) { + if (response.success) { + const template = response.data; + self.currentTemplateId = template.id; + self.isEditing = true; + + // Populate template form + $('#hvac_template_title').val(template.title); + $('#hvac_template_content').val(template.content); + $('#hvac_template_category').val(template.category); + $('#hvac_template_description').val(template.description); + + // Show template form + $('.hvac-template-form').addClass('active'); + + self.showMessage('Template loaded for editing', 'success'); + + } else { + self.showMessage(response.data.message, 'error'); + } + }, + complete: function() { + $('.hvac-btn-edit').removeClass('hvac-loading'); + } + }); + }, + + // Delete template + deleteTemplate: function(templateId) { + const self = this; + + $.ajax({ + url: this.config.ajaxUrl, + type: 'POST', + data: { + action: 'hvac_delete_template', + nonce: this.config.nonce, + template_id: templateId + }, + beforeSend: function() { + $('.hvac-btn-delete').addClass('hvac-loading'); + }, + success: function(response) { + if (response.success) { + self.showMessage(response.data.message, 'success'); + self.loadTemplates(); // Refresh template list + } else { + self.showMessage(response.data.message, 'error'); + } + }, + complete: function() { + $('.hvac-btn-delete').removeClass('hvac-loading'); + } + }); + }, + + // Save template + saveTemplate: function() { + const self = this; + + const templateData = { + action: 'hvac_save_template', + nonce: this.config.nonce, + template_id: this.currentTemplateId || 0, + title: $('#hvac_template_title').val(), + content: $('#hvac_template_content').val(), + category: $('#hvac_template_category').val(), + description: $('#hvac_template_description').val() + }; + + // Validation + if (!templateData.title || !templateData.content) { + this.showMessage('Template title and content are required', 'error'); + return; + } + + $.ajax({ + url: this.config.ajaxUrl, + type: 'POST', + data: templateData, + beforeSend: function() { + $('.hvac-template-form-save').addClass('hvac-loading'); + }, + success: function(response) { + if (response.success) { + self.showMessage(response.data.message, 'success'); + self.cancelTemplateForm(); + self.loadTemplates(); // Refresh template list + } else { + self.showMessage(response.data.message, 'error'); + } + }, + complete: function() { + $('.hvac-template-form-save').removeClass('hvac-loading'); + } + }); + }, + + // Cancel template form + cancelTemplateForm: function() { + this.currentTemplateId = null; + this.isEditing = false; + + // Clear form + $('#hvac_template_title').val(''); + $('#hvac_template_content').val(''); + $('#hvac_template_category').val(''); + $('#hvac_template_description').val(''); + + // Hide form + $('.hvac-template-form').removeClass('active'); + }, + + // Setup placeholder helper + setupPlaceholderHelper: function() { + const $helper = $('.hvac-placeholder-helper'); + if ($helper.length === 0) return; + + const $grid = $helper.find('.hvac-placeholder-grid'); + + Object.keys(this.config.placeholders).forEach(function(placeholder) { + const description = HVACTemplates.config.placeholders[placeholder]; + + const $item = $('
' + + '' + placeholder + '' + + '' + description + '' + + '
'); + + $grid.append($item); + }); + }, + + // Insert placeholder into content + insertPlaceholder: function(placeholder) { + // Try to insert into WordPress editor first + if (typeof tinyMCE !== 'undefined' && tinyMCE.get('email_message')) { + const editor = tinyMCE.get('email_message'); + editor.insertContent(placeholder); + return; + } + + // Try template content textarea + if ($('#hvac_template_content').length) { + const $textarea = $('#hvac_template_content'); + const cursorPos = $textarea[0].selectionStart; + const textBefore = $textarea.val().substring(0, cursorPos); + const textAfter = $textarea.val().substring(cursorPos); + + $textarea.val(textBefore + placeholder + textAfter); + $textarea[0].setSelectionRange(cursorPos + placeholder.length, cursorPos + placeholder.length); + $textarea.focus(); + return; + } + + // Fallback to email message textarea + if ($('#email_message').length) { + const $textarea = $('#email_message'); + const cursorPos = $textarea[0].selectionStart; + const textBefore = $textarea.val().substring(0, cursorPos); + const textAfter = $textarea.val().substring(cursorPos); + + $textarea.val(textBefore + placeholder + textAfter); + $textarea[0].setSelectionRange(cursorPos + placeholder.length, cursorPos + placeholder.length); + $textarea.focus(); + } + }, + + // Check for unsaved changes + hasUnsavedChanges: function() { + if (!this.isEditing) return false; + + return $('#hvac_template_title').val() !== '' || + $('#hvac_template_content').val() !== '' || + $('#hvac_template_category').val() !== '' || + $('#hvac_template_description').val() !== ''; + }, + + // Show messages + showMessage: function(message, type) { + const $container = $('.hvac-template-manager'); + + // Remove existing messages + $container.find('.hvac-template-message').remove(); + + // Add new message + const $message = $('
' + message + '
'); + $container.prepend($message); + + // Auto-hide success messages + if (type === 'success') { + setTimeout(function() { + $message.fadeOut(function() { + $message.remove(); + }); + }, 3000); + } + }, + + // Create new template (helper method) + createNewTemplate: function() { + this.currentTemplateId = null; + this.isEditing = true; + + // Clear and show form + this.cancelTemplateForm(); + $('.hvac-template-form').addClass('active'); + + // Focus on title field + $('#hvac_template_title').focus(); + }, + + // Utility: Get current email content + getCurrentEmailContent: function() { + if (typeof tinyMCE !== 'undefined' && tinyMCE.get('email_message')) { + return tinyMCE.get('email_message').getContent(); + } + return $('#email_message').val() || ''; + }, + + // Utility: Get current email subject + getCurrentEmailSubject: function() { + return $('#email_subject').val() || ''; + }, + + // Save current email as template + saveCurrentEmailAsTemplate: function() { + const content = this.getCurrentEmailContent(); + const subject = this.getCurrentEmailSubject(); + + if (!content && !subject) { + this.showMessage('No email content to save as template', 'error'); + return; + } + + // Pre-fill form with current email content + $('#hvac_template_title').val(subject || 'New Template'); + $('#hvac_template_content').val(content); + + this.createNewTemplate(); + } + }; + + // Initialize when document is ready + $(document).ready(function() { + // Only initialize if template manager is present + if ($('.hvac-template-manager').length || $('.hvac-template-toggle').length) { + HVACTemplates.init(); + } + }); + + // Expose to global scope for external usage + window.HVACTemplates = HVACTemplates; + +})(jQuery); \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php index 00b57fa4..26eef361 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/class-hvac-community-events.php @@ -78,7 +78,8 @@ class HVAC_Community_Events { 'community/class-email-debug.php', // Email debugging tools 'certificates/test-rewrite-rules.php', // Rewrite rules testing (temporary) 'google-sheets/class-google-sheets-auth.php', // Google Sheets authentication - 'google-sheets/class-google-sheets-manager.php' // Google Sheets management + 'google-sheets/class-google-sheets-manager.php', // Google Sheets management + 'communication/class-communication-templates.php' // Email template management ]; // Make sure Login_Handler is loaded first for shortcode registration $login_handler_path = HVAC_CE_PLUGIN_DIR . 'includes/community/class-login-handler.php'; @@ -385,6 +386,9 @@ class HVAC_Community_Events { // Add Google Sheets admin shortcode add_shortcode('hvac_google_sheets', array($this, 'render_google_sheets_admin')); + + // Add communication templates shortcode + add_shortcode('hvac_communication_templates', array($this, 'render_communication_templates')); // Removed shortcode override - let The Events Calendar Community Events handle this shortcode // add_shortcode('tribe_community_events', array($this, 'render_tribe_community_events')); @@ -704,6 +708,11 @@ class HVAC_Community_Events { if (is_page('edit-profile')) { $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/template-edit-profile.php'; } + + // Check for communication-templates page + if (is_page('communication-templates')) { + $custom_template = HVAC_CE_PLUGIN_DIR . 'templates/communication/template-communication-templates.php'; + } // Check for single event view (temporary) if (is_singular('tribe_events')) { @@ -778,5 +787,29 @@ class HVAC_Community_Events { new HVAC_Google_Sheets_Admin(); } } + + /** + * Render communication templates content + */ + public function render_communication_templates() { + if (!is_user_logged_in()) { + return '

Please log in to manage communication templates.

'; + } + + // Check if user is a trainer or has permission to manage templates + $current_user = wp_get_current_user(); + if (!in_array('hvac_trainer', $current_user->roles) && !current_user_can('edit_posts')) { + return '

You do not have permission to manage communication templates.

'; + } + + // Initialize the communication templates class + if (!class_exists('HVAC_Communication_Templates')) { + require_once HVAC_CE_PLUGIN_DIR . 'includes/communication/class-communication-templates.php'; + } + + ob_start(); + include HVAC_CE_PLUGIN_DIR . 'templates/communication/template-communication-templates.php'; + return ob_get_clean(); + } } // End class HVAC_Community_Events \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/communication/class-communication-templates.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/communication/class-communication-templates.php new file mode 100644 index 00000000..033ba400 --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/includes/communication/class-communication-templates.php @@ -0,0 +1,479 @@ + 'Attendee Name', + '{event_title}' => 'Event Title', + '{event_date}' => 'Event Date', + '{event_time}' => 'Event Time', + '{event_location}' => 'Event Location', + '{trainer_name}' => 'Trainer Name', + '{business_name}' => 'Business Name', + '{trainer_email}' => 'Trainer Email', + '{trainer_phone}' => 'Trainer Phone', + '{current_date}' => 'Current Date', + '{website_name}' => 'Website Name', + '{website_url}' => 'Website URL' + ); + + /** + * Default template categories + */ + const DEFAULT_CATEGORIES = array( + 'pre_event' => 'Pre-Event Communications', + 'event_reminder' => 'Event Reminders', + 'post_event' => 'Post-Event Follow-up', + 'certificate' => 'Certificate Information', + 'general' => 'General Communications' + ); + + /** + * Constructor + */ + public function __construct() { + add_action( 'init', array( $this, 'register_post_type' ) ); + add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); + add_action( 'wp_ajax_hvac_save_template', array( $this, 'ajax_save_template' ) ); + add_action( 'wp_ajax_hvac_load_template', array( $this, 'ajax_load_template' ) ); + add_action( 'wp_ajax_hvac_delete_template', array( $this, 'ajax_delete_template' ) ); + add_action( 'wp_ajax_hvac_get_templates', array( $this, 'ajax_get_templates' ) ); + } + + /** + * Register the email template custom post type + */ + public function register_post_type() { + $args = array( + 'label' => __( 'Email Templates', 'hvac-community-events' ), + 'public' => false, + 'show_ui' => false, + 'supports' => array( 'title', 'editor', 'author' ), + 'capability_type' => 'post', + 'capabilities' => array( + 'create_posts' => 'edit_posts', + 'delete_posts' => 'delete_posts', + 'delete_others_posts' => 'delete_others_posts', + 'delete_private_posts' => 'delete_private_posts', + 'delete_published_posts' => 'delete_published_posts', + 'edit_posts' => 'edit_posts', + 'edit_others_posts' => 'edit_others_posts', + 'edit_private_posts' => 'edit_private_posts', + 'edit_published_posts' => 'edit_published_posts', + 'publish_posts' => 'publish_posts', + 'read_private_posts' => 'read_private_posts', + ), + ); + + register_post_type( self::POST_TYPE, $args ); + } + + /** + * Enqueue scripts for template management + */ + public function enqueue_scripts() { + global $post; + + // Only enqueue on pages that use templates + if ( is_a( $post, 'WP_Post' ) && ( + has_shortcode( $post->post_content, 'hvac_email_attendees' ) || + has_shortcode( $post->post_content, 'hvac_template_manager' ) + ) ) { + wp_enqueue_script( + 'hvac-communication-templates', + HVAC_CE_PLUGIN_URL . 'assets/js/communication-templates.js', + array( 'jquery' ), + HVAC_CE_VERSION, + true + ); + + wp_localize_script( 'hvac-communication-templates', 'hvacTemplates', array( + 'ajaxUrl' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'hvac_templates_nonce' ), + 'placeholders' => self::PLACEHOLDERS, + 'categories' => self::DEFAULT_CATEGORIES, + 'strings' => array( + 'saveTemplate' => __( 'Save Template', 'hvac-community-events' ), + 'templateSaved' => __( 'Template saved successfully', 'hvac-community-events' ), + 'templateDeleted' => __( 'Template deleted successfully', 'hvac-community-events' ), + 'confirmDelete' => __( 'Are you sure you want to delete this template?', 'hvac-community-events' ), + 'error' => __( 'An error occurred. Please try again.', 'hvac-community-events' ), + 'templateName' => __( 'Template Name', 'hvac-community-events' ), + 'selectCategory' => __( 'Select Category', 'hvac-community-events' ), + 'insertPlaceholder' => __( 'Insert Placeholder', 'hvac-community-events' ), + ) + ) ); + + wp_enqueue_style( + 'hvac-communication-templates', + HVAC_CE_PLUGIN_URL . 'assets/css/communication-templates.css', + array(), + HVAC_CE_VERSION + ); + } + } + + /** + * Get templates for a specific user + * + * @param int $user_id User ID (defaults to current user) + * @param string $category Optional category filter + * @return array Array of templates + */ + public function get_user_templates( $user_id = 0, $category = '' ) { + if ( empty( $user_id ) ) { + $user_id = get_current_user_id(); + } + + $args = array( + 'post_type' => self::POST_TYPE, + 'author' => $user_id, + 'post_status' => 'publish', + 'posts_per_page' => -1, + 'orderby' => 'title', + 'order' => 'ASC', + ); + + if ( ! empty( $category ) ) { + $args['meta_query'] = array( + array( + 'key' => '_hvac_template_category', + 'value' => $category, + 'compare' => '=' + ) + ); + } + + $templates = get_posts( $args ); + $formatted_templates = array(); + + foreach ( $templates as $template ) { + $formatted_templates[] = array( + 'id' => $template->ID, + 'title' => $template->post_title, + 'content' => $template->post_content, + 'category' => get_post_meta( $template->ID, '_hvac_template_category', true ), + 'description' => get_post_meta( $template->ID, '_hvac_template_description', true ), + 'created' => $template->post_date, + 'modified' => $template->post_modified, + ); + } + + return $formatted_templates; + } + + /** + * Save a template + * + * @param array $template_data Template data + * @return int|WP_Error Template ID on success, WP_Error on failure + */ + public function save_template( $template_data ) { + // Validate required fields + if ( empty( $template_data['title'] ) || empty( $template_data['content'] ) ) { + return new WP_Error( 'missing_data', __( 'Template title and content are required.', 'hvac-community-events' ) ); + } + + $post_data = array( + 'post_type' => self::POST_TYPE, + 'post_title' => sanitize_text_field( $template_data['title'] ), + 'post_content' => wp_kses_post( $template_data['content'] ), + 'post_status' => 'publish', + 'post_author' => get_current_user_id(), + ); + + // Update existing template if ID provided + if ( ! empty( $template_data['id'] ) ) { + $post_data['ID'] = intval( $template_data['id'] ); + + // Verify ownership + $existing_template = get_post( $post_data['ID'] ); + if ( ! $existing_template || $existing_template->post_author != get_current_user_id() ) { + return new WP_Error( 'permission_denied', __( 'You can only edit your own templates.', 'hvac-community-events' ) ); + } + } + + $template_id = wp_insert_post( $post_data ); + + if ( is_wp_error( $template_id ) ) { + return $template_id; + } + + // Save metadata + if ( ! empty( $template_data['category'] ) ) { + update_post_meta( $template_id, '_hvac_template_category', sanitize_text_field( $template_data['category'] ) ); + } + + if ( ! empty( $template_data['description'] ) ) { + update_post_meta( $template_id, '_hvac_template_description', sanitize_text_field( $template_data['description'] ) ); + } + + return $template_id; + } + + /** + * Delete a template + * + * @param int $template_id Template ID + * @return bool Success status + */ + public function delete_template( $template_id ) { + $template = get_post( $template_id ); + + if ( ! $template || $template->post_type !== self::POST_TYPE ) { + return false; + } + + // Verify ownership + if ( $template->post_author != get_current_user_id() && ! current_user_can( 'delete_others_posts' ) ) { + return false; + } + + return wp_delete_post( $template_id, true ) !== false; + } + + /** + * Process placeholders in template content + * + * @param string $content Template content + * @param array $context Context data for placeholders + * @return string Processed content + */ + public function process_placeholders( $content, $context = array() ) { + $current_user = wp_get_current_user(); + + // Default context values + $defaults = array( + 'attendee_name' => '', + 'event_title' => '', + 'event_date' => '', + 'event_time' => '', + 'event_location' => '', + 'trainer_name' => $current_user->display_name, + 'business_name' => get_user_meta( $current_user->ID, 'business_name', true ), + 'trainer_email' => $current_user->user_email, + 'trainer_phone' => get_user_meta( $current_user->ID, 'phone_number', true ), + 'current_date' => date( 'F j, Y' ), + 'website_name' => get_bloginfo( 'name' ), + 'website_url' => home_url(), + ); + + // Get trainer contact email if available + if ( in_array( 'hvac_trainer', $current_user->roles ) ) { + $contact_email = get_user_meta( $current_user->ID, 'contact_email', true ); + if ( ! empty( $contact_email ) && is_email( $contact_email ) ) { + $defaults['trainer_email'] = $contact_email; + } + } + + $context = wp_parse_args( $context, $defaults ); + + // Replace placeholders + foreach ( self::PLACEHOLDERS as $placeholder => $description ) { + $key = str_replace( array( '{', '}' ), '', $placeholder ); + if ( isset( $context[ $key ] ) ) { + $content = str_replace( $placeholder, $context[ $key ], $content ); + } + } + + return $content; + } + + /** + * Get default templates + * + * @return array Default templates + */ + public function get_default_templates() { + return array( + array( + 'title' => __( 'Event Reminder - 24 Hours', 'hvac-community-events' ), + 'category' => 'event_reminder', + 'description' => __( 'Reminder sent 24 hours before the event', 'hvac-community-events' ), + 'content' => "Hello {attendee_name},\n\nThis is a friendly reminder that you're registered for {event_title} tomorrow at {event_time}.\n\nEvent Details:\n- Date: {event_date}\n- Time: {event_time}\n- Location: {event_location}\n\nPlease bring a valid ID and any materials mentioned in your registration confirmation.\n\nIf you have any questions, please don't hesitate to contact me.\n\nBest regards,\n{trainer_name}\n{business_name}\n{trainer_email}\n{trainer_phone}" + ), + array( + 'title' => __( 'Welcome & Pre-Event Information', 'hvac-community-events' ), + 'category' => 'pre_event', + 'description' => __( 'Welcome message with event preparation information', 'hvac-community-events' ), + 'content' => "Welcome {attendee_name}!\n\nThank you for registering for {event_title}. I'm excited to have you join us on {event_date} at {event_time}.\n\nTo help you prepare for the training:\n\n1. Please arrive 15 minutes early for check-in\n2. Bring a valid photo ID\n3. Dress comfortably and wear closed-toe shoes\n4. Bring a notebook and pen for taking notes\n5. Lunch will be provided\n\nIf you have any questions before the event, please feel free to reach out.\n\nLooking forward to seeing you there!\n\n{trainer_name}\n{business_name}\n{trainer_email}\n{trainer_phone}" + ), + array( + 'title' => __( 'Thank You & Certificate Information', 'hvac-community-events' ), + 'category' => 'post_event', + 'description' => __( 'Post-event thank you with certificate details', 'hvac-community-events' ), + 'content' => "Dear {attendee_name},\n\nThank you for attending {event_title} on {event_date}. It was great having you participate in the training.\n\nYour certificate of completion will be available within 3-5 business days. You can download it from your attendee profile on our website.\n\nIf you have any questions about the training content or need additional resources, please don't hesitate to contact me.\n\nThank you again for your participation, and I look forward to seeing you at future training events.\n\nBest regards,\n{trainer_name}\n{business_name}\n{trainer_email}\n{trainer_phone}" + ), + array( + 'title' => __( 'Certificate Ready for Download', 'hvac-community-events' ), + 'category' => 'certificate', + 'description' => __( 'Notification when certificate is ready', 'hvac-community-events' ), + 'content' => "Hello {attendee_name},\n\nGreat news! Your certificate of completion for {event_title} is now ready for download.\n\nTo access your certificate:\n1. Visit {website_url}\n2. Log into your attendee profile\n3. Navigate to the 'My Certificates' section\n4. Download your certificate for {event_title}\n\nYour certificate includes:\n- Official completion verification\n- Training date and hours\n- Digital security features\n- Suitable for continuing education records\n\nIf you have any trouble accessing your certificate, please contact me directly.\n\nCongratulations on completing the training!\n\n{trainer_name}\n{business_name}\n{trainer_email}\n{trainer_phone}" + ) + ); + } + + /** + * Install default templates for a user + * + * @param int $user_id User ID + */ + public function install_default_templates( $user_id ) { + $defaults = $this->get_default_templates(); + + foreach ( $defaults as $template ) { + $template_data = array( + 'title' => $template['title'], + 'content' => $template['content'], + 'category' => $template['category'], + 'description' => $template['description'], + ); + + // Temporarily switch to the target user + $current_user_id = get_current_user_id(); + wp_set_current_user( $user_id ); + + $this->save_template( $template_data ); + + // Switch back to original user + wp_set_current_user( $current_user_id ); + } + } + + /** + * AJAX handler for saving templates + */ + public function ajax_save_template() { + check_ajax_referer( 'hvac_templates_nonce', 'nonce' ); + + if ( ! is_user_logged_in() ) { + wp_send_json_error( array( 'message' => __( 'You must be logged in to save templates.', 'hvac-community-events' ) ) ); + } + + $template_data = array( + 'id' => isset( $_POST['template_id'] ) ? intval( $_POST['template_id'] ) : 0, + 'title' => isset( $_POST['title'] ) ? sanitize_text_field( $_POST['title'] ) : '', + 'content' => isset( $_POST['content'] ) ? wp_kses_post( $_POST['content'] ) : '', + 'category' => isset( $_POST['category'] ) ? sanitize_text_field( $_POST['category'] ) : '', + 'description' => isset( $_POST['description'] ) ? sanitize_text_field( $_POST['description'] ) : '', + ); + + $result = $this->save_template( $template_data ); + + if ( is_wp_error( $result ) ) { + wp_send_json_error( array( 'message' => $result->get_error_message() ) ); + } + + wp_send_json_success( array( + 'template_id' => $result, + 'message' => __( 'Template saved successfully.', 'hvac-community-events' ) + ) ); + } + + /** + * AJAX handler for loading templates + */ + public function ajax_load_template() { + check_ajax_referer( 'hvac_templates_nonce', 'nonce' ); + + if ( ! is_user_logged_in() ) { + wp_send_json_error( array( 'message' => __( 'You must be logged in to load templates.', 'hvac-community-events' ) ) ); + } + + $template_id = isset( $_POST['template_id'] ) ? intval( $_POST['template_id'] ) : 0; + + if ( empty( $template_id ) ) { + wp_send_json_error( array( 'message' => __( 'Invalid template ID.', 'hvac-community-events' ) ) ); + } + + $template = get_post( $template_id ); + + if ( ! $template || $template->post_type !== self::POST_TYPE ) { + wp_send_json_error( array( 'message' => __( 'Template not found.', 'hvac-community-events' ) ) ); + } + + // Verify ownership or admin access + if ( $template->post_author != get_current_user_id() && ! current_user_can( 'edit_others_posts' ) ) { + wp_send_json_error( array( 'message' => __( 'You can only load your own templates.', 'hvac-community-events' ) ) ); + } + + wp_send_json_success( array( + 'id' => $template->ID, + 'title' => $template->post_title, + 'content' => $template->post_content, + 'category' => get_post_meta( $template->ID, '_hvac_template_category', true ), + 'description' => get_post_meta( $template->ID, '_hvac_template_description', true ), + ) ); + } + + /** + * AJAX handler for deleting templates + */ + public function ajax_delete_template() { + check_ajax_referer( 'hvac_templates_nonce', 'nonce' ); + + if ( ! is_user_logged_in() ) { + wp_send_json_error( array( 'message' => __( 'You must be logged in to delete templates.', 'hvac-community-events' ) ) ); + } + + $template_id = isset( $_POST['template_id'] ) ? intval( $_POST['template_id'] ) : 0; + + if ( empty( $template_id ) ) { + wp_send_json_error( array( 'message' => __( 'Invalid template ID.', 'hvac-community-events' ) ) ); + } + + $result = $this->delete_template( $template_id ); + + if ( ! $result ) { + wp_send_json_error( array( 'message' => __( 'Failed to delete template.', 'hvac-community-events' ) ) ); + } + + wp_send_json_success( array( 'message' => __( 'Template deleted successfully.', 'hvac-community-events' ) ) ); + } + + /** + * AJAX handler for getting templates list + */ + public function ajax_get_templates() { + check_ajax_referer( 'hvac_templates_nonce', 'nonce' ); + + if ( ! is_user_logged_in() ) { + wp_send_json_error( array( 'message' => __( 'You must be logged in to view templates.', 'hvac-community-events' ) ) ); + } + + $category = isset( $_POST['category'] ) ? sanitize_text_field( $_POST['category'] ) : ''; + $templates = $this->get_user_templates( get_current_user_id(), $category ); + + wp_send_json_success( array( 'templates' => $templates ) ); + } +} + +// Initialize the class +new HVAC_Communication_Templates(); \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-communication-templates.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-communication-templates.php new file mode 100644 index 00000000..368ef0f6 --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-communication-templates.php @@ -0,0 +1,584 @@ +get_user_templates(); +$categories = HVAC_Communication_Templates::DEFAULT_CATEGORIES; + +// Handle first-time user setup +$current_user = wp_get_current_user(); +$has_templates = !empty($user_templates); + +// Install default templates if this is a new trainer +if (!$has_templates && in_array('hvac_trainer', $current_user->roles)) { + $install_defaults = isset($_GET['install_defaults']) ? $_GET['install_defaults'] === 'true' : false; + + if ($install_defaults) { + $templates_manager->install_default_templates(get_current_user_id()); + wp_redirect(remove_query_arg('install_defaults')); + exit; + } +} + +// Get the site title for the page title +$site_title = get_bloginfo( 'name' ); +?> + + +> + + + + <?php echo esc_html( $site_title ); ?> - <?php _e( 'Communication Templates', 'hvac-community-events' ); ?> + + + + + +> + + +
+
+
+

+

+
+ +
+ + + + +
+
+ + roles)) : ?> +
+

+

+ +
+ + + + +
+ + +
+ + + + +
+
+
+
+
+ + + +
+
+
+
+ +
+
+
+
+
+ + +
+
+ + +
+ + $label) : ?> + + 0) : ?> +
+ + +
+ + +
+ + +
+ +
+
+

+ + + + + +
+ + +

+ + +
+ + + +
+
+ +
+ + + +
+
+

+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ + +
+

+

+
+
+ +
+ + +
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-manager-widget.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-manager-widget.php new file mode 100644 index 00000000..0960e47d --- /dev/null +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/communication/template-manager-widget.php @@ -0,0 +1,180 @@ +get_user_templates(); +$categories = HVAC_Communication_Templates::DEFAULT_CATEGORIES; + +// Check if this is the first time user setup +$current_user = wp_get_current_user(); +$has_templates = !empty($user_templates); +?> + + + + +
+ +
+ + \ No newline at end of file diff --git a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/email-attendees/template-email-attendees.php b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/email-attendees/template-email-attendees.php index 49f6de37..e3158a5e 100644 --- a/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/email-attendees/template-email-attendees.php +++ b/wordpress-dev/wordpress/wp-content/plugins/hvac-community-events/templates/email-attendees/template-email-attendees.php @@ -245,6 +245,9 @@ $site_title = get_bloginfo( 'name' ); + + +