| 1 |
<template> |
| 2 |
<div class="wpfnl-mm-build-funnel"> |
| 3 |
<!-- Header --> |
| 4 |
<div class="wpfnl-mm-build-funnel-header"> |
| 5 |
<h2 class="wpfnl-mm-build-funnel-title">Create Your Revenue-Boosting Funnel</h2> |
| 6 |
<p class="wpfnl-mm-build-funnel-subtitle"> |
| 7 |
Choose products and add upsells or order bumps to increase your average order value. |
| 8 |
</p> |
| 9 |
</div> |
| 10 |
|
| 11 |
<!-- Main Container --> |
| 12 |
<div class="wpfnl-mm-build-funnel-container"> |
| 13 |
<!-- Left Panel - Product Selection --> |
| 14 |
<div class="wpfnl-mm-build-funnel-form" v-if="hasCheckout || hasUpsell"> |
| 15 |
<div class="wpfnl-mm-build-funnel-fields"> |
| 16 |
<!-- Main Product --> |
| 17 |
<div class="wpfnl-mm-build-funnel-field" v-if="hasCheckout"> |
| 18 |
<label class="wpfnl-mm-build-funnel-label">Main Product</label> |
| 19 |
<div class="wpfnl-mm-build-funnel-dropdown" :class="{ 'open': showMainProductDropdown, 'has-value': selectedMainProduct }"> |
| 20 |
<div class="wpfnl-mm-build-funnel-dropdown-trigger" @click="toggleMainProductDropdown"> |
| 21 |
<span v-if="!selectedMainProduct" class="placeholder">Choose product</span> |
| 22 |
<span v-else class="selected-value"> |
| 23 |
{{ selectedMainProduct.name }} <span v-html="formatPrice(selectedMainProduct.priceHtml)"></span> |
| 24 |
</span> |
| 25 |
<svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 26 |
<path d="M4 6L8 10L12 6" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 27 |
</svg> |
| 28 |
</div> |
| 29 |
<div class="wpfnl-mm-build-funnel-dropdown-menu" v-if="showMainProductDropdown" @click.stop> |
| 30 |
<div class="wpfnl-mm-build-funnel-search"> |
| 31 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 32 |
<path d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 33 |
<path d="M14 14L11.1 11.1" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 34 |
</svg> |
| 35 |
<input |
| 36 |
type="text" |
| 37 |
v-model="mainProductSearch" |
| 38 |
@input="searchMainProducts" |
| 39 |
placeholder="Search products..." |
| 40 |
ref="mainProductSearchInput" |
| 41 |
/> |
| 42 |
</div> |
| 43 |
<div class="wpfnl-mm-build-funnel-dropdown-list"> |
| 44 |
<div v-if="loadingMainProducts" class="wpfnl-mm-build-funnel-dropdown-loading"> |
| 45 |
<svg class="wpfnl-spinner" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 46 |
<circle cx="10" cy="10" r="8" stroke="#6E42D3" stroke-width="2" stroke-dasharray="40 15" stroke-linecap="round"/> |
| 47 |
</svg> |
| 48 |
<span>Searching...</span> |
| 49 |
</div> |
| 50 |
<template v-else> |
| 51 |
<div v-if="mainProducts.length === 0" class="wpfnl-mm-build-funnel-dropdown-empty"> |
| 52 |
<p>{{ mainProductSearch ? 'No products found' : 'No products available' }}</p> |
| 53 |
<button class="wpfnl-mm-create-product-btn" @click="showCreateProductModal"> |
| 54 |
<svg width="12" height="12" fill="none" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">> |
| 55 |
<path stroke="#6E42D3" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M5.918.9v10.013M.9 5.907h10.032"/> |
| 56 |
</svg> |
| 57 |
Create New Product |
| 58 |
</button> |
| 59 |
</div> |
| 60 |
<div |
| 61 |
v-for="product in mainProducts" |
| 62 |
:key="product.id" |
| 63 |
class="wpfnl-mm-build-funnel-dropdown-item" |
| 64 |
:class="{ 'selected': selectedMainProduct && selectedMainProduct.id === product.id }" |
| 65 |
@click="selectMainProduct(product)" |
| 66 |
> |
| 67 |
<span class="product-name">{{ product.name }}</span> |
| 68 |
<span class="product-price" v-html="formatPrice(product.priceHtml)"></span> |
| 69 |
<svg v-if="selectedMainProduct && selectedMainProduct.id === product.id" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 70 |
<path d="M13.3334 4L6.00002 11.3333L2.66669 8" stroke="#6E42D3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 71 |
</svg> |
| 72 |
</div> |
| 73 |
</template> |
| 74 |
</div> |
| 75 |
</div> |
| 76 |
</div> |
| 77 |
<p class="wpfnl-mm-build-funnel-hint">Select a product that’s already a top seller to maximize conversions.</p> |
| 78 |
</div> |
| 79 |
|
| 80 |
<!-- Order Bump --> |
| 81 |
<div class="wpfnl-mm-build-funnel-field" v-if="hasCheckout"> |
| 82 |
<label class="wpfnl-mm-build-funnel-label">Order Bump</label> |
| 83 |
<div class="wpfnl-mm-build-funnel-dropdown" :class="{ 'open': showOrderBumpDropdown, 'has-value': selectedOrderBump }"> |
| 84 |
<div class="wpfnl-mm-build-funnel-dropdown-trigger" @click="toggleOrderBumpDropdown"> |
| 85 |
<span v-if="!selectedOrderBump" class="placeholder">Choose product</span> |
| 86 |
<span v-else class="selected-value"> |
| 87 |
{{ selectedOrderBump.name }} <span v-html="formatPrice(selectedOrderBump.priceHtml)"></span> |
| 88 |
</span> |
| 89 |
<svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 90 |
<path d="M4 6L8 10L12 6" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 91 |
</svg> |
| 92 |
</div> |
| 93 |
<div class="wpfnl-mm-build-funnel-dropdown-menu" v-if="showOrderBumpDropdown" @click.stop> |
| 94 |
<div class="wpfnl-mm-build-funnel-search"> |
| 95 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 96 |
<path d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 97 |
<path d="M14 14L11.1 11.1" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 98 |
</svg> |
| 99 |
<input |
| 100 |
type="text" |
| 101 |
v-model="orderBumpSearch" |
| 102 |
@input="searchOrderBumpProducts" |
| 103 |
placeholder="Search products..." |
| 104 |
ref="orderBumpSearchInput" |
| 105 |
/> |
| 106 |
</div> |
| 107 |
<div class="wpfnl-mm-build-funnel-dropdown-list"> |
| 108 |
<div v-if="loadingOrderBumpProducts" class="wpfnl-mm-build-funnel-dropdown-loading"> |
| 109 |
<svg class="wpfnl-spinner" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 110 |
<circle cx="10" cy="10" r="8" stroke="#6E42D3" stroke-width="2" stroke-dasharray="40 15" stroke-linecap="round"/> |
| 111 |
</svg> |
| 112 |
<span>Searching...</span> |
| 113 |
</div> |
| 114 |
<template v-else> |
| 115 |
<div v-if="orderBumpProducts.length === 0" class="wpfnl-mm-build-funnel-dropdown-empty"> |
| 116 |
<p>{{ orderBumpSearch ? 'No products found' : 'No products available' }}</p> |
| 117 |
<button class="wpfnl-mm-create-product-btn" @click="showCreateProductModal"> |
| 118 |
<svg width="12" height="12" fill="none" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">> |
| 119 |
<path stroke="#6E42D3" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M5.918.9v10.013M.9 5.907h10.032"/> |
| 120 |
</svg> |
| 121 |
Create New Product |
| 122 |
</button> |
| 123 |
</div> |
| 124 |
<div |
| 125 |
v-for="product in orderBumpProducts" |
| 126 |
:key="product.id" |
| 127 |
class="wpfnl-mm-build-funnel-dropdown-item" |
| 128 |
:class="{ 'selected': selectedOrderBump && selectedOrderBump.id === product.id }" |
| 129 |
@click="selectOrderBump(product)" |
| 130 |
> |
| 131 |
<span class="product-name">{{ product.name }}</span> |
| 132 |
<span class="product-price" v-html="formatPrice(product.priceHtml)"></span> |
| 133 |
<svg v-if="selectedOrderBump && selectedOrderBump.id === product.id" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 134 |
<path d="M13.3334 4L6.00002 11.3333L2.66669 8" stroke="#6E42D3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 135 |
</svg> |
| 136 |
</div> |
| 137 |
</template> |
| 138 |
</div> |
| 139 |
</div> |
| 140 |
</div> |
| 141 |
<p class="wpfnl-mm-build-funnel-hint">Add a complementary product with one click at checkout.</p> |
| 142 |
</div> |
| 143 |
|
| 144 |
<!-- Upsell Product --> |
| 145 |
<div class="wpfnl-mm-build-funnel-field" v-if="hasUpsell"> |
| 146 |
<label class="wpfnl-mm-build-funnel-label">Upsell Product <span class="optional">(optional)</span></label> |
| 147 |
<div class="wpfnl-mm-build-funnel-dropdown" :class="{ 'open': showUpsellDropdown, 'has-value': selectedUpsell }"> |
| 148 |
<div class="wpfnl-mm-build-funnel-dropdown-trigger" @click="toggleUpsellDropdown"> |
| 149 |
<span v-if="!selectedUpsell" class="placeholder">Choose product</span> |
| 150 |
<span v-else class="selected-value"> |
| 151 |
{{ selectedUpsell.name }} <span v-html="formatPrice(selectedUpsell.priceHtml)"></span> |
| 152 |
</span> |
| 153 |
<svg class="dropdown-icon" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 154 |
<path d="M4 6L8 10L12 6" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 155 |
</svg> |
| 156 |
</div> |
| 157 |
<div class="wpfnl-mm-build-funnel-dropdown-menu" v-if="showUpsellDropdown" @click.stop> |
| 158 |
<div class="wpfnl-mm-build-funnel-search"> |
| 159 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 160 |
<path d="M7.33333 12.6667C10.2789 12.6667 12.6667 10.2789 12.6667 7.33333C12.6667 4.38781 10.2789 2 7.33333 2C4.38781 2 2 4.38781 2 7.33333C2 10.2789 4.38781 12.6667 7.33333 12.6667Z" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 161 |
<path d="M14 14L11.1 11.1" stroke="#7A8C9A" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 162 |
</svg> |
| 163 |
<input |
| 164 |
type="text" |
| 165 |
v-model="upsellSearch" |
| 166 |
@input="searchUpsellProducts" |
| 167 |
placeholder="Search products..." |
| 168 |
ref="upsellSearchInput" |
| 169 |
/> |
| 170 |
</div> |
| 171 |
<div class="wpfnl-mm-build-funnel-dropdown-list"> |
| 172 |
<div v-if="loadingUpsellProducts" class="wpfnl-mm-build-funnel-dropdown-loading"> |
| 173 |
<svg class="wpfnl-spinner" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 174 |
<circle cx="10" cy="10" r="8" stroke="#6E42D3" stroke-width="2" stroke-dasharray="40 15" stroke-linecap="round"/> |
| 175 |
</svg> |
| 176 |
<span>Searching...</span> |
| 177 |
</div> |
| 178 |
<template v-else> |
| 179 |
<div v-if="upsellProducts.length === 0" class="wpfnl-mm-build-funnel-dropdown-empty"> |
| 180 |
<p>{{ upsellSearch ? 'No products found' : 'No products available' }}</p> |
| 181 |
<button class="wpfnl-mm-create-product-btn" @click="showCreateProductModal"> |
| 182 |
<svg width="12" height="12" fill="none" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">> |
| 183 |
<path stroke="#6E42D3" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" d="M5.918.9v10.013M.9 5.907h10.032"/> |
| 184 |
</svg> |
| 185 |
Create New Product |
| 186 |
</button> |
| 187 |
</div> |
| 188 |
<div |
| 189 |
v-for="product in upsellProducts" |
| 190 |
:key="product.id" |
| 191 |
class="wpfnl-mm-build-funnel-dropdown-item" |
| 192 |
:class="{ 'selected': selectedUpsell && selectedUpsell.id === product.id }" |
| 193 |
@click="selectUpsell(product)" |
| 194 |
> |
| 195 |
<span class="product-name">{{ product.name }}</span> |
| 196 |
<span class="product-price" v-html="formatPrice(product.priceHtml)"></span> |
| 197 |
<svg v-if="selectedUpsell && selectedUpsell.id === product.id" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 198 |
<path d="M13.3334 4L6.00002 11.3333L2.66669 8" stroke="#6E42D3" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 199 |
</svg> |
| 200 |
</div> |
| 201 |
</template> |
| 202 |
</div> |
| 203 |
</div> |
| 204 |
</div> |
| 205 |
<p class="wpfnl-mm-build-funnel-hint">Offer an extra product after checkout to increase order value.</p> |
| 206 |
</div> |
| 207 |
</div> |
| 208 |
|
| 209 |
<!-- Potential Revenue --> |
| 210 |
<div class="wpfnl-mm-build-funnel-revenue" v-if="hasCheckout && selectedMainProduct"> |
| 211 |
<div class="wpfnl-mm-revenue-header"> |
| 212 |
<p class="wpfnl-mm-build-funnel-revenue-label">Potential Revenue per Customer</p> |
| 213 |
</div> |
| 214 |
|
| 215 |
<div class="wpfnl-mm-revenue-breakdown"> |
| 216 |
<!-- Main Product --> |
| 217 |
<div class="wpfnl-mm-revenue-item"> |
| 218 |
<div class="wpfnl-mm-revenue-item-content"> |
| 219 |
<div class="wpfnl-mm-revenue-item-label">Main Product</div> |
| 220 |
<div class="wpfnl-mm-revenue-item-name">{{ selectedMainProduct.text }}</div> |
| 221 |
</div> |
| 222 |
<div class="wpfnl-mm-revenue-item-price">{{ formatSimplePrice(selectedMainProduct.numericPrice) }}</div> |
| 223 |
</div> |
| 224 |
|
| 225 |
<!-- Order Bump --> |
| 226 |
<div class="wpfnl-mm-revenue-item wpfnl-mm-revenue-item-bonus" v-if="selectedOrderBump"> |
| 227 |
<div class="wpfnl-mm-revenue-item-content"> |
| 228 |
<div class="wpfnl-mm-revenue-item-label">Order Bump <span class="wpfnl-mm-revenue-badge">+Bonus</span></div> |
| 229 |
<div class="wpfnl-mm-revenue-item-name">{{ selectedOrderBump.text }}</div> |
| 230 |
</div> |
| 231 |
<div class="wpfnl-mm-revenue-item-price wpfnl-mm-revenue-bonus">+{{ formatSimplePrice(selectedOrderBump.numericPrice) }}</div> |
| 232 |
</div> |
| 233 |
|
| 234 |
<!-- Upsell --> |
| 235 |
<div class="wpfnl-mm-revenue-item wpfnl-mm-revenue-item-bonus" v-if="selectedUpsell"> |
| 236 |
<div class="wpfnl-mm-revenue-item-content"> |
| 237 |
<div class="wpfnl-mm-revenue-item-label">Upsell Product <span class="wpfnl-mm-revenue-badge">+Bonus</span></div> |
| 238 |
<div class="wpfnl-mm-revenue-item-name">{{ selectedUpsell.text }}</div> |
| 239 |
</div> |
| 240 |
<div class="wpfnl-mm-revenue-item-price wpfnl-mm-revenue-bonus">+{{ formatSimplePrice(selectedUpsell.numericPrice) }}</div> |
| 241 |
</div> |
| 242 |
|
| 243 |
<!-- Separator --> |
| 244 |
<div class="wpfnl-mm-revenue-separator"></div> |
| 245 |
|
| 246 |
<!-- Total --> |
| 247 |
<div class="wpfnl-mm-revenue-total"> |
| 248 |
<div class="wpfnl-mm-revenue-total-content"> |
| 249 |
<div class="wpfnl-mm-revenue-total-label">Total Potential Revenue</div> |
| 250 |
<div class="wpfnl-mm-revenue-total-value">{{ formatSimplePrice(potentialRevenue) }}</div> |
| 251 |
</div> |
| 252 |
<div class="wpfnl-mm-revenue-boost-inline" v-if="selectedOrderBump || selectedUpsell"> |
| 253 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 254 |
<path d="M8 1.33331V14.6666M8 1.33331L3.33334 5.99998M8 1.33331L12.6667 5.99998" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 255 |
</svg> |
| 256 |
<span>+{{ calculateRevenueBoost }}%</span> |
| 257 |
</div> |
| 258 |
</div> |
| 259 |
</div> |
| 260 |
</div> |
| 261 |
</div> |
| 262 |
|
| 263 |
<!-- Right Panel - Preview --> |
| 264 |
<div class="wpfnl-mm-build-funnel-preview"> |
| 265 |
<!-- Sub-step Tabs --> |
| 266 |
<div class="wpfnl-mm-build-funnel-tabs"> |
| 267 |
<template v-for="(step, index) in availableSteps" :key="step"> |
| 268 |
<div |
| 269 |
class="wpfnl-mm-build-funnel-tab" |
| 270 |
:class="{ 'active': activeSubStep === step }" |
| 271 |
@click="setActiveSubStep(step)" |
| 272 |
> |
| 273 |
<div class="wpfnl-mm-build-funnel-tab-icon"> |
| 274 |
<svg v-if="step === 'landing'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 275 |
<rect x="3" y="3" width="14" height="14" rx="2" stroke="currentColor" stroke-width="1.5"/> |
| 276 |
<path d="M3 7H17" stroke="currentColor" stroke-width="1.5"/> |
| 277 |
<path d="M7 7V17" stroke="currentColor" stroke-width="1.5"/> |
| 278 |
</svg> |
| 279 |
<svg v-else-if="step === 'checkout'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 280 |
<path d="M5 5H17L15.5 13H6.5L5 5Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 281 |
<circle cx="7" cy="16" r="1.5" stroke="currentColor" stroke-width="1.5"/> |
| 282 |
<circle cx="15" cy="16" r="1.5" stroke="currentColor" stroke-width="1.5"/> |
| 283 |
<path d="M5 5L4 2H2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 284 |
</svg> |
| 285 |
<svg v-else-if="step === 'upsell'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 286 |
<path d="M10 4V16M10 4L6 8M10 4L14 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 287 |
</svg> |
| 288 |
<svg v-else-if="step === 'thankyou'" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 289 |
<path d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18Z" stroke="currentColor" stroke-width="1.5"/> |
| 290 |
<path d="M7 10L9 12L13 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 291 |
</svg> |
| 292 |
</div> |
| 293 |
<span class="wpfnl-mm-build-funnel-tab-label"> |
| 294 |
{{ step === 'landing' ? 'Landing' : step === 'checkout' ? 'Checkout' : step === 'upsell' ? 'Upsell' : 'Thank You' }} |
| 295 |
</span> |
| 296 |
</div> |
| 297 |
<div v-if="index < availableSteps.length - 1" class="wpfnl-mm-build-funnel-tab-line"></div> |
| 298 |
</template> |
| 299 |
</div> |
| 300 |
|
| 301 |
<!-- Preview Content --> |
| 302 |
<div class="wpfnl-mm-build-funnel-preview-content"> |
| 303 |
<!-- Landing Preview --> |
| 304 |
<div v-if="activeSubStep === 'landing'" class="wpfnl-mm-build-funnel-preview-image"> |
| 305 |
<img v-if="templateImages.landing" :src="templateImages.landing" alt="Landing Page Preview" /> |
| 306 |
<div v-else class="wpfnl-mm-build-funnel-preview-placeholder"> |
| 307 |
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 308 |
<rect x="6" y="6" width="36" height="36" rx="4" stroke="#C4C4C4" stroke-width="2"/> |
| 309 |
<path d="M6 14H42" stroke="#C4C4C4" stroke-width="2"/> |
| 310 |
<path d="M14 14V42" stroke="#C4C4C4" stroke-width="2"/> |
| 311 |
</svg> |
| 312 |
<p>Landing page preview</p> |
| 313 |
</div> |
| 314 |
</div> |
| 315 |
|
| 316 |
<!-- Checkout Preview --> |
| 317 |
<div v-if="activeSubStep === 'checkout'" class="wpfnl-mm-build-funnel-preview-image"> |
| 318 |
<img v-if="templateImages.checkout" :src="templateImages.checkout" alt="Checkout Page Preview" /> |
| 319 |
<div v-else class="wpfnl-mm-build-funnel-preview-placeholder"> |
| 320 |
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 321 |
<path d="M10 10H42L38 26H14L10 10Z" stroke="#C4C4C4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 322 |
<circle cx="16" cy="36" r="3" stroke="#C4C4C4" stroke-width="2"/> |
| 323 |
<circle cx="36" cy="36" r="3" stroke="#C4C4C4" stroke-width="2"/> |
| 324 |
</svg> |
| 325 |
<p>Checkout page preview</p> |
| 326 |
</div> |
| 327 |
</div> |
| 328 |
|
| 329 |
<!-- Upsell Preview --> |
| 330 |
<div v-if="activeSubStep === 'upsell'" class="wpfnl-mm-build-funnel-preview-image"> |
| 331 |
<template v-if="selectedUpsell"> |
| 332 |
<img v-if="templateImages.upsell" :src="templateImages.upsell" alt="Upsell Page Preview" /> |
| 333 |
<div v-else class="wpfnl-mm-build-funnel-preview-placeholder"> |
| 334 |
<p>Upsell page preview</p> |
| 335 |
</div> |
| 336 |
</template> |
| 337 |
<div v-else class="wpfnl-mm-build-funnel-preview-empty"> |
| 338 |
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 339 |
<path d="M24 8V40M24 8L16 16M24 8L32 16" stroke="#C4C4C4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 340 |
</svg> |
| 341 |
<h4>Upsell</h4> |
| 342 |
<p>Select a upsell product to preview your funnel</p> |
| 343 |
</div> |
| 344 |
</div> |
| 345 |
|
| 346 |
<!-- Thank You Preview --> |
| 347 |
<div v-if="activeSubStep === 'thankyou'" class="wpfnl-mm-build-funnel-preview-image"> |
| 348 |
<img v-if="templateImages.thankyou" :src="templateImages.thankyou" alt="Thank You Page Preview" /> |
| 349 |
<div v-else class="wpfnl-mm-build-funnel-preview-placeholder"> |
| 350 |
<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 351 |
<circle cx="24" cy="24" r="18" stroke="#C4C4C4" stroke-width="2"/> |
| 352 |
<path d="M16 24L22 30L32 18" stroke="#C4C4C4" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 353 |
</svg> |
| 354 |
<p>Thank you page preview</p> |
| 355 |
</div> |
| 356 |
</div> |
| 357 |
</div> |
| 358 |
</div> |
| 359 |
</div> |
| 360 |
|
| 361 |
<!-- Buttons --> |
| 362 |
<div class="wpfnl-mm-build-funnel-buttons wpfnl-mm-buttons-container"> |
| 363 |
<button class="wpfnl-mm-btn wpfnl-mm-btn-secondary" @click="goBack" :disabled="isProcessing"> |
| 364 |
Back |
| 365 |
</button> |
| 366 |
<div class="wpfnl-mm-btn-group"> |
| 367 |
<button |
| 368 |
class="wpfnl-mm-btn wpfnl-mm-btn-primary" |
| 369 |
@click="handleContinue" |
| 370 |
:disabled="isContinueDisabled" |
| 371 |
> |
| 372 |
<span v-if="!isProcessing && !isGeneratingFunnel">Continue</span> |
| 373 |
<span v-else-if="isGeneratingFunnel">{{ funnelStatusMessage || 'Creating funnel...' }}</span> |
| 374 |
<span v-else>Processing...</span> |
| 375 |
<svg v-if="!isProcessing && !isGeneratingFunnel" width="17" height="12" viewBox="0 0 17 12" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 376 |
<path d="M1 6H16M16 6L11 1M16 6L11 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 377 |
</svg> |
| 378 |
<svg v-else class="wpfnl-spinner" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 379 |
<circle cx="8" cy="8" r="6" stroke="white" stroke-width="2" stroke-dasharray="30 10" stroke-linecap="round"/> |
| 380 |
</svg> |
| 381 |
</button> |
| 382 |
</div> |
| 383 |
</div> |
| 384 |
|
| 385 |
<!-- Create Product Modal --> |
| 386 |
<div class="wpfnl-modal-overlay" v-if="isCreateProduct"> |
| 387 |
<div class="wpfnl-modal-wrapper"> |
| 388 |
<div class="wpfnl-modal-close"> |
| 389 |
<span class="wpfnl-modal-close-btn" @click="removeCreateProductModal"> |
| 390 |
<svg width="12" height="13" fill="none" viewBox="0 0 12 13" xmlns="http://www.w3.org/2000/svg">> |
| 391 |
<path stroke="#7A8B9A" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 1.969l-10 9.99m0-9.99l10 9.99"></path> |
| 392 |
</svg> |
| 393 |
</span> |
| 394 |
</div> |
| 395 |
|
| 396 |
<span class="wpfnl-loader" v-if="isShowModalLoader"></span> |
| 397 |
<div id="wpfnl-create-product" :style="{ display: !isShowModalLoader ? 'block' : 'none' }"> |
| 398 |
</div> |
| 399 |
</div> |
| 400 |
</div> |
| 401 |
|
| 402 |
<!-- Help Button --> |
| 403 |
<div class="wpfnl-mm-help-btn"> |
| 404 |
<button class="wpfnl-mm-help-btn-circle" @click="showHelp"> |
| 405 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 406 |
<path d="M6.06 5.99999C6.2167 5.55443 6.52627 5.17872 6.93329 4.93941C7.34031 4.7001 7.81926 4.61252 8.28478 4.69247C8.75031 4.77242 9.17254 5.01433 9.47671 5.37567C9.78087 5.73702 9.94736 6.19433 9.94667 6.66666C9.94667 7.99999 7.94667 8.66666 7.94667 8.66666M8 11.3333H8.00667M14.6667 8C14.6667 11.6819 11.6819 14.6667 8 14.6667C4.31811 14.6667 1.33334 11.6819 1.33334 8C1.33334 4.31809 4.31811 1.33333 8 1.33333C11.6819 1.33333 14.6667 4.31809 14.6667 8Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 407 |
</svg> |
| 408 |
</button> |
| 409 |
</div> |
| 410 |
</div> |
| 411 |
</template> |
| 412 |
|
| 413 |
<script> |
| 414 |
import { __ } from '@wordpress/i18n' |
| 415 |
import apiFetch from '@wordpress/api-fetch' |
| 416 |
|
| 417 |
export default { |
| 418 |
name: 'BuildFunnel', |
| 419 |
props: { |
| 420 |
template: { |
| 421 |
type: Object, |
| 422 |
default: null |
| 423 |
}, |
| 424 |
goal: { |
| 425 |
type: String, |
| 426 |
default: 'sales' |
| 427 |
}, |
| 428 |
builder: { |
| 429 |
type: String, |
| 430 |
default: 'gutenberg' |
| 431 |
} |
| 432 |
}, |
| 433 |
data() { |
| 434 |
return { |
| 435 |
activeSubStep: 'landing', |
| 436 |
isProcessing: false, |
| 437 |
isCreateProduct: false, |
| 438 |
isShowModalLoader: false, |
| 439 |
|
| 440 |
// Dropdown states |
| 441 |
showMainProductDropdown: false, |
| 442 |
showOrderBumpDropdown: false, |
| 443 |
showUpsellDropdown: false, |
| 444 |
|
| 445 |
// Search queries |
| 446 |
mainProductSearch: '', |
| 447 |
orderBumpSearch: '', |
| 448 |
upsellSearch: '', |
| 449 |
|
| 450 |
// Loading states |
| 451 |
loadingMainProducts: false, |
| 452 |
loadingOrderBumpProducts: false, |
| 453 |
loadingUpsellProducts: false, |
| 454 |
|
| 455 |
// Search results |
| 456 |
mainProducts: [], |
| 457 |
orderBumpProducts: [], |
| 458 |
upsellProducts: [], |
| 459 |
|
| 460 |
// Selected products |
| 461 |
selectedMainProduct: null, |
| 462 |
selectedOrderBump: null, |
| 463 |
selectedUpsell: null, |
| 464 |
|
| 465 |
// Debounce timers |
| 466 |
mainProductDebounce: null, |
| 467 |
orderBumpDebounce: null, |
| 468 |
upsellDebounce: null, |
| 469 |
|
| 470 |
// Template images |
| 471 |
templateImages: { |
| 472 |
landing: '', |
| 473 |
checkout: '', |
| 474 |
upsell: '', |
| 475 |
thankyou: '' |
| 476 |
}, |
| 477 |
|
| 478 |
// Funnel creation state |
| 479 |
isGeneratingFunnel: false, |
| 480 |
funnelStatusMessage: '', |
| 481 |
createdFunnelId: null, |
| 482 |
createdFirstStepLink: '' |
| 483 |
} |
| 484 |
}, |
| 485 |
computed: { |
| 486 |
potentialRevenue() { |
| 487 |
let total = 0 |
| 488 |
if (this.selectedMainProduct) { |
| 489 |
total += parseFloat(this.selectedMainProduct.numericPrice) || 0 |
| 490 |
} |
| 491 |
if (this.selectedOrderBump) { |
| 492 |
total += parseFloat(this.selectedOrderBump.numericPrice) || 0 |
| 493 |
} |
| 494 |
if (this.selectedUpsell) { |
| 495 |
total += parseFloat(this.selectedUpsell.numericPrice) || 0 |
| 496 |
} |
| 497 |
return total |
| 498 |
}, |
| 499 |
calculateRevenueBoost() { |
| 500 |
if (!this.selectedMainProduct) return 0 |
| 501 |
|
| 502 |
const mainPrice = this.selectedMainProduct.numericPrice || 0 |
| 503 |
const bumpPrice = this.selectedOrderBump ? (this.selectedOrderBump.numericPrice || 0) : 0 |
| 504 |
const upsellPrice = this.selectedUpsell ? (this.selectedUpsell.numericPrice || 0) : 0 |
| 505 |
|
| 506 |
if (mainPrice === 0) return 0 |
| 507 |
|
| 508 |
const additionalRevenue = bumpPrice + upsellPrice |
| 509 |
const boost = (additionalRevenue / mainPrice) * 100 |
| 510 |
return Math.round(boost) |
| 511 |
}, |
| 512 |
hasLanding() { |
| 513 |
if (!this.template || !this.template.steps) return false |
| 514 |
return this.template.steps.some(step => step.step_type === 'landing') |
| 515 |
}, |
| 516 |
hasCheckout() { |
| 517 |
if (!this.template || !this.template.steps) return false |
| 518 |
return this.template.steps.some(step => step.step_type === 'checkout') |
| 519 |
}, |
| 520 |
hasUpsell() { |
| 521 |
if (!this.template || !this.template.steps) return false |
| 522 |
return this.template.steps.some(step => step.step_type === 'upsell') |
| 523 |
}, |
| 524 |
hasThankyou() { |
| 525 |
if (!this.template || !this.template.steps) return false |
| 526 |
return this.template.steps.some(step => step.step_type === 'thankyou') |
| 527 |
}, |
| 528 |
availableSteps() { |
| 529 |
const steps = [] |
| 530 |
if (this.hasLanding) steps.push('landing') |
| 531 |
if (this.hasCheckout) steps.push('checkout') |
| 532 |
if (this.hasUpsell) steps.push('upsell') |
| 533 |
if (this.hasThankyou) steps.push('thankyou') |
| 534 |
return steps |
| 535 |
}, |
| 536 |
isContinueDisabled() { |
| 537 |
// For order-value goal, both main product and order bump must be selected |
| 538 |
if (this.goal === 'order-value') { |
| 539 |
return !this.selectedMainProduct || !this.selectedOrderBump || this.isProcessing || this.isGeneratingFunnel |
| 540 |
} |
| 541 |
return this.isProcessing || this.isGeneratingFunnel |
| 542 |
} |
| 543 |
}, |
| 544 |
mounted() { |
| 545 |
this.loadTemplateImages() |
| 546 |
document.addEventListener('click', this.closeDropdowns) |
| 547 |
// Set active tab to first available step |
| 548 |
if (this.availableSteps.length > 0) { |
| 549 |
this.activeSubStep = this.availableSteps[0] |
| 550 |
} |
| 551 |
}, |
| 552 |
beforeDestroy() { |
| 553 |
document.removeEventListener('click', this.closeDropdowns) |
| 554 |
// Clear debounce timers |
| 555 |
if (this.mainProductDebounce) clearTimeout(this.mainProductDebounce) |
| 556 |
if (this.orderBumpDebounce) clearTimeout(this.orderBumpDebounce) |
| 557 |
if (this.upsellDebounce) clearTimeout(this.upsellDebounce) |
| 558 |
}, |
| 559 |
methods: { |
| 560 |
stripHtml(html) { |
| 561 |
if (!html) return '' |
| 562 |
const tmp = document.createElement('DIV') |
| 563 |
tmp.innerHTML = html |
| 564 |
return tmp.textContent || tmp.innerText || '' |
| 565 |
}, |
| 566 |
|
| 567 |
extractNumericPrice(priceString) { |
| 568 |
if (!priceString) return 0 |
| 569 |
|
| 570 |
// If it's already a number, return it |
| 571 |
if (typeof priceString === 'number') { |
| 572 |
return priceString |
| 573 |
} |
| 574 |
|
| 575 |
// Convert to string if not already |
| 576 |
const priceStr = String(priceString) |
| 577 |
|
| 578 |
// Strip HTML tags first |
| 579 |
const cleanPrice = this.stripHtml(priceStr) |
| 580 |
|
| 581 |
// Remove all non-numeric characters except dots and commas |
| 582 |
// Then handle different decimal separator formats |
| 583 |
let numericStr = cleanPrice.replace(/[^\d.,]/g, '') |
| 584 |
|
| 585 |
// Handle European format (1.234,56) vs US format (1,234.56) |
| 586 |
// If there's both comma and dot, determine which is the decimal separator |
| 587 |
if (numericStr.includes(',') && numericStr.includes('.')) { |
| 588 |
// If comma comes after dot, comma is decimal separator (European) |
| 589 |
if (numericStr.lastIndexOf(',') > numericStr.lastIndexOf('.')) { |
| 590 |
numericStr = numericStr.replace(/\./g, '').replace(',', '.') |
| 591 |
} else { |
| 592 |
// US format - just remove commas |
| 593 |
numericStr = numericStr.replace(/,/g, '') |
| 594 |
} |
| 595 |
} else if (numericStr.includes(',')) { |
| 596 |
// Only comma - could be decimal or thousand separator |
| 597 |
// If there are 2 digits after the last comma, it's a decimal separator |
| 598 |
const parts = numericStr.split(',') |
| 599 |
if (parts.length === 2 && parts[1].length <= 2) { |
| 600 |
numericStr = numericStr.replace(',', '.') |
| 601 |
} else { |
| 602 |
numericStr = numericStr.replace(/,/g, '') |
| 603 |
} |
| 604 |
} |
| 605 |
|
| 606 |
const result = parseFloat(numericStr) |
| 607 |
return isNaN(result) ? 0 : result |
| 608 |
}, |
| 609 |
|
| 610 |
formatPrice(priceString) { |
| 611 |
if (!priceString) return this.getCurrencySymbol() + '0.00' |
| 612 |
// If it contains HTML, return as is for v-html |
| 613 |
if (priceString.includes('<')) { |
| 614 |
return priceString |
| 615 |
} |
| 616 |
// Otherwise format as simple price with currency |
| 617 |
const symbol = this.getCurrencySymbol() |
| 618 |
const position = window.setup_wizard_obj?.currency_position || 'left' |
| 619 |
|
| 620 |
if (position === 'right') { |
| 621 |
return `${priceString}${symbol}` |
| 622 |
} else if (position === 'right_space') { |
| 623 |
return `${priceString} ${symbol}` |
| 624 |
} else if (position === 'left_space') { |
| 625 |
return `${symbol} ${priceString}` |
| 626 |
} |
| 627 |
// Default: left |
| 628 |
return `${symbol}${priceString}` |
| 629 |
}, |
| 630 |
|
| 631 |
getCurrencySymbol() { |
| 632 |
return window.setup_wizard_obj?.currency_symbol || '$' |
| 633 |
}, |
| 634 |
|
| 635 |
formatSimplePrice(amount) { |
| 636 |
const symbol = this.getCurrencySymbol() |
| 637 |
const position = window.setup_wizard_obj?.currency_position || 'left' |
| 638 |
|
| 639 |
// Ensure amount is a valid number |
| 640 |
let numericAmount = 0 |
| 641 |
if (typeof amount === 'number') { |
| 642 |
numericAmount = amount |
| 643 |
} else if (typeof amount === 'string') { |
| 644 |
numericAmount = parseFloat(amount) || 0 |
| 645 |
} |
| 646 |
|
| 647 |
const price = numericAmount.toFixed(2) |
| 648 |
|
| 649 |
if (position === 'right') { |
| 650 |
return `${price}${symbol}` |
| 651 |
} else if (position === 'right_space') { |
| 652 |
return `${price} ${symbol}` |
| 653 |
} else if (position === 'left_space') { |
| 654 |
return `${symbol} ${price}` |
| 655 |
} |
| 656 |
// Default: left |
| 657 |
return `${symbol}${price}` |
| 658 |
}, |
| 659 |
|
| 660 |
async searchProducts(query, limit = 0) { |
| 661 |
try { |
| 662 |
const params = new URLSearchParams({ |
| 663 |
action: 'wpfnl_product_search', |
| 664 |
term: query || '', |
| 665 |
security: window.setup_wizard_obj.admin_nonce, |
| 666 |
isLms: 'false' |
| 667 |
}) |
| 668 |
|
| 669 |
if (limit > 0) { |
| 670 |
params.append('limit', limit) |
| 671 |
} |
| 672 |
|
| 673 |
const response = await fetch(`${window.setup_wizard_obj.ajax_url}?${params.toString()}`, { |
| 674 |
method: 'GET' |
| 675 |
}) |
| 676 |
|
| 677 |
const data = await response.json() |
| 678 |
|
| 679 |
if (data && typeof data === 'object') { |
| 680 |
// Convert object to array format |
| 681 |
return Object.keys(data).map(id => { |
| 682 |
const product = data[id] |
| 683 |
// Try to get price from various possible fields |
| 684 |
const priceValue = product.price || product.regular_price || product.sale_price || '0' |
| 685 |
|
| 686 |
return { |
| 687 |
id: id, |
| 688 |
name: product.name || product.text || '', |
| 689 |
price: priceValue, |
| 690 |
priceHtml: priceValue, |
| 691 |
numericPrice: this.extractNumericPrice(priceValue) |
| 692 |
} |
| 693 |
}) |
| 694 |
} |
| 695 |
return [] |
| 696 |
} catch (error) { |
| 697 |
console.error('Error searching products:', error) |
| 698 |
return [] |
| 699 |
} |
| 700 |
}, |
| 701 |
|
| 702 |
searchMainProducts() { |
| 703 |
if (this.mainProductDebounce) clearTimeout(this.mainProductDebounce) |
| 704 |
|
| 705 |
this.mainProductDebounce = setTimeout(async () => { |
| 706 |
if (!this.mainProductSearch || this.mainProductSearch.length < 2) { |
| 707 |
return |
| 708 |
} |
| 709 |
|
| 710 |
this.loadingMainProducts = true |
| 711 |
this.mainProducts = await this.searchProducts(this.mainProductSearch) |
| 712 |
this.loadingMainProducts = false |
| 713 |
}, 300) |
| 714 |
}, |
| 715 |
|
| 716 |
async loadInitialProducts(type) { |
| 717 |
if (type === 'main') { |
| 718 |
if (this.mainProducts.length > 0) { |
| 719 |
return |
| 720 |
} |
| 721 |
this.loadingMainProducts = true |
| 722 |
// Fetch recent products (empty term + limit returns latest products) |
| 723 |
const products = await this.searchProducts('', 10) |
| 724 |
this.mainProducts = products |
| 725 |
this.loadingMainProducts = false |
| 726 |
} else if (type === 'orderbump') { |
| 727 |
if (this.orderBumpProducts.length > 0) { |
| 728 |
return |
| 729 |
} |
| 730 |
this.loadingOrderBumpProducts = true |
| 731 |
const products = await this.searchProducts('', 10) |
| 732 |
this.orderBumpProducts = products |
| 733 |
this.loadingOrderBumpProducts = false |
| 734 |
} else if (type === 'upsell') { |
| 735 |
if (this.upsellProducts.length > 0) { |
| 736 |
return |
| 737 |
} |
| 738 |
this.loadingUpsellProducts = true |
| 739 |
const products = await this.searchProducts('', 10) |
| 740 |
this.upsellProducts = products |
| 741 |
this.loadingUpsellProducts = false |
| 742 |
} |
| 743 |
}, |
| 744 |
|
| 745 |
searchOrderBumpProducts() { |
| 746 |
if (this.orderBumpDebounce) clearTimeout(this.orderBumpDebounce) |
| 747 |
|
| 748 |
this.orderBumpDebounce = setTimeout(async () => { |
| 749 |
if (!this.orderBumpSearch || this.orderBumpSearch.length < 2) { |
| 750 |
return |
| 751 |
} |
| 752 |
|
| 753 |
this.loadingOrderBumpProducts = true |
| 754 |
this.orderBumpProducts = await this.searchProducts(this.orderBumpSearch) |
| 755 |
this.loadingOrderBumpProducts = false |
| 756 |
}, 300) |
| 757 |
}, |
| 758 |
|
| 759 |
searchUpsellProducts() { |
| 760 |
if (this.upsellDebounce) clearTimeout(this.upsellDebounce) |
| 761 |
|
| 762 |
this.upsellDebounce = setTimeout(async () => { |
| 763 |
if (!this.upsellSearch || this.upsellSearch.length < 2) { |
| 764 |
return |
| 765 |
} |
| 766 |
|
| 767 |
this.loadingUpsellProducts = true |
| 768 |
this.upsellProducts = await this.searchProducts(this.upsellSearch) |
| 769 |
this.loadingUpsellProducts = false |
| 770 |
}, 300) |
| 771 |
}, |
| 772 |
|
| 773 |
loadTemplateImages() { |
| 774 |
if (this.template && this.template.steps) { |
| 775 |
this.template.steps.forEach(step => { |
| 776 |
if (step.step_type === 'landing') { |
| 777 |
this.templateImages.landing = step.featured_image || step.preview_image || '' |
| 778 |
} else if (step.step_type === 'checkout') { |
| 779 |
this.templateImages.checkout = step.featured_image || step.preview_image || '' |
| 780 |
} else if (step.step_type === 'upsell') { |
| 781 |
this.templateImages.upsell = step.featured_image || step.preview_image || '' |
| 782 |
} else if (step.step_type === 'thankyou') { |
| 783 |
this.templateImages.thankyou = step.featured_image || step.preview_image || '' |
| 784 |
} |
| 785 |
}) |
| 786 |
} |
| 787 |
|
| 788 |
// Use template featured image as fallback for landing |
| 789 |
if (!this.templateImages.landing && this.template && this.template.featured_image) { |
| 790 |
this.templateImages.landing = this.template.featured_image |
| 791 |
} |
| 792 |
}, |
| 793 |
|
| 794 |
closeDropdowns(e) { |
| 795 |
if (!e.target.closest('.wpfnl-mm-build-funnel-dropdown')) { |
| 796 |
this.showMainProductDropdown = false |
| 797 |
this.showOrderBumpDropdown = false |
| 798 |
this.showUpsellDropdown = false |
| 799 |
} |
| 800 |
}, |
| 801 |
|
| 802 |
toggleMainProductDropdown() { |
| 803 |
this.showMainProductDropdown = !this.showMainProductDropdown |
| 804 |
this.showOrderBumpDropdown = false |
| 805 |
this.showUpsellDropdown = false |
| 806 |
|
| 807 |
if (this.showMainProductDropdown) { |
| 808 |
this.loadInitialProducts('main') |
| 809 |
this.$nextTick(() => { |
| 810 |
if (this.$refs.mainProductSearchInput) { |
| 811 |
this.$refs.mainProductSearchInput.focus() |
| 812 |
} |
| 813 |
}) |
| 814 |
} |
| 815 |
}, |
| 816 |
|
| 817 |
toggleOrderBumpDropdown() { |
| 818 |
this.showOrderBumpDropdown = !this.showOrderBumpDropdown |
| 819 |
this.showMainProductDropdown = false |
| 820 |
this.showUpsellDropdown = false |
| 821 |
|
| 822 |
if (this.showOrderBumpDropdown) { |
| 823 |
this.loadInitialProducts('orderbump') |
| 824 |
this.$nextTick(() => { |
| 825 |
if (this.$refs.orderBumpSearchInput) { |
| 826 |
this.$refs.orderBumpSearchInput.focus() |
| 827 |
} |
| 828 |
}) |
| 829 |
} |
| 830 |
}, |
| 831 |
|
| 832 |
toggleUpsellDropdown() { |
| 833 |
this.showUpsellDropdown = !this.showUpsellDropdown |
| 834 |
this.showMainProductDropdown = false |
| 835 |
this.showOrderBumpDropdown = false |
| 836 |
|
| 837 |
if (this.showUpsellDropdown) { |
| 838 |
this.loadInitialProducts('upsell') |
| 839 |
this.$nextTick(() => { |
| 840 |
if (this.$refs.upsellSearchInput) { |
| 841 |
this.$refs.upsellSearchInput.focus() |
| 842 |
} |
| 843 |
}) |
| 844 |
} |
| 845 |
}, |
| 846 |
|
| 847 |
selectMainProduct(product) { |
| 848 |
this.selectedMainProduct = product |
| 849 |
this.showMainProductDropdown = false |
| 850 |
this.mainProductSearch = '' |
| 851 |
this.mainProducts = [] |
| 852 |
// Auto-switch to checkout preview if available |
| 853 |
if (this.hasCheckout) { |
| 854 |
this.activeSubStep = 'checkout' |
| 855 |
} |
| 856 |
}, |
| 857 |
|
| 858 |
selectOrderBump(product) { |
| 859 |
this.selectedOrderBump = product |
| 860 |
this.showOrderBumpDropdown = false |
| 861 |
this.orderBumpSearch = '' |
| 862 |
this.orderBumpProducts = [] |
| 863 |
// Auto-switch to checkout preview if available |
| 864 |
if (this.hasCheckout) { |
| 865 |
this.activeSubStep = 'checkout' |
| 866 |
} |
| 867 |
}, |
| 868 |
|
| 869 |
selectUpsell(product) { |
| 870 |
this.selectedUpsell = product |
| 871 |
this.showUpsellDropdown = false |
| 872 |
this.upsellSearch = '' |
| 873 |
this.upsellProducts = [] |
| 874 |
// Auto-switch to upsell preview if available |
| 875 |
if (this.hasUpsell) { |
| 876 |
this.activeSubStep = 'upsell' |
| 877 |
} |
| 878 |
}, |
| 879 |
|
| 880 |
setActiveSubStep(step) { |
| 881 |
this.activeSubStep = step |
| 882 |
}, |
| 883 |
|
| 884 |
showCreateProductModal() { |
| 885 |
this.isCreateProduct = true |
| 886 |
this.isShowModalLoader = true |
| 887 |
|
| 888 |
setTimeout(() => { |
| 889 |
const container = document.getElementById('wpfnl-create-product') |
| 890 |
const productUrl = window?.setup_wizard_obj?.product_url |
| 891 |
|
| 892 |
// Create an iframe element |
| 893 |
const iframe = document.createElement('iframe') |
| 894 |
|
| 895 |
// Set the attributes of the iframe |
| 896 |
iframe.setAttribute('src', productUrl) |
| 897 |
iframe.setAttribute('width', '100%') |
| 898 |
iframe.setAttribute('height', '100%') |
| 899 |
iframe.setAttribute('frameborder', '0') |
| 900 |
|
| 901 |
iframe.addEventListener('load', () => { |
| 902 |
this.isShowModalLoader = false |
| 903 |
}) |
| 904 |
|
| 905 |
container.appendChild(iframe) |
| 906 |
}, 100) |
| 907 |
}, |
| 908 |
|
| 909 |
removeCreateProductModal() { |
| 910 |
this.isCreateProduct = false |
| 911 |
const container = document.getElementById('wpfnl-create-product') |
| 912 |
if (container) { |
| 913 |
container.innerHTML = '' |
| 914 |
} |
| 915 |
|
| 916 |
// Clear cached product lists so dropdowns reload with fresh data |
| 917 |
// (including any product just created via iframe) |
| 918 |
this.mainProducts = [] |
| 919 |
this.orderBumpProducts = [] |
| 920 |
this.upsellProducts = [] |
| 921 |
|
| 922 |
// Reload products for any currently open dropdown |
| 923 |
if (this.showMainProductDropdown) { |
| 924 |
this.loadInitialProducts('main') |
| 925 |
} |
| 926 |
if (this.showOrderBumpDropdown) { |
| 927 |
this.loadInitialProducts('orderbump') |
| 928 |
} |
| 929 |
if (this.showUpsellDropdown) { |
| 930 |
this.loadInitialProducts('upsell') |
| 931 |
} |
| 932 |
}, |
| 933 |
|
| 934 |
goBack() { |
| 935 |
this.$emit('prev-step') |
| 936 |
}, |
| 937 |
|
| 938 |
async handleContinue() { |
| 939 |
// For order-value goal, create the funnel directly |
| 940 |
if (this.goal === 'order-value') { |
| 941 |
await this.createFunnelForOrderValue(); |
| 942 |
return; |
| 943 |
} |
| 944 |
|
| 945 |
// For other goals, emit product selections to the next step (GenerateFunnel) |
| 946 |
this.$emit('next-step', { |
| 947 |
mainProduct: this.selectedMainProduct, |
| 948 |
orderBump: this.selectedOrderBump, |
| 949 |
upsell: this.selectedUpsell |
| 950 |
}) |
| 951 |
}, |
| 952 |
|
| 953 |
async createFunnelForOrderValue() { |
| 954 |
if (!this.template || !this.template.steps) { |
| 955 |
alert('No template selected. Please go back and select a template.'); |
| 956 |
return; |
| 957 |
} |
| 958 |
|
| 959 |
this.isGeneratingFunnel = true; |
| 960 |
this.funnelStatusMessage = 'Creating your funnel...'; |
| 961 |
|
| 962 |
try { |
| 963 |
const templateType = 'wc'; |
| 964 |
|
| 965 |
// Update general settings |
| 966 |
await this.updateGeneralSettings(); |
| 967 |
|
| 968 |
// Create funnel |
| 969 |
this.funnelStatusMessage = 'Creating funnel structure...'; |
| 970 |
const funnelResponse = await this.createFunnel(templateType); |
| 971 |
const funnelId = funnelResponse?.funnelID; |
| 972 |
|
| 973 |
if (!funnelId) { |
| 974 |
throw new Error('Funnel could not be created. Please try again.'); |
| 975 |
} |
| 976 |
|
| 977 |
// Import steps |
| 978 |
this.funnelStatusMessage = 'Importing template steps...'; |
| 979 |
const { importedSteps, firstStepLink } = await this.importSteps(funnelId); |
| 980 |
|
| 981 |
// Assign products |
| 982 |
this.funnelStatusMessage = 'Assigning products...'; |
| 983 |
await this.assignProductsToSteps(importedSteps); |
| 984 |
|
| 985 |
// Finalize |
| 986 |
this.funnelStatusMessage = 'Finalizing funnel...'; |
| 987 |
await this.afterFunnelCreation(funnelId, importedSteps); |
| 988 |
|
| 989 |
this.createdFunnelId = funnelId; |
| 990 |
this.createdFirstStepLink = firstStepLink; |
| 991 |
this.isGeneratingFunnel = false; |
| 992 |
this.funnelStatusMessage = 'Funnel created successfully!'; |
| 993 |
|
| 994 |
// Proceed to Complete step |
| 995 |
this.$emit('next-step', { |
| 996 |
funnelId: this.createdFunnelId, |
| 997 |
firstStepLink: this.createdFirstStepLink |
| 998 |
}); |
| 999 |
|
| 1000 |
} catch (error) { |
| 1001 |
console.error('Funnel creation failed:', error); |
| 1002 |
this.isGeneratingFunnel = false; |
| 1003 |
this.funnelStatusMessage = ''; |
| 1004 |
alert(error && error.message ? error.message : 'Unable to create the funnel. Please try again.'); |
| 1005 |
} |
| 1006 |
}, |
| 1007 |
|
| 1008 |
updateGeneralSettings() { |
| 1009 |
return new Promise((resolve, reject) => { |
| 1010 |
wpAjaxHelperRequest('update-general-settings', { |
| 1011 |
builder: this.builder || 'gutenberg' |
| 1012 |
}) |
| 1013 |
.success(() => resolve()) |
| 1014 |
.error(error => reject(error)); |
| 1015 |
}); |
| 1016 |
}, |
| 1017 |
|
| 1018 |
createFunnel(templateType) { |
| 1019 |
const steps = this.filterStepsForImport(this.template?.steps || []); |
| 1020 |
const data = { |
| 1021 |
steps: steps, |
| 1022 |
name: this.template?.title || 'My Order Value Funnel', |
| 1023 |
source: 'remote', |
| 1024 |
remoteID: this.template?.ID || this.template?.id, |
| 1025 |
type: templateType, |
| 1026 |
status: 'draft' |
| 1027 |
}; |
| 1028 |
|
| 1029 |
return new Promise((resolve, reject) => { |
| 1030 |
wpAjaxHelperRequest('wpfunnel-import-funnel', data) |
| 1031 |
.success(response => resolve(response || {})) |
| 1032 |
.error(error => reject(error)); |
| 1033 |
}); |
| 1034 |
}, |
| 1035 |
|
| 1036 |
filterStepsForImport(steps) { |
| 1037 |
const isProActive = window?.setup_wizard_obj?.is_pro_active === 'yes'; |
| 1038 |
return (steps || []).filter(step => { |
| 1039 |
const stepType = step?.step_type || step?.stepType || step?.type; |
| 1040 |
|
| 1041 |
// For order-value, include all steps except downsell if pro is not active |
| 1042 |
if (stepType === 'downsell' && !isProActive) { |
| 1043 |
return false; |
| 1044 |
} |
| 1045 |
|
| 1046 |
return true; |
| 1047 |
}); |
| 1048 |
}, |
| 1049 |
|
| 1050 |
async importSteps(funnelId) { |
| 1051 |
const stepsToImport = this.filterStepsForImport(this.template?.steps || []); |
| 1052 |
const importedSteps = {}; |
| 1053 |
let firstStepLink = ''; |
| 1054 |
|
| 1055 |
for (let index = 0; index < stepsToImport.length; index++) { |
| 1056 |
const step = stepsToImport[index]; |
| 1057 |
try { |
| 1058 |
const response = await apiFetch({ |
| 1059 |
path: `${window.setup_wizard_obj.rest_api_url}wpfunnels/v1/steps/wpfunnel-import-step`, |
| 1060 |
method: 'POST', |
| 1061 |
data: { |
| 1062 |
step, |
| 1063 |
funnelID: funnelId, |
| 1064 |
source: 'remote', |
| 1065 |
importType: 'templates' |
| 1066 |
} |
| 1067 |
}); |
| 1068 |
|
| 1069 |
if (response?.stepID && step?.step_type) { |
| 1070 |
importedSteps[step.step_type] = response.stepID; |
| 1071 |
} |
| 1072 |
|
| 1073 |
if (index === 0 && response?.stepViewLink) { |
| 1074 |
firstStepLink = response.stepViewLink; |
| 1075 |
} |
| 1076 |
} catch (error) { |
| 1077 |
console.error(`Error importing step ${step?.step_type || index}:`, error); |
| 1078 |
} |
| 1079 |
} |
| 1080 |
|
| 1081 |
if (!Object.keys(importedSteps).length) { |
| 1082 |
throw new Error('Unable to import the selected template steps.'); |
| 1083 |
} |
| 1084 |
|
| 1085 |
return { importedSteps, firstStepLink }; |
| 1086 |
}, |
| 1087 |
|
| 1088 |
async assignProductsToSteps(importedSteps) { |
| 1089 |
// Assign main product to checkout step |
| 1090 |
if (importedSteps.checkout && this.selectedMainProduct && this.selectedMainProduct.id) { |
| 1091 |
try { |
| 1092 |
await apiFetch({ |
| 1093 |
path: `${window.setup_wizard_obj.rest_api_url}wpfunnels/v1/checkout/wpfnl-add-product`, |
| 1094 |
method: 'POST', |
| 1095 |
data: { |
| 1096 |
id: this.selectedMainProduct.id, |
| 1097 |
step_id: importedSteps.checkout, |
| 1098 |
quantity: 1 |
| 1099 |
} |
| 1100 |
}); |
| 1101 |
} catch (error) { |
| 1102 |
console.error('Error assigning main product:', error); |
| 1103 |
} |
| 1104 |
} |
| 1105 |
|
| 1106 |
// Assign order bump to checkout step |
| 1107 |
if (importedSteps.checkout && this.selectedOrderBump && this.selectedOrderBump.id) { |
| 1108 |
try { |
| 1109 |
let productImage = { |
| 1110 |
id: 0, |
| 1111 |
url: window.setup_wizard_obj.plugin_url ? window.setup_wizard_obj.plugin_url + 'admin/assets/images/placeholder.png' : '' |
| 1112 |
}; |
| 1113 |
|
| 1114 |
try { |
| 1115 |
const productData = await apiFetch({ |
| 1116 |
path: `${window.setup_wizard_obj.rest_api_url}wpfunnels/v1/updateSelectedProduct?product=${this.selectedOrderBump.id}`, |
| 1117 |
method: 'GET' |
| 1118 |
}); |
| 1119 |
|
| 1120 |
if (productData && productData.img) { |
| 1121 |
const imgTag = productData.img; |
| 1122 |
const srcMatch = imgTag.match(/src="([^"]+)"/); |
| 1123 |
if (srcMatch) { |
| 1124 |
productImage.url = srcMatch[1]; |
| 1125 |
} |
| 1126 |
const idMatch = imgTag.match(/wp-image-(\d+)/); |
| 1127 |
if (idMatch) { |
| 1128 |
productImage.id = parseInt(idMatch[1]); |
| 1129 |
} |
| 1130 |
} |
| 1131 |
} catch (imgError) { |
| 1132 |
console.error('Could not fetch product image, using placeholder:', imgError); |
| 1133 |
} |
| 1134 |
|
| 1135 |
const orderBumpData = [{ |
| 1136 |
name: 'Order Bump', |
| 1137 |
selectedStyle: 'style1', |
| 1138 |
isEnabled: true, |
| 1139 |
position: 'after-order', |
| 1140 |
product: this.selectedOrderBump.id, |
| 1141 |
productName: this.selectedOrderBump.name, |
| 1142 |
chooseVariantName: 'Choose an Option', |
| 1143 |
productSearchName: this.selectedOrderBump.name, |
| 1144 |
productType: '', |
| 1145 |
price: '', |
| 1146 |
salePrice: '', |
| 1147 |
quantity: '1', |
| 1148 |
htmlPrice: this.selectedOrderBump.priceHtml || '', |
| 1149 |
numericRegularPrice: '', |
| 1150 |
numericSalePrice: '', |
| 1151 |
discountPrice: '', |
| 1152 |
discountPriceHtml: '', |
| 1153 |
productImage: productImage, |
| 1154 |
highLightText: this.selectedOrderBump.name, |
| 1155 |
checkBoxLabel: 'Yes, I want this!', |
| 1156 |
productDescriptionText: 'Add this special offer to your order', |
| 1157 |
discountOption: 'original', |
| 1158 |
discountapply: 'regular', |
| 1159 |
discountValue: '', |
| 1160 |
couponName: '', |
| 1161 |
obNextStep: 'default', |
| 1162 |
isReplace: 'no', |
| 1163 |
replaceSettings: { |
| 1164 |
isAllReplace: 'yes', |
| 1165 |
selectedProducts: [] |
| 1166 |
}, |
| 1167 |
replace: '', |
| 1168 |
obArrowColor: '#EE8134', |
| 1169 |
obPrimaryColor: '#6E42D2', |
| 1170 |
obBgColor: '', |
| 1171 |
obTitleColor: '#363B4E', |
| 1172 |
obHighlightColor: '#6E42D3', |
| 1173 |
obCheckboxTitleColor: '#d9d9d9', |
| 1174 |
obDescriptionColor: '#7A8B9A', |
| 1175 |
isRemoveObBgColor: '', |
| 1176 |
obPriceColor: '#E86F2C', |
| 1177 |
obChooseVariantColor: '#F34D01', |
| 1178 |
prePurchaseUpsell: 'no' |
| 1179 |
}]; |
| 1180 |
|
| 1181 |
await apiFetch({ |
| 1182 |
path: `${window.setup_wizard_obj.rest_api_url}wpfunnels/v1/order-bump`, |
| 1183 |
method: 'POST', |
| 1184 |
data: { |
| 1185 |
value: orderBumpData, |
| 1186 |
stepID: importedSteps.checkout |
| 1187 |
} |
| 1188 |
}); |
| 1189 |
} catch (error) { |
| 1190 |
console.error('Error creating order bump:', error); |
| 1191 |
} |
| 1192 |
} |
| 1193 |
|
| 1194 |
// Assign upsell product to upsell step |
| 1195 |
if (importedSteps.upsell && this.selectedUpsell && this.selectedUpsell.id) { |
| 1196 |
try { |
| 1197 |
const upsellData = { |
| 1198 |
id: this.selectedUpsell.id, |
| 1199 |
quantity: 1 |
| 1200 |
}; |
| 1201 |
|
| 1202 |
await apiFetch({ |
| 1203 |
path: `${window.setup_wizard_obj.rest_api_url}wpfunnels/v1/offer/saveUpsellData/`, |
| 1204 |
method: 'POST', |
| 1205 |
data: { |
| 1206 |
step_id: importedSteps.upsell, |
| 1207 |
product: JSON.stringify(upsellData) |
| 1208 |
} |
| 1209 |
}); |
| 1210 |
} catch (error) { |
| 1211 |
console.error('Error assigning upsell product:', error); |
| 1212 |
} |
| 1213 |
} |
| 1214 |
}, |
| 1215 |
|
| 1216 |
afterFunnelCreation(funnelId, importedSteps) { |
| 1217 |
const payload = { |
| 1218 |
funnelID: funnelId, |
| 1219 |
source: 'remote', |
| 1220 |
importedSteps: Object.values(importedSteps || {}) |
| 1221 |
}; |
| 1222 |
|
| 1223 |
return new Promise(resolve => { |
| 1224 |
wpAjaxHelperRequest('wpfunnel-after-funnel-creation', payload) |
| 1225 |
.success(response => resolve(response)) |
| 1226 |
.error(error => { |
| 1227 |
console.error('After funnel creation error:', error); |
| 1228 |
resolve(); |
| 1229 |
}); |
| 1230 |
}); |
| 1231 |
}, |
| 1232 |
} |
| 1233 |
} |
| 1234 |
</script> |
| 1235 |
|
| 1236 |
<style scoped> |
| 1237 |
.wpfnl-mm-build-funnel { |
| 1238 |
width: 100%; |
| 1239 |
max-width: 1049px; |
| 1240 |
display: flex; |
| 1241 |
flex-direction: column; |
| 1242 |
gap: 15px; |
| 1243 |
position: relative; |
| 1244 |
} |
| 1245 |
|
| 1246 |
/* Header */ |
| 1247 |
.wpfnl-mm-build-funnel-header { |
| 1248 |
text-align: center; |
| 1249 |
margin-bottom: 5px; |
| 1250 |
} |
| 1251 |
|
| 1252 |
.wpfnl-mm-build-funnel-title { |
| 1253 |
font-size: 24px; |
| 1254 |
font-weight: 700; |
| 1255 |
font-family: 'DM Sans', sans-serif; |
| 1256 |
color: #363B4E; |
| 1257 |
line-height: 35px; |
| 1258 |
letter-spacing: -1px; |
| 1259 |
margin: 0 0 8px 0; |
| 1260 |
} |
| 1261 |
|
| 1262 |
.wpfnl-mm-build-funnel-subtitle { |
| 1263 |
font-size: 15px; |
| 1264 |
font-weight: 400; |
| 1265 |
font-family: 'DM Sans', sans-serif; |
| 1266 |
color: #6E7A85; |
| 1267 |
line-height: 15px; |
| 1268 |
margin: 0; |
| 1269 |
} |
| 1270 |
|
| 1271 |
/* Main Container */ |
| 1272 |
.wpfnl-mm-build-funnel-container { |
| 1273 |
display: flex; |
| 1274 |
gap: 3px; |
| 1275 |
} |
| 1276 |
|
| 1277 |
/* Left Panel - Form */ |
| 1278 |
.wpfnl-mm-build-funnel-form { |
| 1279 |
width: 461px; |
| 1280 |
background: #FFF; |
| 1281 |
border-radius: 16px; |
| 1282 |
padding: 40px; |
| 1283 |
display: flex; |
| 1284 |
flex-direction: column; |
| 1285 |
min-height: 556px; |
| 1286 |
} |
| 1287 |
|
| 1288 |
.wpfnl-mm-build-funnel-fields { |
| 1289 |
display: flex; |
| 1290 |
flex-direction: column; |
| 1291 |
gap: 40px; |
| 1292 |
flex: 1; |
| 1293 |
} |
| 1294 |
|
| 1295 |
.wpfnl-mm-build-funnel-field { |
| 1296 |
display: flex; |
| 1297 |
flex-direction: column; |
| 1298 |
gap: 9px; |
| 1299 |
} |
| 1300 |
|
| 1301 |
.wpfnl-mm-build-funnel-label { |
| 1302 |
font-size: 15px; |
| 1303 |
font-weight: 500; |
| 1304 |
font-family: 'DM Sans', sans-serif; |
| 1305 |
color: #363B4E; |
| 1306 |
letter-spacing: -0.44px; |
| 1307 |
line-height: 16px; |
| 1308 |
} |
| 1309 |
|
| 1310 |
.wpfnl-mm-build-funnel-label .required { |
| 1311 |
color: red; |
| 1312 |
} |
| 1313 |
|
| 1314 |
.wpfnl-mm-build-funnel-label .optional { |
| 1315 |
font-weight: 400; |
| 1316 |
color: #7A8C9A; |
| 1317 |
} |
| 1318 |
|
| 1319 |
/* Dropdown */ |
| 1320 |
.wpfnl-mm-build-funnel-dropdown { |
| 1321 |
position: relative; |
| 1322 |
} |
| 1323 |
|
| 1324 |
.wpfnl-mm-build-funnel-dropdown-trigger { |
| 1325 |
height: 46px; |
| 1326 |
background: #FFF; |
| 1327 |
border: 1px solid #F1EFF7; |
| 1328 |
border-radius: 8px; |
| 1329 |
padding: 0 16px; |
| 1330 |
display: flex; |
| 1331 |
align-items: center; |
| 1332 |
justify-content: space-between; |
| 1333 |
cursor: pointer; |
| 1334 |
transition: all 0.3s ease; |
| 1335 |
} |
| 1336 |
|
| 1337 |
.wpfnl-mm-build-funnel-dropdown.open .wpfnl-mm-build-funnel-dropdown-trigger { |
| 1338 |
border-color: #6E42D3; |
| 1339 |
} |
| 1340 |
|
| 1341 |
.wpfnl-mm-build-funnel-dropdown-trigger .placeholder { |
| 1342 |
font-size: 14px; |
| 1343 |
font-family: 'DM Sans', sans-serif; |
| 1344 |
color: #7A8C9A; |
| 1345 |
} |
| 1346 |
|
| 1347 |
.wpfnl-mm-build-funnel-dropdown-trigger .selected-value { |
| 1348 |
font-size: 14px; |
| 1349 |
font-family: 'DM Sans', sans-serif; |
| 1350 |
color: #363B4E; |
| 1351 |
} |
| 1352 |
|
| 1353 |
.wpfnl-mm-build-funnel-dropdown-trigger .dropdown-icon { |
| 1354 |
transition: transform 0.3s ease; |
| 1355 |
} |
| 1356 |
|
| 1357 |
.wpfnl-mm-build-funnel-dropdown.open .dropdown-icon { |
| 1358 |
transform: rotate(180deg); |
| 1359 |
} |
| 1360 |
|
| 1361 |
.wpfnl-mm-build-funnel-dropdown-menu { |
| 1362 |
position: absolute; |
| 1363 |
top: 100%; |
| 1364 |
left: 0; |
| 1365 |
right: 0; |
| 1366 |
background: #FFF; |
| 1367 |
border: 1px solid #F1EFF7; |
| 1368 |
border-radius: 8px; |
| 1369 |
margin-top: 4px; |
| 1370 |
z-index: 100; |
| 1371 |
box-shadow: 0px 4px 12px rgba(0, 0, 0, 0.1); |
| 1372 |
overflow: hidden; |
| 1373 |
} |
| 1374 |
|
| 1375 |
/* Search Input */ |
| 1376 |
.wpfnl-mm-build-funnel-search { |
| 1377 |
display: flex; |
| 1378 |
align-items: center; |
| 1379 |
gap: 10px; |
| 1380 |
padding: 12px 16px; |
| 1381 |
border-bottom: 1px solid #F1EFF7; |
| 1382 |
} |
| 1383 |
|
| 1384 |
.wpfnl-mm-build-funnel-search svg { |
| 1385 |
flex-shrink: 0; |
| 1386 |
} |
| 1387 |
|
| 1388 |
.wpfnl-mm-build-funnel-search input { |
| 1389 |
flex: 1; |
| 1390 |
border: none; |
| 1391 |
outline: none; |
| 1392 |
font-size: 14px; |
| 1393 |
font-family: 'DM Sans', sans-serif; |
| 1394 |
color: #363B4E; |
| 1395 |
background: transparent; |
| 1396 |
} |
| 1397 |
|
| 1398 |
.wpfnl-mm-build-funnel-search input::placeholder { |
| 1399 |
color: #7A8C9A; |
| 1400 |
} |
| 1401 |
|
| 1402 |
.wpfnl-mm-build-funnel-dropdown-list { |
| 1403 |
max-height: 200px; |
| 1404 |
overflow-y: auto; |
| 1405 |
} |
| 1406 |
|
| 1407 |
.wpfnl-mm-build-funnel-dropdown-loading, |
| 1408 |
.wpfnl-mm-build-funnel-dropdown-empty { |
| 1409 |
padding: 16px; |
| 1410 |
text-align: center; |
| 1411 |
font-size: 14px; |
| 1412 |
font-family: 'DM Sans', sans-serif; |
| 1413 |
color: #7A8C9A; |
| 1414 |
display: flex; |
| 1415 |
flex-direction: column; |
| 1416 |
align-items: center; |
| 1417 |
justify-content: center; |
| 1418 |
gap: 12px; |
| 1419 |
} |
| 1420 |
|
| 1421 |
.wpfnl-mm-build-funnel-dropdown-empty p { |
| 1422 |
margin: 0; |
| 1423 |
} |
| 1424 |
|
| 1425 |
.wpfnl-mm-create-product-btn { |
| 1426 |
display: inline-flex; |
| 1427 |
align-items: center; |
| 1428 |
gap: 8px; |
| 1429 |
padding: 8px 16px; |
| 1430 |
background: #FFF; |
| 1431 |
border: 1px solid #6E42D3; |
| 1432 |
border-radius: 6px; |
| 1433 |
font-size: 13px; |
| 1434 |
font-weight: 500; |
| 1435 |
font-family: 'DM Sans', sans-serif; |
| 1436 |
color: #6E42D3; |
| 1437 |
cursor: pointer; |
| 1438 |
transition: all 0.3s ease; |
| 1439 |
} |
| 1440 |
|
| 1441 |
.wpfnl-mm-create-product-btn:hover { |
| 1442 |
background: #6E42D3; |
| 1443 |
color: #FFF; |
| 1444 |
} |
| 1445 |
|
| 1446 |
.wpfnl-mm-create-product-btn:hover svg path { |
| 1447 |
stroke: #FFF; |
| 1448 |
} |
| 1449 |
|
| 1450 |
.wpfnl-mm-create-product-btn svg { |
| 1451 |
width: 12px; |
| 1452 |
height: 12px; |
| 1453 |
} |
| 1454 |
|
| 1455 |
.wpfnl-mm-build-funnel-dropdown-item { |
| 1456 |
padding: 12px 16px; |
| 1457 |
font-size: 14px; |
| 1458 |
font-family: 'DM Sans', sans-serif; |
| 1459 |
color: #363B4E; |
| 1460 |
cursor: pointer; |
| 1461 |
display: flex; |
| 1462 |
align-items: center; |
| 1463 |
gap: 8px; |
| 1464 |
transition: background 0.2s ease; |
| 1465 |
} |
| 1466 |
|
| 1467 |
.wpfnl-mm-build-funnel-dropdown-item:hover { |
| 1468 |
background: #F6F5FA; |
| 1469 |
} |
| 1470 |
|
| 1471 |
.wpfnl-mm-build-funnel-dropdown-item.selected { |
| 1472 |
background: #F6F5FA; |
| 1473 |
color: #6E42D3; |
| 1474 |
} |
| 1475 |
|
| 1476 |
.wpfnl-mm-build-funnel-dropdown-item .product-name { |
| 1477 |
flex: 1; |
| 1478 |
} |
| 1479 |
|
| 1480 |
.wpfnl-mm-build-funnel-dropdown-item .product-price { |
| 1481 |
color: #6E42D3; |
| 1482 |
font-weight: 500; |
| 1483 |
} |
| 1484 |
|
| 1485 |
.wpfnl-mm-build-funnel-hint { |
| 1486 |
font-size: 12px; |
| 1487 |
font-family: 'Inter', sans-serif; |
| 1488 |
color: #7A8C9A; |
| 1489 |
line-height: 16px; |
| 1490 |
margin: 0; |
| 1491 |
} |
| 1492 |
|
| 1493 |
/* Potential Revenue */ |
| 1494 |
.wpfnl-mm-build-funnel-revenue { |
| 1495 |
margin-top: auto; |
| 1496 |
padding: 20px; |
| 1497 |
background: #FFFFFF; |
| 1498 |
border: 1px solid #ECEBF0; |
| 1499 |
border-radius: 12px; |
| 1500 |
} |
| 1501 |
|
| 1502 |
.wpfnl-mm-revenue-header { |
| 1503 |
margin-bottom: 16px; |
| 1504 |
} |
| 1505 |
|
| 1506 |
.wpfnl-mm-build-funnel-revenue-label { |
| 1507 |
font-size: 13px; |
| 1508 |
font-family: 'DM Sans', sans-serif; |
| 1509 |
font-weight: 600; |
| 1510 |
color: #363B4E; |
| 1511 |
margin: 0; |
| 1512 |
letter-spacing: -0.2px; |
| 1513 |
} |
| 1514 |
|
| 1515 |
.wpfnl-mm-revenue-breakdown { |
| 1516 |
display: flex; |
| 1517 |
flex-direction: column; |
| 1518 |
gap: 10px; |
| 1519 |
} |
| 1520 |
|
| 1521 |
.wpfnl-mm-revenue-item { |
| 1522 |
display: flex; |
| 1523 |
justify-content: space-between; |
| 1524 |
align-items: center; |
| 1525 |
border: none; |
| 1526 |
padding: 10px 0 0; |
| 1527 |
border-radius: 8px; |
| 1528 |
gap: 12px; |
| 1529 |
} |
| 1530 |
|
| 1531 |
.wpfnl-mm-revenue-item-bonus { |
| 1532 |
background: #F6F5FA; |
| 1533 |
} |
| 1534 |
|
| 1535 |
.wpfnl-mm-revenue-item-content { |
| 1536 |
display: flex; |
| 1537 |
flex-direction: column; |
| 1538 |
gap: 4px; |
| 1539 |
flex: 1; |
| 1540 |
min-width: 0; |
| 1541 |
} |
| 1542 |
|
| 1543 |
.wpfnl-mm-revenue-item-label { |
| 1544 |
font-size: 11px; |
| 1545 |
font-family: 'DM Sans', sans-serif; |
| 1546 |
color: #7A8C9A; |
| 1547 |
font-weight: 500; |
| 1548 |
text-transform: uppercase; |
| 1549 |
letter-spacing: 0.5px; |
| 1550 |
display: flex; |
| 1551 |
align-items: center; |
| 1552 |
gap: 6px; |
| 1553 |
} |
| 1554 |
|
| 1555 |
.wpfnl-mm-revenue-item-name { |
| 1556 |
font-size: 14px; |
| 1557 |
font-family: 'DM Sans', sans-serif; |
| 1558 |
color: #363B4E; |
| 1559 |
font-weight: 500; |
| 1560 |
white-space: nowrap; |
| 1561 |
overflow: hidden; |
| 1562 |
text-overflow: ellipsis; |
| 1563 |
} |
| 1564 |
|
| 1565 |
.wpfnl-mm-revenue-badge { |
| 1566 |
display: inline-block; |
| 1567 |
padding: 2px 6px; |
| 1568 |
background: #6E42D3; |
| 1569 |
color: #FFFFFF; |
| 1570 |
font-size: 9px; |
| 1571 |
font-weight: 600; |
| 1572 |
border-radius: 3px; |
| 1573 |
text-transform: uppercase; |
| 1574 |
letter-spacing: 0.3px; |
| 1575 |
} |
| 1576 |
|
| 1577 |
.wpfnl-mm-revenue-item-price { |
| 1578 |
font-size: 16px; |
| 1579 |
font-family: 'DM Sans', sans-serif; |
| 1580 |
font-weight: 600; |
| 1581 |
color: #363B4E; |
| 1582 |
flex-shrink: 0; |
| 1583 |
} |
| 1584 |
|
| 1585 |
.wpfnl-mm-revenue-bonus { |
| 1586 |
color: #6E42D3; |
| 1587 |
font-weight: 700; |
| 1588 |
} |
| 1589 |
|
| 1590 |
.wpfnl-mm-revenue-separator { |
| 1591 |
height: 1px; |
| 1592 |
background: #ECEBF0; |
| 1593 |
margin: 6px 0; |
| 1594 |
} |
| 1595 |
|
| 1596 |
.wpfnl-mm-revenue-total { |
| 1597 |
display: flex; |
| 1598 |
justify-content: space-between; |
| 1599 |
align-items: center; |
| 1600 |
padding: 16px; |
| 1601 |
background: #FFFFFF; |
| 1602 |
border-radius: 8px; |
| 1603 |
gap: 12px; |
| 1604 |
} |
| 1605 |
|
| 1606 |
.wpfnl-mm-revenue-total-content { |
| 1607 |
display: flex; |
| 1608 |
flex-direction: column; |
| 1609 |
gap: 4px; |
| 1610 |
flex: 1; |
| 1611 |
} |
| 1612 |
|
| 1613 |
.wpfnl-mm-revenue-total-label { |
| 1614 |
font-size: 11px; |
| 1615 |
font-family: 'DM Sans', sans-serif; |
| 1616 |
font-weight: 500; |
| 1617 |
color: #000; |
| 1618 |
text-transform: uppercase; |
| 1619 |
letter-spacing: 0.5px; |
| 1620 |
} |
| 1621 |
|
| 1622 |
.wpfnl-mm-revenue-total-value { |
| 1623 |
font-size: 24px; |
| 1624 |
font-family: 'DM Sans', sans-serif; |
| 1625 |
font-weight: 700; |
| 1626 |
color: #000; |
| 1627 |
letter-spacing: -0.5px; |
| 1628 |
} |
| 1629 |
|
| 1630 |
.wpfnl-mm-revenue-boost-inline { |
| 1631 |
display: flex; |
| 1632 |
gap: 2px; |
| 1633 |
border-radius: 6px; |
| 1634 |
background: #33a6461a; |
| 1635 |
flex-direction: row; |
| 1636 |
height: auto; |
| 1637 |
justify-content: center; |
| 1638 |
align-items: center; |
| 1639 |
padding: 16px 12px; |
| 1640 |
line-height: 1; |
| 1641 |
} |
| 1642 |
|
| 1643 |
.wpfnl-mm-revenue-boost-inline svg { |
| 1644 |
color: #33A646; |
| 1645 |
width: 12px; |
| 1646 |
height: 12px; |
| 1647 |
} |
| 1648 |
|
| 1649 |
.wpfnl-mm-revenue-boost-inline span { |
| 1650 |
font-size: 12px; |
| 1651 |
font-family: 'DM Sans', sans-serif; |
| 1652 |
font-weight: 700; |
| 1653 |
color: #33A646; |
| 1654 |
letter-spacing: 0.4px; |
| 1655 |
} |
| 1656 |
|
| 1657 |
/* Tabs */ |
| 1658 |
.wpfnl-mm-build-funnel-tabs { |
| 1659 |
display: flex; |
| 1660 |
align-items: center; |
| 1661 |
justify-content: center; |
| 1662 |
padding: 20px 20px 0; |
| 1663 |
gap: 0; |
| 1664 |
flex-wrap: wrap; |
| 1665 |
} |
| 1666 |
|
| 1667 |
.wpfnl-mm-build-funnel-tab { |
| 1668 |
display: flex; |
| 1669 |
flex-direction: column; |
| 1670 |
align-items: center; |
| 1671 |
gap: 8px; |
| 1672 |
cursor: pointer; |
| 1673 |
flex-shrink: 0; |
| 1674 |
} |
| 1675 |
|
| 1676 |
.wpfnl-mm-build-funnel-tab-icon { |
| 1677 |
width: 48px; |
| 1678 |
height: 48px; |
| 1679 |
border-radius: 50%; |
| 1680 |
border: 1px solid #F1EFF7; |
| 1681 |
display: flex; |
| 1682 |
align-items: center; |
| 1683 |
justify-content: center; |
| 1684 |
color: #6E7A85; |
| 1685 |
transition: all 0.3s ease; |
| 1686 |
} |
| 1687 |
|
| 1688 |
.wpfnl-mm-build-funnel-tab.active .wpfnl-mm-build-funnel-tab-icon { |
| 1689 |
border: 1.5px solid #6E42D3; |
| 1690 |
color: #6E42D3; |
| 1691 |
box-shadow: 0px 20px 30px rgba(199, 191, 217, 0.3); |
| 1692 |
} |
| 1693 |
|
| 1694 |
.wpfnl-mm-build-funnel-tab-label { |
| 1695 |
font-size: 12px; |
| 1696 |
font-family: 'Inter', sans-serif; |
| 1697 |
font-weight: 500; |
| 1698 |
color: #6E7A85; |
| 1699 |
text-align: center; |
| 1700 |
white-space: nowrap; |
| 1701 |
} |
| 1702 |
|
| 1703 |
.wpfnl-mm-build-funnel-tab.active .wpfnl-mm-build-funnel-tab-label { |
| 1704 |
color: #363B4E; |
| 1705 |
} |
| 1706 |
|
| 1707 |
.wpfnl-mm-build-funnel-tab-line { |
| 1708 |
width: 16px; |
| 1709 |
height: 1px; |
| 1710 |
background: #E5E5E5; |
| 1711 |
margin: 0 6px; |
| 1712 |
margin-bottom: 24px; |
| 1713 |
flex-shrink: 0; |
| 1714 |
} |
| 1715 |
|
| 1716 |
/* Preview Content */ |
| 1717 |
.wpfnl-mm-build-funnel-preview-content { |
| 1718 |
flex: 1; |
| 1719 |
padding: 20px; |
| 1720 |
} |
| 1721 |
|
| 1722 |
|
| 1723 |
.wpfnl-mm-build-funnel-preview-placeholder, |
| 1724 |
.wpfnl-mm-build-funnel-preview-empty { |
| 1725 |
display: flex; |
| 1726 |
flex-direction: column; |
| 1727 |
align-items: center; |
| 1728 |
justify-content: center; |
| 1729 |
height: 100%; |
| 1730 |
min-height: 400px; |
| 1731 |
color: #7A8C9A; |
| 1732 |
text-align: center; |
| 1733 |
padding: 40px; |
| 1734 |
} |
| 1735 |
|
| 1736 |
.wpfnl-mm-build-funnel-preview-placeholder svg, |
| 1737 |
.wpfnl-mm-build-funnel-preview-empty svg { |
| 1738 |
margin-bottom: 16px; |
| 1739 |
opacity: 0.5; |
| 1740 |
} |
| 1741 |
|
| 1742 |
.wpfnl-mm-build-funnel-preview-placeholder p, |
| 1743 |
.wpfnl-mm-build-funnel-preview-empty p { |
| 1744 |
font-size: 14px; |
| 1745 |
margin: 0; |
| 1746 |
} |
| 1747 |
|
| 1748 |
.wpfnl-mm-build-funnel-preview-empty h4 { |
| 1749 |
font-size: 18px; |
| 1750 |
font-weight: 600; |
| 1751 |
color: #363B4E; |
| 1752 |
margin: 0 0 8px 0; |
| 1753 |
} |
| 1754 |
|
| 1755 |
/* Buttons */ |
| 1756 |
.wpfnl-mm-build-funnel-buttons { |
| 1757 |
display: flex; |
| 1758 |
justify-content: space-between; |
| 1759 |
align-items: center; |
| 1760 |
width: 100%; |
| 1761 |
} |
| 1762 |
|
| 1763 |
.wpfnl-mm-btn { |
| 1764 |
padding: 10px 24px; |
| 1765 |
border-radius: 10px; |
| 1766 |
font-size: 16px; |
| 1767 |
font-weight: 700; |
| 1768 |
font-family: 'DM Sans', sans-serif; |
| 1769 |
line-height: 24px; |
| 1770 |
cursor: pointer; |
| 1771 |
transition: all 0.3s ease; |
| 1772 |
border: none; |
| 1773 |
display: inline-flex; |
| 1774 |
align-items: center; |
| 1775 |
justify-content: center; |
| 1776 |
gap: 8px; |
| 1777 |
height: 44px; |
| 1778 |
} |
| 1779 |
|
| 1780 |
.wpfnl-mm-btn-secondary { |
| 1781 |
background: #FFF; |
| 1782 |
color: #363B4E; |
| 1783 |
border: 1px solid #ECEBF0; |
| 1784 |
min-width: 87px; |
| 1785 |
} |
| 1786 |
|
| 1787 |
.wpfnl-mm-btn-secondary:hover { |
| 1788 |
border-color: #6E42D3; |
| 1789 |
color: #6E42D3; |
| 1790 |
} |
| 1791 |
|
| 1792 |
.wpfnl-mm-btn-skip { |
| 1793 |
background: transparent; |
| 1794 |
color: #7A8C9A; |
| 1795 |
font-weight: 500; |
| 1796 |
font-size: 15px; |
| 1797 |
padding: 10px; |
| 1798 |
} |
| 1799 |
|
| 1800 |
.wpfnl-mm-btn-skip:hover { |
| 1801 |
color: #6E42D3; |
| 1802 |
} |
| 1803 |
|
| 1804 |
.wpfnl-mm-btn-primary { |
| 1805 |
background: #6E42D3; |
| 1806 |
color: #FFF; |
| 1807 |
font-weight: 600; |
| 1808 |
letter-spacing: 0.2px; |
| 1809 |
min-width: 146px; |
| 1810 |
} |
| 1811 |
|
| 1812 |
.wpfnl-mm-btn-primary svg { |
| 1813 |
width: 17px; |
| 1814 |
height: 12px; |
| 1815 |
} |
| 1816 |
|
| 1817 |
.wpfnl-mm-btn-primary:hover { |
| 1818 |
background: #5c36b3; |
| 1819 |
} |
| 1820 |
|
| 1821 |
.wpfnl-mm-btn-primary:disabled { |
| 1822 |
background: #ccc; |
| 1823 |
cursor: not-allowed; |
| 1824 |
} |
| 1825 |
|
| 1826 |
.wpfnl-mm-btn-group { |
| 1827 |
display: flex; |
| 1828 |
gap: 10px; |
| 1829 |
align-items: center; |
| 1830 |
} |
| 1831 |
|
| 1832 |
/* Spinner */ |
| 1833 |
@keyframes spin { |
| 1834 |
from { transform: rotate(0deg); } |
| 1835 |
to { transform: rotate(360deg); } |
| 1836 |
} |
| 1837 |
|
| 1838 |
.wpfnl-spinner { |
| 1839 |
animation: spin 1s linear infinite; |
| 1840 |
} |
| 1841 |
|
| 1842 |
/* Help Button */ |
| 1843 |
.wpfnl-mm-help-btn { |
| 1844 |
position: fixed; |
| 1845 |
bottom: 40px; |
| 1846 |
right: 54px; |
| 1847 |
z-index: 100; |
| 1848 |
} |
| 1849 |
|
| 1850 |
.wpfnl-mm-help-btn-circle { |
| 1851 |
width: 34px; |
| 1852 |
height: 34px; |
| 1853 |
border-radius: 100px; |
| 1854 |
background: #201F22; |
| 1855 |
border: none; |
| 1856 |
cursor: pointer; |
| 1857 |
display: flex; |
| 1858 |
align-items: center; |
| 1859 |
justify-content: center; |
| 1860 |
box-shadow: 0px 1px 2px rgba(190, 190, 215, 0.16); |
| 1861 |
transition: all 0.3s ease; |
| 1862 |
} |
| 1863 |
|
| 1864 |
.wpfnl-mm-help-btn-circle svg { |
| 1865 |
width: 16px; |
| 1866 |
height: 16px; |
| 1867 |
} |
| 1868 |
|
| 1869 |
.wpfnl-mm-help-btn-circle:hover { |
| 1870 |
background: #363B4E; |
| 1871 |
transform: scale(1.05); |
| 1872 |
} |
| 1873 |
|
| 1874 |
/* Create Product Modal */ |
| 1875 |
.wpfnl-modal-overlay { |
| 1876 |
position: fixed; |
| 1877 |
top: 0; |
| 1878 |
left: 0; |
| 1879 |
right: 0; |
| 1880 |
bottom: 0; |
| 1881 |
background: rgba(0, 0, 0, 0.5); |
| 1882 |
display: flex; |
| 1883 |
align-items: center; |
| 1884 |
justify-content: center; |
| 1885 |
z-index: 10000; |
| 1886 |
} |
| 1887 |
|
| 1888 |
.wpfnl-modal-wrapper { |
| 1889 |
position: relative; |
| 1890 |
width: 90%; |
| 1891 |
max-width: 1400px; |
| 1892 |
height: 90vh; |
| 1893 |
background: #FFF; |
| 1894 |
border-radius: 12px; |
| 1895 |
overflow: hidden; |
| 1896 |
box-shadow: 0px 10px 40px rgba(0, 0, 0, 0.2); |
| 1897 |
} |
| 1898 |
|
| 1899 |
.wpfnl-modal-close { |
| 1900 |
position: absolute; |
| 1901 |
top: 16px; |
| 1902 |
right: 16px; |
| 1903 |
z-index: 10; |
| 1904 |
} |
| 1905 |
|
| 1906 |
.wpfnl-modal-close-btn { |
| 1907 |
width: 32px; |
| 1908 |
height: 32px; |
| 1909 |
border-radius: 50%; |
| 1910 |
background: #FFF; |
| 1911 |
border: 1px solid #E5E5E5; |
| 1912 |
display: flex; |
| 1913 |
align-items: center; |
| 1914 |
justify-content: center; |
| 1915 |
cursor: pointer; |
| 1916 |
transition: all 0.3s ease; |
| 1917 |
} |
| 1918 |
|
| 1919 |
.wpfnl-modal-close-btn:hover { |
| 1920 |
background: #F6F5FA; |
| 1921 |
border-color: #6E42D3; |
| 1922 |
} |
| 1923 |
|
| 1924 |
.wpfnl-modal-close-btn svg path { |
| 1925 |
transition: stroke 0.3s ease; |
| 1926 |
} |
| 1927 |
|
| 1928 |
.wpfnl-modal-close-btn:hover svg path { |
| 1929 |
stroke: #6E42D3; |
| 1930 |
} |
| 1931 |
|
| 1932 |
.wpfnl-loader { |
| 1933 |
position: absolute; |
| 1934 |
top: 50%; |
| 1935 |
left: 50%; |
| 1936 |
transform: translate(-50%, -50%); |
| 1937 |
width: 40px; |
| 1938 |
height: 40px; |
| 1939 |
border: 4px solid #F6F5FA; |
| 1940 |
border-top-color: #6E42D3; |
| 1941 |
border-radius: 50%; |
| 1942 |
animation: spin 1s linear infinite; |
| 1943 |
} |
| 1944 |
|
| 1945 |
#wpfnl-create-product { |
| 1946 |
width: 100%; |
| 1947 |
height: 100%; |
| 1948 |
} |
| 1949 |
|
| 1950 |
#wpfnl-create-product iframe { |
| 1951 |
width: 100%; |
| 1952 |
height: 100%; |
| 1953 |
border: none; |
| 1954 |
} |
| 1955 |
</style> |
| 1956 |
|