| 1 |
<template> |
| 2 |
<div class="wpfnl-mm-preview-modal-overlay" @click.self="closeModal"> |
| 3 |
<div class="wpfnl-mm-preview-modal"> |
| 4 |
<!-- Modal Header --> |
| 5 |
<div class="wpfnl-mm-preview-modal-header"> |
| 6 |
<h3 class="wpfnl-mm-preview-modal-title">{{ template.title }}</h3> |
| 7 |
<div class="wpfnl-mm-preview-device-switcher"> |
| 8 |
<button |
| 9 |
class="wpfnl-mm-device-btn" |
| 10 |
:class="{ 'active': activeView === 'desktop' }" |
| 11 |
@click="activeView = 'desktop'" |
| 12 |
title="Desktop View" |
| 13 |
> |
| 14 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 15 |
<path d="M14 2H2C1.44772 2 1 2.44772 1 3V11C1 11.5523 1.44772 12 2 12H14C14.5523 12 15 11.5523 15 11V3C15 2.44772 14.5523 2 14 2Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 16 |
<path d="M5 14H11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 17 |
<path d="M8 12V14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> |
| 18 |
</svg> |
| 19 |
</button> |
| 20 |
<button |
| 21 |
class="wpfnl-mm-device-btn" |
| 22 |
:class="{ 'active': activeView === 'tablet' }" |
| 23 |
@click="activeView = 'tablet'" |
| 24 |
title="Tablet View" |
| 25 |
> |
| 26 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 27 |
<rect x="3" y="1" width="10" height="14" rx="1.5" stroke="currentColor" stroke-width="1.5"/> |
| 28 |
<path d="M7 12H9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> |
| 29 |
</svg> |
| 30 |
</button> |
| 31 |
<button |
| 32 |
class="wpfnl-mm-device-btn" |
| 33 |
:class="{ 'active': activeView === 'mobile' }" |
| 34 |
@click="activeView = 'mobile'" |
| 35 |
title="Mobile View" |
| 36 |
> |
| 37 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 38 |
<rect x="4" y="1" width="8" height="14" rx="1.5" stroke="currentColor" stroke-width="1.5"/> |
| 39 |
<path d="M7 12H9" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> |
| 40 |
</svg> |
| 41 |
</button> |
| 42 |
</div> |
| 43 |
|
| 44 |
<div class="wpfnl-mm-preview-modal-actions"> |
| 45 |
<button class="wpfnl-mm-btn wpfnl-mm-btn-primary wpfnl-mm-btn-import-modal" @click="importTemplate"> |
| 46 |
Import |
| 47 |
<svg width="17" height="12" viewBox="0 0 17 12" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 48 |
<path d="M1 6H16M16 6L11 1M16 6L11 11" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 49 |
</svg> |
| 50 |
</button> |
| 51 |
|
| 52 |
<!-- Close Button --> |
| 53 |
<button class="wpfnl-mm-preview-close-btn" @click="closeModal" title="Close"> |
| 54 |
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">> |
| 55 |
<path d="M12 4L4 12M4 4L12 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> |
| 56 |
</svg> |
| 57 |
</button> |
| 58 |
</div> |
| 59 |
</div> |
| 60 |
|
| 61 |
<!-- Modal Body --> |
| 62 |
<div class="wpfnl-mm-preview-modal-body"> |
| 63 |
<!-- Steps Navigation --> |
| 64 |
<div class="wpfnl-mm-preview-steps"> |
| 65 |
<div |
| 66 |
v-for="step in displaySteps" |
| 67 |
:key="step.ID" |
| 68 |
class="wpfnl-mm-preview-step-card" |
| 69 |
:class="{ 'active': activeStep.ID === step.ID }" |
| 70 |
@click="setActiveStep(step)" |
| 71 |
> |
| 72 |
<div class="wpfnl-mm-preview-step-thumbnail"> |
| 73 |
<img :src="step.featured_image" :alt="step.title"> |
| 74 |
</div> |
| 75 |
<p class="wpfnl-mm-preview-step-type">{{ step.step_type }}</p> |
| 76 |
</div> |
| 77 |
</div> |
| 78 |
|
| 79 |
<!-- Preview Content --> |
| 80 |
<div class="wpfnl-mm-preview-content" :class="activeView"> |
| 81 |
<div :class="`wpfnl-mm-preview-device-frame ${shouldShowImagePreview(activeStep) ? 'image-preview' : ''}`"> |
| 82 |
<div class="wpfnl-mm-preview-iframe-wrapper"> |
| 83 |
<iframe |
| 84 |
:src="activeStep?.link" |
| 85 |
width="100%" |
| 86 |
height="100%" |
| 87 |
frameborder="0" |
| 88 |
@load="iframeLoaded" |
| 89 |
v-if="!shouldShowImagePreview(activeStep)" |
| 90 |
></iframe> |
| 91 |
<div class="wpfnl-mm-preview-loader" v-if="isLoading && !shouldShowImagePreview(activeStep)"> |
| 92 |
<span class="wpfnl-mm-loader"></span> |
| 93 |
</div> |
| 94 |
|
| 95 |
<div v-if="shouldShowImagePreview(activeStep)" class="wpfnl-mm-preview-checkout-placeholder"> |
| 96 |
<img :src="getStepImageForView(activeStep)" :alt="activeStep?.title"> |
| 97 |
</div> |
| 98 |
</div> |
| 99 |
</div> |
| 100 |
</div> |
| 101 |
</div> |
| 102 |
</div> |
| 103 |
</div> |
| 104 |
</template> |
| 105 |
|
| 106 |
<script> |
| 107 |
export default { |
| 108 |
name: 'PreviewTemplate', |
| 109 |
props: { |
| 110 |
template: { |
| 111 |
type: Object, |
| 112 |
required: true, |
| 113 |
default: () => ({ |
| 114 |
steps: [], |
| 115 |
title: '' |
| 116 |
}) |
| 117 |
}, |
| 118 |
isStoreCheckout: { |
| 119 |
type: Boolean, |
| 120 |
default: false |
| 121 |
}, |
| 122 |
isSalesFunnel: { |
| 123 |
type: Boolean, |
| 124 |
default: false |
| 125 |
} |
| 126 |
}, |
| 127 |
data() { |
| 128 |
return { |
| 129 |
activeStep: {}, |
| 130 |
activeView: 'desktop', |
| 131 |
isLoading: true |
| 132 |
} |
| 133 |
}, |
| 134 |
computed: { |
| 135 |
displaySteps() { |
| 136 |
if (!this.template.steps) return []; |
| 137 |
if (this.isStoreCheckout) { |
| 138 |
return this.template.steps.filter(s => s.step_type === 'checkout' || s.step_type === 'thankyou'); |
| 139 |
} |
| 140 |
if (this.isSalesFunnel) { |
| 141 |
return this.template.steps.filter(s => |
| 142 |
s.step_type === 'landing' || |
| 143 |
s.step_type === 'checkout' || |
| 144 |
s.step_type === 'thankyou' |
| 145 |
); |
| 146 |
} |
| 147 |
return this.template.steps; |
| 148 |
} |
| 149 |
}, |
| 150 |
mounted() { |
| 151 |
if (this.displaySteps.length > 0) { |
| 152 |
this.activeStep = this.displaySteps[0]; |
| 153 |
} |
| 154 |
// Prevent body scroll when modal is open |
| 155 |
document.body.style.overflow = 'hidden'; |
| 156 |
}, |
| 157 |
beforeUnmount() { |
| 158 |
// Restore body scroll when modal is closed |
| 159 |
document.body.style.overflow = ''; |
| 160 |
}, |
| 161 |
methods: { |
| 162 |
getStepImageForView(step) { |
| 163 |
if (!step) { |
| 164 |
return ''; |
| 165 |
} |
| 166 |
|
| 167 |
if (this.activeView === 'desktop') { |
| 168 |
return step.desktop_view_image || ''; |
| 169 |
} |
| 170 |
|
| 171 |
if (this.activeView === 'tablet') { |
| 172 |
return step.tablet_view_image || ''; |
| 173 |
} |
| 174 |
|
| 175 |
if (this.activeView === 'mobile') { |
| 176 |
return step.mobile_view_image || ''; |
| 177 |
} |
| 178 |
|
| 179 |
return ''; |
| 180 |
}, |
| 181 |
shouldShowImagePreview(step) { |
| 182 |
const stepType = step?.step_type; |
| 183 |
if (stepType !== 'checkout' && stepType !== 'thankyou') { |
| 184 |
return false; |
| 185 |
} |
| 186 |
|
| 187 |
return !!this.getStepImageForView(step); |
| 188 |
}, |
| 189 |
setActiveStep(step) { |
| 190 |
this.activeStep = step; |
| 191 |
this.isLoading = true; |
| 192 |
}, |
| 193 |
iframeLoaded() { |
| 194 |
this.isLoading = false; |
| 195 |
}, |
| 196 |
closeModal() { |
| 197 |
this.$emit('close'); |
| 198 |
}, |
| 199 |
importTemplate() { |
| 200 |
this.$emit('import', this.template); |
| 201 |
} |
| 202 |
} |
| 203 |
} |
| 204 |
</script> |