PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
yatra / templates / setup-wizard / theme.php

theme.php in Yatra – Travel Booking & Tour Operator Software trunk, at templates/setup-wizard/theme.php

324 lines 18.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Setup Wizard - Theme Step
4 *
5 * @package Yatra
6 */
7
8 defined('ABSPATH') || exit;
9
10 $resa_theme = wp_get_theme('resa');
11 $is_resa_installed = $resa_theme->exists();
12 $current_theme = wp_get_theme();
13 $current_theme_slug = $current_theme->get_stylesheet();
14 $is_resa_active = ($current_theme_slug === 'resa') || ($current_theme->get('Name') === 'Resa') || (get_template() === 'resa') || (get_stylesheet() === 'resa');
15 ?>
16
17 <form method="post" class="wizard-step">
18 <?php wp_nonce_field('yatra-setup'); ?>
19 <input type="hidden" name="save_step" value="theme">
20
21 <div class="wizard-header wizard-header--task">
22 <p class="wizard-header-kicker"><?php echo esc_html($this->get_wizard_progress_label()); ?></p>
23 <h1><?php esc_html_e('Site appearance', 'yatra'); ?></h1>
24 <p class="wizard-header-lead"><?php esc_html_e('Optional: Resa is built for travel layouts and pairs well with Yatra trip pages.', 'yatra'); ?></p>
25 </div>
26
27 <div class="wizard-content">
28 <!-- Resa Theme Card -->
29 <div class="theme-card-full" style="max-width: 600px; margin: 0 auto; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 6px rgba(0,0,0,0.1);">
30 <div style="width: 100%; height: 300px; overflow: hidden;">
31 <img src="https://i0.wp.com/themes.svn.wordpress.org/resa/1.0.6/screenshot.png"
32 alt="<?php esc_attr_e('Resa Theme', 'yatra'); ?>"
33 style="width: 100%; height: 100%; object-fit: cover;"
34 onerror="this.src='<?php echo esc_url(YATRA_PLUGIN_URI . 'assets/images/resa-theme-preview.jpg'); ?>'">
35 </div>
36 <div style="padding: 24px; background: #fff;">
37 <div style="display: flex; align-items: center; gap: 12px; margin-bottom: 16px;">
38 <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#4f46e5" stroke-width="2">
39 <path d="M12 2L2 7l10 5 10-5-10-5z"></path>
40 <path d="M2 17l10 5 10-5M2 12l10 5 10-5"></path>
41 </svg>
42 <h3 style="margin: 0; font-size: 20px; font-weight: 600; color: #111827;"><?php esc_html_e('Resa Theme', 'yatra'); ?></h3>
43 <span style="margin-left: auto; padding: 4px 12px; background: #4f46e5; color: #fff; font-size: 11px; font-weight: 700; border-radius: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Recommended', 'yatra'); ?></span>
44 <?php if ($is_resa_installed && $is_resa_active) : ?>
45 <span style="padding: 4px 12px; background: #10b981; color: #fff; font-size: 11px; font-weight: 700; border-radius: 12px; text-transform: uppercase; letter-spacing: 0.05em;"><?php esc_html_e('Activated', 'yatra'); ?></span>
46 <?php endif; ?>
47 </div>
48
49 <p style="color: #6b7280; margin-bottom: 20px; line-height: 1.5;">
50 <?php esc_html_e('The perfect theme for travel and trip booking websites. Designed specifically to work seamlessly with Yatra plugin.', 'yatra'); ?>
51 </p>
52
53 <?php if ($is_resa_installed && $is_resa_active) : ?>
54 <!-- Theme is active, show no action buttons -->
55 <?php elseif ($is_resa_installed && !$is_resa_active) : ?>
56 <div style="display: flex; align-items: center; justify-content: space-between; background: #fef3c7; border: 1px solid #f59e0b; border-radius: 8px; padding: 16px;">
57 <div style="display: flex; align-items: center;">
58 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#f59e0b" stroke-width="2" style="margin-right: 12px;">
59 <path d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
60 </svg>
61 <span style="font-weight: 600; color: #92400e;"><?php esc_html_e('Installed but not activated', 'yatra'); ?></span>
62 </div>
63 <button type="button" class="btn btn-warning" onclick="activateTheme('resa')" style="display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; background: #f59e0b; color: #fff; border: none; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.15s ease;" onmouseover="this.style.background='#d97706'; this.style.transform='translateY(-1px)';" onmouseout="this.style.background='#f59e0b'; this.style.transform='translateY(0)';">
64 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
65 <path d="M19 14l-7 7m0 0l-7-7m7 7V3"></path>
66 </svg>
67 <?php esc_html_e('Activate', 'yatra'); ?>
68 </button>
69 </div>
70 <?php else : ?>
71 <div style="display: flex; align-items: center; justify-content: space-between; background: #eff6ff; border: 1px solid #3b82f6; border-radius: 8px; padding: 16px;">
72 <div style="display: flex; align-items: center;">
73 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#3b82f6" stroke-width="2" style="margin-right: 12px;">
74 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
75 <polyline points="7 10 12 15 17 10"></polyline>
76 <line x1="12" y1="15" x2="12" y2="3"></line>
77 </svg>
78 <span style="font-weight: 600; color: #1e40af;"><?php esc_html_e('Not installed', 'yatra'); ?></span>
79 </div>
80 <button type="button" class="btn btn-primary" onclick="installAndActivateTheme('resa')" style="display: inline-flex; align-items: center; gap: 6px; padding: 8px 16px; background: #3b82f6; color: #fff; border: none; border-radius: 6px; font-size: 14px; font-weight: 500; cursor: pointer; transition: all 0.15s ease;" onmouseover="this.style.background='#2563eb'; this.style.transform='translateY(-1px)';" onmouseout="this.style.background='#3b82f6'; this.style.transform='translateY(0)';">
81 <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
82 <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
83 <polyline points="7 10 12 15 17 10"></polyline>
84 <line x1="12" y1="15" x2="12" y2="3"></line>
85 </svg>
86 <?php esc_html_e('Install & Activate', 'yatra'); ?>
87 </button>
88 </div>
89 <?php endif; ?>
90 </div>
91 </div>
92 </div>
93
94 <div class="wizard-footer">
95 <a href="<?php echo esc_url($this->get_step_url('currency')); ?>" class="btn btn-secondary wizard-footer-back">
96 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>
97 <?php esc_html_e('Back', 'yatra'); ?>
98 </a>
99 <div class="wizard-footer-actions">
100 <a href="<?php echo esc_url($this->get_next_step_link()); ?>" class="btn btn-secondary btn-skip"><?php esc_html_e('Skip', 'yatra'); ?></a>
101 <button type="submit" class="btn btn-primary">
102 <?php esc_html_e('Continue', 'yatra'); ?>
103 <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" aria-hidden="true"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
104 </button>
105 </div>
106 </div>
107 </form>
108
109 <script>
110 // Define ajaxurl if not available
111 if (typeof ajaxurl === 'undefined') {
112 ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
113 }
114
115 function installAndActivateTheme(themeSlug) {
116 const button = event.target;
117 const originalContent = button.innerHTML;
118 const yatraThemeWizardI18n = {
119 installing: <?php echo wp_json_encode(__('Installing...', 'yatra')); ?>,
120 activating: <?php echo wp_json_encode(__('Activating...', 'yatra')); ?>,
121 installationFailedInvalidResponse: <?php echo wp_json_encode(__('Installation failed: Invalid response format', 'yatra')); ?>,
122 activationFailedPrefix: <?php echo wp_json_encode(__('Activation failed:', 'yatra')); ?>,
123 installationFailedPrefix: <?php echo wp_json_encode(__('Installation failed:', 'yatra')); ?>,
124 activationRequestFailed: <?php echo wp_json_encode(__('Activation request failed. Please try again.', 'yatra')); ?>,
125 installationRequestFailed: <?php echo wp_json_encode(__('Installation request failed. Please try again.', 'yatra')); ?>,
126 unknownActivationError: <?php echo wp_json_encode(__('Unknown activation error', 'yatra')); ?>,
127 unknownInstallationError: <?php echo wp_json_encode(__('Unknown installation error', 'yatra')); ?>
128 };
129
130 // Show loading state with spinner
131 button.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="animation: spin 1s linear infinite;"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"></circle><path d="M12 2v10l4 2" fill="none" stroke="currentColor" stroke-width="2"></path></svg> ' + yatraThemeWizardI18n.installing;
132 button.disabled = true;
133 button.style.cursor = 'not-allowed';
134 button.style.opacity = '0.7';
135
136 // Add CSS animation for spinner
137 if (!document.querySelector('#spinner-style')) {
138 const style = document.createElement('style');
139 style.id = 'spinner-style';
140 style.textContent = '@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }';
141 document.head.appendChild(style);
142 }
143
144 // Make AJAX request to install theme
145 jQuery.ajax({
146 url: ajaxurl,
147 type: 'POST',
148 data: {
149 action: 'yatra_install_theme',
150 theme_slug: themeSlug,
151 nonce: '<?php echo wp_create_nonce('yatra_theme_actions'); ?>'
152 },
153 success: function(response) {
154 window.YATRA_DEBUG && console.log('Raw installation response:', response); // Debug log
155
156 // Handle case where HTML is mixed with JSON
157 let jsonResponse = response;
158 if (typeof response === 'string' && response.includes('{')) {
159 // Extract JSON from mixed HTML/JSON response
160 const jsonStart = response.lastIndexOf('{');
161 const jsonEnd = response.lastIndexOf('}') + 1;
162 const jsonString = response.substring(jsonStart, jsonEnd);
163
164 try {
165 jsonResponse = JSON.parse(jsonString);
166 } catch (e) {
167 console.error('Failed to parse JSON:', e);
168 resetButtonState(button, originalContent);
169 alert(yatraThemeWizardI18n.installationFailedInvalidResponse);
170 return;
171 }
172 }
173
174 if (jsonResponse && jsonResponse.success) {
175 // Theme installed successfully, now activate it
176 button.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="animation: spin 1s linear infinite;"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"></circle><path d="M12 2v10l4 2" fill="none" stroke="currentColor" stroke-width="2"></path></svg> ' + yatraThemeWizardI18n.activating;
177
178 jQuery.ajax({
179 url: ajaxurl,
180 type: 'POST',
181 data: {
182 action: 'yatra_activate_theme',
183 theme_slug: themeSlug,
184 nonce: '<?php echo wp_create_nonce('yatra_theme_actions'); ?>'
185 },
186 success: function(activateResponse) {
187 window.YATRA_DEBUG && console.log('Activation response:', activateResponse); // Debug log
188 if (activateResponse && activateResponse.success) {
189 // Update UI dynamically to show activated state
190 updateThemeCardToActivated();
191 } else {
192 resetButtonState(button, originalContent);
193 const errorMsg = activateResponse && activateResponse.data ? activateResponse.data : yatraThemeWizardI18n.unknownActivationError;
194 alert(yatraThemeWizardI18n.activationFailedPrefix + ' ' + errorMsg);
195 }
196 },
197 error: function(xhr, status, error) {
198 window.YATRA_DEBUG && console.log('Activation AJAX error:', {xhr: xhr, status: status, error: error}); // Debug log
199 resetButtonState(button, originalContent);
200 alert(yatraThemeWizardI18n.activationRequestFailed);
201 }
202 });
203 } else {
204 resetButtonState(button, originalContent);
205 const errorMsg = jsonResponse && jsonResponse.data ? jsonResponse.data : yatraThemeWizardI18n.unknownInstallationError;
206 alert(yatraThemeWizardI18n.installationFailedPrefix + ' ' + errorMsg);
207 }
208 },
209 error: function() {
210 button.innerHTML = originalContent;
211 button.disabled = false;
212 alert(yatraThemeWizardI18n.installationRequestFailed);
213 }
214 });
215 }
216
217 function activateTheme(themeSlug) {
218 const button = event.target;
219 const originalContent = button.innerHTML;
220 const yatraThemeWizardI18n = {
221 activating: <?php echo wp_json_encode(__('Activating...', 'yatra')); ?>,
222 activationFailedPrefix: <?php echo wp_json_encode(__('Activation failed:', 'yatra')); ?>,
223 activationRequestFailed: <?php echo wp_json_encode(__('Activation request failed. Please try again.', 'yatra')); ?>,
224 unknownActivationError: <?php echo wp_json_encode(__('Unknown activation error', 'yatra')); ?>
225 };
226
227 // Show loading state with spinner
228 button.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="animation: spin 1s linear infinite;"><circle cx="12" cy="12" r="10" fill="none" stroke="currentColor" stroke-width="2"></circle><path d="M12 2v10l4 2" fill="none" stroke="currentColor" stroke-width="2"></path></svg> ' + yatraThemeWizardI18n.activating;
229 button.disabled = true;
230 button.style.cursor = 'not-allowed';
231 button.style.opacity = '0.7';
232
233 // Add CSS animation for spinner if not already added
234 if (!document.querySelector('#spinner-style')) {
235 const style = document.createElement('style');
236 style.id = 'spinner-style';
237 style.textContent = '@keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }';
238 document.head.appendChild(style);
239 }
240
241 // Make AJAX request to activate theme
242 jQuery.ajax({
243 url: ajaxurl,
244 type: 'POST',
245 data: {
246 action: 'yatra_activate_theme',
247 theme_slug: themeSlug,
248 nonce: '<?php echo wp_create_nonce('yatra_theme_actions'); ?>'
249 },
250 success: function(response) {
251 window.YATRA_DEBUG && console.log('Activation response:', response); // Debug log
252 if (response && response.success) {
253 // Update UI dynamically to show activated state
254 updateThemeCardToActivated();
255 } else {
256 resetButtonState(button, originalContent);
257 const errorMsg = response && response.data ? response.data : yatraThemeWizardI18n.unknownActivationError;
258 alert(yatraThemeWizardI18n.activationFailedPrefix + ' ' + errorMsg);
259 }
260 },
261 error: function(xhr, status, error) {
262 window.YATRA_DEBUG && console.log('Activation AJAX error:', {xhr: xhr, status: status, error: error}); // Debug log
263 resetButtonState(button, originalContent);
264 alert(yatraThemeWizardI18n.activationRequestFailed);
265 }
266 });
267 }
268
269 function resetButtonState(button, originalContent) {
270 button.innerHTML = originalContent;
271 button.disabled = false;
272 button.style.cursor = 'pointer';
273 button.style.opacity = '1';
274 }
275
276 function updateThemeCardToActivated() {
277 // Find the theme card and update it to show activated state
278 const themeCard = document.querySelector('.theme-card-full');
279 if (!themeCard) return;
280
281 // Remove any existing action blocks
282 const actionBlocks = themeCard.querySelectorAll('div[style*="background: #fef3c7"], div[style*="background: #eff6ff"]');
283 actionBlocks.forEach(block => block.remove());
284
285 // Add "Activated" badge if not already present
286 const header = themeCard.querySelector('div[style*="align-items: center; gap: 12px"]');
287 if (header) {
288 // Remove existing "Activated" badge if present
289 const existingBadge = header.querySelector('span[style*="background: #10b981"]');
290 if (existingBadge) existingBadge.remove();
291
292 // Add new "Activated" badge
293 const activatedBadge = document.createElement('span');
294 activatedBadge.style.cssText = 'padding: 4px 12px; background: #10b981; color: #fff; font-size: 11px; font-weight: 700; border-radius: 12px; text-transform: uppercase; letter-spacing: 0.05em;';
295 activatedBadge.textContent = '<?php esc_html_e('Activated', 'yatra'); ?>';
296 header.appendChild(activatedBadge);
297 }
298
299 // Show success message briefly
300 const successMsg = document.createElement('div');
301 successMsg.style.cssText = 'background: #d1fae5; border: 1px solid #10b981; border-radius: 8px; padding: 16px; margin-bottom: 20px; text-align: center; color: #065f46; font-weight: 600;';
302 successMsg.innerHTML = `
303 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="#10b981" stroke-width="2.5" style="display: inline-block; vertical-align: middle; margin-right: 8px;">
304 <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path>
305 <polyline points="22 4 12 14.01 9 11.01"></polyline>
306 </svg>
307 <?php esc_html_e('Theme activated successfully!', 'yatra'); ?>
308 `;
309
310 // Insert success message after the description
311 const description = themeCard.querySelector('p[style*="color: #6b7280"]');
312 if (description && description.nextElementSibling) {
313 description.parentNode.insertBefore(successMsg, description.nextElementSibling);
314 }
315
316 // Remove success message after 3 seconds
317 setTimeout(() => {
318 if (successMsg.parentNode) {
319 successMsg.remove();
320 }
321 }, 3000);
322 }
323 </script>
324