web/satellite: reworked new Add coupon modal to use common VModal component

Reworked new Add coupon modal to use common VModal component to improve UX.

Issue:
https://github.com/storj/storj/issues/5104

Change-Id: Idd186ffd30a529761d15052bee4fac7cee4f5814
This commit is contained in:
Vitalii 2022-11-01 16:42:41 +02:00
parent 7f285c2eee
commit 7ac1e38e28
8 changed files with 94 additions and 190 deletions

View File

@ -42,10 +42,6 @@
</div> </div>
</div> </div>
</div> </div>
<AddCouponCode2
v-if="showCreateCode"
@toggleMethod="toggleCreateModal"
/>
</div> </div>
</div> </div>
</template> </template>
@ -57,20 +53,18 @@ import { PAYMENTS_ACTIONS } from '@/store/modules/payments';
import { Coupon } from '@/types/payments'; import { Coupon } from '@/types/payments';
import { AnalyticsHttpApi } from '@/api/analytics'; import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames'; import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
import AddCouponCode2 from '@/components/account/billing/coupons/AddCouponCode2.vue';
import VLoader from '@/components/common/VLoader.vue'; import VLoader from '@/components/common/VLoader.vue';
// @vue/component // @vue/component
@Component({ @Component({
components: { components: {
VLoader, VLoader,
AddCouponCode2,
}, },
}) })
export default class Coupons extends Vue { export default class Coupons extends Vue {
public isCouponFetching = true; public isCouponFetching = true;
public showCreateCode = false;
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi(); private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
@ -93,7 +87,7 @@ export default class Coupons extends Vue {
*/ */
public toggleCreateModal(): void { public toggleCreateModal(): void {
this.analytics.eventTriggered(AnalyticsEvent.APPLY_NEW_COUPON_CLICKED); this.analytics.eventTriggered(AnalyticsEvent.APPLY_NEW_COUPON_CLICKED);
this.showCreateCode = !this.showCreateCode; this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_NEW_BILLING_ADD_COUPON_MODAL_SHOWN);
} }
/** /**

View File

@ -1,127 +0,0 @@
// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<div class="add-coupon__wrapper">
<div class="add-coupon__modal">
<div class="add-coupon__container">
<div class="add-coupon__header-wrapper">
<CloseIcon
class="add-coupon__close-icon"
@click="onCloseClick"
/>
</div>
<div class="add-coupon__body-wrapper">
<CouponIcon />
<h2 class="add-coupon__body-wrapper__title">Apply Coupon Code</h2>
<p class="add-coupon__body-wrapper__text">If you have a coupon active, it will automatically be replaced.</p>
</div>
<AddCouponCodeInput2 @close="onCloseClick" />
</div>
</div>
</div>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import AddCouponCodeInput2 from '@/components/common/AddCouponCodeInput2.vue';
import CloseIcon from '@/../static/images/common/closeCross.svg';
import CouponIcon from '@/../static/images/account/billing/greenCoupon.svg';
// @vue/component
@Component({
components: {
CloseIcon,
AddCouponCodeInput2,
CouponIcon,
},
})
export default class AddCouponCode2 extends Vue {
@Prop({ default: false })
protected readonly success: boolean;
@Prop({ default: false })
protected readonly error: boolean;
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
/**
* Closes add coupon modal.
*/
public onCloseClick(): void {
this.analytics.eventTriggered(AnalyticsEvent.COUPON_CODE_APPLIED);
this.$emit('toggleMethod');
}
}
</script>
<style scoped lang="scss">
.add-coupon {
&__wrapper {
background: #1b2533c7 75%;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
}
&__modal {
width: 40%;
min-width: 300px;
max-width: 390px;
aspect-ratio: 1/1;
height: auto;
background: #fff;
border-radius: 8px;
margin: 15% auto;
position: relative;
padding-bottom: 20px;
}
&__container {
width: 85%;
padding-top: 10px;
margin: 0 auto;
}
&__header-wrapper {
display: flex;
justify-content: right;
padding-bottom: 20px;
}
&__body-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: column;
height: 150px;
&__title {
font-family: sans-serif;
font-weight: 800;
text-align: center;
}
&__text {
font-family: sans-serif;
text-align: center;
}
}
&__close-icon {
position: relative;
top: 17px;
cursor: pointer;
}
}
</style>

View File

@ -4,13 +4,8 @@
<template> <template>
<div class="add-coupon__input-container"> <div class="add-coupon__input-container">
<div class="add-coupon__input-wrapper"> <div class="add-coupon__input-wrapper">
<p class="add-coupon__input-wrapper__label">
Coupon Code:
</p>
<VInput <VInput
placeholder="Enter Coupon Code" placeholder="Enter Coupon Code"
height="52px"
with-icon
@setData="setCouponCode" @setData="setCouponCode"
/> />
</div> </div>
@ -24,7 +19,7 @@
<VButton <VButton
class="add-coupon__apply-button" class="add-coupon__apply-button"
label="Apply Coupon Code" label="Apply Coupon Code"
width="150px" width="100%"
height="44px" height="44px"
font-size="14px" font-size="14px"
:on-press="applyCouponCode" :on-press="applyCouponCode"
@ -50,7 +45,7 @@ import VButton from '@/components/common/VButton.vue';
ValidationMessage, ValidationMessage,
}, },
}) })
export default class AddCouponCodeInput2 extends Vue { export default class NewBillingAddCouponCodeInput extends Vue {
private showValidationMessage = false; private showValidationMessage = false;
private isCodeValid = false; private isCodeValid = false;
private errorMessage = ''; private errorMessage = '';
@ -86,6 +81,7 @@ export default class AddCouponCodeInput2 extends Vue {
<style scoped lang="scss"> <style scoped lang="scss">
.add-coupon { .add-coupon {
font-family: 'font_regular', sans-serif;
&__input-container { &__input-container {
display: flex; display: flex;
@ -93,52 +89,11 @@ export default class AddCouponCodeInput2 extends Vue {
} }
&__input-wrapper { &__input-wrapper {
position: relative; margin: 10px 0;
margin: 30px 0 10px;
&__label {
font-family: sans-serif;
font-weight: 700;
font-size: 14px;
color: var(--c-grey-6);
margin-top: -15px;
}
} }
&__valid-message { &__valid-message {
position: relative;
margin-bottom: 10px; margin-bottom: 10px;
} }
&__apply-button {
left: 0;
right: 0;
margin: 0 auto;
bottom: 20px;
background: #2683ff;
&:hover {
background: #0059d0;
} }
}
&__check {
position: absolute;
right: 15px;
bottom: 15px;
}
&__confirm-message {
font-family: 'font_regular', sans-serif;
font-size: 18px;
margin-top: 35px;
}
&__button-wrapper {
display: flex;
justify-content: space-evenly;
margin-top: 30px;
}
}
</style> </style>

View File

@ -13,7 +13,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'; import { Component, Vue } from 'vue-property-decorator';
import { RouteConfig } from '@/router'; import { RouteConfig } from '@/router';
import { AnalyticsHttpApi } from '@/api/analytics'; import { AnalyticsHttpApi } from '@/api/analytics';
@ -30,11 +30,6 @@ import VModal from '@/components/common/VModal.vue';
}, },
}) })
export default class AddCouponCodeModal extends Vue { export default class AddCouponCodeModal extends Vue {
@Prop({ default: false })
protected readonly success: boolean;
@Prop({ default: false })
protected readonly error: boolean;
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi(); private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
/** /**

View File

@ -20,6 +20,7 @@
<NewFolderModal v-if="isNewFolderModal" /> <NewFolderModal v-if="isNewFolderModal" />
<DeleteBucketModal v-if="isDeleteBucketModal" /> <DeleteBucketModal v-if="isDeleteBucketModal" />
<AddCouponCodeModal v-if="isAddCouponModal" /> <AddCouponCodeModal v-if="isAddCouponModal" />
<NewBillingAddCouponCodeModal v-if="isNewBillingAddCouponModal" />
</div> </div>
</template> </template>
@ -43,6 +44,7 @@ import NewFolderModal from '@/components/modals/NewFolderModal.vue';
import ShareObjectModal from '@/components/modals/ShareObjectModal.vue'; import ShareObjectModal from '@/components/modals/ShareObjectModal.vue';
import DeleteBucketModal from '@/components/modals/DeleteBucketModal.vue'; import DeleteBucketModal from '@/components/modals/DeleteBucketModal.vue';
import AddCouponCodeModal from '@/components/modals/AddCouponCodeModal.vue'; import AddCouponCodeModal from '@/components/modals/AddCouponCodeModal.vue';
import NewBillingAddCouponCodeModal from '@/components/modals/NewBillingAddCouponCodeModal.vue';
// @vue/component // @vue/component
@Component({ @Component({
@ -64,6 +66,7 @@ import AddCouponCodeModal from '@/components/modals/AddCouponCodeModal.vue';
ObjectDetailsModal, ObjectDetailsModal,
NewFolderModal, NewFolderModal,
AddCouponCodeModal, AddCouponCodeModal,
NewBillingAddCouponCodeModal,
}, },
}) })
export default class AllModals extends Vue { export default class AllModals extends Vue {
@ -186,5 +189,12 @@ export default class AllModals extends Vue {
public get isAddCouponModal(): boolean { public get isAddCouponModal(): boolean {
return this.$store.state.appStateModule.appState.isAddCouponModalShown; return this.$store.state.appStateModule.appState.isAddCouponModalShown;
} }
/**
* Indicates if new add coupon modal is shown.
*/
public get isNewBillingAddCouponModal(): boolean {
return this.$store.state.appStateModule.appState.isNewBillingAddCouponModalShown;
}
} }
</script> </script>

View File

@ -0,0 +1,72 @@
// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
<template>
<VModal :on-close="onCloseClick">
<template #content>
<div class="modal">
<CouponIcon />
<h2 class="modal__title">Apply Coupon Code</h2>
<p class="modal__text">If you have a coupon active, it will automatically be replaced.</p>
<NewBillingAddCouponCodeInput @close="onCloseClick" />
</div>
</template>
</VModal>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import { AnalyticsHttpApi } from '@/api/analytics';
import { AnalyticsEvent } from '@/utils/constants/analyticsEventNames';
import { APP_STATE_MUTATIONS } from '@/store/mutationConstants';
import NewBillingAddCouponCodeInput from '@/components/common/NewBillingAddCouponCodeInput.vue';
import VModal from '@/components/common/VModal.vue';
import CouponIcon from '@/../static/images/account/billing/greenCoupon.svg';
// @vue/component
@Component({
components: {
VModal,
NewBillingAddCouponCodeInput,
CouponIcon,
},
})
export default class NewBillingAddCouponCodeModal extends Vue {
private readonly analytics: AnalyticsHttpApi = new AnalyticsHttpApi();
/**
* Closes add coupon modal.
*/
public onCloseClick(): void {
this.analytics.eventTriggered(AnalyticsEvent.COUPON_CODE_APPLIED);
this.$store.commit(APP_STATE_MUTATIONS.TOGGLE_NEW_BILLING_ADD_COUPON_MODAL_SHOWN);
}
}
</script>
<style scoped lang="scss">
.modal {
width: 500px;
padding: 32px;
font-family: 'font_regular', sans-serif;
@media screen and (max-width: 650px) {
width: unset;
padding: 24px;
}
&__title {
font-family: 'font_bold', sans-serif;
font-size: 16px;
line-height: 148.31%;
margin: 15px 0;
}
&__text {
text-align: center;
}
}
</style>

View File

@ -43,6 +43,7 @@ class ViewsState {
public isNewFolderModalShown = false, public isNewFolderModalShown = false,
public isObjectDetailsModalShown = false, public isObjectDetailsModalShown = false,
public isAddCouponModalShown = false, public isAddCouponModalShown = false,
public isNewBillingAddCouponModalShown = false,
public isBillingNotificationShown = true, public isBillingNotificationShown = true,
public onbAGStepBackRoute = '', public onbAGStepBackRoute = '',
@ -168,6 +169,9 @@ export const appStateModule = {
[APP_STATE_MUTATIONS.TOGGLE_ADD_COUPON_MODAL_SHOWN](state: State): void { [APP_STATE_MUTATIONS.TOGGLE_ADD_COUPON_MODAL_SHOWN](state: State): void {
state.appState.isAddCouponModalShown = !state.appState.isAddCouponModalShown; state.appState.isAddCouponModalShown = !state.appState.isAddCouponModalShown;
}, },
[APP_STATE_MUTATIONS.TOGGLE_NEW_BILLING_ADD_COUPON_MODAL_SHOWN](state: State): void {
state.appState.isNewBillingAddCouponModalShown = !state.appState.isNewBillingAddCouponModalShown;
},
[APP_STATE_MUTATIONS.TOGGLE_NEW_FOLDER_MODAL_SHOWN](state: State): void { [APP_STATE_MUTATIONS.TOGGLE_NEW_FOLDER_MODAL_SHOWN](state: State): void {
state.appState.isNewFolderModalShown = !state.appState.isNewFolderModalShown; state.appState.isNewFolderModalShown = !state.appState.isNewFolderModalShown;
}, },

View File

@ -42,6 +42,7 @@ export const APP_STATE_MUTATIONS = {
TOGGLE_DELETE_BUCKET_MODAL_SHOWN: 'TOGGLE_DELETE_BUCKET_MODAL_SHOWN', TOGGLE_DELETE_BUCKET_MODAL_SHOWN: 'TOGGLE_DELETE_BUCKET_MODAL_SHOWN',
TOGGLE_OBJECT_DETAILS_MODAL_SHOWN: 'TOGGLE_OBJECT_DETAILS_MODAL_SHOWN', TOGGLE_OBJECT_DETAILS_MODAL_SHOWN: 'TOGGLE_OBJECT_DETAILS_MODAL_SHOWN',
TOGGLE_ADD_COUPON_MODAL_SHOWN: 'TOGGLE_ADD_COUPON_MODAL_SHOWN', TOGGLE_ADD_COUPON_MODAL_SHOWN: 'TOGGLE_ADD_COUPON_MODAL_SHOWN',
TOGGLE_NEW_BILLING_ADD_COUPON_MODAL_SHOWN: 'TOGGLE_NEW_BILLING_ADD_COUPON_MODAL_SHOWN',
TOGGLE_NEW_FOLDER_MODAL_SHOWN: 'TOGGLE_NEW_FOLDER_MODAL_SHOWN', TOGGLE_NEW_FOLDER_MODAL_SHOWN: 'TOGGLE_NEW_FOLDER_MODAL_SHOWN',
SHOW_DELETE_PAYMENT_METHOD_POPUP: 'SHOW_DELETE_PAYMENT_METHOD_POPUP', SHOW_DELETE_PAYMENT_METHOD_POPUP: 'SHOW_DELETE_PAYMENT_METHOD_POPUP',
SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP: 'SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP', SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP: 'SHOW_SET_DEFAULT_PAYMENT_METHOD_POPUP',