@hulkapps/app-manager-vue 2.5.13 → 3.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,987 +1,620 @@
1
1
  <template>
2
- <!-- <PSkeletonPage :title="translateMe('Plans')"-->
3
- <!-- :fullWidth="false"-->
4
- <!-- primaryAction-->
5
- <!-- :secondaryActions="2"-->
6
- <!-- :breadcrumbs="false"-->
7
- <!-- v-if="planLoading">-->
8
- <!-- <PLayout>-->
9
- <!-- <PLayoutSection oneThird="">-->
10
- <!-- <PCard sectioned="">-->
11
- <!-- <PTextContainer>-->
12
- <!-- <PSkeletonDisplayText size="small" />-->
13
- <!-- <PSkeletonBodyText />-->
14
- <!-- </PTextContainer>-->
15
- <!-- </PCard>-->
16
- <!-- </PLayoutSection>-->
17
- <!-- <PLayoutSection oneThird="">-->
18
- <!-- <PCard sectioned="">-->
19
- <!-- <PTextContainer>-->
20
- <!-- <PSkeletonDisplayText size="small" />-->
21
- <!-- <PSkeletonBodyText />-->
22
- <!-- </PTextContainer>-->
23
- <!-- </PCard>-->
24
- <!-- </PLayoutSection>-->
25
- <!-- <PLayoutSection oneThird="">-->
26
- <!-- <PCard sectioned="">-->
27
- <!-- <PTextContainer>-->
28
- <!-- <PSkeletonDisplayText size="small" />-->
29
- <!-- <PSkeletonBodyText />-->
30
- <!-- </PTextContainer>-->
31
- <!-- </PCard>-->
32
- <!-- </PLayoutSection>-->
33
- <!-- </PLayout>-->
34
- <!-- <PLayout style="margin-top: 20px">-->
35
- <!-- <PLayoutSection>-->
36
- <!-- <PCard sectioned=""><PSkeletonBodyText /></PCard>-->
37
- <!-- <PCard sectioned=""><PSkeletonBodyText /></PCard>-->
38
- <!-- <PCard sectioned=""><PSkeletonBodyText /></PCard>-->
39
- <!-- <PCard sectioned=""><PSkeletonBodyText /></PCard>-->
40
- <!-- </PLayoutSection>-->
41
- <!-- </PLayout>-->
42
- <!-- </PSkeletonPage>-->
43
- <PEmptyState
44
- :heading="translateMe('No Plans')"
45
- image="https://cdn.shopify.com/s/files/1/0262/4071/2726/files/emptystate-files.png"
46
- v-if="!this.planLoading && this.plans.length === 0"
47
- >
48
- </PEmptyState>
49
- <div v-else-if="!this.planLoading && this.plans.length > 0" class="app-manager-plan-banner">
50
- <PlanBanners position="header" @handlePlanBannerClose="handlePlanBannerClose" />
51
-
2
+ <PEmptyState
3
+ :heading="translateMe('No Plans')"
4
+ image="https://cdn.shopify.com/s/files/1/0262/4071/2726/files/emptystate-files.png"
5
+ v-if="!this.planLoading && this.plans.length === 0"
6
+ >
7
+ </PEmptyState>
8
+ <div v-else-if="!this.planLoading && this.plans.length > 0">
9
+ <PlanBanners position="header" @handlePlanBannerClose="handlePlanBannerClose" class="app-manager-plan-banner"/>
10
+ <div class="bill-cycle-select-group">
11
+ <a class="bill-cycle-back" @click="selectPlan('monthly')">
12
+ <img src="../../assets/ArrowLeft.svg" alt="Left Arrow"/>
13
+ {{ translateMe('Back to App pricing') }}
14
+ </a>
15
+ <div class="bill-cycle-select-group__inner-left">
16
+ <SelectButton
17
+ id="pricing-tab"
18
+ :variant="selectedPlan === 'monthly' ? 'primary' : 'secondary'"
19
+ @click="selectPlan('monthly')"
20
+ >
21
+ {{ translateMe('Billed Monthly') }}
22
+ </SelectButton>
23
+ <SelectButton
24
+ id="pricing-tab"
25
+ v-if="valid_annual_plans.length > 0"
26
+ :variant="selectedPlan === 'annually' ? 'primary' : 'secondary'"
27
+ @click="selectPlan('annually')"
28
+ >
29
+ {{ translateMe('Billed Yearly') }}
30
+ <strong style="white-space: pre;">{{ translateMe(' 17% Off') }}</strong>
31
+ </SelectButton>
32
+ </div>
33
+ <ToggleButton
34
+ id="pricing-tab"
35
+ v-if="bundle_plan !== null"
36
+ :toggled="selectedPlan === 'bundle'"
37
+ @click="selectPlan('bundle')"
38
+ >
39
+ {{ translateMe('App Bundle Plan -') }}
40
+ <strong style="white-space: pre; font-weight: 900;">{{ translateMe('70% Off') }}</strong>
41
+ </ToggleButton>
42
+ </div>
43
+ <PlanShowcaseBanner
44
+ v-if="bundle_plan"
45
+ :useCardStyle="true"
46
+ :showcaseData="bundle_plan"
47
+ :realPrice="parseFloat(calculateDiscountedPrice(bundle_plan)).toFixed(0)"
48
+ :oldPrice="bundle_plan.price" @plan-clicked="handlePlanClicked(bundle_plan)"
49
+ :isCurrentPlan="isCurrentPlanId(bundle_plan)"
50
+ />
52
51
  <PPage
53
- class="app-manager-plan-page-slider custom-title"
54
- :title="selectedPlan === 'bundle' ? '' : translateMe('Plans')"
55
- :subtitle = "selectedPlan === 'bundle' ? '' : subtitleContent"
52
+ class="app-manager-plan-page-slider custom-title"
56
53
  >
57
-
58
- <PStack slot="primaryAction">
59
- <PStackItem style="margin-top: 20px">
60
- <!-- <PButtonGroup class="btn-group" segmented> -->
61
- <!-- <PButton v-if="monthlyPlan.length && yearlyPlan.length" :class="selectedPlan === 'monthly' ? 'plan-active-tab' : '' " :style="selectedPlan === 'monthly' ? monthlySelectedStyle : monthlyStyle " @click="selectPlan('monthly')">
62
- <p style="font-size: 17px; font-weight: 500" slot="default">{{translateMe('Monthly')}}</p>
63
- </PButton>
64
-
65
- <PButton v-if="yearlyPlan.length && monthlyPlan.length" :class="selectedPlan === 'annually'? 'plan-active-tab' : '' " :style="selectedPlan === 'annually' ? yearlySelectedStyle : yearlyStyle " @click="selectPlan('annually')" :primary="selectedPlan === 'annually' " >
66
- <YearlyPlanPromotion />
67
- </PButton>
68
- <PButton :class="selectedPlan === 'bundle' ? 'plan-active-tab' : '' " :style="selectedPlan === 'bundle' ? bundleSelectedSyle : bundleStyle " @click="selectPlan('bundle')">
69
- <p style="font-size: 17px; font-weight: 500" slot="default">{{translateMe('Bundle')}}</p>
70
- </PButton> -->
71
- <div class="button-group-new">
72
- <VariantButton id="pricing-tab" :variant="selectedPlan === 'monthly' ? 'primary' : 'secondary'" @click="selectPlan('monthly')" :additionalText="'1 App'">
73
- {{ translateMe('Monthly') }}
74
- </VariantButton>
75
- <VariantButton id="pricing-tab" v-if="valid_annual_plans.length > 0" :variant="selectedPlan === 'annually' ? 'primary' : 'secondary'" @click="selectPlan('annually')">
76
- {{ translateMe('Annually') }}
77
- </VariantButton>
78
- <VariantButton id="pricing-tab" v-if="bundle_plan !== null" :variant="selectedPlan === 'bundle' ? 'primary' : 'secondary'" @click="selectPlan('bundle')" :additionalText=" totalBundleApps +' Apps'">
79
- {{ translateMe('Bundle') }}
80
- </VariantButton>
81
- </div>
82
- <!-- </PButtonGroup> -->
83
- </PStackItem>
84
- </PStack>
85
- <!-- <hr style="width: 100%; margin-right: auto;margin-left: auto;margin-bottom: 20px;" /> -->
86
- <div class="light-divider" style="margin: 20px 0;"></div>
87
- <!--=======================================================-->
88
- <PLayout class="custom-plan">
89
- <PLayoutSection style="display: flex;border-radius: 20px;">
90
- <template style="margin-bottom: 20px; display: flex !important;">
91
- <template >
92
- <div class="Polaris-ResourceList__ResourceListWrapper features" style="width: 20%">
93
- <div class="plan__price"></div>
94
- <ul class="Polaris-ResourceList">
95
- <li class="Polaris-ResourceList__ItemWrapper pro_title" :class="`${feature.value_type}__type__${feature.slug} feature__type__${feature.value_type} feature__class`" v-for="(feature, key) in features" :key="key">
96
- <div class="Polaris-ResourceList-Item__Container">
97
- <div class="Polaris-ResourceList-Item__Content">
98
- <h1 class="for-price-per-month"><span>{{ translateMe(feature.name) }}</span></h1>
99
- </div>
100
- </div>
101
- </li>
102
- </ul>
103
- </div>
104
- </template>
105
- <carousel style="width: 80%" :per-page="perPage" :mouseDrag="false" :navigation-enabled="true" :paginationEnabled="false" :navigateTo="[this.currentSlide,true]" @transition-start="handleNavigationClick($event)">
106
- <template>
107
- <slide :id="key" :class="`slide-${key}`" v-for="(plan, key) in selectedPlan === 'monthly' ? monthlyPlan : yearlyPlan" :key="`slide-${key}`" >
108
- <div class="plan__price" :style="activePlanStyle(plan)">
109
- <div v-if="plan.price === 0">
110
- <b v-if="plan.name !== 'Free'" style="font-size: 16px">{{translateMe(plan.name)}}</b>
111
- <p style="display: flex;margin-top: 10px">
112
- <PHeading style="font-size: 23px;font-weight: 700;">{{translateMe('Free')}}</PHeading>
113
- </p>
114
- </div>
115
- <div v-else-if="plan.discount && plan.discount > 0 && !isCurrentPlan(plan)" >
116
- <b style="font-size: 16px">{{translateMe(plan.name)}}</b>
117
- <p style="display: flex;margin-top: 10px">
118
- <PHeading style="font-size: 23px;font-weight: 700;">${{parseFloat(calculateDiscountedPrice(plan)).toFixed(2)}}</PHeading>
119
- <b style="margin-top: 5px;font-size: 17px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
120
- </p>
121
- <p style="display: flex;margin-top: 7px">
122
- <PHeading style="font-size: 18px;font-weight: 500; text-decoration:line-through;">${{parseFloat(plan.price).toFixed(2)}}</PHeading>
123
- <b style="margin-top: 3px;font-size: 14px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
124
- </p>
125
- </div>
126
- <div v-else-if="promotional_discount && promotional_discount.length !== 0 && !promotional_discount.errors && !plan.is_global && promotional_discount.plan_relation.length > 0 && promotional_discount.plan_relation.includes(plan.id) && !isCurrentPlan(plan)" >
127
- <b style="font-size: 16px">{{translateMe(plan.name)}}</b>
128
- <p style="display: flex;margin-top: 10px">
129
- <PHeading style="font-size: 23px;font-weight: 700;">${{parseFloat(calculatePromotionalDiscountedPrice(plan, promotional_discount)).toFixed(2)}}</PHeading>
130
- <b style="margin-top: 5px;font-size: 17px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
131
- </p>
132
- <p style="display: flex;margin-top: 7px">
133
- <PHeading style="font-size: 18px;font-weight: 500; text-decoration:line-through;">${{parseFloat(plan.price).toFixed(2)}}</PHeading>
134
- <b style="margin-top: 3px;font-size: 14px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
135
- </p>
136
- </div>
137
- <div v-else-if="promotional_discount && promotional_discount.length !== 0 && !promotional_discount.errors && !plan.is_global && promotional_discount.plan_relation.length === 0 && promotional_discount.value > 0 && !isCurrentPlan(plan)" >
138
- <b style="font-size: 16px">{{translateMe(plan.name)}}</b>
139
- <p style="display: flex;margin-top: 10px">
140
- <PHeading style="font-size: 23px;font-weight: 700;">${{parseFloat(calculatePromotionalDiscountedPrice(plan, promotional_discount)).toFixed(2)}}</PHeading>
141
- <b style="margin-top: 5px;font-size: 17px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
142
- </p>
143
- <p style="display: flex;margin-top: 7px">
144
- <PHeading style="font-size: 18px;font-weight: 500; text-decoration:line-through;">${{parseFloat(plan.price).toFixed(2)}}</PHeading>
145
- <b style="margin-top: 3px;font-size: 14px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
146
- </p>
147
- </div>
148
- <div v-else>
149
- <b style="font-size: 16px">{{translateMe(plan.name)}}</b>
150
- <p style="display: flex;margin-top: 10px">
151
- <PHeading style="font-size: 23px;font-weight: 700;">${{parseFloat(plan.price).toFixed(2)}}</PHeading>
152
- <b style="margin-top: 5px;font-size: 17px">/{{translateMe(selectedPlan === 'monthly' ? ("mo") : ("year"))}}</b>
153
- </p>
154
- </div>
155
- </div>
156
- <div>
157
- <ul>
158
-
159
- <li v-for="(feature, key) in features" :class="`${feature.value_type}__type__${feature.slug} feature__list feature__type__${feature.value_type}`" :key="key" :style="activePlanStyle(plan)">
160
- <div>
161
- <template v-if="plan.features && plan.features[feature.uuid]" style="display: flex">
162
- <template v-if="plan.features[feature.uuid].value_type === 'boolean'">
163
- <PIcon v-if="parseInt(plan.features[feature.uuid].value) === 1" color="success" source="TickMinor"/>
164
- <PIcon v-else color="subdued" source="MinusMinor"/>
165
- </template>
166
- <template v-else style="display: flex">
167
- <span v-if="plan.features[feature.uuid].value">{{ format(plan.features[feature.uuid]) }}</span>
168
- <PIcon v-else color="subdued" source="MinusMinor"/>
169
- </template>
170
- </template>
171
- <template v-else>
172
- <PIcon color="subdued" source="MinusMinor"/>
173
- </template>
174
- </div>
175
- </li>
176
- <li v-if="features.length > 0" :class="`${features[features.length - 1].value_type}__type__${features[features.length - 1].slug} feature__list feature__type__${features[features.length - 1].value_type}`">
177
- <div>
178
- <PButton v-if="isCurrentPlan(plan)" :disabled="isCurrentPlan(plan)"
179
- full-width
180
- :pressed="isCurrentPlan(plan)">
181
- {{ translateMe('Current Plan') }}
182
- </PButton>
183
- <PButton v-else-if="(!plan.store_base_plan || plan.shopify_plans.includes(shop.shopify_plan))"
184
- full-width
185
- :disabled="isActivePlanGlobal() && !isActiveGlobalCharge()"
186
- @click="plan ? getPlanUrl(plan) : 'javascript:void'"
187
- class="custom-choose-button">
188
- {{ isActivePlanGlobal() ? (!isActiveGlobalCharge() ? translateMe('Not Applicable') : translateMe('Choose Plan')) : translateMe('Choose Plan') }}
189
- </PButton>
190
- <PButton v-else :disabled="true"
191
- full-width
192
- :pressed="true">
193
- {{ translateMe('Not applicable') }}
194
- </PButton>
195
- </div>
196
- </li>
197
- <li></li>
198
- </ul>
199
- </div>
200
- </slide>
201
- </template>
202
- </carousel>
203
- </template>
204
- </PLayoutSection>
205
- </PLayout>
206
- <div v-if="bundle_plan !== null" class="bundle-plan">
207
- <PlanShowcaseBanner useCardStyle="true" :bundleApps="totalBundleApps" :showcaseData="bundle_plan" :realPrice="parseFloat(calculateDiscountedPrice(bundle_plan)).toFixed(0)" :oldPrice="bundle_plan.price" @plan-clicked="handlePlanClicked(bundle_plan)" :isCurrentPlan="isCurrentPlanId(bundle_plan)"/>
208
- <div class="light-divider"></div>
209
- <div class="bundle-category" v-for="category in bundle_details">
210
- <CategoryHeading :headingData="category" />
211
- <div class="bundle-category-apps">
212
- <AppCard v-for="app in category.apps_relation" :appData="app" />
213
- </div>
214
- </div>
215
- <CategoryHeading :headingData="additionalBenefitsHeading" />
216
- <BenefitsBanner />
217
- <PlanShowcaseBanner style="margin-top: 20px;" :bundleApps="totalBundleApps" :showcaseData="bundle_plan" :realPrice="parseFloat(calculateDiscountedPrice(bundle_plan)).toFixed(0)" :oldPrice="bundle_plan.price" :showDescription="false" :isCurrentPlan="isCurrentPlanId(bundle_plan)" @plan-clicked="handlePlanClicked(bundle_plan)"/>
54
+ <!-- -------------------- Bundle Plan Banner -------------------- -->
55
+ <!-- <div class="promotional-banner">
56
+ <VariantButton id="pricing-tab" :variant="'primary'" @click="selectPlan('bundle')">
57
+ {{ translateMe('Start Saving Now') }}
58
+ </VariantButton>
59
+ </div> -->
60
+
61
+ <PLayout class="custom-plan">
62
+ <PlanCardsHighlights
63
+ :plans="plans"
64
+ :features="features"
65
+ :currentPlan="plan"
66
+ :promotionalDiscount="promotional_discount"
67
+ :selectedInterval="selectedPlan"
68
+ @plan-clicked="handlePlanClicked"
69
+ />
70
+ <div style="display: flex; flex-direction: column; align-items: center; gap: 16px;">
71
+ <a href="#" class="toggle-plans-features" @click.prevent="togglePlansFeatures">
72
+ {{ showPlansFeatures ? translateMe("Hide all features") : translateMe("Show all features") }}
73
+ </a>
74
+ <PlanTable
75
+ :plans="plans"
76
+ :currentPlan="plan"
77
+ :promotionalDiscount="promotional_discount"
78
+ :selectedInterval="selectedPlan"
79
+ :features="features"
80
+ @plan-clicked="handlePlanClicked"
81
+ :class="{ 'hide-all-features': !showPlansFeatures }"
82
+ />
218
83
  </div>
219
- <!--====================================================================-->
84
+
220
85
  <PStack v-if="onboard" class="choose-plan-btn" alignment="center" distribution="center" vertical>
221
- <PStackItem fill>
222
- <PButton plain @click="activePlan">{{ translateMe('I will choose the plan later') }}</PButton>
223
- </PStackItem>
86
+ <PStackItem fill>
87
+ <PButton plain @click="activePlan">{{ translateMe('I will choose the plan later') }}</PButton>
88
+ </PStackItem>
224
89
  </PStack>
225
- <PlanBanners position="footer" @handlePlanBannerClose="handlePlanBannerClose" />
90
+
91
+ <div class="customization-bundle-section">
92
+ <!-- -------------------- Customization Block -------------------- -->
93
+ <!-- <GetCustomBlock
94
+ v-if="is_customizable"
95
+ @click="handleCustomizePlan"
96
+ :title="translateMe('Customization')"
97
+ :description="translateMe('Check out all customization services that we offer')"
98
+ :buttonText="translateMe('Get customization now')"
99
+ style="flex-basis: 30%; flex-grow: 1;"
100
+ /> -->
101
+ <BundlePlanCard
102
+ :plan="bundle_plan"
103
+ :plan_details="bundle_details"
104
+ @plan-clicked="selectPlan"
105
+ style="flex-basis: 62%; flex-grow: 1;"
106
+ />
107
+ </div>
108
+ <CustomizationModal
109
+ :visible="this.showCustomizationModal"
110
+ @cancel="handleCustomizePlanClose"
111
+ @submit=""
112
+ />
113
+ </PLayout>
114
+ <div v-if="bundle_plan !== null" class="bundle-plan">
115
+ <div class="light-divider"></div>
116
+ <div class="bundle-category" v-for="category in bundle_details">
117
+ <CategoryHeading :headingData="category"/>
118
+ <div class="bundle-category-apps">
119
+ <AppCard v-for="app in category.apps_relation" :appData="app"/>
120
+ </div>
121
+ </div>
122
+ <CategoryHeading :headingData="additionalBenefitsHeading"/>
123
+ <BenefitsBanner/>
124
+ </div>
125
+ <PlanBanners position="footer" @handlePlanBannerClose="handlePlanBannerClose"/>
226
126
  </PPage>
227
- </div>
127
+ </div>
228
128
  </template>
229
129
 
230
130
  <script>
231
131
 
232
- import axios from "axios";
233
- import PlanBanners from "./PlanBanners";
234
- import YearlyPlanPromotion from "./YearlyPlanPromotion";
235
- import PPage from "../polaris-vue/src/components/PPage/PPage";
236
- import PStack from "../polaris-vue/src/components/PStack/PStack";
237
- import PStackItem from "../polaris-vue/src/components/PStack/components/PStackItem/PStackItem";
238
- import {PButton} from "../polaris-vue/src/components/PButton";
239
- import {PButtonGroup} from "../polaris-vue/src/components/PButtonGroup";
240
- import {PHeading} from "../polaris-vue/src/components/PHeading";
241
- import {PLayout} from "../polaris-vue/src/components/PLayout";
242
- import {PLayoutSection} from "../polaris-vue/src/components/PLayout/components/PLayoutSection";
243
- import {PTextContainer} from "../polaris-vue/src/components/PTextContainer";
244
- import {PDataTable} from "../polaris-vue/src/components/PDataTable";
245
- import {PDataTableCol} from "../polaris-vue/src/components/PDataTable/components/PDataTableCol";
246
- import {PDataTableRow} from "../polaris-vue/src/components/PDataTable/components/PDataTableRow";
247
- import {PIcon} from "../polaris-vue/src/components/PIcon";
248
- import {PTextStyle} from "../polaris-vue/src/components/PTextStyle";
249
- import {PCard} from "../polaris-vue/src/components/PCard"
250
- import {PCardSection} from "../polaris-vue/src/components/PCard/components/PCardSection"
251
- import {PSkeletonPage} from "../polaris-vue/src/components/PSkeletonPage"
252
- import {PSkeletonDisplayText} from "../polaris-vue/src/components/PSkeletonDisplayText"
253
- import {PSkeletonBodyText} from "../polaris-vue/src/components/PSkeletonBodyText"
254
- import {PEmptyState} from "../polaris-vue/src/components/PEmptyState"
255
- import {Carousel, Slide} from 'vue-carousel';
256
- import AppCard from "../PolarisNew/AppCard";
257
- import PlanShowcaseBanner from "../PolarisNew/PlanShowcaseBanner";
258
- import CategoryHeading from "../PolarisNew/CategoryHeading";
259
- import BenefitsBanner from "../PolarisNew/BenefitsBanner";
260
- import VariantButton from "../PolarisNew/VariantButton";
261
-
262
- export default {
263
- name: "AppManagerSliderPlan",
264
- components: { Carousel, Slide, YearlyPlanPromotion, PlanBanners, PPage, PStack, PStackItem, PButton, PButtonGroup, PHeading, PLayout, PLayoutSection, PTextContainer, PDataTable, PDataTableCol, PDataTableRow, PIcon, PTextStyle, PCardSection, PCard, PSkeletonDisplayText, PSkeletonBodyText, PSkeletonPage, PEmptyState, AppCard, PlanShowcaseBanner, CategoryHeading, BenefitsBanner, VariantButton },
265
- props: ['shop_domain','host', 'discount_code'],
266
- data() {
267
- return {
268
- slideLength : 0,
269
- perPage: 0,
270
- currentSlide: 0,
271
- planLoading: false,
272
- plan: {},
273
- plans: [],
274
- valid_annual_plans: [],
275
- promotional_discount: [],
276
- features: [],
277
- featureValues:[],
278
- shopify_plan: '',
279
- default_plan_id: null,
280
- onboard: true,
281
- choose_later: false,
282
- has_active_charge: false,
283
- global_plan_charge: false,
284
- subtitleContent: '',
285
- checkList: [
286
- "60 days free trial",
287
- ],
288
- selectedPlan:'monthly',
289
- monthlySelectedStyle:{
290
- height: '60px',
291
- backgroundColor:'#257f60',
292
- color:'#fff',
293
- position:'relative',
294
- right:'-5px',
295
- borderRadius:'8px',
296
- zIndex: 1,
297
- },
298
- yearlySelectedStyle:{
299
- height: '60px',
300
- backgroundColor:'#257f60',
301
- position:'relative',
302
- left:'-5px',
303
- borderRadius:'8px'
304
- },
305
- bundleSelectedSyle:{
306
- height: '60px',
307
- backgroundColor:'#257f60',
308
- position:'relative',
309
- left:'-5px',
310
- borderRadius:'8px'
311
- },
312
- monthlyStyle:{
313
- height: '55px',
314
- backgroundColor:'#FFFFFF',
315
- boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px',
316
- border:'none',
317
- borderRadius:'8px',
318
- ZIndex: 11,
319
- },
320
- yearlyStyle:{
321
- color:'#258060',
322
- height: '55px',
323
- backgroundColor:'#FFFFFF',
324
- boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px',
325
- border:'none',
326
- borderRadius:'8px'
327
- },
328
- bundleStyle:{
329
- color:'#258060',
330
- height: '55px',
331
- backgroundColor:'#FFFFFF',
332
- boxShadow: 'rgba(99, 99, 99, 0.2) 0px 2px 8px 0px',
333
- border:'none',
334
- borderRadius:'8px'
335
- },
336
- additionalBenefitsHeading:{
337
- category_name: "Unlock Additional Benefits"
338
- },
339
- "bundle_details": null,
340
- "bundle_plan": null
341
- }
342
- },
343
- computed: {
344
- shop() {
345
- return {
346
- "name": this.shop_domain,
347
- "shopify_plan": this.shopify_plan,
348
- "has_plan": !!this.plan,
349
- "plan": this.plan,
350
- "default_plan_id": this.default_plan_id,
351
- };
352
- },
353
- headings() {
354
- let headings = [this.translateMe('Plans & Features')];
355
- this.plans.forEach(plan => {
356
-
357
- let heading = (plan.name);
358
- if (plan.price > 0) heading += ` ($${plan.price}/mo)`;
359
- headings.push(heading);
360
- });
361
- return headings;
362
- },
363
- monthlyPlan() {
364
- const plans = [];
365
- for(let planKey in this.plans) {
366
- if(this.plans[planKey].interval === 'EVERY_30_DAYS') {
367
- plans.push(this.plans[planKey]);
368
- }
369
- }
370
- return plans;
371
- },
372
- yearlyPlan() {
373
- const plans = [];
374
- for(let planKey in this.plans) {
375
- if(this.plans[planKey].interval === 'ANNUAL') {
376
- plans.push(this.plans[planKey]);
377
- }
378
- }
379
- return plans;
380
- },
381
- totalBundleApps() {
382
- let totalApps = 0;
383
- if (this.bundle_details) {
384
- this.bundle_details.forEach(category => {
385
- totalApps += category.apps_relation.length;
386
- });
387
- }
388
- return totalApps;
389
- },
390
- },
391
- methods: {
392
- translateMe(message){
393
- return this.$translations.hasOwnProperty(message)?this.$translations[message]:message;
394
- },
395
- handleNavigationClick($event) {
396
- const activeSlideIds = [];
397
- let activeSlides = document.getElementsByClassName('VueCarousel-slide-active')
398
- for (let i=0, max=activeSlides.length; i < max; i++) {
399
- activeSlideIds.push(parseInt(activeSlides[i].id))
400
- }
401
- let last = activeSlideIds.pop();
402
- let first = last - (this.perPage - 1)
403
-
404
- let allSlides = document.getElementsByClassName('VueCarousel-slide');
405
- for (let i=0, max=allSlides.length; i < max; i++) {
406
- let slide = document.getElementById(allSlides[i].id);
407
- slide.classList.remove('first-slide')
408
- slide.classList.remove('last-slide')
409
- }
410
-
411
- let firstSlideClassName = '.slide-' + first
412
- let element = document.querySelector(firstSlideClassName);
413
- element.classList.add('first-slide')
414
-
415
- let lastSlideClassName = '.slide-' + last
416
- element = document.querySelector(lastSlideClassName);
417
- element.classList.add('last-slide')
418
-
419
- if (document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev')) {
420
- document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev').style.left = -document.querySelector('.Polaris-ResourceList__ResourceListWrapper.features').offsetWidth + 'px';
421
- }
422
- },
423
- activePlanStyle(plan) {
424
- return [plan.shopify_plans.includes(this.shop.shopify_plan) || !plan.store_base_plan ? {backgroundColor: '#FFF', color: '#202223'} : {}];
425
- },
426
- activePlanClass(plan) {
427
- return plan.shopify_plans.includes(this.shop.shopify_plan) || !plan.store_base_plan ? 'active-plan' : '';
428
- },
429
- isCurrentPlanId(plan) {
430
- return this.shop.plan && plan.id === this.shop.plan.id;
431
- },
432
- isCurrentPlan(plan) {
433
- return this.has_active_charge && this.shop.plan && (plan.id === this.shop.plan.id || (!plan.is_custom && plan.base_plan === this.shop.plan.id));
434
- },
435
- isActivePlanGlobal() {
436
- return Boolean(this.shop.plan?.is_global);
437
- },
438
- isActiveGlobalCharge() {
439
- return Boolean(this.global_plan_charge);
440
- },
441
- isSamePlanInOtherInterval(plan) {
442
- return this.shop.plan && (plan.shopify_plans === this.shop.plan.shopify_plans)
443
- },
444
- format(feature) {
445
- if (['double', 'integer'].includes(feature?.value_type)) {
446
- if (feature.format === 'percentage') {
447
- return `${feature.value}%`
448
- } else if (feature.format === 'count') {
449
- return (feature.value < 0 ? this.translateMe(`Unlimited`) : feature.value)
450
- } else return this.translateMe(feature.value);
451
- }
452
- else if(feature?.value_type === 'array') {
453
- let values= JSON.parse(feature.value);
454
- let that = this;
455
- values = values.map(function(value){
456
- return that.translateMe(that.featureValues[feature.feature_id][value]);
457
- });
458
- return values.join(', ');
459
- }
460
- else if(feature?.value_type === 'string') {
461
- return this.translateMe(feature.value.replace('"', '').replace('"', ''));
462
- }
463
- },
464
- calculateDiscountedPrice(plan) {
465
- if (plan.discount_type === 'percentage') {
466
- return plan.price - (plan.price * plan.discount)/100
467
- }
468
- else if (plan.discount_type === 'amount') {
469
- if(plan.discount > plan.price){
470
- return 0.00;
471
- }
472
- return plan.price - plan.discount
473
- }
474
- },
475
- calculatePromotionalDiscountedPrice(plan, promotional_discount) {
476
- if (promotional_discount.type === 'percentage') {
477
- return plan.price - (plan.price * promotional_discount.value)/100
478
- }
479
- else if (promotional_discount.type === 'amount') {
480
- if(promotional_discount.value > plan.price){
481
- return 0.00;
482
- }
483
- return plan.price - promotional_discount.value
484
- }
485
- },
486
- handlePlanClicked(plan) {
487
- this.getPlanUrl(plan);
488
- },
489
- async getPlanUrl(plan) {
490
- let shopName = this.shop.name;
491
- let host = this.host;
492
- let discount_code = this.discount_code;
493
- let queryString = `shop=${shopName}`;
494
- if(host != null){
495
- queryString +=`&host=${host}`
496
- }
497
- if(discount_code != null){
498
- queryString +=`&discount_code=${discount_code}`
499
- }
500
- const response = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plan/process/${plan.id}?${queryString}`).catch(error => {
501
- console.error(error)
502
- });
503
- if(response.data.plan_type === 'free_plan'){
504
- this.$emit('handlePlanSelect', {free_plan: true})
505
- }else{
506
- let redirectUrl = response.data.redirect_url;
507
- if (redirectUrl) {
508
- window.top.location.href = redirectUrl;
509
- }
510
- }
511
- },
512
- async activePlan() {
513
- const response = await this.activeWithoutPlan()
514
- if (response.data.status === true && this.onboard) {
515
- // Create the event
516
- this.$emit('handlePlanSelect', {choose_later: true})
517
- this.onboard = false;
518
- }
519
- },
520
- async activeWithoutPlan() {
521
- return await axios.post(`${this.app_manager_config.baseUrl}/api/app-manager/active-without-plan`, {
522
- shop_domain: this.shop.name,
523
- plan_id: this.shop.default_plan_id
524
- }).catch(error => {
525
- console.error(error)
526
- });
527
- },
528
- async selectPlan(value){
529
- this.selectedPlan = value;
530
- if (this.bundle_plan !== null) {
531
- let planElement = document.querySelector('.custom-plan');
532
- let bundleElement = document.querySelector('.bundle-plan');
533
- if (this.selectedPlan == 'bundle') {
534
- planElement.style.display = 'none';
535
- bundleElement.style.display = 'flex';
536
- } else {
537
- bundleElement.style.display = 'none';
538
- planElement.style.display = 'flex';
539
- }
540
- }
541
- this.$nextTick(() => {
542
-
543
- let elements = document.querySelectorAll('.plan__price');
544
- let maxHeight = 0;
545
- elements.forEach((item) => {
546
- if (maxHeight < item.offsetHeight) {
547
- maxHeight = item.offsetHeight
548
- }
549
- });
550
- elements.forEach((item) => {
551
- item.style.minHeight = maxHeight + 'px';
552
- });
553
-
554
- this.slideLength = this.selectedPlan === 'monthly' ? this.monthlyPlan.length : this.yearlyPlan.length;
555
- this.perPage = this.slideLength >= 4 ? 4 : this.slideLength;
556
-
557
- // calculate and reset height of rows
558
- this.features.forEach((feature) => {
559
- let className = feature.value_type + '__type__' + feature.slug;
560
- let elements = document.querySelectorAll('.' + className);
561
- let maxHeight = 0;
562
- elements.forEach((item) => {
563
- item.style.minHeight = 'unset';
564
- if (maxHeight < item.offsetHeight) {
565
- maxHeight = item.offsetHeight
566
- }
567
- });
568
- elements.forEach((item) => {
569
- item.style.minHeight = maxHeight + 'px';
570
- });
571
- })
572
-
573
- // remove first-slide and last-slide classes
574
- let allSlides = document.getElementsByClassName('VueCarousel-slide');
575
- for (let i=0, max=allSlides.length; i < max; i++) {
576
- let slide = document.getElementById(allSlides[i].id);
577
- slide.classList.remove('first-slide')
578
- slide.classList.remove('last-slide')
579
- }
580
-
581
- // add first-slide and last-slide classes
582
- let pagesCount = this.slideLength;
583
- setTimeout(() => {
584
- let element = document.querySelector('.slide-0');
585
- if (element) {
586
- element.classList.add('first-slide')
587
- if (pagesCount < 4) {
588
- let lastSlideClass = '.slide-' + (pagesCount-1)
589
- element = document.querySelector(lastSlideClass);
590
- element.classList.add('last-slide')
591
- }
592
- else {
593
- element = document.querySelector('.slide-3');
594
- element.classList.add('last-slide')
595
- }
596
- if (document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev')) {
597
- document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev').style.left = -document.querySelector('.Polaris-ResourceList__ResourceListWrapper.features').offsetWidth + 'px';
598
- }
599
- }
600
- }, 100)
601
-
602
- });
603
- },
604
- async fetchFeatures() {
605
- let {data} = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plan-features`).catch(error => {
606
- console.error(error)
607
- });
608
- if (data.features.length) {
609
- this.features = data.features;
610
- this.features = this.features?.filter((item) => item.hidden_feature !== true)
611
- this.features = this.features?.sort((featureA, featureB) => parseInt(featureA.display_order) - parseInt(featureB.display_order));
612
- //Get feature array time values
613
- this.features.forEach((feature) => {
614
- if(feature.value_type == 'array'){
615
- this.featureValues[feature.uuid] = feature.values;
616
- }
617
- });
618
- }
619
- },
620
- async fetchPlans() {
621
- let params = {
622
- 'shop_domain': this.shop_domain
623
- };
624
- if (this.discount_code !== null) {
625
- params['discount_code'] = this.discount_code;
626
- }
627
- let {data} = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plans`, { params: params }).catch(error => {
628
- console.error(error)
629
- });
630
- if (data.plans.length) {
631
- for (let i = 0; i < data.plans.length; i++) {
632
- if (data.plans[i].interval === 'ANNUAL') {
633
- this.valid_annual_plans.push(data.plans[i]);
634
- }
635
- }
636
- this.plans = data.plans;
637
- this.plans = this.plans?.sort((planA, planB) => parseFloat(planA.price) - parseFloat(planB.price));
638
-
639
- if (this.plans[0].store_base_plan) {
640
- this.subtitleContent = this.translateMe('App plans are based on your existing shopify plan');
641
- }
642
-
643
- this.plan = data.plan;
644
- if (this.plan?.interval === 'ANNUAL') {
645
- this.selectedPlan = 'annually'
646
- }
647
- if (this.plan?.is_global) {
648
- this.selectedPlan = 'bundle'
649
- }
650
- this.shopify_plan = data.shopify_plan;
651
- this.default_plan_id = data.default_plan_id;
652
- this.choose_later = data.choose_later;
653
- this.onboard = this.default_plan_id && this.choose_later;
654
- this.has_active_charge = data.has_active_charge;
655
- this.global_plan_charge = data.global_plan_charge;
656
- this.promotional_discount = (data.promotional_discount !== undefined)?data.promotional_discount:[];
657
- if (data.bundle_plan) {
658
- this.bundle_plan = data.bundle_plan;
659
- }
660
- if (data.bundle_details) {
661
- this.bundle_details = data.bundle_details;
662
- }
663
- }
664
- },
665
- headerClasses(firstColumn) {
666
- return {
667
- 'Polaris-DataTable__Cell': true,
668
- 'Polaris-DataTable__Cell--header': true,
669
- 'Polaris-DataTable__Cell--verticalAlignMiddle': true,
670
- 'Polaris-DataTable__Cell--firstColumn': Boolean(firstColumn),
671
- };
672
- },
673
- isPlanButtonColor(plan){
674
- if(this.has_active_charge && this.shop.plan){
675
- if(plan.price > this.shop.plan.price){
676
- return true;
677
- }
678
- }
679
- return false;
680
- },
681
- planChooseButtonClass(plan){
682
- if(this.has_active_charge && this.shop.plan){
683
- if(plan.price > this.shop.plan.price){
684
- return '';
685
- }
686
- }
687
- return 'custom-choose-button';
688
- },
689
- handlePlanBannerClose(payload) {
690
- this.$emit('handlePlanBannerClose', payload)
691
- this.$emit('handle-plan-banner-close', payload)
692
- }
693
- },
694
- async mounted() {
695
- this.planLoading = true;
696
- await this.fetchFeatures();
697
- await this.fetchPlans();
698
- this.planLoading = false;
699
-
700
- this.$nextTick(() => {
701
-
702
- // calculate height of cell
703
- setTimeout(() => {
704
-
705
- let elements = document.querySelectorAll('.plan__price');
706
- let maxHeight = 0;
707
- elements.forEach((item) => {
708
- item.style.minHeight = 'unset';
709
- if (maxHeight < item.offsetHeight) {
710
- maxHeight = item.offsetHeight
711
- }
712
- });
713
- elements.forEach((item) => {
714
- item.style.minHeight = maxHeight + 'px';
715
- });
716
-
717
- this.features.forEach((feature) => {
718
- let className = feature.value_type + '__type__' + feature.slug;
719
- elements = document.querySelectorAll('.' + className);
720
- maxHeight = 0;
721
- elements.forEach((item) => {
722
- if (maxHeight < item.offsetHeight) {
723
- maxHeight = item.offsetHeight
724
- }
725
- });
726
- elements.forEach((item) => {
727
- item.style.minHeight = maxHeight + 'px';
728
- });
729
- })
730
- }, 100);
731
-
732
- // remove fist-slide and last-slide classes from all slides
733
- let allSlides = document.getElementsByClassName('VueCarousel-slide');
734
- for (let i=0, max=allSlides.length; i < max; i++) {
735
- let slide = document.getElementById(allSlides[i].id);
736
- slide.classList.remove('first-slide')
737
- slide.classList.remove('last-slide')
738
- }
739
-
740
- // add first-slide and last-slide
741
- this.slideLength = this.selectedPlan === 'monthly' ? this.monthlyPlan.length : this.yearlyPlan.length;
742
- this.perPage = this.slideLength >= 4 ? 4 : this.slideLength;
743
-
744
- let pagesCount = this.slideLength;
745
- setTimeout(() => {
746
- let element = document.querySelector('.slide-0');
747
- if (element) {
748
- element.classList.add('first-slide')
749
- if (pagesCount < 4) {
750
- let lastSlideClass = '.slide-' + (pagesCount-1)
751
- element = document.querySelector(lastSlideClass);
752
- element.classList.add('last-slide')
753
- }
754
- else {
755
- element = document.querySelector('.slide-3');
756
- element.classList.add('last-slide')
757
- }
758
- if (document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev')) {
759
- document.querySelector('.VueCarousel-navigation-button.VueCarousel-navigation-prev').style.left = -document.querySelector('.Polaris-ResourceList__ResourceListWrapper.features').offsetWidth + 'px';
760
- }
761
- }
762
- }, 100)
763
-
764
- this.selectPlan(this.selectedPlan);
765
-
766
- });
767
- },
768
- }
769
- </script>
770
-
771
- <style lang="scss">
772
-
773
- @import url('https://fonts.googleapis.com/css2?family=Satisfy&display=swap');
774
-
775
- .app-manager .app-manager-plan-page-slider ul
776
- {
777
- list-style: none;
778
- margin: 0;
779
- padding: 0;
780
- }
781
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li,
782
- .app-manager .app-manager-plan-page-slider .Polaris-Layout__Section .VueCarousel-slide li,
783
- .app-manager .app-manager-plan-page-slider .plan__price
784
- {
785
- padding: 16px 16px 16px 20px;
786
- }
787
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li,
788
- .app-manager .app-manager-plan-page-slider .Polaris-Layout__Section .VueCarousel-slide li:not(:last-child),
789
- .app-manager .app-manager-plan-page-slider .Polaris-Layout.custom-plan .VueCarousel .plan__price
790
- {
791
- border-top: 1px solid #dddddd;
792
- border-right: 1px solid #dddddd;
793
- background: #fff;
794
- }
795
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li{
796
- border-right: none;
797
- border-left: 1px solid #dddddd;
798
- }
799
- /*.app-manager .app-manager-plan-page-slider .plan__price{
800
- min-height:121px;
801
- }*/
802
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:last-child,
803
- .app-manager .app-manager-plan-page-slider .Polaris-Layout__Section .VueCarousel-slide li:nth-last-child(2)
804
- {
805
- border-bottom: 1px solid #dddddd;
806
- }
807
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:first-child
808
- {
809
- border-top-left-radius: 12px;
810
- }
811
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:last-child
812
- {
813
- border-bottom-left-radius: 12px;
814
- }
815
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.first-slide ul li:not(:last-child)
816
- {
817
- border-left: 1px solid #dddddd;
818
- }
819
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.first-slide .plan__price
820
- {
821
- border-left: 1px solid #dddddd;
822
- box-shadow: none;
823
- border-top-left-radius: 12px;
824
- overflow: hidden;
825
- }
826
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.last-slide ul li:nth-last-child(2)
827
- {
828
- border-bottom-right-radius: 12px;
829
- }
830
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.first-slide ul li:nth-last-child(2)
831
- {
832
- border-bottom-left-radius: 12px;
833
- }
834
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.last-slide .plan__price
835
- {
836
- border-right: 1px solid #dddddd;
837
- box-shadow: none;
838
- border-top-right-radius: 12px;
839
- overflow: hidden;
840
- }
841
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.last-slide
842
- {
843
- border-top-right-radius: 12px;
844
- }
845
- .app-manager .app-manager-plan-page-slider .VueCarousel-inner .VueCarousel-slide.first-slide
846
- {
847
- border-top-left-radius: 12px;
848
- }
849
- .app-manager .app-manager-plan-page-slider .VueCarousel .VueCarousel-inner li
850
- {
851
- text-align: center;
852
- }
853
- .app-manager .app-manager-plan-page-slider .VueCarousel-navigation-button
854
- {
855
- color: #257f60;
856
- }
857
- .app-manager .app-manager-plan-page-slider .btn-group .Polaris-ButtonGroup__Item
858
- {
859
- margin-left: 0px !important;
860
- z-index: unset !important;
861
- }
862
- .app-manager .Polaris-Button::after {
863
- box-shadow: none !important;
864
- }
865
- .app-manager .Polaris-Button:focus {
866
- box-shadow: none !important;
867
- border-color: black !important;
868
- }
869
- .app-manager .app-manager-plan-page-slider .feature__list,
870
- .app-manager .app-manager-plan-page-slider .feature__type__array
871
- {
872
- display: flex;
873
- align-items: center;
874
- word-spacing: 999px;
875
- justify-content: center;
876
- }
877
- .app-manager .app-manager-plan-page-slider .feature__type__array.feature__class
878
- {
879
- justify-content: left;
880
- }
881
-
882
- .app-manager .app-manager-plan-page-slider .plan-heading b{
883
- overflow-wrap: break-word;
884
- word-wrap: break-word;
885
- white-space: initial;
886
- }
887
-
888
- .app-manager .app-manager-plan-page-slider .custom-choose-button:hover{
889
- // background: #006e52;
890
- // border-color: transparent;
891
- // color: #fff;
892
- }
893
-
894
- .app-manager-plan-banner {
895
- margin-right: 30px;
896
- margin-left: 30px;
897
- }
898
-
899
- .bundle-plan {
900
- display: none;
901
- flex-direction: column;
902
- gap: 20px;
903
- }
904
-
905
- .bundle-category {
906
- display: flex;
907
- flex-direction: column;
908
- gap: 20px;
909
- margin-bottom: 10px;
910
- }
911
-
912
- .bundle-category-apps {
913
- display: flex;
914
- flex-direction: column;
915
- gap: 10px;
916
- }
917
-
918
- .light-divider {
919
- border-top: 1px solid #E3E3E3;
920
- margin-top: 10px;
921
- margin-bottom: 10px;
922
- }
923
-
924
- .app-manager .Polaris-Icon--colorSuccess svg {
925
- fill: black !important;
926
- }
927
-
928
- .button-group-new {
929
- display: flex;
930
- align-items: center;
931
- justify-content: center;
932
- gap: 4px;
933
- }
934
-
935
- @media (min-width: 0px) and (max-width: 576px) {
936
- .custom-plan>.Polaris-Layout__Section>.VueCarousel>.VueCarousel-wrapper>.VueCarousel-inner {
937
- overflow-x: scroll;
132
+ import axios from "axios";
133
+ import PlanBanners from "./PlanBanners";
134
+ import YearlyPlanPromotion from "./YearlyPlanPromotion";
135
+ import PPage from "../polaris-vue/src/components/PPage/PPage";
136
+ import PStack from "../polaris-vue/src/components/PStack/PStack";
137
+ import PStackItem from "../polaris-vue/src/components/PStack/components/PStackItem/PStackItem";
138
+ import {PButton} from "../polaris-vue/src/components/PButton";
139
+ import {PButtonGroup} from "../polaris-vue/src/components/PButtonGroup";
140
+ import {PHeading} from "../polaris-vue/src/components/PHeading";
141
+ import {PLayout} from "../polaris-vue/src/components/PLayout";
142
+ import {PEmptyState} from "../polaris-vue/src/components/PEmptyState"
143
+ import AppCard from "../PolarisNew/AppCard";
144
+ import PlanShowcaseBanner from "../PolarisNew/PlanShowcaseBanner";
145
+ import CategoryHeading from "../PolarisNew/CategoryHeading";
146
+ import BenefitsBanner from "../PolarisNew/BenefitsBanner";
147
+ import VariantButton from "../PolarisNew/VariantButton";
148
+ import SelectButton from "../PolarisNew/SelectButton.vue";
149
+ import ToggleButton from "../PolarisNew/ToggleButton.vue";
150
+ import PlanCardsHighlights from "../PolarisNew/PlanCardsHighlights.vue";
151
+ import GetCustomBlock from "../PolarisNew/GetCustomBlock.vue";
152
+ import PlanTable from "../PolarisNew/PlanTable.vue";
153
+ import BundlePlanCard from "../PolarisNew/BundlePlanCard.vue";
154
+ import CustomizationModal from "@/components/PolarisNew/CustomizationModal.vue";
155
+ import { calculatePlanPriceWithDiscounts } from "@/helpers";
156
+
157
+ export default {
158
+ name: "AppManagerSliderPlan",
159
+ components: {
160
+ CustomizationModal,
161
+ PPage,
162
+ PStack,
163
+ PStackItem,
164
+ PButton,
165
+ PButtonGroup,
166
+ PHeading,
167
+ PLayout,
168
+ PEmptyState,
169
+ AppCard,
170
+ PlanShowcaseBanner,
171
+ CategoryHeading,
172
+ BenefitsBanner,
173
+ VariantButton,
174
+ SelectButton,
175
+ ToggleButton,
176
+ PlanCardsHighlights,
177
+ GetCustomBlock,
178
+ PlanTable,
179
+ BundlePlanCard
180
+ },
181
+ props: ['shop_domain', 'host', 'discount_code', 'is_customizable'],
182
+ data() {
183
+ return {
184
+ planLoading: false,
185
+ plan: {},
186
+ plans: [],
187
+ valid_annual_plans: [],
188
+ promotional_discount: {},
189
+ features: [],
190
+ featureValues: [],
191
+ shopify_plan: '',
192
+ default_plan_id: null,
193
+ onboard: true,
194
+ choose_later: false,
195
+ has_active_charge: false,
196
+ global_plan_charge: false,
197
+ subtitleContent: '',
198
+ selectedPlan: 'monthly',
199
+ bundle_details: null,
200
+ bundle_plan: null,
201
+ showPlansFeatures: false,
202
+ showCustomizationModal: false
203
+ }
204
+ },
205
+ computed: {
206
+ shop() {
207
+ return {
208
+ "name": this.shop_domain,
209
+ "shopify_plan": this.shopify_plan,
210
+ "has_plan": !!this.plan,
211
+ "plan": this.plan,
212
+ "default_plan_id": this.default_plan_id,
213
+ };
214
+ },
215
+ monthlyPlan() {
216
+ return this.plans.filter(plan => plan.interval === 'EVERY_30_DAYS');
217
+ },
218
+ yearlyPlan() {
219
+ return this.plans.filter(plan => plan.interval === 'ANNUAL');
220
+ },
221
+ },
222
+ methods: {
223
+ translateMe(message) {
224
+ return this.$translations.hasOwnProperty(message) ? this.$translations[message] : message;
225
+ },
226
+ isCurrentPlanId(plan) {
227
+ return this.shop.plan && plan.id === this.shop.plan.id;
228
+ },
229
+ isActivePlanGlobal() {
230
+ return Boolean(this.shop.plan?.is_global);
231
+ },
232
+ isActiveGlobalCharge() {
233
+ return Boolean(this.global_plan_charge);
234
+ },
235
+ isSamePlanInOtherInterval(plan) {
236
+ return this.shop.plan && (plan.shopify_plans === this.shop.plan.shopify_plans)
237
+ },
238
+ format(feature) {
239
+ if (['double', 'integer'].includes(feature?.value_type)) {
240
+ if (feature.format === 'percentage') {
241
+ return `${feature.value}%`
242
+ } else if (feature.format === 'count') {
243
+ return (feature.value < 0 ? this.translateMe(`Unlimited`) : feature.value)
244
+ } else return this.translateMe(feature.value);
245
+ } else if (feature?.value_type === 'array') {
246
+ let values = JSON.parse(feature.value);
247
+ let that = this;
248
+ values = values.map(function (value) {
249
+ return that.translateMe(that.featureValues[feature.feature_id][value]);
250
+ });
251
+ return values.join(', ');
252
+ } else if (feature?.value_type === 'string') {
253
+ return this.translateMe(feature.value.replace('"', '').replace('"', ''));
938
254
  }
939
- }
940
-
941
- @media (max-width: 700px) {
942
- .Polaris-ButtonGroup__Item {
943
- width: auto !important;
255
+ },
256
+ calculateDiscountedPrice(plan) {
257
+ const planDetails = calculatePlanPriceWithDiscounts(plan, this.promotional_discount);
258
+ return planDetails.price;
259
+ },
260
+ handlePlanClicked(plan) {
261
+ this.getPlanUrl(plan);
262
+ },
263
+ async getPlanUrl(plan) {
264
+ let shopName = this.shop.name;
265
+ let host = this.host;
266
+ let discount_code = this.discount_code;
267
+ let queryString = `shop=${shopName}`;
268
+ if (host != null) {
269
+ queryString += `&host=${host}`
944
270
  }
945
- .app-manager .Polaris-Button {
946
- padding: 7px 8px !important;
947
- }
948
- }
949
-
950
- @media (min-width: 0px) and (max-width: 467px) {
951
-
952
- .app-manager .Polaris-Page-Header__RightAlign {
953
- margin-left: -34px !important;
271
+ if (discount_code != null) {
272
+ queryString += `&discount_code=${discount_code}`
954
273
  }
955
- #app_manager > div > div.Polaris-Page-Header.Polaris-Page-Header--hasNavigation.Polaris-Page-Header--mediumTitle.Polaris-Page-Header--mobileView > div > div.Polaris-Page-Header__RightAlign > div > div > div > div > div > div:nth-child(2) > button > span > span > div > div > div > span > span > div{
956
- width: 222px !important;
274
+ const response = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plan/process/${plan.id}?${queryString}`).catch(error => {
275
+ console.error(error)
276
+ });
277
+ if (response.data.plan_type === 'free_plan') {
278
+ this.$emit('handlePlanSelect', {free_plan: true})
279
+ } else {
280
+ let redirectUrl = response.data.redirect_url;
281
+ if (redirectUrl) {
282
+ window.top.location.href = redirectUrl;
283
+ }
957
284
  }
958
- .app-manager .app-manager-plan-page-slider .Polaris-Layout__Section .VueCarousel-slide li:nth-last-child(2) {
959
- min-height: 100px !important;
285
+ },
286
+ async activePlan() {
287
+ const response = await this.activeWithoutPlan()
288
+ if (response.data.status === true && this.onboard) {
289
+ this.$emit('handlePlanSelect', {choose_later: true})
290
+ this.onboard = false;
960
291
  }
961
- .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li{
962
- padding: 16px 16px 16px 5px;
292
+ },
293
+ async activeWithoutPlan() {
294
+ return await axios.post(`${this.app_manager_config.baseUrl}/api/app-manager/active-without-plan`, {
295
+ shop_domain: this.shop.name,
296
+ plan_id: this.shop.default_plan_id
297
+ }).catch(error => {
298
+ console.error(error)
299
+ });
300
+ },
301
+ async selectPlan(value) {
302
+ this.selectedPlan = value;
303
+ if (this.bundle_plan !== null) {
304
+ let planElement = document.querySelector('.custom-plan');
305
+ let bundleElement = document.querySelector('.bundle-plan');
306
+ let billCycleBack = document.querySelector('.bill-cycle-back');
307
+ let billCycleSelect = document.querySelector('.bill-cycle-select-group__inner-left');
308
+ let promotionalBanner = document.querySelector('.promotional-banner');
309
+ let bundlePlanShowcaseBanner = document.querySelector('.bundle-plan-showcase-banner');
310
+ if (this.selectedPlan == 'bundle') {
311
+ planElement.style.display = 'none';
312
+ bundleElement.style.display = 'flex';
313
+ billCycleBack.style.display = 'flex';
314
+ billCycleSelect.style.display = 'none';
315
+ if (promotionalBanner) {
316
+ promotionalBanner.style.display = 'none';
317
+ }
318
+ bundlePlanShowcaseBanner.style.display = 'flex';
319
+ } else {
320
+ bundleElement.style.display = 'none';
321
+ planElement.style.display = 'flex';
322
+ billCycleBack.style.display = 'none';
323
+ billCycleSelect.style.display = 'flex';
324
+ if (promotionalBanner) {
325
+ promotionalBanner.style.display = 'flex';
326
+ }
327
+ bundlePlanShowcaseBanner.style.display = 'none';
328
+ }
963
329
  }
964
- .app-manager .Polaris-Button {
965
- padding: 7px 8px !important;
330
+ },
331
+ async fetchFeatures() {
332
+ let {data} = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plan-features`).catch(error => {
333
+ console.error(error)
334
+ });
335
+ if (data.features.length) {
336
+ this.features = data.features;
337
+ this.features = this.features?.filter((item) => item.hidden_feature !== true)
338
+ this.features = this.features?.sort((featureA, featureB) => parseInt(featureA.display_order) - parseInt(featureB.display_order));
339
+ //Get feature array time values
340
+ this.features.forEach((feature) => {
341
+ if (feature.value_type == 'array') {
342
+ this.featureValues[feature.uuid] = feature.values;
343
+ }
344
+ });
966
345
  }
967
- .VueCarousel-slide {
968
- flex-basis: auto !important;
346
+ },
347
+ async fetchPlans() {
348
+ let params = {
349
+ 'shop_domain': this.shop_domain
350
+ };
351
+ if (this.discount_code !== null) {
352
+ params['discount_code'] = this.discount_code;
969
353
  }
970
- .Polaris-ResourceList__ResourceListWrapper.features{
971
- width: 30% !important;
354
+ let {data} = await axios.get(`${this.app_manager_config.baseUrl}/api/app-manager/plans`, {params: params}).catch(error => {
355
+ console.error(error)
356
+ });
357
+ if (data.plans.length) {
358
+ for (let i = 0; i < data.plans.length; i++) {
359
+ if (data.plans[i].interval === 'ANNUAL') {
360
+ this.valid_annual_plans.push(data.plans[i]);
361
+ }
362
+ }
363
+ this.plans = data.plans;
364
+ this.plans = this.plans?.sort((planA, planB) => parseFloat(planA.price) - parseFloat(planB.price));
365
+
366
+ if (this.plans[0].store_base_plan) {
367
+ this.subtitleContent = this.translateMe('App plans are based on your existing shopify plan');
368
+ }
369
+
370
+ this.plan = data.plan;
371
+ if (this.plan?.interval === 'ANNUAL') {
372
+ this.selectedPlan = 'annually'
373
+ }
374
+ if (this.plan?.is_global) {
375
+ this.selectedPlan = 'bundle'
376
+ }
377
+ this.shopify_plan = data.shopify_plan;
378
+ this.default_plan_id = data.default_plan_id;
379
+ this.choose_later = data.choose_later;
380
+ this.onboard = this.default_plan_id && this.choose_later;
381
+ this.has_active_charge = data.has_active_charge;
382
+ this.global_plan_charge = data.global_plan_charge;
383
+ this.promotional_discount =
384
+ data.promotional_discount
385
+ && typeof data.promotional_discount === 'object'
386
+ && Object.keys(data.promotional_discount).length > 0
387
+ ? data.promotional_discount
388
+ : {};
389
+ if (data.bundle_plan) {
390
+ this.bundle_plan = data.bundle_plan;
391
+ }
392
+ if (data.bundle_details) {
393
+ this.bundle_details = data.bundle_details;
394
+ }
972
395
  }
973
- }
974
-
975
- @media (min-width: 467px) and (max-width: 1003px) {
976
- #app_manager > div > div.Polaris-Page-Header.Polaris-Page-Header--hasNavigation.Polaris-Page-Header--mediumTitle.Polaris-Page-Header--mobileView > div > div.Polaris-Page-Header__RightAlign > div > div > div > div > div > div:nth-child(2) > button > span > span > div > div > div > span > span > div{
977
- width: 222px !important;
978
- }
979
- .app-manager .app-manager-plan-page-slider .Polaris-Layout__Section .VueCarousel-slide li:nth-last-child(2) {
980
- min-height: 100px !important;
981
- }
982
- .app-manager .Polaris-Button {
983
- padding: 7px 8px !important;
984
- }
985
- }
396
+ },
397
+ handlePlanBannerClose(payload) {
398
+ this.$emit('handlePlanBannerClose', payload)
399
+ this.$emit('handle-plan-banner-close', payload)
400
+ },
401
+ togglePlansFeatures() {
402
+ this.showPlansFeatures = !this.showPlansFeatures;
403
+ },
404
+ handleCustomizePlan() {
405
+ this.showCustomizationModal = true
406
+ this.$emit('handleCustomizePlan')
407
+ },
408
+ handleCustomizePlanClose() {
409
+ this.showCustomizationModal = false
410
+ }
411
+ },
412
+ async mounted() {
413
+ this.planLoading = true;
414
+ await this.fetchFeatures();
415
+ await this.fetchPlans();
416
+ this.planLoading = false;
417
+ },
418
+ }
419
+ </script>
986
420
 
421
+ <style lang="scss">
422
+ @import url('https://fonts.googleapis.com/css2?family=Satisfy&display=swap');
423
+
424
+ .app-manager .app-manager-plan-page-slider ul {
425
+ list-style: none;
426
+ margin: 0;
427
+ padding: 0;
428
+ }
429
+
430
+ .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li,
431
+ .app-manager .app-manager-plan-page-slider .plan__price {
432
+ padding: 16px 16px 16px 20px;
433
+ }
434
+
435
+ .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li {
436
+ border-top: 1px solid #dddddd;
437
+ border-right: 1px solid #dddddd;
438
+ background: #fff;
439
+ border-right: none;
440
+ border-left: 1px solid #dddddd;
441
+ }
442
+
443
+ .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:last-child {
444
+ border-bottom: 1px solid #dddddd;
445
+ }
446
+
447
+ .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:first-child {
448
+ border-top-left-radius: 12px;
449
+ }
450
+
451
+ .app-manager .app-manager-plan-page-slider .Polaris-ResourceList__ResourceListWrapper.features li:last-child {
452
+ border-bottom-left-radius: 12px;
453
+ }
454
+
455
+ .app-manager .app-manager-plan-page-slider .plan__price {
456
+ border-left: 1px solid #dddddd;
457
+ box-shadow: none;
458
+ border-top-left-radius: 12px;
459
+ overflow: hidden;
460
+ }
461
+
462
+ .app-manager .app-manager-plan-page-slider .feature__list,
463
+ .app-manager .app-manager-plan-page-slider .feature__type__array {
464
+ display: flex;
465
+ align-items: center;
466
+ word-spacing: 999px;
467
+ justify-content: center;
468
+ }
469
+
470
+ .app-manager .app-manager-plan-page-slider .feature__type__array.feature__class {
471
+ justify-content: left;
472
+ }
473
+
474
+ .app-manager .app-manager-plan-page-slider .plan-heading b {
475
+ overflow-wrap: break-word;
476
+ word-wrap: break-word;
477
+ white-space: initial;
478
+ }
479
+
480
+ .app-manager-plan-banner {
481
+ margin-right: 30px;
482
+ margin-left: 30px;
483
+ }
484
+
485
+ .bundle-plan {
486
+ display: none;
487
+ flex-direction: column;
488
+ gap: 20px;
489
+ }
490
+
491
+ .bundle-category {
492
+ display: flex;
493
+ flex-direction: column;
494
+ gap: 20px;
495
+ margin-bottom: 10px;
496
+ }
497
+
498
+ .bundle-category-apps {
499
+ display: flex;
500
+ flex-direction: column;
501
+ gap: 10px;
502
+ }
503
+
504
+ .light-divider {
505
+ border-top: 1px solid #E3E3E3;
506
+ margin-top: 10px;
507
+ margin-bottom: 10px;
508
+ }
509
+
510
+ .app-manager .Polaris-Icon--colorSuccess svg {
511
+ fill: black !important;
512
+ }
513
+
514
+ .button-group-new {
515
+ display: flex;
516
+ align-items: center;
517
+ justify-content: center;
518
+ gap: 4px;
519
+ }
520
+
521
+ .bill-cycle-select-group {
522
+ display: flex;
523
+ align-items: center;
524
+ justify-content: space-between;
525
+ gap: 4px;
526
+ max-width: 998px;
527
+ margin-left: auto;
528
+ margin-right: auto;
529
+ padding: 0px 32px;
530
+ }
531
+
532
+ .bill-cycle-select-group__inner-left {
533
+ width: fit-content;
534
+ display: flex;
535
+ gap: 4px;
536
+ align-items: center;
537
+ justify-content: center;
538
+ border-radius: 40px;
539
+ padding: 4px;
540
+ border: 1px solid black;
541
+ }
542
+
543
+ .bill-cycle-back {
544
+ display: none;
545
+ align-items: center;
546
+ color: #006FBB;
547
+ cursor: pointer;
548
+ gap: 4px;
549
+ font-weight: 450;
550
+ font-size: 14px;
551
+ }
552
+
553
+ .promotional-banner {
554
+ width: 100%;
555
+ height: 100px;
556
+ display: flex;
557
+ align-items: center;
558
+ justify-content: end;
559
+ padding-right: 36px;
560
+ background-image: url('../../assets/25for70lessBanner.png');
561
+ background-size: cover;
562
+ background-repeat: no-repeat;
563
+ background-position: center;
564
+ border-radius: 8px;
565
+ margin-bottom: 22px;
566
+ }
567
+
568
+ .custom-plan {
569
+ display: flex;
570
+ flex-direction: column;
571
+ align-items: center !important;
572
+ gap: 24px;
573
+ margin-left: 0 !important;
574
+ margin-right: 0 !important;
575
+ }
576
+
577
+ .toggle-plans-features {
578
+ font-size: 13px;
579
+ font-weight: 500;
580
+ color: #303030;
581
+ text-decoration: none;
582
+ }
583
+
584
+ .hide-all-features {
585
+ visibility: hidden;
586
+ overflow: hidden;
587
+ height: 0px;
588
+ margin-top: 0px !important;
589
+ }
590
+
591
+ .customization-bundle-section {
592
+ display: flex;
593
+ flex-direction: row;
594
+ gap: 24px;
595
+ width: 100%;
596
+ }
597
+
598
+ @media (max-width: 700px) {
599
+ .Polaris-ButtonGroup__Item {
600
+ width: auto !important;
601
+ }
602
+ .app-manager .Polaris-Button {
603
+ padding: 7px 8px !important;
604
+ }
605
+ }
606
+
607
+ @media (max-width: 767px) {
608
+ .bill-cycle-select-group {
609
+ flex-direction: column-reverse;
610
+ gap: 10px;
611
+ }
612
+ }
613
+
614
+ @media (max-width: 1023px) {
615
+ .customization-bundle-section {
616
+ flex-direction: column;
617
+ gap: 20px;
618
+ }
619
+ }
987
620
  </style>