PluginProbe
Subscriptions for WooCommerce with Stripe Recurring Payments / 2.3.0
Subscriptions for WooCommerce with Stripe Recurring Payments v2.3.0
2.4.0 2.3.0 2.2.0 2.1.0 2.0.0 1.11.2 1.11.1 1.11.0 1.10.9 1.10.8 1.10.7 1.10.6 1.10.5 1.10.4 1.10.3 1.10.2 1.10.1 1.10.0 1.9.6 1.9.5 trunk 1.3.0 1.3.1 1.3.2 1.4.0 All 65 releases
← All changes | includes/Admin/views/onboarding-wizard.php +498 -1500 1.10.2 → 2.3.0 View file →
@@ -1,9 +1,15 @@
1 1 <?php
2 2 /**
3 - * Onboarding Wizard Template
4 - * SPA-style: all pages rendered at once, JS controls visibility
3 + * Onboarding Wizard Template.
5 4 *
5 + * SPA-style: every section is rendered at once and JS toggles visibility.
6 + * Flow: Create Plan (type + name) -> Set Frequency (duration) ->
7 + * Connect to a Product -> Finish. A persistent right-rail preview shows the
8 + * plan → durations → products flow and fills in live as each step is filled.
9 + * The plan (group), duration (term) and product relation are created through
10 + * the Plans REST API; only product creation uses admin-ajax.
11 + *
6 12 * @package SpringDevs\Subscription\Admin
7 13 */
8 14
9 15 if ( ! defined( 'ABSPATH' ) ) {
@@ -9,1579 +15,571 @@
9 15 if ( ! defined( 'ABSPATH' ) ) {
10 16 exit;
11 17 }
12 18
13 -// Get wizard data from session
14 -$session_data = isset( $_SESSION['subscrpt_onboarding_wizard'] ) ? $_SESSION['subscrpt_onboarding_wizard'] : array();
15 -$wizard_page = isset( $session_data['page'] ) ? (int) $session_data['page'] : 1;
16 -$product_id = isset( $session_data['product_id'] ) ? (int) $session_data['product_id'] : 0;
17 -$subscriptions_url = admin_url( 'admin.php?page=wp-subscription' );
18 -$is_pro = subscrpt_pro_activated();
19 +$is_pro = subscrpt_pro_activated();
20 +$currency_symbol = get_woocommerce_currency_symbol();
19 21
20 -// Get existing products for dropdown
21 -$args = array(
22 - 'post_type' => 'product',
23 - 'posts_per_page' => -1,
24 - 'post_status' => 'any',
25 - 'orderby' => 'title',
26 - 'order' => 'ASC',
22 +// Whether the store has any product at all — decides the connect step's shape.
23 +$has_products = (bool) wc_get_products(
24 + array(
25 + 'status' => array( 'publish', 'draft', 'pending', 'private' ),
26 + 'limit' => 1,
27 + 'return' => 'ids',
28 + )
27 29 );
28 -$products = get_posts( $args );
29 30
30 -// Load product if exists
31 -$product = null;
32 -if ( $product_id > 0 ) {
33 - $product = wc_get_product( $product_id );
34 -}
31 +// Plan types. Only "recurring" is available on the free plugin; the others are
32 +// shown Pro-locked so the choice is visible but not selectable without Pro.
33 +$plan_types = array(
34 + array(
35 + 'key' => 'recurring',
36 + 'label' => __( 'Recurring', 'subscription' ),
37 + 'desc' => __( 'Charge on a repeating schedule.', 'subscription' ),
38 + 'name' => __( 'Recurring Subscription', 'subscription' ),
39 + 'pro' => false,
40 + 'icon' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="23 4 23 10 17 10"/><polyline points="1 20 1 14 7 14"/><path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15"/></svg>',
41 + ),
42 + array(
43 + 'key' => 'subscribe_save',
44 + 'label' => __( 'Subscribe & Save', 'subscription' ),
45 + 'desc' => __( 'Recurring with a discount.', 'subscription' ),
46 + 'name' => __( 'Subscribe & Save', 'subscription' ),
47 + 'pro' => true,
48 + 'icon' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"/><line x1="7" y1="7" x2="7.01" y2="7"/></svg>',
49 + ),
50 + array(
51 + 'key' => 'installments',
52 + 'label' => __( 'Installments', 'subscription' ),
53 + 'desc' => __( 'Split a price into payments.', 'subscription' ),
54 + 'name' => __( 'Installment Plan', 'subscription' ),
55 + 'pro' => true,
56 + 'icon' => '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg>',
57 + ),
58 +);
59 +
60 +$interval_options = array(
61 + array(
62 + 'value' => 'day',
63 + 'label' => __( 'Day(s)', 'subscription' ),
64 + ),
65 + array(
66 + 'value' => 'week',
67 + 'label' => __( 'Week(s)', 'subscription' ),
68 + ),
69 + array(
70 + 'value' => 'month',
71 + 'label' => __( 'Month(s)', 'subscription' ),
72 + ),
73 + array(
74 + 'value' => 'year',
75 + 'label' => __( 'Year(s)', 'subscription' ),
76 + ),
77 +);
78 +
79 +$avatar_palette = array(
80 + array(
81 + 'bg' => '#fde8d8',
82 + 'fg' => '#b85c20',
83 + ),
84 + array(
85 + 'bg' => '#dbeafe',
86 + 'fg' => '#1d4ed8',
87 + ),
88 + array(
89 + 'bg' => '#ede9fe',
90 + 'fg' => '#6d28d9',
91 + ),
92 + array(
93 + 'bg' => '#d1fae5',
94 + 'fg' => '#065f46',
95 + ),
96 + array(
97 + 'bg' => '#fce7f3',
98 + 'fg' => '#9d174d',
99 + ),
100 +);
101 +
102 +// Small SVG icons reused inside the preview graph nodes.
103 +$subscrpt_icon_cal = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg>';
104 +$subscrpt_icon_box = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 0 1-8 0"/></svg>';
105 +$subscrpt_icon_plan = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"/><polyline points="2 17 12 22 22 17"/><polyline points="2 12 12 17 22 12"/></svg>';
35 106 ?>
36 -<style>
37 -#subscrpt-onboarding-wizard {
38 - max-width: 680px;
39 -}
40 -#subscrpt-onboarding-wizard:has(#subscrpt-section-1.active),
41 -#subscrpt-onboarding-wizard:has(#subscrpt-section-2.active) {
42 - max-width: 900px;
43 -}
44 -/* Page sections — all rendered, JS toggles visibility */
45 -.wizard-section {
46 - display: none;
47 -}
48 -.wizard-section.active {
49 - display: block;
50 -}
51 -/* Stepper */
52 -.wpsubs-wizard-stepper {
53 - display: flex;
54 - align-items: center;
55 - width: fit-content;
56 - margin: 0 auto 32px;
57 - gap: 0;
58 -}
59 -.wpsubs-wizard-stepper__step {
60 - display: flex;
61 - align-items: center;
62 - gap: 10px;
63 -}
64 -.wpsubs-wizard-stepper__num {
65 - width: 28px;
66 - height: 28px;
67 - border-radius: 50%;
68 - background: var(--wpsubs-surface-muted);
69 - border: 1.5px solid var(--wpsubs-border);
70 - display: flex;
71 - align-items: center;
72 - justify-content: center;
73 - font-size: 12px;
74 - font-weight: 600;
75 - color: var(--wpsubs-text-muted);
76 - flex-shrink: 0;
77 - transition: all 0.2s;
78 -}
79 -.wpsubs-wizard-stepper__step.active .wpsubs-wizard-stepper__num {
80 - background: var(--wpsubs-brand);
81 - border-color: var(--wpsubs-brand);
82 - color: var(--wpsubs-surface);
83 -}
84 -.wpsubs-wizard-stepper__step.done .wpsubs-wizard-stepper__num {
85 - background: var(--wpsubs-brand);
86 - border-color: var(--wpsubs-brand);
87 - color: transparent;
88 - position: relative;
89 -}
90 -.wpsubs-wizard-stepper__step.done .wpsubs-wizard-stepper__num::after {
91 - content: "✓";
92 - position: absolute;
93 - color: var(--wpsubs-surface);
94 - font-size: 11px;
95 - font-weight: 700;
96 - top: 50%;
97 - left: 50%;
98 - transform: translate(-50%, -50%);
99 -}
100 -.wpsubs-wizard-stepper__step.done + .wpsubs-wizard-stepper__line {
101 - background: var(--wpsubs-brand);
102 -}
103 -.wpsubs-wizard-stepper__label {
104 - font-size: 13px;
105 - font-weight: 500;
106 - color: var(--wpsubs-text-muted);
107 - white-space: nowrap;
108 - transition: color 0.2s;
109 -}
110 -.wpsubs-wizard-stepper__step.active .wpsubs-wizard-stepper__label {
111 - color: var(--wpsubs-brand);
112 -}
113 -.wpsubs-wizard-stepper__line {
114 - width: 48px;
115 - flex-shrink: 0;
116 - height: 1px;
117 - background: var(--wpsubs-border);
118 - margin: 0 8px;
119 -}
120 -/* Card */
121 -.wizard-card {
122 - background: var(--wpsubs-surface);
123 - border: 1px solid var(--wpsubs-border);
124 - border-radius: var(--wpsubs-radius);
125 - padding: 28px 32px;
126 - margin-bottom: 16px;
127 -}
128 -/* Form rows (shared) */
129 -.form-row {
130 - margin-bottom: 16px;
131 -}
132 -.form-row label {
133 - display: block;
134 - font-size: 13px;
135 - font-weight: 500;
136 - color: var(--wpsubs-text);
137 - margin-bottom: 6px;
138 -}
139 -/* Page 2 */
140 -.p2-page-title {
141 - font-size: 22px;
142 - font-weight: 800;
143 - color: var(--wpsubs-text);
144 - margin: 0 0 8px;
145 - line-height: 1.25;
146 -}
147 -.p2-page-subtitle {
148 - font-size: 13.5px;
149 - color: var(--wpsubs-text-muted);
150 - line-height: 1.6;
151 - margin: 0 0 28px;
152 -}
153 -.p2-section-block {
154 - margin-bottom: 28px;
155 -}
156 -.p2-section-label {
157 - font-size: 14px;
158 - font-weight: 700;
159 - color: var(--wpsubs-text);
160 - margin: 0 0 4px;
161 -}
162 -.p2-section-desc {
163 - font-size: 13px;
164 - color: var(--wpsubs-text-muted);
165 - margin: 0 0 14px;
166 -}
167 -/* Option cards */
168 -.p2-option-cards {
169 - display: grid;
170 - grid-template-columns: 1fr 1fr;
171 - gap: 12px;
172 - margin-bottom: 12px;
173 -}
174 -.p2-option-card {
175 - position: relative;
176 - display: flex;
177 - flex-direction: column;
178 - gap: 6px;
179 - padding: 16px;
180 - border: 1px solid var(--wpsubs-border);
181 - border-radius: var(--wpsubs-radius);
182 - background: var(--wpsubs-surface);
183 - cursor: pointer;
184 - text-align: left;
185 - transition: border-color 0.15s, background 0.15s;
186 -}
187 -.p2-option-card:hover {
188 - border-color: var(--wpsubs-brand);
189 -}
190 -.p2-option-card.active {
191 - border-color: var(--wpsubs-brand);
192 - background: var(--wpsubs-brand-light);
193 -}
194 -.p2-option-card__check {
195 - position: absolute;
196 - top: 10px;
197 - right: 10px;
198 - width: 20px;
199 - height: 20px;
200 - border-radius: 50%;
201 - background: var(--wpsubs-brand);
202 - display: none;
203 - align-items: center;
204 - justify-content: center;
205 - color: var(--wpsubs-surface);
206 - font-size: 11px;
207 - font-weight: 700;
208 -}
209 -.p2-option-card.active .p2-option-card__check {
210 - display: flex;
211 -}
212 -.p2-option-card__icon {
213 - width: 32px;
214 - height: 32px;
215 - border-radius: 6px;
216 - border: 1px solid var(--wpsubs-border);
217 - background: var(--wpsubs-surface);
218 - display: flex;
219 - align-items: center;
220 - justify-content: center;
221 - color: var(--wpsubs-text-muted);
222 - margin-bottom: 4px;
223 -}
224 -.p2-option-card.active .p2-option-card__icon {
225 - border-color: var(--wpsubs-brand);
226 - color: var(--wpsubs-brand);
227 -}
228 -.p2-option-card__title {
229 - font-size: 13px;
230 - font-weight: 700;
231 - color: var(--wpsubs-text);
232 - margin: 0;
233 -}
234 -.p2-option-card__desc {
235 - font-size: 12px;
236 - color: var(--wpsubs-text-muted);
237 - margin: 0;
238 - line-height: 1.5;
239 -}
240 -/* Selected product chip */
241 -.p2-selected-product {
242 - display: flex;
243 - align-items: center;
244 - gap: 12px;
245 - padding: 10px 14px;
246 - border: 1px solid var(--wpsubs-border);
247 - border-radius: var(--wpsubs-radius);
248 - background: var(--wpsubs-surface);
249 - margin-bottom: 4px;
250 -}
251 -.p2-selected-product__avatar {
252 - width: 36px;
253 - height: 36px;
254 - border-radius: 6px;
255 - background: var(--wpsubs-surface-muted);
256 - border: 1px solid var(--wpsubs-border);
257 - display: flex;
258 - align-items: center;
259 - justify-content: center;
260 - font-size: 11px;
261 - font-weight: 700;
262 - color: var(--wpsubs-text-muted);
263 - flex-shrink: 0;
264 -}
265 -.p2-selected-product__info {
266 - flex: 1;
267 - min-width: 0;
268 -}
269 -.p2-selected-product__name {
270 - font-size: 13px;
271 - font-weight: 600;
272 - color: var(--wpsubs-text);
273 - margin: 0 0 2px;
274 - white-space: nowrap;
275 - overflow: hidden;
276 - text-overflow: ellipsis;
277 -}
278 -.p2-selected-product__meta {
279 - font-size: 12px;
280 - color: var(--wpsubs-text-muted);
281 - margin: 0;
282 -}
283 -.p2-selected-product__clear {
284 - background: none;
285 - border: none;
286 - cursor: pointer;
287 - color: var(--wpsubs-text-muted);
288 - font-size: 18px;
289 - line-height: 1;
290 - padding: 0 4px;
291 - flex-shrink: 0;
292 - transition: color 0.15s;
293 -}
294 -.p2-selected-product__clear:hover {
295 - color: var(--wpsubs-text);
296 -}
297 -/* Section 2 body */
298 -.p2-body {
299 - display: grid;
300 - grid-template-columns: 1fr 260px;
301 - gap: 32px;
302 - align-items: start;
303 -}
304 -.p2-form-grid {
305 - display: grid;
306 - grid-template-columns: 1fr 1fr;
307 - gap: 16px;
308 - margin-bottom: 16px;
309 -}
310 -.p2-form-grid .form-row {
311 - margin-bottom: 0;
312 -}
313 -.p2-input-wrap {
314 - position: relative;
315 -}
316 -.p2-input-prefix {
317 - position: absolute;
318 - left: 11px;
319 - top: 50%;
320 - transform: translateY(-50%);
321 - font-size: 13px;
322 - color: var(--wpsubs-text-muted);
323 - pointer-events: none;
324 - z-index: 1;
325 -}
326 -.p2-input-prefix + .wpsubs-input {
327 - padding-left: 24px !important;
328 -}
329 -.p2-input-suffix {
330 - position: absolute;
331 - right: 11px;
332 - top: 50%;
333 - transform: translateY(-50%);
334 - font-size: 13px;
335 - color: var(--wpsubs-text-muted);
336 - pointer-events: none;
337 -}
338 -.p2-input-suffix-input {
339 - padding-right: 44px !important;
340 -}
341 -.p2-field-hint {
342 - font-size: 12px;
343 - color: var(--wpsubs-text-muted);
344 - margin-top: 5px;
345 - line-height: 1.4;
346 -}
347 -.p2-label-optional {
348 - font-weight: 400;
349 - color: var(--wpsubs-text-subtle);
350 - font-size: 12px;
351 - margin-left: 4px;
352 -}
353 -/* Page 2 right preview */
354 -.p2-preview-col {
355 - position: sticky;
356 - top: 80px;
357 -}
358 -.p2-preview-col-label {
359 - font-size: 11px;
360 - font-weight: 700;
361 - letter-spacing: 0.08em;
362 - text-transform: uppercase;
363 - color: var(--wpsubs-text-muted);
364 - margin: 0 0 10px;
365 -}
366 -.p2-preview-col-desc {
367 - font-size: 12px;
368 - color: var(--wpsubs-text-muted);
369 - line-height: 1.5;
370 - margin-top: 10px;
371 -}
372 -/* Page 2 nav (outside card) */
373 -.p2-nav {
374 - display: flex;
375 - align-items: center;
376 - justify-content: space-between;
377 - margin-top: 16px;
378 -}
379 -.p2-nav-back {
380 - background: none;
381 - border: none;
382 - cursor: pointer;
383 - font-size: 13px;
384 - color: var(--wpsubs-text-muted);
385 - display: flex;
386 - align-items: center;
387 - gap: 4px;
388 - padding: 0;
389 - transition: color 0.15s;
390 -}
391 -.p2-nav-back:hover {
392 - color: var(--wpsubs-text);
393 -}
394 -/* Product search */
395 -.p2-product-search {
396 - position: relative;
397 -}
398 -.p2-product-search__input-wrap {
399 - display: flex;
400 - align-items: center;
401 - gap: 8px;
402 - border: 1px solid var(--wpsubs-border);
403 - border-radius: var(--wpsubs-radius);
404 - padding: 0 12px;
405 - background: var(--wpsubs-surface);
406 - transition: border-color 0.15s, box-shadow 0.15s;
407 -}
408 -.p2-product-search__input-wrap:focus-within {
409 - border-color: var(--wpsubs-brand);
410 - box-shadow: 0 0 0 3px var(--wpsubs-brand-ring);
411 -}
412 -.p2-product-search__icon {
413 - color: var(--wpsubs-text-muted);
414 - flex-shrink: 0;
415 -}
416 -.p2-product-search__input,
417 -.p2-product-search__input:focus {
418 - flex: 1;
419 - border: none !important;
420 - outline: none !important;
421 - box-shadow: none !important;
422 - padding: 9px 0 !important;
423 - font-size: 13px;
424 - background: transparent !important;
425 -}
426 -.p2-product-search__dropdown {
427 - position: absolute;
428 - top: calc(100% + 4px);
429 - left: 0;
430 - right: 0;
431 - background: var(--wpsubs-surface);
432 - border: 1px solid var(--wpsubs-border);
433 - border-radius: var(--wpsubs-radius);
434 - box-shadow: var(--wpsubs-shadow-md);
435 - z-index: 999;
436 - max-height: 300px;
437 - overflow-y: auto;
438 - padding: 4px;
439 -}
440 -.p2-product-search__item {
441 - display: flex;
442 - align-items: center;
443 - gap: 12px;
444 - padding: 9px 10px;
445 - border-radius: var(--wpsubs-radius-sm);
446 - cursor: pointer;
447 - transition: background 0.1s;
448 -}
449 -.p2-product-search__item:hover {
450 - background: var(--wpsubs-surface-muted);
451 -}
452 -.p2-product-search__avatar {
453 - width: 36px;
454 - height: 36px;
455 - border-radius: 8px;
456 - display: flex;
457 - align-items: center;
458 - justify-content: center;
459 - font-size: 12px;
460 - font-weight: 700;
461 - flex-shrink: 0;
462 -}
463 -.p2-product-search__info {
464 - flex: 1;
465 - min-width: 0;
466 -}
467 -.p2-product-search__name {
468 - font-size: 13px;
469 - font-weight: 600;
470 - color: var(--wpsubs-text);
471 - margin: 0 0 2px;
472 - white-space: nowrap;
473 - overflow: hidden;
474 - text-overflow: ellipsis;
475 -}
476 -.p2-product-search__meta {
477 - font-size: 12px;
478 - color: var(--wpsubs-text-muted);
479 - margin: 0;
480 -}
481 -.p2-product-search__price {
482 - font-size: 13px;
483 - font-weight: 600;
484 - color: var(--wpsubs-text);
485 - white-space: nowrap;
486 - flex-shrink: 0;
487 -}
488 -.p2-product-search__empty {
489 - padding: 12px 10px;
490 - font-size: 13px;
491 - color: var(--wpsubs-text-muted);
492 - text-align: center;
493 -}
494 -.p2-product-search__item--locked {
495 - opacity: 0.55;
496 - cursor: not-allowed;
497 -}
498 -/* Billing every group — number input + standalone adv-select */
499 -.p2-billing-group {
500 - width: 100%;
501 -}
502 -.p2-billing-group .p2-billing-per-input {
503 - flex-grow: 1;
504 -}
505 -#subscrpt-billing-period-select {
506 - width: 100%;
507 -}
508 -/* Pro badge + locked fields */
509 -.p2-pro-badge {
510 - display: inline-flex;
511 - align-items: center;
512 - background: var(--wpsubs-brand);
513 - color: var(--wpsubs-surface);
514 - font-size: 10px;
515 - font-weight: 700;
516 - padding: 2px 6px;
517 - border-radius: 3px;
518 - text-transform: uppercase;
519 - letter-spacing: 0.04em;
520 - margin-left: 6px;
521 - vertical-align: middle;
522 -}
523 -.p2-field-pro-locked {
524 - opacity: 0.6;
525 -}
526 -/* Variation picker */
527 -.p2-variation-picker {
528 - margin-top: 12px;
529 -}
530 -.p2-variation-picker__label {
531 - font-size: 11px;
532 - font-weight: 700;
533 - letter-spacing: 0.06em;
534 - text-transform: uppercase;
535 - color: var(--wpsubs-text-muted);
536 - margin: 0 0 8px;
537 -}
538 -.p2-variation-picker__loading {
539 - font-size: 13px;
540 - color: var(--wpsubs-text-muted);
541 - padding: 10px 0;
542 -}
543 -.p2-variation-picker__list {
544 - border: 1px solid var(--wpsubs-border);
545 - border-radius: var(--wpsubs-radius);
546 - overflow: hidden;
547 -}
548 -.p2-variation-item {
549 - display: flex;
550 - align-items: center;
551 - gap: 12px;
552 - padding: 10px 12px;
553 - cursor: pointer;
554 - transition: background 0.1s;
555 - border-bottom: 1px solid var(--wpsubs-border);
556 -}
557 -.p2-variation-item:last-child {
558 - border-bottom: none;
559 -}
560 -.p2-variation-item:hover {
561 - background: var(--wpsubs-surface-muted);
562 -}
563 -.p2-variation-item.selected {
564 - background: var(--wpsubs-brand-light);
565 -}
566 -.p2-variation-item__check {
567 - width: 18px;
568 - height: 18px;
569 - border-radius: 50%;
570 - border: 1.5px solid var(--wpsubs-border);
571 - flex-shrink: 0;
572 - display: flex;
573 - align-items: center;
574 - justify-content: center;
575 - font-size: 10px;
576 - font-weight: 700;
577 - color: transparent;
578 - transition: all 0.15s;
579 -}
580 -.p2-variation-item.selected .p2-variation-item__check {
581 - background: var(--wpsubs-brand);
582 - border-color: var(--wpsubs-brand);
583 - color: var(--wpsubs-surface);
584 -}
585 -.p2-variation-item__info {
586 - flex: 1;
587 - min-width: 0;
588 -}
589 -.p2-variation-item__name {
590 - font-size: 13px;
591 - font-weight: 500;
592 - color: var(--wpsubs-text);
593 - margin: 0;
594 - white-space: nowrap;
595 - overflow: hidden;
596 - text-overflow: ellipsis;
597 -}
598 -.p2-variation-item__meta {
599 - font-size: 12px;
600 - color: var(--wpsubs-text-muted);
601 - margin: 0;
602 -}
603 -.p2-variation-item__price {
604 - font-size: 13px;
605 - font-weight: 600;
606 - color: var(--wpsubs-text);
607 - white-space: nowrap;
608 - flex-shrink: 0;
609 -}
610 -/* Page 3 */
611 -.p3-card {
612 - text-align: center;
613 - padding: 40px 40px 32px;
614 -}
615 -.p3-success-icon {
616 - width: 52px;
617 - height: 52px;
618 - border-radius: 50%;
619 - background: var(--wpsubs-brand);
620 - display: flex;
621 - align-items: center;
622 - justify-content: center;
623 - margin: 0 auto 20px;
624 -}
625 -.p3-heading {
626 - font-size: 24px;
627 - font-weight: 700;
628 - color: var(--wpsubs-text);
629 - margin-bottom: 10px;
630 -}
631 -.p3-subtext {
632 - font-size: 13.5px;
633 - color: var(--wpsubs-text-muted);
634 - line-height: 1.6;
635 - max-width: 440px;
636 - margin: 0 auto 28px;
637 -}
638 -/* Product card */
639 -.p3-product-card {
640 - border: 1px solid var(--wpsubs-border);
641 - border-radius: var(--wpsubs-radius);
642 - overflow: hidden;
643 - margin-bottom: 24px;
644 - text-align: left;
645 -}
646 -.p3-product-card__header {
647 - display: grid;
648 - grid-template-columns: 1fr 160px 110px;
649 - padding: 8px 16px;
650 - border-bottom: 1px solid var(--wpsubs-border);
651 -}
652 -.p3-product-card__header span {
653 - font-size: 10px;
654 - font-weight: 600;
655 - letter-spacing: 0.06em;
656 - color: var(--wpsubs-text-muted);
657 - text-transform: uppercase;
658 -}
659 -.p3-product-card__row {
660 - display: grid;
661 - grid-template-columns: 1fr 160px 110px;
662 - align-items: center;
663 - padding: 14px 16px;
664 -}
665 -.p3-product-card__product {
666 - display: flex;
667 - align-items: center;
668 - gap: 12px;
669 -}
670 -.p3-product-avatar {
671 - width: 36px;
672 - height: 36px;
673 - border-radius: 6px;
674 - background: #fde8d8;
675 - color: #c2440f;
676 - font-size: 12px;
677 - font-weight: 700;
678 - display: flex;
679 - align-items: center;
680 - justify-content: center;
681 - flex-shrink: 0;
682 -}
683 -.p3-product-name {
684 - font-size: 13px;
685 - font-weight: 600;
686 - color: var(--wpsubs-text);
687 - margin: 0 0 2px;
688 -}
689 -.p3-product-meta {
690 - font-size: 11.5px;
691 - color: var(--wpsubs-text-muted);
692 - margin: 0;
693 -}
694 -.p3-product-card__status {
695 - display: flex;
696 - flex-direction: column;
697 - gap: 4px;
698 -}
699 -.p3-status-badge {
700 - display: inline-flex;
701 - align-items: center;
702 - gap: 5px;
703 - background: #ecfdf5;
704 - color: #065f46;
705 - font-size: 12px;
706 - font-weight: 500;
707 - padding: 3px 8px 3px 6px;
708 - border-radius: 12px;
709 - width: fit-content;
710 -}
711 -.p3-status-badge__dot {
712 - width: 6px;
713 - height: 6px;
714 - border-radius: 50%;
715 - background: #10b981;
716 - flex-shrink: 0;
717 -}
718 -.p3-status-sub {
719 - font-size: 11.5px;
720 - color: var(--wpsubs-text-muted);
721 - margin: 0;
722 -}
723 -.p3-product-card__price {
724 - text-align: right;
725 -}
726 -.p3-price-amount {
727 - display: block;
728 - font-size: 15px;
729 - font-weight: 700;
730 - color: var(--wpsubs-text);
731 -}
732 -.p3-price-period {
733 - font-size: 11.5px;
734 - color: var(--wpsubs-text-muted);
735 -}
736 -/* What now section */
737 -.p3-what-now-label {
738 - font-size: 10.5px;
739 - font-weight: 700;
740 - letter-spacing: 0.08em;
741 - color: var(--wpsubs-text-muted);
742 - text-transform: uppercase;
743 - text-align: left;
744 - margin-bottom: 8px;
745 -}
746 -.p3-action-rows {
747 - display: flex;
748 - flex-direction: column;
749 - gap: 0;
750 - border: 1px solid var(--wpsubs-border);
751 - border-radius: var(--wpsubs-radius);
752 - overflow: hidden;
753 - margin-bottom: 20px;
754 -}
755 -.p3-action-row {
756 - display: flex;
757 - align-items: center;
758 - gap: 14px;
759 - padding: 14px 16px;
760 - background: var(--wpsubs-surface);
761 - text-decoration: none;
762 - text-align: left;
763 - border: none;
764 - cursor: pointer;
765 - width: 100%;
766 - box-sizing: border-box;
767 - transition: background 0.12s;
768 - font-family: inherit;
769 -}
770 -.p3-action-row + .p3-action-row {
771 - border-top: 1px solid var(--wpsubs-border);
772 -}
773 -.p3-action-row:hover {
774 - background: var(--wpsubs-surface-muted);
775 -}
776 -.p3-action-row__icon {
777 - width: 34px;
778 - height: 34px;
779 - border: 1px solid var(--wpsubs-border);
780 - border-radius: var(--wpsubs-radius-sm);
781 - background: var(--wpsubs-surface-muted);
782 - display: flex;
783 - align-items: center;
784 - justify-content: center;
785 - flex-shrink: 0;
786 - color: var(--wpsubs-text-muted);
787 -}
788 -.p3-action-row__content {
789 - flex: 1;
790 - min-width: 0;
791 -}
792 -.p3-action-row__title {
793 - font-size: 13px;
794 - font-weight: 600;
795 - color: var(--wpsubs-text);
796 - margin: 0 0 2px;
797 -}
798 -.p3-action-row__desc {
799 - font-size: 12px;
800 - color: var(--wpsubs-text-muted);
801 - margin: 0;
802 -}
803 -.p3-action-row__chevron {
804 - color: var(--wpsubs-text-subtle);
805 - flex-shrink: 0;
806 -}
807 -/* Help footer */
808 -.p3-help-text {
809 - font-size: 12.5px;
810 - color: var(--wpsubs-text-muted);
811 - text-align: center;
812 -}
813 -.p3-help-link {
814 - color: var(--wpsubs-brand);
815 - text-decoration: none;
816 -}
817 -.p3-help-link:hover {
818 - text-decoration: underline;
819 -}
820 -/* Page 3 nav */
821 -.p3-nav {
822 - display: flex;
823 - align-items: center;
824 - justify-content: flex-end;
825 - gap: 10px;
826 - margin-top: 16px;
827 -}
828 -.p3-nav .wpsubs-btn {
829 - min-width: 140px;
830 - height: 36px;
831 - box-sizing: border-box;
832 -}
833 -/* Page 1 specific — two-column hero layout */
834 -#subscrpt-section-1 {
835 - max-width: 860px;
836 -}
837 -#subscrpt-section-1 .wizard-card {
838 - padding: 56px 48px;
839 - display: grid;
840 - grid-template-columns: 1fr 1fr;
841 - gap: 64px;
842 - align-items: center;
843 -}
844 -.p1-left {
845 - display: flex;
846 - flex-direction: column;
847 - gap: 0;
848 -}
849 -.p1-badge {
850 - display: inline-flex;
851 - align-items: center;
852 - gap: 6px;
853 - background: var(--wpsubs-brand-light);
854 - color: var(--wpsubs-brand);
855 - font-size: 12px;
856 - font-weight: 600;
857 - padding: 4px 10px;
858 - border-radius: 20px;
859 - border: 1px solid var(--wpsubs-border);
860 - margin-bottom: 20px;
861 - width: fit-content;
862 -}
863 -.p1-badge__dot {
864 - width: 7px;
865 - height: 7px;
866 - border-radius: 50%;
867 - background: var(--wpsubs-brand);
868 - flex-shrink: 0;
869 -}
870 -.p1-heading {
871 - font-size: 26px;
872 - font-weight: 800;
873 - color: var(--wpsubs-text);
874 - line-height: 1.25;
875 - margin: 0 0 20px;
876 -}
877 -.p1-heading__accent {
878 - color: var(--wpsubs-brand);
879 -}
880 -.p1-desc {
881 - font-size: 13.5px;
882 - color: var(--wpsubs-text-muted);
883 - line-height: 1.6;
884 - margin: 0 0 24px;
885 -}
886 -.p1-bullets {
887 - list-style: none;
888 - padding: 0;
889 - margin: 0 0 36px;
890 - display: flex;
891 - flex-direction: column;
892 - gap: 12px;
893 -}
894 -.p1-bullets li {
895 - display: flex;
896 - align-items: center;
897 - gap: 8px;
898 - font-size: 13px;
899 - color: var(--wpsubs-text);
900 -}
901 -.p1-bullet-dot {
902 - width: 7px;
903 - height: 7px;
904 - border-radius: 50%;
905 - background: var(--wpsubs-brand);
906 - flex-shrink: 0;
907 -}
908 -.p1-actions {
909 - display: flex;
910 - align-items: center;
911 - gap: 16px;
912 - flex-wrap: wrap;
913 -}
914 -.p1-skip {
915 - font-size: 13px;
916 - color: var(--wpsubs-text-muted);
917 - background: none;
918 - border: none;
919 - cursor: pointer;
920 - padding: 0;
921 - text-decoration: none;
922 -}
923 -.p1-skip:hover {
924 - color: var(--wpsubs-text);
925 -}
926 -/* Right — product preview mockup */
927 -.p1-right {
928 - background: var(--wpsubs-surface-muted);
929 - border-radius: var(--wpsubs-radius);
930 - padding: 20px 20px 14px;
931 - border: 1px solid var(--wpsubs-border);
932 - transform: rotate(-3deg);
933 - transform-origin: center center;
934 -}
935 -.p1-preview-label {
936 - font-size: 13px;
937 - font-weight: 600;
938 - color: var(--wpsubs-text);
939 - margin: 0 0 2px;
940 -}
941 -.p1-preview-sublabel {
942 - font-size: 12px;
943 - color: var(--wpsubs-text-muted);
944 - margin: 0 0 16px;
945 -}
946 -.p1-preview-card {
947 - background: var(--wpsubs-surface);
948 - border-radius: var(--wpsubs-radius);
949 - border: 1px solid var(--wpsubs-border);
950 - overflow: hidden;
951 - box-shadow: var(--wpsubs-shadow-md);
952 -}
953 -.p1-preview-img {
954 - width: 100%;
955 - height: 100px;
956 - background: linear-gradient(135deg, var(--wpsubs-brand-light) 0%, var(--wpsubs-surface-muted) 100%);
957 - display: flex;
958 - align-items: center;
959 - justify-content: center;
960 - flex-direction: column;
961 - gap: 6px;
962 - border-bottom: 1px solid var(--wpsubs-border);
963 -}
964 -.p1-preview-img svg {
965 - width: 36px;
966 - height: 36px;
967 - color: var(--wpsubs-brand);
968 - opacity: 0.8;
969 -}
970 -.p1-preview-img__dots {
971 - display: flex;
972 - gap: 4px;
973 -}
974 -.p1-preview-img__dots span {
975 - width: 5px;
976 - height: 5px;
977 - border-radius: 50%;
978 - background: var(--wpsubs-brand);
979 - opacity: 0.3;
980 -}
981 -.p1-preview-body {
982 - padding: 14px;
983 -}
984 -.p1-preview-name {
985 - font-size: 13px;
986 - font-weight: 700;
987 - text-align: center;
988 - color: var(--wpsubs-text);
989 - margin: 0 0 4px;
990 -}
991 -.p1-preview-price {
992 - font-size: 13px;
993 - text-align: center;
994 - color: var(--wpsubs-text);
995 - margin: 0 0 12px;
996 -}
997 -.p1-preview-price span {
998 - color: var(--wpsubs-text-muted);
999 - font-size: 12px;
1000 -}
1001 -.p1-preview-btn {
1002 - display: block;
1003 - width: 100%;
1004 - box-sizing: border-box;
1005 - background: var(--wpsubs-brand);
1006 - color: var(--wpsubs-surface);
1007 - text-align: center;
1008 - padding: 9px 12px;
1009 - border-radius: var(--wpsubs-radius-sm);
1010 - font-size: 13px;
1011 - font-weight: 600;
1012 - border: none;
1013 - cursor: default;
1014 - white-space: nowrap;
1015 - overflow: hidden;
1016 - text-overflow: ellipsis;
1017 -}
1018 -.p1-preview-skeletons {
1019 - margin-top: 10px;
1020 - display: flex;
1021 - flex-direction: column;
1022 - gap: 6px;
1023 -}
1024 -.p1-preview-skeleton {
1025 - height: 10px;
1026 - border-radius: 4px;
1027 - background: var(--wpsubs-border);
1028 -}
1029 -.p1-preview-skeleton:last-child {
1030 - width: 65%;
1031 -}
1032 -.p1-starts-here {
1033 - text-align: right;
1034 - font-size: 11px;
1035 - color: var(--wpsubs-brand);
1036 - margin-top: 12px;
1037 - font-style: italic;
1038 - display: flex;
1039 - align-items: center;
1040 - justify-content: flex-end;
1041 - gap: 4px;
1042 -}
1043 -@media (max-width: 680px) {
1044 - #subscrpt-section-1 .wizard-card {
1045 - grid-template-columns: 1fr;
1046 - }
1047 - .p1-right {
1048 - display: none;
1049 - }
1050 -}
1051 -</style>
107 +<div class="wpsubs-layout" id="subscrpt-onboarding-wizard">
1052 108
1053 -<div class="wpsubs-tw-root wpsubs-layout" id="subscrpt-onboarding-wizard">
1054 - <!-- Page 2+ only: stepper indicator -->
1055 - <div class="wpsubs-wizard-stepper" id="subscrpt-stepper" style="display:none;">
1056 - <div class="wpsubs-wizard-stepper__step active" data-step="1">
109 + <!-- Step indicator -->
110 + <div class="wpsubs-wizard-stepper" id="subscrpt-stepper">
111 + <div class="wpsubs-wizard-stepper__step" data-step="1">
1057 112 <div class="wpsubs-wizard-stepper__num">1</div>
1058 - <div class="wpsubs-wizard-stepper__label">Welcome</div>
113 + <div class="wpsubs-wizard-stepper__label"><?php esc_html_e( 'Plan', 'subscription' ); ?></div>
1059 114 </div>
1060 115 <div class="wpsubs-wizard-stepper__line"></div>
1061 116 <div class="wpsubs-wizard-stepper__step" data-step="2">
1062 117 <div class="wpsubs-wizard-stepper__num">2</div>
1063 - <div class="wpsubs-wizard-stepper__label">Product Setup</div>
118 + <div class="wpsubs-wizard-stepper__label"><?php esc_html_e( 'Durations', 'subscription' ); ?></div>
1064 119 </div>
1065 120 <div class="wpsubs-wizard-stepper__line"></div>
1066 121 <div class="wpsubs-wizard-stepper__step" data-step="3">
1067 122 <div class="wpsubs-wizard-stepper__num">3</div>
1068 - <div class="wpsubs-wizard-stepper__label"><?php esc_html_e( 'Done', 'subscription' ); ?></div>
123 + <div class="wpsubs-wizard-stepper__label"><?php esc_html_e( 'Product', 'subscription' ); ?></div>
1069 124 </div>
125 + <div class="wpsubs-wizard-stepper__line"></div>
126 + <div class="wpsubs-wizard-stepper__step" data-step="4">
127 + <div class="wpsubs-wizard-stepper__num">4</div>
128 + <div class="wpsubs-wizard-stepper__label"><?php esc_html_e( 'Finish', 'subscription' ); ?></div>
129 + </div>
1070 130 </div>
1071 131
1072 132 <!-- Hidden state -->
1073 - <input type="hidden" name="subscrpt_wizard_page" id="subscrpt-wizard-page" value="<?php echo esc_attr( $wizard_page ); ?>">
1074 - <input type="hidden" name="subscrpt_product_id" id="subscrpt-product-id" value="<?php echo esc_attr( $product_id ); ?>">
1075 - <input type="hidden" id="subscrpt-ajax-url" value="<?php echo esc_url( admin_url( 'admin-ajax.php' ) ); ?>">
1076 - <input type="hidden" id="subscrpt-subscriptions-url" value="<?php echo esc_url( admin_url( 'admin.php?page=wp-subscription' ) ); ?>">
133 + <input type="hidden" id="subscrpt-wizard-page" value="0">
134 + <input type="hidden" id="subscrpt-has-products" value="<?php echo $has_products ? '1' : '0'; ?>">
135 + <input type="hidden" id="subscrpt-plan-type" value="recurring">
1077 136 <?php wp_nonce_field( 'subscrpt_onboarding_wizard', 'subscrpt_wizard_nonce' ); ?>
1078 137
1079 - <!-- =========================================== -->
1080 - <!-- SECTION 1: Welcome -->
1081 - <!-- =========================================== -->
1082 - <div class="wizard-section <?php echo 1 === $wizard_page ? 'active' : ''; ?>" data-page="1" id="subscrpt-section-1">
1083 - <div class="wizard-card">
1084 - <!-- Left: content -->
1085 - <div class="p1-left">
1086 - <div class="p1-badge">
1087 - <span class="p1-badge__dot"></span>
1088 - <?php esc_html_e( 'Getting started', 'subscription' ); ?>
1089 - </div>
1090 - <h1 class="p1-heading">
1091 - <?php esc_html_e( 'Your first subscription', 'subscription' ); ?>
1092 - <span class="p1-heading__accent"><?php esc_html_e( 'starts here', 'subscription' ); ?></span>
1093 - </h1>
1094 - <p class="p1-desc"><?php esc_html_e( 'Set up your first subscription product in minutes. Start from scratch or convert a product you already sell.', 'subscription' ); ?></p>
1095 - <ul class="p1-bullets">
1096 - <li><span class="p1-bullet-dot"></span><?php esc_html_e( 'Daily, weekly, monthly, or annual billing', 'subscription' ); ?></li>
1097 - <li><span class="p1-bullet-dot"></span><?php esc_html_e( 'Free trials and one-time sign-up fees', 'subscription' ); ?></li>
138 + <div class="wpsubs-wizard-layout">
139 +
140 + <!-- ======================= Steps (left) ======================= -->
141 + <div class="wpsubs-wizard-steps">
142 +
143 + <!-- PAGE 0: Welcome (no preview / no footer — button lives in the card) -->
144 + <div class="wpsubs-wizard-section active" data-page="0" id="subscrpt-section-0">
145 + <div class="wpsubs-welcome-bg" aria-hidden="true"></div>
146 + <div class="wpsubs-wizard-card wpsubs-welcome">
147 + <img class="wpsubs-welcome__logo" src="<?php echo esc_url( SUBSCRPT_ASSETS . '/images/logo.png' ); ?>" width="64" height="64" alt="<?php esc_attr_e( 'WPSubscription', 'subscription' ); ?>">
148 + <h1 class="wpsubs-welcome__title"><?php esc_html_e( 'Thank you for installing WPSubscription!', 'subscription' ); ?></h1>
149 + <p class="wpsubs-welcome__lead"><?php esc_html_e( "Let's set up your first subscription plan. A plan decides how customers are billed and connects to a product they can subscribe to.", 'subscription' ); ?></p>
150 + <ul class="wpsubs-welcome__steps">
151 + <li><span class="wpsubs-welcome__num">1</span><?php esc_html_e( 'Create a plan and choose how customers are billed', 'subscription' ); ?></li>
152 + <li><span class="wpsubs-welcome__num">2</span><?php esc_html_e( 'Add one or more billing durations', 'subscription' ); ?></li>
153 + <li><span class="wpsubs-welcome__num">3</span><?php esc_html_e( 'Connect it to a product', 'subscription' ); ?></li>
1098 154 </ul>
1099 - <div class="p1-actions">
1100 - <button type="button" id="subscrpt-btn-start" class="wpsubs-btn wpsubs-btn--primary">
1101 - <?php esc_html_e( 'Create my first subscription', 'subscription' ); ?> &rsaquo;
1102 - </button>
1103 - <button type="button" id="subscrpt-btn-skip" class="p1-skip">
1104 - <?php esc_html_e( 'Skip the intro', 'subscription' ); ?>
1105 - </button>
155 + <div class="wpsubs-welcome__actions">
156 + <button type="button" id="subscrpt-btn-start" class="wpsubs-btn wpsubs-btn--primary wpsubs-btn--lg">
157 + <?php esc_html_e( "Let's go", 'subscription' ); ?> &rsaquo;
158 + </button>
159 + <button type="button" id="subscrpt-btn-skip" class="wpsubs-welcome__skip">
160 + <?php esc_html_e( 'Skip setup', 'subscription' ); ?>
161 + </button>
162 + </div>
1106 163 </div>
1107 164 </div>
1108 - <!-- Right: product preview mockup -->
1109 - <div class="p1-right" aria-hidden="true">
1110 - <p class="p1-preview-label"><?php esc_html_e( 'Your shop', 'subscription' ); ?></p>
1111 - <p class="p1-preview-sublabel"><?php esc_html_e( 'How customers see the product', 'subscription' ); ?></p>
1112 - <div class="p1-preview-card">
1113 - <div class="p1-preview-img">
1114 - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1115 - <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path>
1116 - <line x1="3" y1="6" x2="21" y2="6"></line>
1117 - <path d="M16 10a4 4 0 0 1-8 0"></path>
1118 - </svg>
1119 - <div class="p1-preview-img__dots">
1120 - <span></span><span></span><span></span>
1121 - </div>
165 +
166 + <!-- PAGE 1: Create Plan (type + name) -->
167 + <div class="wpsubs-wizard-section" data-page="1" id="subscrpt-section-1">
168 + <div class="wpsubs-wizard-card">
169 + <h1 class="wpsubs-p2-page-title"><?php esc_html_e( 'Create a plan', 'subscription' ); ?></h1>
170 + <p class="wpsubs-p2-page-subtitle"><?php esc_html_e( 'Choose how customers are billed, then name your plan.', 'subscription' ); ?></p>
171 +
172 + <div class="wpsubs-p2-section-block">
173 + <p class="wpsubs-p2-section-label"><?php esc_html_e( '1. Plan type', 'subscription' ); ?></p>
174 + <div class="wpsubs-p2-option-cards wpsubs-p2-option-cards--list">
175 + <?php foreach ( $plan_types as $subscrpt_type ) : ?>
176 + <?php $subscrpt_locked = $subscrpt_type['pro'] && ! $is_pro; ?>
177 + <button type="button"
178 + class="wpsubs-p2-option-card wpsubs-plan-type-card<?php echo 'recurring' === $subscrpt_type['key'] ? ' active' : ''; ?>"
179 + data-type="<?php echo esc_attr( $subscrpt_type['key'] ); ?>"
180 + data-name="<?php echo esc_attr( $subscrpt_type['name'] ); ?>"
181 + data-label="<?php echo esc_attr( $subscrpt_type['label'] ); ?>"
182 + <?php echo $subscrpt_locked ? 'disabled' : ''; ?>>
183 + <div class="wpsubs-p2-option-card__icon"><?php echo $subscrpt_type['icon']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG defined above. ?></div>
184 + <div class="wpsubs-p2-option-card__text">
185 + <p class="wpsubs-p2-option-card__title">
186 + <?php echo esc_html( $subscrpt_type['label'] ); ?>
187 + <?php if ( $subscrpt_locked ) : ?>
188 + <span class="wpsubs-p2-pro-badge" title="<?php esc_attr_e( 'WPSubscription Pro required', 'subscription' ); ?>"><?php esc_html_e( 'Pro', 'subscription' ); ?></span>
189 + <?php endif; ?>
190 + </p>
191 + <p class="wpsubs-p2-option-card__desc"><?php echo esc_html( $subscrpt_type['desc'] ); ?></p>
192 + </div>
193 + </button>
194 + <?php endforeach; ?>
1122 195 </div>
1123 - <div class="p1-preview-body">
1124 - <p class="p1-preview-name"><?php esc_html_e( 'Monthly Subscription Box', 'subscription' ); ?></p>
1125 - <p class="p1-preview-price">24.00$ <span>/ <?php esc_html_e( 'month', 'subscription' ); ?></span></p>
1126 - <div class="p1-preview-btn"><?php esc_html_e( 'Sign up', 'subscription' ); ?></div>
1127 - <div class="p1-preview-skeletons">
1128 - <div class="p1-preview-skeleton"></div>
1129 - <div class="p1-preview-skeleton"></div>
1130 - </div>
196 + </div>
197 +
198 + <div class="wpsubs-p2-section-block" style="margin-bottom:0;">
199 + <p class="wpsubs-p2-section-label"><?php esc_html_e( '2. Plan name', 'subscription' ); ?></p>
200 + <div class="wpsubs-form-row" style="margin-bottom:0;max-width:420px;">
201 + <input type="text" id="subscrpt_plan_title" class="wpsubs-input" autocomplete="off" value="<?php esc_attr_e( 'Recurring Subscription', 'subscription' ); ?>" placeholder="<?php esc_attr_e( 'e.g. Monthly Box', 'subscription' ); ?>">
1131 202 </div>
203 + </div>
1132 204 </div>
1133 - </div>
1134 - </div>
1135 - </div>
205 + </div>
1136 206
1137 - <!-- =========================================== -->
1138 - <!-- SECTION 2: Product & Subscription Setup -->
1139 - <!-- =========================================== -->
1140 - <div class="wizard-section <?php echo 2 === $wizard_page ? 'active' : ''; ?>" id="subscrpt-section-2">
1141 - <div class="wizard-card">
1142 - <h1 class="p2-page-title"><?php esc_html_e( 'Create your subscription product', 'subscription' ); ?></h1>
1143 - <p class="p2-page-subtitle"><?php esc_html_e( 'Set the basics now. Once published, customers can subscribe from your shop and you can fine-tune everything later in the product editor.', 'subscription' ); ?></p>
207 + <!-- PAGE 2: Set Frequency (duration) -->
208 + <div class="wpsubs-wizard-section" data-page="2" id="subscrpt-section-2">
209 + <div class="wpsubs-wizard-card">
210 + <h1 class="wpsubs-p2-page-title"><?php esc_html_e( 'Add billing durations', 'subscription' ); ?></h1>
211 + <p class="wpsubs-p2-page-subtitle"><?php esc_html_e( 'How often a customer is charged. Add one or more to offer a choice.', 'subscription' ); ?></p>
1144 212
1145 - <!-- 1. Pick a starting point -->
1146 - <div class="p2-section-block">
1147 - <p class="p2-section-label"><?php esc_html_e( '1. Pick a starting point', 'subscription' ); ?></p>
1148 - <p class="p2-section-desc"><?php esc_html_e( 'Build a fresh subscription product, or convert one you already sell.', 'subscription' ); ?></p>
213 + <div id="subscrpt-durations" data-durations></div>
1149 214
1150 - <div class="p2-option-cards">
1151 - <button type="button"
1152 - class="p2-option-card product-toggle-btn <?php echo 'existing' !== ( isset( $session_data['product_mode'] ) ? $session_data['product_mode'] : 'new' ) ? 'active' : ''; ?>"
1153 - id="subscrpt-btn-create-new" data-mode="new">
1154 - <div class="p2-option-card__check">✓</div>
1155 - <div class="p2-option-card__icon">
1156 - <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>
1157 - </div>
1158 - <p class="p2-option-card__title"><?php esc_html_e( 'Create a new product', 'subscription' ); ?></p>
1159 - <p class="p2-option-card__desc"><?php esc_html_e( 'Start with a blank subscription product.', 'subscription' ); ?></p>
215 + <button type="button" id="subscrpt-btn-add-duration" class="wpsubs-btn wpsubs-btn--outline" style="width:100%;justify-content:center;margin-top:4px;">
216 + <span class="dashicons dashicons-plus-alt2" style="font-size:15px;width:15px;height:15px;line-height:1;"></span>
217 + <?php esc_html_e( 'Add another duration', 'subscription' ); ?>
1160 218 </button>
1161 219
1162 - <?php if ( ! empty( $products ) ) : ?>
1163 - <button type="button"
1164 - class="p2-option-card product-toggle-btn <?php echo 'existing' === ( isset( $session_data['product_mode'] ) ? $session_data['product_mode'] : '' ) ? 'active' : ''; ?>"
1165 - id="subscrpt-btn-use-existing" data-mode="existing">
1166 - <div class="p2-option-card__check">✓</div>
1167 - <div class="p2-option-card__icon">
1168 - <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg>
1169 - </div>
1170 - <p class="p2-option-card__title"><?php esc_html_e( 'Use an existing product', 'subscription' ); ?></p>
1171 - <p class="p2-option-card__desc"><?php esc_html_e( 'Convert a WooCommerce product into a subscription.', 'subscription' ); ?></p>
1172 - </button>
1173 - <?php endif; ?>
1174 - </div>
1175 -
1176 - <!-- Existing product selector -->
1177 - <?php if ( ! empty( $products ) ) : ?>
1178 - <div id="subscrpt-existing-product-fields" style="<?php echo 'existing' !== ( isset( $session_data['product_mode'] ) ? $session_data['product_mode'] : '' ) ? 'display:none;' : ''; ?>">
1179 - <div id="subscrpt-product-select-wrap">
1180 - <?php
1181 - $avatar_palette = array(
1182 - array(
1183 - 'bg' => '#fde8d8',
1184 - 'fg' => '#b85c20',
1185 - ),
1186 - array(
1187 - 'bg' => '#dbeafe',
1188 - 'fg' => '#1d4ed8',
1189 - ),
1190 - array(
1191 - 'bg' => '#ede9fe',
1192 - 'fg' => '#6d28d9',
1193 - ),
1194 - array(
1195 - 'bg' => '#d1fae5',
1196 - 'fg' => '#065f46',
1197 - ),
1198 - array(
1199 - 'bg' => '#fce7f3',
1200 - 'fg' => '#9d174d',
1201 - ),
1202 - array(
1203 - 'bg' => '#fef9c3',
1204 - 'fg' => '#854d0e',
1205 - ),
1206 - );
1207 - ?>
1208 - <div class="p2-product-search">
1209 - <div class="p2-product-search__input-wrap">
1210 - <svg class="p2-product-search__icon" width="15" height="15" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z"/></svg>
1211 - <input type="text" class="p2-product-search__input wpsubs-input" id="subscrpt-product-search-input"
1212 - placeholder="<?php esc_attr_e( 'Search WooCommerce products by name or SKU...', 'subscription' ); ?>"
1213 - autocomplete="off">
220 + <template id="subscrpt-duration-tpl">
221 + <div class="wpsubs-dur is-open" data-dur>
222 + <div class="wpsubs-dur__head" data-dur-toggle>
223 + <span class="wpsubs-dur__icon"><?php echo $subscrpt_icon_cal; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
224 + <span class="wpsubs-dur__title" data-dur-title></span>
225 + <button type="button" class="wpsubs-dur__remove" data-dur-remove title="<?php esc_attr_e( 'Remove duration', 'subscription' ); ?>" aria-label="<?php esc_attr_e( 'Remove duration', 'subscription' ); ?>">&times;</button>
226 + <svg class="wpsubs-dur__chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"></polyline></svg>
1214 227 </div>
1215 - <div class="p2-product-search__dropdown" id="subscrpt-product-search-dropdown" style="display:none;">
1216 - <?php
1217 - foreach ( $products as $i => $p ) :
1218 - $wc_p = wc_get_product( $p->ID );
1219 - $price = $wc_p ? $wc_p->get_price() : '';
1220 - $type = $wc_p ? ucfirst( $wc_p->get_type() ) . ' ' . __( 'product', 'subscription' ) : '';
1221 - $sku = $wc_p ? $wc_p->get_sku() : '';
1222 - $billing_period_meta = $wc_p ? $wc_p->get_meta( '_subscrpt_timing_option' ) : '';
1223 - $billing_per_meta = $wc_p ? $wc_p->get_meta( '_subscrpt_timing_per' ) : '';
1224 - $trial_per_meta = $wc_p ? $wc_p->get_meta( '_subscrpt_trial_timing_per' ) : '';
1225 - $signup_fee_meta = $wc_p ? $wc_p->get_meta( '_subscrpt_signup_fee' ) : '';
1226 - $words = array_filter( explode( ' ', $p->post_title ) );
1227 - $initials = implode(
1228 - '',
1229 - array_slice(
1230 - array_map(
1231 - function ( $w ) {
1232 - return mb_strtoupper( mb_substr( $w, 0, 1 ) );
1233 - },
1234 - $words
1235 - ),
1236 - 0,
1237 - 2
1238 - )
1239 - );
1240 - $color = $avatar_palette[ $i % count( $avatar_palette ) ];
1241 - ?>
1242 - <?php $is_variable_locked = ( $wc_p && 'variable' === $wc_p->get_type() && ! $is_pro ); ?>
1243 - <div class="p2-product-search__item<?php echo $is_variable_locked ? ' p2-product-search__item--locked' : ''; ?>"
1244 - data-id="<?php echo esc_attr( $p->ID ); ?>"
1245 - data-price="<?php echo esc_attr( $price ); ?>"
1246 - data-type="<?php echo esc_attr( $type ); ?>"
1247 - data-product-type="<?php echo esc_attr( $wc_p ? $wc_p->get_type() : '' ); ?>"
1248 - data-sku="<?php echo esc_attr( $sku ); ?>"
1249 - data-name="<?php echo esc_attr( $p->post_title ); ?>"
1250 - data-billing-period="<?php echo esc_attr( $billing_period_meta ); ?>"
1251 - data-billing-per="<?php echo esc_attr( $billing_per_meta ?: '1' ); ?>"
1252 - data-trial-per="<?php echo esc_attr( $trial_per_meta ); ?>"
1253 - data-signup-fee="<?php echo esc_attr( $signup_fee_meta ); ?>">
1254 - <div class="p2-product-search__avatar" style="background:<?php echo esc_attr( $color['bg'] ); ?>;color:<?php echo esc_attr( $color['fg'] ); ?>">
1255 - <?php echo esc_html( $initials ?: '?' ); ?>
228 + <div class="wpsubs-dur__body">
229 + <div class="wpsubs-form-row">
230 + <label><?php esc_html_e( 'Billing every', 'subscription' ); ?></label>
231 + <div class="wpsubs-p2-billing-group">
232 + <input type="number" class="wpsubs-input wpsubs-p2-billing-per-input" autocomplete="off" min="1" value="1" data-dur-freq
233 + <?php echo $is_pro ? '' : 'readonly max="1" title="' . esc_attr__( 'Upgrade to Pro to bill every few periods.', 'subscription' ) . '"'; ?>>
234 +<?php
235 + wpsubs_render_adv_select(
236 + array(
237 + 'name' => 'subscrpt_dur_interval',
238 + 'value' => 'month',
239 + 'options' => $interval_options,
240 + 'class' => 'wpsubs-dur__interval',
241 + 'attrs' => array( 'data-dur-interval' => '1' ),
242 + )
243 + );
244 + ?>
1256 245 </div>
1257 - <div class="p2-product-search__info">
1258 - <p class="p2-product-search__name">
1259 - <?php echo esc_html( $p->post_title ); ?>
1260 - <?php if ( $is_variable_locked ) : ?>
1261 - <span class="p2-pro-badge" title="<?php esc_attr_e( 'WPSubscription Pro required', 'subscription' ); ?>"><?php esc_html_e( 'Pro', 'subscription' ); ?></span>
1262 - <?php endif; ?>
1263 - </p>
1264 - <p class="p2-product-search__meta"><?php echo esc_html( ( $sku ? 'SKU ' . $sku . ' · ' : '' ) . $type ); ?></p>
1265 - </div>
1266 - <?php if ( '' !== $price ) : ?>
1267 - <span class="p2-product-search__price"><?php echo esc_html( get_woocommerce_currency_symbol() . number_format( (float) $price, 2 ) ); ?></span>
1268 - <?php endif; ?>
1269 246 </div>
1270 - <?php endforeach; ?>
1271 - <div class="p2-product-search__empty" style="display:none;"><?php esc_html_e( 'No products found.', 'subscription' ); ?></div>
247 + <div class="wpsubs-form-row" style="margin-bottom:0;">
248 + <label><?php esc_html_e( 'Name', 'subscription' ); ?></label>
249 + <input type="text" class="wpsubs-input" autocomplete="off" data-dur-name placeholder="<?php esc_attr_e( 'e.g. Every Month', 'subscription' ); ?>">
250 + </div>
1272 251 </div>
1273 252 </div>
1274 - <input type="hidden" name="subscrpt_existing_product" id="subscrpt-existing-product-hidden" value="<?php echo $product_id > 0 ? esc_attr( $product_id ) : ''; ?>">
1275 - </div>
1276 - <div id="subscrpt-selected-product-chip" class="p2-selected-product" style="display:none;">
1277 - <div class="p2-selected-product__avatar" id="p2-chip-avatar"></div>
1278 - <div class="p2-selected-product__info">
1279 - <p class="p2-selected-product__name" id="p2-chip-name"></p>
1280 - <p class="p2-selected-product__meta" id="p2-chip-meta"></p>
1281 - </div>
1282 - <button type="button" class="p2-selected-product__clear" id="subscrpt-btn-clear-product" aria-label="<?php esc_attr_e( 'Clear selection', 'subscription' ); ?>">×</button>
1283 - </div>
1284 - <!-- Variation picker (shown when a variable product is selected) -->
1285 - <div id="subscrpt-variation-picker-wrap" class="p2-variation-picker" style="display:none;">
1286 - <div id="subscrpt-variation-picker-list"></div>
1287 - </div>
1288 - <input type="hidden" name="subscrpt_variation_id" id="subscrpt-variation-id-hidden" value="">
253 + </template>
1289 254 </div>
1290 - <?php endif; ?>
1291 255 </div>
1292 256
1293 - <!-- 2. Subscription details -->
1294 - <div class="p2-section-block" style="margin-bottom:0;">
1295 - <p class="p2-section-label"><?php esc_html_e( '2. Subscription details', 'subscription' ); ?></p>
1296 - <p class="p2-section-desc"><?php esc_html_e( 'How and how often customers are billed once they subscribe.', 'subscription' ); ?></p>
257 + <!-- PAGE 3: Connect to a Product -->
258 + <div class="wpsubs-wizard-section" data-page="3" id="subscrpt-section-3">
259 + <div class="wpsubs-wizard-card">
260 + <h1 class="wpsubs-p2-page-title"><?php esc_html_e( 'Connect the plan to a product', 'subscription' ); ?></h1>
261 + <p class="wpsubs-p2-page-subtitle"><?php esc_html_e( 'Connect this plan to a product to make it subscribable.', 'subscription' ); ?></p>
1297 262
1298 - <div class="p2-body">
1299 - <!-- Left: form -->
1300 - <div>
1301 - <!-- Product name -->
1302 - <div id="subscrpt-new-product-fields">
1303 - <div class="form-row">
1304 - <label for="subscrpt_product_name"><?php esc_html_e( 'Product name', 'subscription' ); ?></label>
1305 - <input type="text" id="subscrpt_product_name" name="subscrpt_product_name" class="wpsubs-input" autocomplete="off" placeholder="<?php esc_attr_e( 'e.g. Monthly Subscription Box', 'subscription' ); ?>" value="<?php echo $product ? esc_attr( $product->get_name() ) : ( isset( $session_data['product_name'] ) ? esc_attr( $session_data['product_name'] ) : '' ); ?>">
1306 - <p class="p2-field-hint"><?php esc_html_e( 'Shown on your store page and in subscription emails.', 'subscription' ); ?></p>
263 + <div class="wpsubs-p2-section-block">
264 + <?php if ( $has_products ) : ?>
265 + <p class="wpsubs-p2-section-label"><?php esc_html_e( '1. Select a product', 'subscription' ); ?></p>
266 + <div class="wpsubs-p2-option-cards wpsubs-p2-option-cards--compact">
267 + <button type="button" class="wpsubs-p2-option-card wpsubs-connect-mode-card active" data-mode="existing">
268 + <div class="wpsubs-p2-option-card__icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></svg></div>
269 + <p class="wpsubs-p2-option-card__title"><?php esc_html_e( 'Use an existing product', 'subscription' ); ?></p>
270 + </button>
271 + <button type="button" class="wpsubs-p2-option-card wpsubs-connect-mode-card" data-mode="new">
272 + <div class="wpsubs-p2-option-card__icon"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg></div>
273 + <p class="wpsubs-p2-option-card__title"><?php esc_html_e( 'Create a new product', 'subscription' ); ?></p>
274 + </button>
1307 275 </div>
1308 - </div>
1309 276
1310 - <?php
1311 - $billing_period = isset( $session_data['billing_period'] ) ? $session_data['billing_period'] : 'months';
1312 - $trial_period = isset( $session_data['trial_timing_option'] ) ? $session_data['trial_timing_option'] : 'days';
1313 - $trial_period_options = array(
1314 - array(
1315 - 'value' => 'days',
1316 - 'label' => __( 'Day', 'subscription' ),
1317 - ),
1318 - array(
1319 - 'value' => 'weeks',
1320 - 'label' => __( 'Week', 'subscription' ),
1321 - ),
1322 - array(
1323 - 'value' => 'months',
1324 - 'label' => __( 'Month', 'subscription' ),
1325 - ),
1326 - array(
1327 - 'value' => 'years',
1328 - 'label' => __( 'Year', 'subscription' ),
1329 - ),
1330 - );
1331 - $period_options = array(
1332 - array(
1333 - 'value' => 'days',
1334 - 'label' => __( 'Day', 'subscription' ),
1335 - ),
1336 - array(
1337 - 'value' => 'weeks',
1338 - 'label' => __( 'Week', 'subscription' ),
1339 - ),
1340 - array(
1341 - 'value' => 'months',
1342 - 'label' => __( 'Month', 'subscription' ),
1343 - ),
1344 - array(
1345 - 'value' => 'years',
1346 - 'label' => __( 'Year', 'subscription' ),
1347 - ),
1348 - );
1349 - ?>
1350 - <input type="hidden" id="subscrpt_timing_option" name="subscrpt_timing_option" value="never">
1351 - <input type="hidden" id="subscrpt_billing_per" name="subscrpt_billing_per" value="<?php echo $is_pro && isset( $session_data['billing_per'] ) ? esc_attr( $session_data['billing_per'] ) : '1'; ?>">
277 + <div id="subscrpt-connect-existing">
278 + <p class="wpsubs-p2-section-desc"><?php esc_html_e( 'Pick a product to attach this plan to.', 'subscription' ); ?></p>
1352 279
1353 - <!-- Row: Price | Billing every (group component) -->
1354 - <div class="p2-form-grid">
1355 - <div class="form-row">
1356 - <label for="subscrpt_product_price"><?php esc_html_e( 'Price', 'subscription' ); ?></label>
1357 - <div class="p2-input-wrap">
1358 - <span class="p2-input-prefix"><?php echo esc_html( get_woocommerce_currency_symbol() ); ?></span>
1359 - <input type="text" id="subscrpt_product_price" name="subscrpt_product_price" class="wpsubs-input" autocomplete="off" style="padding-left:24px!important;" placeholder="0.00" value="<?php echo $product ? esc_attr( $product->get_price() ) : ( isset( $session_data['product_price'] ) ? esc_attr( $session_data['product_price'] ) : '' ); ?>">
280 + <div id="subscrpt-product-select-wrap">
281 + <div class="wpsubs-p2-product-search">
282 + <div class="wpsubs-p2-product-search__input-wrap">
283 + <svg class="wpsubs-p2-product-search__icon" width="15" height="15" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-4.35-4.35M17 11A6 6 0 1 1 5 11a6 6 0 0 1 12 0z"/></svg>
284 + <input type="text" class="wpsubs-p2-product-search__input wpsubs-input" id="subscrpt-product-search-input"
285 + placeholder="<?php esc_attr_e( 'Search products by name or SKU...', 'subscription' ); ?>" autocomplete="off">
286 + </div>
287 + <div class="wpsubs-p2-product-search__dropdown" id="subscrpt-product-search-dropdown" style="display:none;">
288 + <?php
289 + $subscrpt_products = wc_get_products(
290 + array(
291 + 'status' => 'publish',
292 + 'limit' => 100,
293 + 'orderby' => 'title',
294 + 'order' => 'ASC',
295 + 'type' => $is_pro ? array( 'simple', 'variable' ) : array( 'simple' ),
296 + )
297 + );
298 + foreach ( $subscrpt_products as $subscrpt_i => $subscrpt_wc_p ) :
299 + $subscrpt_price = $subscrpt_wc_p->get_price();
300 + $subscrpt_sku = $subscrpt_wc_p->get_sku();
301 + $subscrpt_type = ucfirst( $subscrpt_wc_p->get_type() ) . ' ' . __( 'product', 'subscription' );
302 + $subscrpt_name = $subscrpt_wc_p->get_name();
303 + $subscrpt_words = array_filter( explode( ' ', $subscrpt_name ) );
304 + $subscrpt_initials = implode(
305 + '',
306 + array_slice(
307 + array_map(
308 + function ( $w ) {
309 + return mb_strtoupper( mb_substr( $w, 0, 1 ) );
310 + },
311 + $subscrpt_words
312 + ),
313 + 0,
314 + 2
315 + )
316 + );
317 + $subscrpt_color = $avatar_palette[ $subscrpt_i % count( $avatar_palette ) ];
318 + // A product already attached to a plan can't be connected again —
319 + // same rule as the Plans page product tab.
320 + $subscrpt_conns = \SpringDevs\Subscription\Illuminate\Plans\PlanRepository::get_product_connections( $subscrpt_wc_p->get_id() );
321 + $subscrpt_connected = ! empty( $subscrpt_conns );
322 + ?>
323 + <div class="wpsubs-p2-product-search__item<?php echo $subscrpt_connected ? ' wpsubs-p2-product-search__item--disabled' : ''; ?>"
324 + data-id="<?php echo esc_attr( $subscrpt_wc_p->get_id() ); ?>"
325 + data-price="<?php echo esc_attr( $subscrpt_price ); ?>"
326 + data-type="<?php echo esc_attr( $subscrpt_type ); ?>"
327 + data-sku="<?php echo esc_attr( $subscrpt_sku ); ?>"
328 + data-name="<?php echo esc_attr( $subscrpt_name ); ?>"
329 + <?php echo $subscrpt_connected ? 'data-connected="1"' : ''; ?>>
330 + <div class="wpsubs-p2-product-search__avatar" style="background:<?php echo esc_attr( $subscrpt_color['bg'] ); ?>;color:<?php echo esc_attr( $subscrpt_color['fg'] ); ?>">
331 + <?php echo esc_html( $subscrpt_initials ? $subscrpt_initials : '?' ); ?>
332 + </div>
333 + <div class="wpsubs-p2-product-search__info">
334 + <p class="wpsubs-p2-product-search__name">
335 + <?php echo esc_html( $subscrpt_name ); ?>
336 + <?php if ( $subscrpt_connected ) : ?>
337 + <span class="wpsubs-p2-product-search__connected"><?php esc_html_e( 'Added to another plan', 'subscription' ); ?></span>
338 + <?php endif; ?>
339 + </p>
340 + <p class="wpsubs-p2-product-search__meta"><?php echo esc_html( ( $subscrpt_sku ? 'SKU ' . $subscrpt_sku . ' · ' : '' ) . $subscrpt_type ); ?></p>
341 + </div>
342 + <?php if ( '' !== $subscrpt_price ) : ?>
343 + <span class="wpsubs-p2-product-search__price"><?php echo esc_html( $currency_symbol . number_format( (float) $subscrpt_price, 2 ) ); ?></span>
344 + <?php endif; ?>
345 + </div>
346 + <?php endforeach; ?>
347 + <div class="wpsubs-p2-product-search__empty" style="display:none;"><?php esc_html_e( 'No products found.', 'subscription' ); ?></div>
348 + </div>
349 + </div>
350 + <input type="hidden" id="subscrpt-existing-product-hidden" value="">
1360 351 </div>
1361 - </div>
1362 - <div class="form-row">
1363 - <label><?php esc_html_e( 'Billing every', 'subscription' ); ?></label>
1364 - <div class="wpsubs-input-group p2-billing-group">
1365 - <?php if ( $is_pro ) : ?>
1366 - <input type="number" id="subscrpt_billing_per_visible" class="wpsubs-input p2-billing-per-input" autocomplete="off" min="1"
1367 - value="<?php echo isset( $session_data['billing_per'] ) ? esc_attr( $session_data['billing_per'] ) : '1'; ?>"
1368 - oninput="document.getElementById('subscrpt_billing_per').value=this.value">
1369 - <?php endif; ?>
1370 - <?php
1371 - wpsubs_render_adv_select(
1372 - array(
1373 - 'name' => 'subscrpt_billing_period',
1374 - 'id' => 'subscrpt-billing-period-select',
1375 - 'value' => $billing_period,
1376 - 'options' => $period_options,
1377 - )
1378 - );
1379 - ?>
352 +
353 + <div id="subscrpt-selected-product-chip" class="wpsubs-p2-selected-product" style="display:none;">
354 + <div class="wpsubs-p2-selected-product__avatar" id="p3-chip-avatar"></div>
355 + <div class="wpsubs-p2-selected-product__info">
356 + <p class="wpsubs-p2-selected-product__name" id="p3-chip-name"></p>
357 + <p class="wpsubs-p2-selected-product__meta" id="p3-chip-meta"></p>
358 + </div>
359 + <button type="button" class="wpsubs-p2-selected-product__clear" id="subscrpt-btn-clear-product" aria-label="<?php esc_attr_e( 'Clear selection', 'subscription' ); ?>">×</button>
1380 360 </div>
361 + </div><!-- /#subscrpt-connect-existing -->
362 + <?php endif; ?>
363 +
364 + <div id="subscrpt-connect-new" <?php echo $has_products ? 'style="display:none;"' : ''; ?>>
365 + <?php if ( ! $has_products ) : ?>
366 + <p class="wpsubs-p2-section-label"><?php esc_html_e( '1. Create a product', 'subscription' ); ?></p>
367 + <p class="wpsubs-p2-section-desc"><?php esc_html_e( "You don't have any products yet. Create one to connect this plan.", 'subscription' ); ?></p>
368 + <?php endif; ?>
369 + <div class="wpsubs-form-row">
370 + <label for="subscrpt_new_product_name"><?php esc_html_e( 'Product name', 'subscription' ); ?></label>
371 + <input type="text" id="subscrpt_new_product_name" class="wpsubs-input" autocomplete="off" placeholder="<?php esc_attr_e( 'e.g. Monthly Subscription Box', 'subscription' ); ?>">
372 + <p class="wpsubs-p2-field-hint"><?php esc_html_e( 'Shown on your store and in emails.', 'subscription' ); ?></p>
1381 373 </div>
1382 374 </div>
1383 375
1384 - <!-- Free trial (free) + Sign-up fee (Pro only) -->
1385 - <div class="p2-form-grid">
1386 - <div class="form-row">
1387 - <label for="subscrpt_trial_timing_per"><?php esc_html_e( 'Free trial', 'subscription' ); ?> <span class="p2-label-optional"><?php esc_html_e( 'Optional', 'subscription' ); ?></span></label>
1388 - <div class="wpsubs-input-group p2-billing-group">
1389 - <input type="number" id="subscrpt_trial_timing_per" name="subscrpt_trial_timing_per" class="wpsubs-input p2-billing-per-input" autocomplete="off" min="0" value="<?php echo isset( $session_data['trial_timing_per'] ) ? esc_attr( $session_data['trial_timing_per'] ) : '0'; ?>">
1390 - <?php
1391 - wpsubs_render_adv_select(
1392 - array(
1393 - 'name' => 'subscrpt_trial_timing_option',
1394 - 'id' => 'subscrpt-trial-period-select',
1395 - 'value' => $trial_period,
1396 - 'options' => $trial_period_options,
1397 - )
1398 - );
1399 - ?>
1400 - </div>
1401 - <p class="p2-field-hint"><?php esc_html_e( 'Free period before the first charge. Leave 0 for none.', 'subscription' ); ?></p>
1402 - </div>
1403 - <div class="form-row <?php echo $is_pro ? '' : 'p2-field-pro-locked'; ?>">
1404 - <label for="subscrpt_signup_fee">
1405 - <?php esc_html_e( 'Sign-up fee', 'subscription' ); ?>
1406 - <?php if ( ! $is_pro ) : ?>
1407 - <span class="p2-pro-badge" title="<?php esc_attr_e( 'WPSubscription Pro required', 'subscription' ); ?>"><?php esc_html_e( 'Pro', 'subscription' ); ?></span>
1408 - <?php else : ?>
1409 - <span class="p2-label-optional"><?php esc_html_e( 'Optional', 'subscription' ); ?></span>
1410 - <?php endif; ?>
1411 - </label>
1412 - <div class="p2-input-wrap">
1413 - <span class="p2-input-prefix"><?php echo esc_html( get_woocommerce_currency_symbol() ); ?></span>
1414 - <input type="text" id="subscrpt_signup_fee" name="subscrpt_signup_fee" class="wpsubs-input" autocomplete="off" style="padding-left:24px!important;" placeholder="0.00"
1415 - value="<?php echo $is_pro && isset( $session_data['signup_fee'] ) ? esc_attr( $session_data['signup_fee'] ) : ''; ?>"
1416 - <?php echo $is_pro ? '' : 'disabled'; ?>>
1417 - </div>
1418 - <?php if ( ! $is_pro ) : ?>
1419 - <p class="p2-field-hint"><?php esc_html_e( 'One-time charge at checkout. Upgrade to Pro to enable.', 'subscription' ); ?></p>
1420 - <?php else : ?>
1421 - <p class="p2-field-hint"><?php esc_html_e( 'One-time charge at checkout.', 'subscription' ); ?></p>
1422 - <?php endif; ?>
1423 - </div>
1424 - </div>
376 + </div><!-- /product section-block -->
1425 377
1426 - <!-- Hidden compat fields -->
1427 - <input type="hidden" id="subscrpt_trial_enabled" name="subscrpt_trial_enabled" value="0">
1428 - <input type="hidden" id="subscrpt_length_enabled" name="subscrpt_length_enabled" value="0">
1429 - <input type="hidden" id="subscrpt_length_per" name="subscrpt_length_per" value="">
1430 - <input type="hidden" id="subscrpt_length_option" name="subscrpt_length_option" value="months">
378 + <!-- Per-duration pricing: each duration from step 2 gets a price and an
379 + on/off toggle. Rows are built from JS (renderConnectDurations). -->
380 + <div class="wpsubs-p2-section-block wpsubs-connect-pricing" style="margin-bottom:0;">
381 + <p class="wpsubs-p2-section-label"><?php esc_html_e( '2. Set pricing', 'subscription' ); ?></p>
382 + <p class="wpsubs-p2-section-desc"><?php esc_html_e( "Set a price for each duration. Turn off any you don't want.", 'subscription' ); ?></p>
383 + <div id="subscrpt-connect-durations"></div>
1431 384 </div>
1432 385
1433 - <!-- Right: shop preview -->
1434 - <div class="p2-preview-col">
1435 - <p class="p2-preview-col-label"><?php esc_html_e( 'Shop Preview', 'subscription' ); ?></p>
1436 - <div class="p1-preview-card">
1437 - <div class="p1-preview-img">
1438 - <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
1439 - <path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path>
1440 - <line x1="3" y1="6" x2="21" y2="6"></line>
1441 - <path d="M16 10a4 4 0 0 1-8 0"></path>
1442 - </svg>
1443 - <div class="p1-preview-img__dots"><span></span><span></span><span></span></div>
386 + <template id="subscrpt-connect-dur-tpl">
387 + <div class="wpsubs-connect-dur" data-connect-row>
388 + <span class="wpsubs-connect-dur__icon"><?php echo $subscrpt_icon_cal; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
389 + <div class="wpsubs-connect-dur__text">
390 + <p class="wpsubs-connect-dur__name" data-connect-name></p>
391 + <p class="wpsubs-connect-dur__billing" data-connect-billing></p>
1444 392 </div>
1445 - <div class="p1-preview-body">
1446 - <p class="p1-preview-name" id="p2-preview-name"><?php echo $product ? esc_html( $product->get_name() ) : esc_html__( 'Your product', 'subscription' ); ?></p>
1447 - <p class="p1-preview-price"><span id="p2-preview-price"><?php echo $product ? esc_html( $product->get_price() ) : '0.00'; ?></span>$ <span>/ <span id="p2-preview-period"><?php echo isset( $session_data['billing_period'] ) ? esc_html( $session_data['billing_period'] ) : esc_html__( 'month', 'subscription' ); ?></span></span></p>
1448 - <div class="p1-preview-btn"><?php esc_html_e( 'Sign up', 'subscription' ); ?></div>
393 + <div class="wpsubs-p2-input-wrap wpsubs-connect-dur__price">
394 + <span class="wpsubs-p2-input-prefix"><?php echo esc_html( $currency_symbol ); ?></span>
395 + <input type="text" class="wpsubs-input" data-connect-price autocomplete="off" placeholder="0.00" style="padding-left:24px!important;">
1449 396 </div>
397 + <label class="wpsubs-connect-dur__switch">
398 + <input type="checkbox" class="wpsubs-toggle" data-connect-enabled checked>
399 + <span class="wpsubs-toggle-ui" aria-hidden="true"></span>
400 + </label>
1450 401 </div>
1451 - <p class="p2-preview-col-desc"><?php esc_html_e( 'This is how the product will appear on your shop page. Each purchase creates a subscription you\'ll manage from the Subscriptions list.', 'subscription' ); ?></p>
1452 - </div>
402 + </template>
1453 403 </div>
1454 404 </div>
1455 - </div>
1456 405
1457 - <!-- Nav outside card -->
1458 - <div class="p2-nav">
1459 - <button type="button" id="subscrpt-btn-back" class="p2-nav-back">
1460 - &#8249; <?php esc_html_e( 'Back', 'subscription' ); ?>
1461 - </button>
1462 - <button type="button" id="subscrpt-btn-save" class="wpsubs-btn wpsubs-btn--primary">
1463 - <?php esc_html_e( 'Create product', 'subscription' ); ?> &rsaquo;
1464 - </button>
1465 - </div>
1466 - </div>
406 + <!-- PAGE 4: Finish — everything is created here, sequentially. -->
407 + <div class="wpsubs-wizard-section" data-page="4" id="subscrpt-section-4">
408 + <div class="wpsubs-wizard-card wpsubs-p3-card">
1467 409
1468 - <!-- =========================================== -->
1469 - <!-- SECTION 3: Completion -->
1470 - <!-- =========================================== -->
1471 - <div class="wizard-section <?php echo 3 === $wizard_page ? 'active' : ''; ?>" id="subscrpt-section-3">
1472 - <div class="wizard-card p3-card">
410 + <!-- Working state: shown while the plan, durations and product are created. -->
411 + <div id="subscrpt-finalize-progress" class="wpsubs-finalize-progress">
412 + <div class="wpsubs-finalize-spinner" aria-hidden="true"></div>
413 + <h1 class="wpsubs-p3-heading"><?php esc_html_e( 'Setting things up…', 'subscription' ); ?></h1>
414 + <p class="wpsubs-p3-subtext"><?php esc_html_e( 'Creating your plan, durations and product. This takes a moment.', 'subscription' ); ?></p>
415 + <ul class="wpsubs-finalize-steps">
416 + <li data-finalize-step="plan"><span class="wpsubs-finalize-steps__dot"></span><?php esc_html_e( 'Create the plan', 'subscription' ); ?></li>
417 + <li data-finalize-step="durations"><span class="wpsubs-finalize-steps__dot"></span><?php esc_html_e( 'Add billing durations', 'subscription' ); ?></li>
418 + <li data-finalize-step="product"><span class="wpsubs-finalize-steps__dot"></span><?php esc_html_e( 'Connect the product', 'subscription' ); ?></li>
419 + </ul>
420 + </div>
1473 421
1474 - <!-- Success icon -->
1475 - <div class="p3-success-icon">
1476 - <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
1477 - <polyline points="20 6 9 17 4 12"></polyline>
1478 - </svg>
1479 - </div>
422 + <!-- Error state: shown if any step fails; the user can retry. -->
423 + <div id="subscrpt-finalize-error" class="wpsubs-finalize-error" hidden>
424 + <div class="wpsubs-finalize-error__icon" aria-hidden="true">
425 + <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>
426 + </div>
427 + <h1 class="wpsubs-p3-heading"><?php esc_html_e( "Something didn't go through.", 'subscription' ); ?></h1>
428 + <p class="wpsubs-p3-subtext" id="subscrpt-finalize-error-msg"></p>
429 + <button type="button" id="subscrpt-btn-retry-finalize" class="wpsubs-btn wpsubs-btn--primary"><?php esc_html_e( 'Try again', 'subscription' ); ?></button>
430 + </div>
1480 431
1481 - <h1 class="p3-heading"><?php esc_html_e( 'Your product is live.', 'subscription' ); ?></h1>
1482 - <p class="p3-subtext"><?php esc_html_e( "It's published to your shop now. When a customer buys it, a subscription is created automatically. You'll see those in the Subscriptions list.", 'subscription' ); ?></p>
432 + <!-- Success state: shown once everything is created. -->
433 + <div id="subscrpt-finalize-success" hidden>
434 + <div class="wpsubs-p3-success-icon">
435 + <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
436 + <polyline points="20 6 9 17 4 12"></polyline>
437 + </svg>
438 + </div>
1483 439
1484 - <?php
1485 - if ( $product ) :
1486 - $p3_price = $product->get_price();
1487 - $p3_period_raw = isset( $session_data['billing_period'] ) ? $session_data['billing_period'] : 'months';
1488 - $p3_billing_per = isset( $session_data['billing_per'] ) ? (int) $session_data['billing_per'] : 1;
1489 - $p3_period_label = $p3_billing_per > 1
1490 - ? $p3_billing_per . ' ' . strtolower( $p3_period_raw )
1491 - : strtolower( subscrpt_get_typos( 1, $p3_period_raw ) );
1492 - $p3_words = array_filter( explode( ' ', $product->get_name() ) );
1493 - $p3_initials = implode(
1494 - '',
1495 - array_map(
1496 - function ( $w ) {
1497 - return strtoupper( mb_substr( $w, 0, 1 ) );
1498 - },
1499 - array_slice( $p3_words, 0, 2 )
1500 - )
1501 - );
1502 - ?>
1503 - <!-- Product card -->
1504 - <div class="p3-product-card">
1505 - <div class="p3-product-card__header">
1506 - <span><?php esc_html_e( 'PRODUCT', 'subscription' ); ?></span>
1507 - <span><?php esc_html_e( 'STATUS', 'subscription' ); ?></span>
1508 - <span><?php esc_html_e( 'PRICE', 'subscription' ); ?></span>
1509 - </div>
1510 - <div class="p3-product-card__row">
1511 - <div class="p3-product-card__product">
1512 - <div class="p3-product-avatar"><?php echo esc_html( $p3_initials ); ?></div>
1513 - <div>
1514 - <p class="p3-product-name"><?php echo esc_html( $product->get_name() ); ?></p>
1515 - <p class="p3-product-meta">
1516 - <?php
1517 - /* translators: %d: product ID */
1518 - echo esc_html( sprintf( __( 'Product #%d', 'subscription' ), $product->get_id() ) );
1519 - ?>
1520 - &middot; <?php esc_html_e( 'Subscription', 'subscription' ); ?>
1521 - </p>
440 + <h1 class="wpsubs-p3-heading"><?php esc_html_e( 'Your plan is live.', 'subscription' ); ?></h1>
441 + <p class="wpsubs-p3-subtext"><?php esc_html_e( 'Your product is now subscribable. When a customer buys it, a subscription is created automatically.', 'subscription' ); ?></p>
442 +
443 + <p class="wpsubs-p3-what-now-label"><?php esc_html_e( 'WHAT NOW?', 'subscription' ); ?></p>
444 +
445 + <div class="wpsubs-p3-action-rows">
446 + <button type="button" id="subscrpt-btn-add-another" class="wpsubs-p3-action-row">
447 + <div class="wpsubs-p3-action-row__icon">
448 + <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
449 + </div>
450 + <div class="wpsubs-p3-action-row__content">
451 + <p class="wpsubs-p3-action-row__title"><?php esc_html_e( 'Create another plan', 'subscription' ); ?></p>
452 + <p class="wpsubs-p3-action-row__desc"><?php esc_html_e( 'Set up another subscription plan now.', 'subscription' ); ?></p>
453 + </div>
454 + <svg class="wpsubs-p3-action-row__chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"></polyline></svg>
455 + </button>
1522 456 </div>
457 +
458 + <p class="wpsubs-p3-help-text">
459 + <?php esc_html_e( 'Need help? Check the', 'subscription' ); ?>
460 + <a href="https://docs.wpsubscription.co/en?utm_source=plugin&utm_medium=admin&utm_campaign=docs" target="_blank" rel="noopener" class="wpsubs-p3-help-link"><?php esc_html_e( 'setup guide', 'subscription' ); ?></a>
461 + <?php esc_html_e( 'or', 'subscription' ); ?>
462 + <a href="https://wordpress.org/support/plugin/subscription/" target="_blank" rel="noopener" class="wpsubs-p3-help-link"><?php esc_html_e( 'contact support', 'subscription' ); ?></a>.
463 + </p>
1523 464 </div>
1524 - <div class="p3-product-card__status">
1525 - <span class="p3-status-badge">
1526 - <span class="p3-status-badge__dot"></span>
1527 - <?php esc_html_e( 'Published', 'subscription' ); ?>
1528 - </span>
1529 - <p class="p3-status-sub"><?php esc_html_e( 'Live in your shop', 'subscription' ); ?></p>
1530 - </div>
1531 - <div class="p3-product-card__price">
1532 - <span class="p3-price-amount"><?php echo wp_kses_post( wc_price( $p3_price ) ); ?></span>
1533 - <span class="p3-price-period">/ <?php echo esc_html( $p3_period_label ); ?></span>
1534 - </div>
1535 465 </div>
1536 466 </div>
1537 - <?php endif; ?>
1538 467
1539 - <!-- What now -->
1540 - <p class="p3-what-now-label"><?php esc_html_e( 'WHAT NOW?', 'subscription' ); ?></p>
468 + </div><!-- /.wpsubs-wizard-steps -->
1541 469
1542 - <div class="p3-action-rows">
1543 - <?php if ( $product ) : ?>
1544 - <a href="<?php echo esc_url( get_permalink( $product->get_id() ) ); ?>" target="_blank" rel="noopener" class="p3-action-row">
1545 - <div class="p3-action-row__icon">
1546 - <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M6 2L3 6v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V6l-3-4z"></path><line x1="3" y1="6" x2="21" y2="6"></line><path d="M16 10a4 4 0 0 1-8 0"></path></svg>
470 + <!-- ===================== Live preview (right) ===================== -->
471 + <aside class="wpsubs-wizard-aside">
472 + <div class="wpsubs-preview">
473 + <p class="wpsubs-preview__label"><?php esc_html_e( 'Live preview', 'subscription' ); ?></p>
474 + <div class="wpsubs-p1-graph" id="subscrpt-preview-graph" data-active="plan" aria-hidden="true">
475 + <svg class="wpsubs-p1-graph__lines" viewBox="0 0 300 420" preserveAspectRatio="none">
476 + <!-- Plan -> durations (left→right offsets +1.5, +3, +1: right highest,
477 + left slightly lower, middle lowest). data-line-dur maps each line
478 + to the duration it feeds, so it colours in when filled. -->
479 + <path class="wpsubs-p1-flow" data-line-dur="1" d="M150,50 C150,80 51,80 51,130" />
480 + <path class="wpsubs-p1-flow" data-line-dur="0" d="M150,50 L150,168" />
481 + <path class="wpsubs-p1-flow" data-line-dur="2" d="M150,50 C150,74 249,74 249,118" />
482 + <!-- Durations -> the single product (start at each card's bottom).
483 + data-line-to="prod" keeps these muted until a product is added, and
484 + each shows only while its duration's toggle is on. -->
485 + <path class="wpsubs-p1-flow" data-line-dur="1" data-line-to="prod" d="M51,168 C51,235 75,235 75,300" />
486 + <path class="wpsubs-p1-flow" data-line-dur="0" data-line-to="prod" d="M150,206 C150,255 75,255 75,300" />
487 + <path class="wpsubs-p1-flow" data-line-dur="2" data-line-to="prod" d="M249,156 C249,250 75,250 75,300" />
488 + <!-- Decorative lines to the second (muted) product. No data-line-*, so they never colour in -- they just keep the second card connected. -->
489 + <path class="wpsubs-p1-flow" d="M51,168 C51,240 225,240 225,330" />
490 + <path class="wpsubs-p1-flow" d="M150,206 C150,262 225,262 225,330" />
491 + <path class="wpsubs-p1-flow" d="M249,156 C249,250 225,250 225,330" />
492 + </svg>
493 +
494 + <div class="wpsubs-p1-node wpsubs-p1-node--plan" data-group="plan" style="left:21%;top:2.9%;">
495 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_plan; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
496 + <span class="wpsubs-p1-node__text">
497 + <span class="wpsubs-p1-node__title" id="subscrpt-preview-plan"><?php esc_html_e( 'Recurring Subscription', 'subscription' ); ?></span>
498 + <span class="wpsubs-p1-node__sub" id="subscrpt-preview-plan-type"><?php esc_html_e( 'Recurring', 'subscription' ); ?></span>
499 + </span>
1547 500 </div>
1548 - <div class="p3-action-row__content">
1549 - <p class="p3-action-row__title"><?php esc_html_e( 'View product in shop', 'subscription' ); ?></p>
1550 - <p class="p3-action-row__desc"><?php esc_html_e( 'See how customers will subscribe to it.', 'subscription' ); ?></p>
501 +
502 + <div class="wpsubs-p1-node wpsubs-p1-node--dur wpsubs-p1-node--ghost" data-group="dur" data-preview-dur="1" style="left:2%;top:31%;">
503 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_cal; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
504 + <span class="wpsubs-p1-node__text">
505 + <span class="wpsubs-p1-node__title"><?php esc_html_e( 'Duration', 'subscription' ); ?></span>
506 + <span class="wpsubs-p1-node__sub"><?php esc_html_e( 'Add more', 'subscription' ); ?></span>
507 + </span>
1551 508 </div>
1552 - <svg class="p3-action-row__chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"></polyline></svg>
1553 - </a>
1554 - <?php endif; ?>
509 + <div class="wpsubs-p1-node wpsubs-p1-node--dur wpsubs-p1-node--ghost" data-group="dur" data-preview-dur="0" style="left:35%;top:40%;">
510 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_cal; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
511 + <span class="wpsubs-p1-node__text">
512 + <span class="wpsubs-p1-node__title"><?php esc_html_e( 'Duration', 'subscription' ); ?></span>
513 + <span class="wpsubs-p1-node__sub"><?php esc_html_e( 'Add more', 'subscription' ); ?></span>
514 + </span>
515 + </div>
516 + <div class="wpsubs-p1-node wpsubs-p1-node--dur wpsubs-p1-node--ghost" data-group="dur" data-preview-dur="2" style="left:68%;top:28%;">
517 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_cal; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
518 + <span class="wpsubs-p1-node__text">
519 + <span class="wpsubs-p1-node__title"><?php esc_html_e( 'Duration', 'subscription' ); ?></span>
520 + <span class="wpsubs-p1-node__sub"><?php esc_html_e( 'Add more', 'subscription' ); ?></span>
521 + </span>
522 + </div>
1555 523
1556 - <button type="button" id="subscrpt-btn-add-another" class="p3-action-row">
1557 - <div class="p3-action-row__icon">
1558 - <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
524 + <div class="wpsubs-p1-node wpsubs-p1-node--prod" data-group="prod" style="left:3%;top:71.4%;">
525 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_box; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
526 + <span class="wpsubs-p1-node__text">
527 + <span class="wpsubs-p1-node__title" id="subscrpt-preview-prod"><?php esc_html_e( 'Product', 'subscription' ); ?></span>
528 + <span class="wpsubs-p1-node__sub" id="subscrpt-preview-prod-sub"><?php esc_html_e( 'Price', 'subscription' ); ?></span>
529 + </span>
1559 530 </div>
1560 - <div class="p3-action-row__content">
1561 - <p class="p3-action-row__title"><?php esc_html_e( 'Add another product', 'subscription' ); ?></p>
1562 - <p class="p3-action-row__desc"><?php esc_html_e( 'Create another subscription product now.', 'subscription' ); ?></p>
531 + <div class="wpsubs-p1-node wpsubs-p1-node--prod wpsubs-p1-node--ghost" data-group="prod" style="left:53%;top:78.6%;">
532 + <span class="wpsubs-p1-node__icon"><?php echo $subscrpt_icon_box; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- trusted static SVG. ?></span>
533 + <span class="wpsubs-p1-node__text">
534 + <span class="wpsubs-p1-node__title"><?php esc_html_e( 'Product', 'subscription' ); ?></span>
535 + <span class="wpsubs-p1-node__sub"><?php esc_html_e( 'Add more', 'subscription' ); ?></span>
536 + </span>
1563 537 </div>
1564 - <svg class="p3-action-row__chevron" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="9 18 15 12 9 6"></polyline></svg>
538 + </div>
539 + <p class="wpsubs-preview__caption"><?php esc_html_e( 'A plan holds billing durations and connects to a product.', 'subscription' ); ?></p>
540 + </div>
541 + </aside>
542 +
543 + <!-- ======================= Footer nav (under the left column) ======================= -->
544 + <div class="wpsubs-wizard-footer">
545 + <div class="wpsubs-wizard-nav" data-nav="1" hidden>
546 + <button type="button" id="subscrpt-btn-back-0" class="wpsubs-p2-nav-back">
547 + &#8249; <?php esc_html_e( 'Back', 'subscription' ); ?>
1565 548 </button>
1566 -
549 + <button type="button" id="subscrpt-btn-next-1" class="wpsubs-btn wpsubs-btn--primary">
550 + <?php esc_html_e( 'Continue', 'subscription' ); ?> &rsaquo;
551 + </button>
1567 552 </div>
1568 -
1569 - <p class="p3-help-text">
1570 - <?php esc_html_e( 'Need help? Check the', 'subscription' ); ?>
1571 - <a href="https://docs.converslabs.com/en" target="_blank" rel="noopener" class="p3-help-link"><?php esc_html_e( 'setup guide', 'subscription' ); ?></a>
1572 - <?php esc_html_e( 'or', 'subscription' ); ?>
1573 - <a href="https://wordpress.org/support/plugin/subscription/" target="_blank" rel="noopener" class="p3-help-link"><?php esc_html_e( 'contact support', 'subscription' ); ?></a>.
1574 - </p>
553 + <div class="wpsubs-wizard-nav" data-nav="2" hidden>
554 + <button type="button" id="subscrpt-btn-back-1" class="wpsubs-p2-nav-back">
555 + &#8249; <?php esc_html_e( 'Back', 'subscription' ); ?>
556 + </button>
557 + <button type="button" id="subscrpt-btn-next-2" class="wpsubs-btn wpsubs-btn--primary">
558 + <?php esc_html_e( 'Continue', 'subscription' ); ?> &rsaquo;
559 + </button>
560 + </div>
561 + <div class="wpsubs-wizard-nav" data-nav="3" hidden>
562 + <button type="button" id="subscrpt-btn-back-2" class="wpsubs-p2-nav-back">
563 + &#8249; <?php esc_html_e( 'Back', 'subscription' ); ?>
564 + </button>
565 + <button type="button" id="subscrpt-btn-next-3" class="wpsubs-btn wpsubs-btn--primary">
566 + <?php esc_html_e( 'Continue', 'subscription' ); ?> &rsaquo;
567 + </button>
568 + </div>
569 + <div class="wpsubs-wizard-nav" data-nav="4" hidden>
570 + <div class="wpsubs-wizard-nav__group">
571 + <a href="#" id="subscrpt-link-plans" class="wpsubs-btn wpsubs-btn--outline" hidden>
572 + <?php esc_html_e( 'Go to Plans', 'subscription' ); ?>
573 + </a>
574 + <a href="#" id="subscrpt-link-products" class="wpsubs-btn wpsubs-btn--outline" hidden>
575 + <?php esc_html_e( 'Go to products', 'subscription' ); ?>
576 + </a>
577 + </div>
578 + <a href="<?php echo esc_url( admin_url( 'admin.php?page=wp-subscription' ) ); ?>" id="subscrpt-btn-finish" class="wpsubs-btn wpsubs-btn--primary" hidden>
579 + <?php esc_html_e( 'Finish', 'subscription' ); ?>
580 + </a>
581 + </div>
1575 582 </div>
1576 583
1577 - <!-- Bottom nav -->
1578 - <div class="p3-nav">
1579 - <button type="button" id="subscrpt-btn-start-over" class="wpsubs-btn wpsubs-btn--outline">
1580 - <?php esc_html_e( 'Start over', 'subscription' ); ?>
1581 - </button>
1582 - <a href="<?php echo esc_url( admin_url( 'edit.php?post_type=product' ) ); ?>" class="wpsubs-btn wpsubs-btn--primary">
1583 - <?php esc_html_e( 'Go to products', 'subscription' ); ?>
1584 - </a>
1585 - </div>
1586 - </div>
584 + </div><!-- /.wpsubs-wizard-layout -->
1587 585 </div>